1

I have a class-function that iterates through a Gtk.TreeStore searching for a child-node. If a matching node is found, I want to change the selection to that node. My function returns an iterator. I suspect this is the root-case of the problem, but I'm not sure what else to return. All the Gtk.TreeSelection functions seem to want a Gtk.TreePath.

Is there a canonical way finding a node in a TreeStore, then selecting it? It seems to be a common use-case, but I can't seem to find an explanation.

def findNodeByDescription( self, desc ):
    root_iterator = self.tree_store.get_iter_first()
    return self.findNodeByDescriptionRecursive( root_iterator, desc )

def findNodeByDescriptionRecursive( self, tree_iter, desc ):
    """ Recursive function to search the tree """
    result = None
    tree_model = self.tree_view.get_model()
    while ( result == None and tree_iter != None ):
        # is it this node?
        if ( tree_model.get_value(tree_iter, 0).description == desc ):
            # found it
            result = tree_iter 
            break
        elif ( self.tree_store.iter_has_child( tree_iter ) ):
            child_iter = self.tree_store.iter_children( tree_iter )
            result = self.findNodeByDescriptionWorker( child_iter, desc )
        tree_iter = self.tree_store.iter_next( tree_iter )
    return result

(NOTE: I'm using custom tree nodes)

It's called like:

EDIT: I found a partial answer in the get_path() function, from the Python GTK FAQ.

EDIT2: Using expand_to_path() expands the tree-node. I think previously it was expanding the child-node, but not the parent. So it was expanded, but still could not be seen. (I have 3-deep branches, and finding the "middle" branch).

def findAndSelectNode( self, text ):
    tree_iter = self.findNodeByDescription( text )
    if ( tree_iter != None ):
        print("###### SELECTING ROW" )
        # THIS EXECUTES, BUT NOTHING HAPPENS?!
        path = self.tree_store.get_path( tree_iter )
        #self.tree_view.expand_row( path, True )  -- doesn't work
        self.tree_view.expand_to_path( path )
        self.tree_view.set_cursor( path )
Kingsley
  • 14,398
  • 5
  • 31
  • 53

1 Answers1

1

Ok, I've worked it out.

First you need to find the desired item in the TreeView using an iterator. (The code to do this is contained in the question).

Once the desired Tree node is found, you are left with a iterator "pointing" to the final node. To highlight that in the tree, there are two steps needed:

  1. Expand the entire branch where the target exists.
  2. Change the selection to include that item
    def findSelectNode( self, text ):
        # BUG: Only by name for now.
        tree_iter = self.findNodeByDescription( text )
        if ( tree_iter != None ):
            print("###### SELECTING ROW" )
            path = self.tree_store.get_path( tree_iter )
            self.tree_view.expand_to_path( path )               # expand the whole branch
            self.tree_view.get_selection().select_path( path )  # select it

This answer assumes you only want a single selection.

Kingsley
  • 14,398
  • 5
  • 31
  • 53