13.6. Tree Example

The tree.py example program is somewhat like the tree example in testgtk.c, but a lot less complete (although much better commented). It puts up a window with a tree, and connects all the signals for the relevant objects, so you can see when they are emitted. Figure 13.1 illustrates the program display:

Figure 13.1 Tree Example

The source code for tree.py is:
 
    1   #!/usr/bin/env python
    2   
    3   # example tree.c
    4   
    5   import gtk
    6   
    7   class TreeExample:
    8       # for all the GtkItem:: and GtkTreeItem:: signals
    9       def cb_itemsignal(self, item, signame):
   10           # It's a Bin, so it has one child, which we know to be a
   11           # label, so get that
   12           label = item.children()[0]
   13           # Get the text of the label
   14           name = label.get()
   15           # Get the level of the tree which the item is in
   16           print "%s called for item %s->%s" % (signame, name, item)
   17   
   18       # Note that this is never called
   19       def cb_unselect_child(self, root_tree, child, subtree):
   20           print ("unselect_child called for root tree %s, "
   21                  "subtree %s, child %s" % (root_tree, subtree, child))
   22   
   23       # Note that this is called every time the user clicks on an item,
   24       # whether it is already selected or not.
   25       def cb_select_child(self, root_tree, child, subtree):
   26           print ("select_child called for root tree %s, subtree %s, "
   27                  "child %s\n" % (root_tree, subtree, child))
   28   
   29       def cb_selection_changed(self, tree):
   30           print "selection_change called for tree %s" % tree
   31           print "selected objects are:"
   32   
   33           for item in tree.get_selection():
   34               label = item.children()[0]
   35               name = label.get()
   36               print "\t%s" % name
   37   
   38       def __init__(self):
   39           itemnames = ["Foo", "Bar", "Baz", "Quux", "Maurice"]
   40           # a generic toplevel window
   41           window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
   42           window.connect("delete_event", gtk.mainquit)
   43           window.set_border_width(5)
   44   
   45           # A generic scrolled window
   46           scrolled_win = gtk.GtkScrolledWindow()
   47           scrolled_win.set_policy(gtk.POLICY_AUTOMATIC,
   48                                   gtk.POLICY_AUTOMATIC)
   49           scrolled_win.set_usize(150, 200)
   50           window.add(scrolled_win)
   51           scrolled_win.show()
   52   
   53           # Create the root tree
   54           tree = gtk.GtkTree()
   55           print "root tree is %s" % tree
   56           # connect all GtkTree:: signals
   57           tree.connect("select_child", self.cb_select_child, tree)
   58           tree.connect("unselect_child", self.cb_unselect_child, tree)
   59           tree.connect("selection_changed", self.cb_selection_changed)
   60           # Add it to the scrolled window
   61           scrolled_win.add_with_viewport(tree)
   62           # Set the selection mode
   63           tree.set_selection_mode(gtk.SELECTION_MULTIPLE)
   64           # Show it
   65           tree.show()
   66   
   67           for i in range(5):
   68               # Create a tree item
   69               item = gtk.GtkTreeItem(itemnames[i])
   70               # Connect all GtkItem:: and GtkTreeItem:: signals
   71               item.connect("select", self.cb_itemsignal, "select")
   72               item.connect("deselect", self.cb_itemsignal, "deselect")
   73               item.connect("toggle", self.cb_itemsignal, "toggle")
   74               item.connect("expand", self.cb_itemsignal, "expand")
   75               item.connect("collapse", self.cb_itemsignal, "collapse")
   76               # Add it to the parent tree
   77               tree.append(item)
   78               # Show it - this can be done at any time
   79               item.show()
   80               # Create this item's subtree
   81               subtree = gtk.GtkTree()
   82               print "-> item %s->%s, subtree %s" % (itemnames[i], item, subtree)
   83   
   84               # This is still necessary if you want these signals to be called
   85               # for the subtree's children.  Note that selection_change will be 
   86               # signalled for the root tree regardless.
   87               subtree.connect("select_child", self.cb_select_child, subtree)
   88               subtree.connect("unselect_child", self.cb_unselect_child, subtree)
   89               # This has absolutely no effect, because it is completely ignored 
   90               # in subtrees
   91               subtree.set_selection_mode(gtk.SELECTION_SINGLE)
   92               # Neither does this, but for a rather different reason - the
   93               # view_mode and view_line values of a tree are propagated to
   94               # subtrees when they are mapped.  So, setting it later on would
   95               # actually have a (somewhat unpredictable) effect
   96               subtree.set_view_mode(gtk.TREE_VIEW_ITEM)
   97               # Set this item's subtree - note that you cannot do this until
   98               # AFTER the item has been added to its parent tree!
   99               item.set_subtree(subtree)
  100   
  101               for j in range(5):
  102                   # Create a subtree item, in much the same way
  103                   subitem = gtk.GtkTreeItem(itemnames[j])
  104                   # Connect all GtkItem:: and GtkTreeItem:: signals
  105                   subitem.connect("select", self.cb_itemsignal, "select")
  106                   subitem.connect("deselect", self.cb_itemsignal, "deselect")
  107                   subitem.connect("toggle", self.cb_itemsignal, "toggle")
  108                   subitem.connect("expand", self.cb_itemsignal, "expand")
  109                   subitem.connect("collapse", self.cb_itemsignal, "collapse")
  110                   print "-> -> item %s->%s\n" % (itemnames[j], subitem)
  111                   # Add it to its parent tree
  112                   subtree.append(subitem)
  113                   # Show it
  114                   subitem.show()
  115           # Show the window and loop endlessly
  116           window.show()
  117   
  118   def main():
  119       gtk.mainloop()
  120       return 0
  121   
  122   if __name__ == "__main__":
  123       TreeExample()
  124       main()