[Gtk-sharp-list] GtkTree{Model,Store} API additions in PyGTK.

James Henstridge james@daa.com.au
Wed, 12 Mar 2003 09:52:05 +0800


This email describes the API additions that have been made to the 
GtkTreeStore and GtkListStore classes in PyGTK in order to make them 
more friendly to Python programmers.  It is cc'd to the GTK# mailing 
list at the request of one of the developers, but should mainly be 
useful to Python programmers.

The description below is of what is currently in CVS.  Most of the 
functionality is in released versions, but some is recent.

There is no special wrapper for GtkTreePaths in PyGTK.  Since a tree 
path is really just an ordered list of indices, we represent them as 
tuples of integers.  In places where a GtkTreePath must be passed to 
GTK, the following Python types will be accepted:

    * strings: these get parsed by gtk_tree_path_new_from_string(). The
      syntax is like "1:2:3:4".
    * tuples of integers: as described above.
    * integers: treated as a path of length one.  Useful for
      GtkListStores, as will become apparent.

By accepting integers as length-one tree paths, the user can just pass 
in integers for GtkListStore methods, and think of them as row numbers. 
 They don't even need to think about paths.

Sequence/mapping behaviour: GtkTreeStore and GtkListStore implement the 
__getitem__/__setitem__ API.  You pass in a tree path as a key and get a 
"row object" as the value.  The row object basically combines a pointer 
to the tree model and a GtkTreeIter for the row.  It in turn looks like 
a sequence -- one item per column in the model.  You can get and set 
columns in the row through this interface.  The best way to explain this 
is with some examples:

    liststore = gtk.ListStore(str, str, int)   # create list store
    treestore = gtk.TreeStore(int, str, str)   # and a tree store
    ...   # fill in some rows
    row = liststore[42]   # get the row object for the 42nd row in the list
    print row[2]   # print 3rd column in row
    print liststore[42][2]   # or the two operations can be combined

    # print first column of first child of the second top level node
    print treestore[1,0][0]

    # assignment works too
    liststore[42][2] = 42

    # you can also assign to the entire row in one go
    treestore[1,0] = (5, 'foo', 'bar')

    # or delete rows
    del liststore[42]

If you have a GtkTreeIter for a row, you can also get the corresponding 
row object for it with "store[iter]".  As well as looking like a 
sequence, row objects have the following attributes:

    * next: next sibling row object
    * parent: parent row object
    * model: the GtkTreeModel for this row
    * path: the tree path of this row.
    * iter: a GtkTreeIter pointing at this row.


Iteration: tree and list stores implement the Python iteration API. 
 This means that you can easily do things like print the value of the 
first column for every row in a list store:

    for row in liststore:
        print row[0]

For tree stores, this only iterates over the toplevel of the tree.  Each 
row object has an iterchildren() method that can be used to iterate over 
the child rows if desired (if you directly iterate over the row, you 
will get the columns).


Extra optional argument on append/prepend/insert methods: I added an 
additional optional argument to the insert, insert_before, insert_after, 
prepend and append methods.  If passed, the additional argument is 
interpreted as a sequence of values of the columns in the new row.  For 
instance:

    liststore.append(('foo', 'bar', 42))

This makes the list store feel a lot more like the standard Python list 
objects.

James.

-- 
Email: james@daa.com.au
WWW:   http://www.daa.com.au/~james/