Blame platform-demos/C/model-view-controller.py.page

Packit 1470ea
Packit 1470ea
Packit 1470ea
      xmlns:its="http://www.w3.org/2005/11/its"
Packit 1470ea
      xmlns:e="http://projectmallard.org/experimental/"
Packit 1470ea
      type="guide" style="task"
Packit 1470ea
      id="model-view-controller.py">
Packit 1470ea
Packit 1470ea
<info>
Packit 1470ea
    <title type="text">The Model/View/Controller design (Python)</title>
Packit 1470ea
  <link type="guide" xref="beginner.py#theory"/>
Packit 1470ea
  <link type="next" xref="combobox_multicolumn.py"/>
Packit 1470ea
  <revision version="0.1" date="2012-06-30" status="stub"/>
Packit 1470ea
Packit 1470ea
  <desc>The Model/View/Controller design</desc>
Packit 1470ea
  <credit type="author copyright">
Packit 1470ea
    <name>Sebastian Pölsterl</name>
Packit 1470ea
    <email its:translate="no">sebp@k-d-w.org</email>
Packit 1470ea
    <years>2011</years>
Packit 1470ea
  </credit>
Packit 1470ea
  <credit type="author copyright editor">
Packit 1470ea
    <name>Marta Maria Casetti</name>
Packit 1470ea
    <email its:translate="no">mmcasetti@gmail.com</email>
Packit 1470ea
    <years>2012</years>
Packit 1470ea
  </credit>
Packit 1470ea
</info>
Packit 1470ea
Packit 1470ea
<title>The Model/View/Controller design</title>
Packit 1470ea
Packit 1470ea
<links type="section" />
Packit 1470ea
Packit 1470ea
<section id="overview">
Packit 1470ea
<title>Overview</title>
Packit 1470ea
Packit 1470ea

