On Tue, Jul 06, 2004 at 12:06:28PM -0700, John Finlay wrote:

> In addition to receiving comments about tutorial problems, errors and 
> enhancements, I'm interested in hearing from poeple who have used the 
> GenericTreeModel. Specifically, I'm interested in what applications 
> require a custom tree model instead of the standard ones, and what 
> issues they encountered developing and using a custom tree model. Same 
> for the GenericCellRenderer.

Attached is a GenericCellRenderer that I used in my Classicollect app
(ripped out of context and simplified a bit), but not shown is the important
part where you have to take care of sending all the
row-insert/changed/deleted etc. signals.  Note that it doesn't do the
subclassing quite correctly.  I could fix this up into a simple working
example if anyone is interested.

Essentially I implemented this tree (really a forest) the way we were taught
in school: each tree node has its cargo, a reference to the parent node, and
a list of child nodes.

I also keep an index for each node, which is its position its parent's child
list, for efficiently finding the path of a node.  Since get_path doesn't
seem to get called much (by treeviews anyway), this may not be necessary,
and it does add some extra bookkeeping if you remove or insert nodes.

I originally wrote this because I didn't know about
TreeViewColumn.set_cell_data_func, and, well, writing a GTM is kinda fun.
Then I went back to it when I found that cell_data_funcs wouldn't work with
interactive searches (there was no TreeView.set_search_func in pygtk at the
time; when I found out about that it was fixed by gjc within the day!) or
with the new ComboBoxes. Now with TreeModelFilter, I don't think I have any
need for a generic TreeModel, though I haven't had a chance to really test
it with a large data set.  And if this works:

http://bugzilla.gnome.org/show_bug.cgi?id=144509

you have yet another easy way to write a custom TreeStore.




import pygtk; pygtk.require('2.0')
import gtk

# Schematically, nodes look something like this:

class Node:

    def __init__(self, parent=None, children=None, data=None,
                 index=0, level=None):
        self.parent = parent
        if children is None: self.children = []
        if data is None: self.data = {} # node cargo
        self.index = index # index of child
        self.level = level # provides info about each depth of the tree 


OUTFILE = sys.stdout        

def print_debug(*args):
    for arg in args:
        print >>OUTFILE, arg,
    print >>OUTFILE
    OUTFILE.flush()

        
class PyListTreeModel(gtk.GenericTreeModel):

    '''A TreeModel using Node objects as its base data structure.'''
    
    def __init__(self, root, *column_types):
        '''constructor for the model.  Make sure you call
        PyTreeModel.__init__'''
        gtk.GenericTreeModel.__init__(self)
        self.set_property("leak_references", 0)
        self.column_types = column_types
        self.ncolumns = len(self.column_types)
        self.root = root
                    
    def on_get_flags(self):
        '''returns the GtkTreeModelFlags for this particular type of model'''
        print_debug("on_get_flags")
        return 0

    def on_get_n_columns(self):
        '''returns the number of columns in the model'''
        print_debug("on_get_n_columns")
        return self.ncolumns
    
    def on_get_column_type(self, index):
        '''returns the type of a column in the model'''
        print_debug("on_get_column_type", index)
        t = self.column_types[index]
        return t

    def on_get_path(self, node):
        '''returns the tree path (a tuple of indices at the various
        levels) for a particular node.'''
        print_debug("on_get_path", node)
        path = []
        while node.parent:
            path.append(node.index)
            node = node.parent
        path.reverse()
        return tuple(path)

    def on_get_iter(self, path):
        '''returns the node corresponding to the given path'''
        print_debug("on_get_iter:", path)
        node = self.root
        try:
            for i in path:
                node = node.children[i]
        except IndexError:
            node = None
        return node

    def on_get_value(self, node, i):
        '''returns the value stored in a particular column for the node'''
        print_debug("on_get_value:", node, i)
        level = node.level
        try:
            value = node.data[level.keys[i]]
        except KeyError:
            value = level.control_cols[i]
        return value

    def on_iter_next(self, node):
        '''returns the next node at this level of the tree'''
        print_debug("on_iter_next", node)
        siblings = node.parent.children
        try:
            next = siblings[node.index+1]
        except IndexError:
            next = None
        return next
    
    def on_iter_children(self, node):
        '''returns the first child of this node'''
        print_debug("on_iter_children", node)
        try:
            child = node.children[0]
        except IndexError:
            child = None
        return child
            
    def on_iter_has_child(self, node):
        '''returns true if this node has children'''
        print_debug("on_iter_has_child", node)
        return len(node.children) > 0

    def on_iter_n_children(self, node):
        '''returns the number of children of this node'''
        print_debug("on_iter_n_children", node)
        return len(node.children)

    def on_iter_nth_child(self, node, n):
        '''returns the nth child of this node'''
        print_debug("on_iter_nth_child", node)
        try:
            nth_child = node.children[n]
        except (AttributeError, IndexError):
            nth_child = None
        return nth_child
    
    def on_iter_parent(self, node):
        '''returns the parent of this node'''
        print_debug("on_iter_parent", node)
        if not node or node.parent is self.root:
            parent = None
        else:
            parent = node.parent
        return parent
        
_______________________________________________
pygtk mailing list   [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to