As I'm sure everyone knows, using TreeViews can be a bit intimidating for new
PyGTK users, especially when they really only want a simple list instead of a
full tree.

I've put together a rather simpler API that works well for me, covers the 80% I
need for lists. There's some work that still needs to be done for robustness
and to cover off the other 20%, but some feedback on the API itself at this
stage would be really helpful.

==documentation by example==
#very simple item for example
class simpleItem:
        def __init__(self, val):
                self.number = val
                self.name = 'Foo'

        def even(self):
                return self.number % 2 == 0

        def odd(self):
                return self.number % 2 == 1



#implemented as a wrapper around treeview widget
# easy to wrap Glade widgets this way
tree = SimpleTree(gtk.TreeView())
#window.add(tree.tv) #underlying treeview widget

#simply provide a list of objects
#no reason we can't extend to basic data types
sampleList = [simpleItem(1),simpleItem(2),simpleItem(3)]
tree.model = sampleList

#columns to display; can be properties or methods
# - future version will allow tuples with header text and type
tree.setCols(["number", "name", "even"])
#future - tree.cols = [("icon", "Status", gtk.PixBuf), ("name", "Article Name",
str)]

#optional designate a property/method to handle row visibility
tree.visibility = "odd"

#do the usual list manipulation
sampleList.append(simpleItem(4))

#get the selected item
# - future version will return array of objects when multi-select
tree.selected.name = "Edited"
# future - tree.selected[0].name = "Edited"

#call whenever changes have been made
tree.refresh()

==simpleTree.py===============
#Copyright 2004 John C Barstow
#distributed under same license as PyGTK package.

def simpleItemProperty(column, cell_renderer, tree_model, iter, user_data):
    item = tree_model.get_value(iter, 0)
    if item == None:
                return
    prop = getattr(item,user_data)
    if(callable(prop)):
        prop = prop()
    cell_renderer.set_property('text', prop)

def simpleItemVisible(tree_model, iter, user_data):
    item = tree_model.get_value(iter, 0)
    if item == None:
        return False
    prop = getattr(item,user_data)
    if(callable(prop)):
        prop = prop()
    return prop


class SimpleTree(object):
        def __init__(self, treeview):
                self.tv = treeview

        def createCols(self):
                cell = gtk.CellRendererText()
                col = gtk.TreeViewColumn("col1")
                col.pack_start(cell, True)
                col.set_attributes(cell, text=0)
                self.tv.append_column(col)

        def setModel(self, l):
                self.baseList = l
                self.tree = gtk.ListStore(object)
                [self.tree.append([item]) for item in l]
                self.tv.set_model(self.tree)

        def setVisibility(self, prop):
                self.filter = self.tree.filter_new()
                self.filter.set_visible_func(simpleItemVisible, prop)
                self.tv.set_model(self.filter)

        def refresh(self):
                existingItems = [o[0] for o in self.tree]
                for item in self.baseList:
                        if item not in existingItems:
                                self.tree.append([item])
                        else:
                                existingItems.remove(item)
                for item in existingItems:
                        iters = [o for o in self.tree if o[0] == item]
                        for row in iters:
                                i = row.iter
                                self.tree.remove(i)
                if hasattr(self, "filter"):
                        self.filter.refilter()

        def setCols(self, cols):
                #self.tv.clear()
                [self.addCol(col) for col in cols]

        def addCol(self, prop):
                cell = gtk.CellRendererText()
                col = gtk.TreeViewColumn(prop, cell)
                col.set_cell_data_func(cell, simpleItemProperty, prop)
                self.tv.append_column(col)

        def getSelected(self):
                model, iter = self.tv.get_selection().get_selected()
                return model[iter][0]

        model = property(None, setModel)
        selected = property(getSelected, None)
        visibility = property(None, setVisibility)
==================END===========================
==example.py====================================
from simpleTree import *

class SimpleTreeDriver:
    def delete_event(self, widget, event, data=None):
        gtk.main_quit()
        return gtk.FALSE

    def createList(self):
        self.list = [simpleItem(1),simpleItem(2),simpleItem(3)]
        self.nextNum = 4
        self.tv = SimpleTree(gtk.TreeView())
        self.tv.model = self.list
        self.tv.setCols(["number", 'name', "cat"])

    def __init__(self):
        # Create a new window
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(300, 200)
        self.window.connect("delete_event", self.delete_event)

        self.createList()

        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.add(self.tv.tv)

        buttons = gtk.HButtonBox()
        rembtn = gtk.Button(stock=gtk.STOCK_REMOVE)
        rembtn.connect("clicked", self.remove)
        buttons.add(rembtn)
        addbtn = gtk.Button(stock=gtk.STOCK_ADD)
        addbtn.connect("clicked", self.add)
        buttons.add(addbtn)

        evenbtn = gtk.Button("Even")
        evenbtn.connect("clicked", self.even)
        buttons.add(evenbtn)
        buttons.set_spacing(6)
        buttons.set_layout(gtk.BUTTONBOX_END)
        vframe = gtk.VBox(spacing=6)
        vframe.pack_start(self.scrolledwindow, expand=True, fill=True)
        vframe.pack_start(buttons, expand=False, fill=False)

        self.window.add(vframe)
        self.window.set_title("simple tree")
        self.window.set_border_width(6)
        self.window.show_all()

    def add(self, event):
        self.list.append(simpleItem(self.nextNum))
        self.nextNum += 1
        self.tv.refresh()

    def remove(self, event):
        self.list.remove(self.tv.selected)
        self.tv.refresh()

    def even(self, event):
        self.tv.setVisibility("even")
        self.tv.refresh()

    def main(self):
                gtk.main()

if __name__ == "__main__":
    ex = SimpleTreeDriver()
    ex.main()

==================END===========================
_______________________________________________
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