Both the <link xref="treeview_simple_liststore.py">TreeView</link> and the <link xref="combobox.py">ComboBox</link> widgets are built on the Model/View/Controller design. The Model (an implementation of Gtk.TreeModel, usually Gtk.TreeStore or Gtk.ListStore) stores the data; the View (e.g. Gtk.TreeView, Gtk.ComboBox, or Gtk.ComboBoxText) gets change notifications and displays the content of the model. The Controller, finally, changes the state of the model (via some methods in the model's implementation - such as append() or remove()) and notifies the view of these changes (via signals like "changed").

Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="model">
Packit 1470ea
<title>The Model</title>
Packit 1470ea
Packit 1470ea

The main difference between the two main implementations of Gtk.TreeModel is that Gtk.ListStore contains simple rows of data without children, whereas Gtk.TreeStore also contains rows of data, but each row may have child rows (which in turn can have child rows, and so on).

Packit 1470ea
Packit 1470ea

The data in the Model can be retrieved or modified using the tree iter and column index, or Gtk.TreeIter, or Gtk.TreePath.

Packit 1470ea
Packit 1470ea

As with Python's built-in list object you can use len() to get the number of rows and use slices to retrieve or set values. Otherwise, the method append() returns a Gtk.TreeIter instance, which points to the location of the newly inserted row. You can also retrieve a Gtk.TreeIter by calling get_iter().

Packit 1470ea
Packit 1470ea

As Gtk.ListStore contains only one level, i.e. nodes do not have any child nodes, a path is essentially the index of the row you want to access. In the case of Gtk.TreeStore, a path is a list of indexes or a string. The string form is a list of numbers separated by a colon. Each number refers to the offset at that level. Thus, the path "0" refers to the root node and the path "2:4" refers to the fifth child of the third node.

Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.TreeModel:

Packit 1470ea
<list>
Packit 1470ea
  <item>

get_iter(path) returns a Gtk.TreeIter instance pointing to path. This is expected to be a colon-separated list of numbers, or a tuple. For example, the string "10:4:0" is equivalent to the tuple (10, 4, 0), as both would create a path of depth 3 pointing to the 11th child of the root node, the 5th child of that 11th child, and the 1st child of that 5th child.

</item>
Packit 1470ea
  <item>

iter_next(treeiter) returns a Gtk.TreeIter instance pointing the node following treeiter at the current level or None if there is no next iter.

</item>
Packit 1470ea
  <item>

iter_has_child(treeiter) returns True if treeiter has children, False otherwise.

</item>
Packit 1470ea
  <item>

iter_children(treeiter) returns a Gtk.TreeIter instance pointing to the first child of treeiter or None if treeiter has no children.

</item>
Packit 1470ea
  <item>

get_iter_first() returns a Gtk.TreeIter instance pointing to the first iterator in the tree (the one at the path "0") or None if the tree is empty.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.ListStore:

Packit 1470ea
<list>
Packit 1470ea
  <item>

append(row) appends a new row to this list store, where row can be a list of values for each column; row can also be omitted or None, and in that case an empty row will be appended. The method returns a Gtk.TreeIter pointing to the appended row.

</item>
Packit 1470ea
  <item>

remove(iter) removes iter from the Gtk.ListStore, and returns True if the iter is valid, and False if the iter is not. After being removed, iter is set to be the next valid row.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.TreeStore:

Packit 1470ea
<list>
Packit 1470ea
  <item>

append(parent, row) appends a new row to this tree store; parent must be a valid Gtk.TreeIter. If parent is not None, then it will append the new row after the last child of parent, otherwise it will append a row to the top level; row can be a list of values for each column, or it can be omitted or None; in this latter case an empty row will be appended. The method returns a Gtk.TreeIter pointing to the appended row.

</item>
Packit 1470ea
  <item>

remove(iter) removes iter from the Gtk.ListStore, and returns True if the iter is valid, and False if the iter is not. After being removed, iter is set to be the next valid row.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="treeview">
Packit 1470ea
<title>The View: the TreeView case</title>
Packit 1470ea
Packit 1470ea

A Treeview shows the structure of children and parent items as a tree. See for instance <link xref="treeview_treestore.py">this example</link>.

Packit 1470ea
Packit 1470ea

The Gtk.TreeViewColumn is used to organize the vertical columns.

Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.TreeView:

Packit 1470ea
<list>
Packit 1470ea
  <item>

set_model(model) sets the model for this tree view. If this tree view already has a model set, it will remove it before setting the new model. If model is None, then it will unset the old model.

</item>
Packit 1470ea
  <item>

get_model() returns the model this tree view is based on, None if the model is unset.

</item>
Packit 1470ea
  <item>

append_column(column) appends column to the list of columns.

</item>
Packit 1470ea
  <item>

get_selection() gets the Gtk.TreeSelection associated with this tree view.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.TreeViewColumn:

Packit 1470ea
<list>
Packit 1470ea
  <item>

add_attribute(renderer, attribute, value) adds an attribute mapping to this column. attribute is the parameter on renderer to be set from the value

</item>
Packit 1470ea
  <item>

pack_start(renderer, expand) packs renderer into the beginning of this column. If expand is False, then renderer is allocated no more space than it needs. Any unused space is divided evenly between cells for which expand is True.

</item>
Packit 1470ea
  <item>

pack_end(renderer, expand) adds renderer to end of this column. If expand is False, then renderer is allocated no more space than it needs. Any unused space is divided evenly between cells for which expand is True.

</item>
Packit 1470ea
  <item>

set_sort_column_id(sort_column_id) sets the column of the model by which this column (of the view) should be sorted. This also makes the column header clickable.

</item>
Packit 1470ea
  <item>

set_sort_indicator(setting) sets whether a little arrow is displayed in the column header; setting can either be True (indicator is shown) or False.

</item>
Packit 1470ea
  <item>

set_sort_order(order) changes the order by which the column is sorted; order can either be Gtk.SortType.ASCENDING or Gtk.SortType.DESCENDING.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="combobox">
Packit 1470ea
<title>The View: the ComboBox case</title>
Packit 1470ea
Packit 1470ea

A Gtk.ComboBox allows for the selection of an item from a dropdown menu, see for instance <link xref="combobox.py">this example</link>. For a list of textual choices, one can also use the simpler Gtk.ComboBoxText. Both Gtk.ComboBox and Gtk.ComboBoxText can contain an entry.

Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.ComboBox:

Packit 1470ea
<list>
Packit 1470ea
  <item>

The static method new_with_entry() creates a new empty Gtk.ComboBox with an entry; the static method new_with_model(model) creates a new one with the model initialized to model; and the static method new_with_model_and_entry(model) is a combination of the two.

</item>
Packit 1470ea
  <item>

get_active_iter() returns a Gtk.TreeIter pointing to the current active item. If no active item exists, None is returned.

</item>
Packit 1470ea
  <item>

set_model(model) sets the model used by this combo box to be model, and it will unset a previously set model (if there is any). If model is None, then it will unset the model. Note that this function does not clear the cell renderers.

</item>
Packit 1470ea
  <item>

set_entry_text_column(text_column) sets the model column which this combo box should use to get strings from to be text_column. The column text_column in the model of this combo box must be of type str (this is only relevant if this combo box has been created with the “has-entry” property set to True).

</item>
Packit 1470ea
  <item>

set_wrap_width(width) sets the wrap width of this combo box to be width. The wrap width is basically the preferred number of columns when you want the popup to be laid out in a grid.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.ComboBoxText:

Packit 1470ea
<list>
Packit 1470ea
  <item>

The static method new_with_entry() creates a new empty Gtk.ComboBoxText with an entry.

</item>
Packit 1470ea
  <item>

append_text(text) appends text to the list of strings stored in this combo box.

</item>
Packit 1470ea
  <item>

get_active_text() returns the currently active string in this combo box, or None if none is selected. If this combo box contains an entry, this function will return its contents (which will not necessarily be an item from the list).

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="cellrenderer">
Packit 1470ea
<title>The View: the Cellrenderers</title>
Packit 1470ea
Packit 1470ea

The View makes use of Gtk.CellRenderers of various types to draw the data.

Packit 1470ea
Packit 1470ea

Implementations of Gtk.CellRenderer and useful methods:

Packit 1470ea
<list>
Packit 1470ea
  <item>

Gtk.CellRendererText - renders text in a cell

</item>
Packit 1470ea
  <item>

Gtk.CellRendererToggle - renders a toggle or radio button in a cell. Useful methods:

Packit 1470ea
    <list>
Packit 1470ea
    <item>

set_active(setting) - activates or deactivates a cell renderer

</item>
Packit 1470ea
    <item>

get_active() - returns whether the cell renderer is active

</item>
Packit 1470ea
    <item>

set_radio(radio) - if radio is True, the cell renderer renders a radio toggle (i.e. a toggle in a group of mutually-exclusive toggles); if False, it renders a check toggle (a standalone boolean option)

</item>
Packit 1470ea
    <item>

get_radio() - returns whether we are rendering radio toggles rather than checkboxes.

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </item>
Packit 1470ea
  <item>

Gtk.CellRendererPixbuf - renders an image in a cell

</item>
Packit 1470ea
  <item>

Gtk.CellRendererCombo - renders text in a cell; but while Gtk.CellRendererText offers a simple entry to edit the text, Gtk.CellRendererCombo offers a Gtk.ComboBox widget to edit the text. It can be used with and without an associated Gtk.Entry widget, depending on the value of the “has-entry” property.

</item>
Packit 1470ea
  <item>

Gtk.CellRendererProgress - renders a numeric value as a progress bar in a cell; it can display a text on top of the progress bar

</item>
Packit 1470ea
  <item>

Gtk.CellRendererSpinner - renders a spinning animation in a cell

</item>
Packit 1470ea
  <item>

Gtk.CellRendererSpin - renders a spin button in a cell

</item>
Packit 1470ea
  <item>

Gtk.CellRendererAccel - renders a keyboard accelerator in a cell

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="selection">
Packit 1470ea
<title>The Controller: the Selection</title>
Packit 1470ea
Packit 1470ea

Most applications will need to not only deal with displaying data, but also receiving input events from users. To do this, simply get a reference to a selection object and connect to the "changed" signal.

Packit 1470ea
Packit 1470ea
Packit 1470ea
select = tree.get_selection()
Packit 1470ea
select.connect("changed", on_tree_selection_changed)
Packit 1470ea
Packit 1470ea
Packit 1470ea

Then to retrieve data for the row selected:

Packit 1470ea
Packit 1470ea
Packit 1470ea
def on_tree_selection_changed(selection):
Packit 1470ea
    model, treeiter = selection.get_selected()
Packit 1470ea
    if treeiter != None:
Packit 1470ea
        print "You selected", model[treeiter][0]
Packit 1470ea
Packit 1470ea
Packit 1470ea

Useful methods for a Gtk.TreeSelection:

Packit 1470ea
Packit 1470ea
<list>
Packit 1470ea
  <item>

set_mode(type) sets the type of selection, where type is one of

Packit 1470ea
  <list>
Packit 1470ea
    <item>

Gtk.SelectionMode.NONE - no selection is possible

</item>
Packit 1470ea
    <item>

Gtk.SelectionMode.SINGLE - zero or one element may be selected

</item>
Packit 1470ea
    <item>

Gtk.SelectionMode.BROWSE - exactly one element is selected. In some circumstances, such as initially or during a search operation, it’s possible for no element to be selected. What is really enforced is that the user can’t deselect a currently selected element except by selecting another element.

</item>
Packit 1470ea
    <item>

Gtk.SelectionMode.MULTIPLE -any number of elements may be selected. Clicks toggle the state of an item. The Ctrl key may be used to enlarge the selection, and Shift key to select between the focus and the child pointed to. Some widgets may also allow Click-drag to select a range of elements.

</item>
Packit 1470ea
  </list>
Packit 1470ea
  </item>
Packit 1470ea
  <item>

get_selected() returns a tuple (model, treeiter), where model is the current model and treeiter a Gtk.TreeIter pointing to the currently selected row, or None if no rows are selected. The method does not work if the selection mode is set to Gtk.SelectionMode.MULTIPLE; in that case, use get_selected_rows() instead, which Returns a list of Gtk.TreePath instances of all selected rows.

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
<section id="references">
Packit 1470ea
<title>References</title>
Packit 1470ea
Packit 1470ea
<list>
Packit 1470ea
  <item>

<link href="http://developer.gnome.org/gtk3/unstable/GtkTreeModel.html">GtkTreeModel</link>

</item>
Packit 1470ea
  <item>

<link href="http://developer.gnome.org/gtk3/unstable/GtkTreeView.html">GtkTreeView</link>

</item>
Packit 1470ea
  <item>

<link href="http://developer.gnome.org/gtk3/unstable/GtkTreeViewColumn.html">GtkTreeViewColumn</link>

</item>
Packit 1470ea
  <item>

<link href="http://developer.gnome.org/gtk3/unstable/GtkComboBox.html">GtkComboBox</link>

</item>
Packit 1470ea
  <item>

<link href="http://developer.gnome.org/gtk3/unstable/GtkCellRenderer.html">GtkCellRenderer</link>

</item>
Packit 1470ea
</list>
Packit 1470ea
Packit 1470ea
</section>
Packit 1470ea
Packit 1470ea
</page>