The Model/View/Controller design

Overview

Both the TreeView and the ComboBox 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").

The Model

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).

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

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().

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.

Useful methods for a Gtk.TreeModel:

  • 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.

  • 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.

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

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

  • 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.

Useful methods for a Gtk.ListStore:

  • 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.

  • 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.

Useful methods for a Gtk.TreeStore:

  • 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.

  • 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.

The View: the TreeView case

A Treeview shows the structure of children and parent items as a tree. See for instance this example.

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

Useful methods for a Gtk.TreeView:

  • 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.

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

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

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

Useful methods for a Gtk.TreeViewColumn:

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

  • 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.

  • 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.

  • 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.

  • 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.

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

The View: the ComboBox case

A Gtk.ComboBox allows for the selection of an item from a dropdown menu, see for instance this example. For a list of textual choices, one can also use the simpler Gtk.ComboBoxText. Both Gtk.ComboBox and Gtk.ComboBoxText can contain an entry.

Useful methods for a Gtk.ComboBox:

  • 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.

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

  • 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.

  • 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).

  • 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.

Useful methods for a Gtk.ComboBoxText:

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

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

  • 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).

The View: the Cellrenderers

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

Implementations of Gtk.CellRenderer and useful methods:

  • Gtk.CellRendererText - renders text in a cell

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

    • set_active(setting) - activates or deactivates a cell renderer

    • get_active() - returns whether the cell renderer is active

    • 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)

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

  • Gtk.CellRendererPixbuf - renders an image in a cell

  • 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.

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

  • Gtk.CellRendererSpinner - renders a spinning animation in a cell

  • Gtk.CellRendererSpin - renders a spin button in a cell

  • Gtk.CellRendererAccel - renders a keyboard accelerator in a cell

The Controller: the Selection

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.

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

Then to retrieve data for the row selected:

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

Useful methods for a Gtk.TreeSelection:

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

    • Gtk.SelectionMode.NONE - no selection is possible

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

    • 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.

    • 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.

  • 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.