On Thursday 07 October 2004 08:58, Christian Robottom Reis wrote: > On Thu, Oct 07, 2004 at 01:54:46PM +0200, Xavier Ordoquy wrote: > > On Thu, 2004-10-07 at 13:46 +0200, Fabien COUTANT wrote: > > > > > > As a GTK 1.2/2.x and PyGtk 0.6/2.x programmer, I think it's worse > > > than that. I think the problem about the list widget lies in Gtk, > > > not in PyGtk. Once upon a time was the CList widget. It was limited > > > but simple and practical, and suited many needs. Using it, it was > > > simple to do simple things, it was moderately complicated to do > > > moderately complicated things, and it was impossible to do > > > complicated things. > > > > You should have done some support on irc about that. gtkclist caused an > > enormous amount of questions, noise and annoyances. > > Even so, it was a lot less noise than TreeView. But let's be practical > here and move on towards something that *is* feasible instead of > complaining about the past. > > I think Fabien's complaint is definitely valid: we need a widget that is > simple enough to be used by anyone not wanting to do rocket-science with > their rows. I've balked at the amount of questions and FAQs we get on > TreeView -- come *on*, the FAQ is *the* indication of a non-trivial API. > > There are two possible solutions. One is writing directly to gtk-devel > and bringing the discussion up. Bringing it up with code in hand is > definitely going to be more prone to acceptance. It is likely that > something harnessing off TreeView's code and simply providing a simple > and unified API would be pretty easy to do and would solve 90% of the > complexity problems users face. > > The other solution, perhaps interim, is to do a decent Python wrapper. > J. Barstow's proposal is a step in the right direction, but it should > really `look' like a regular GTK+ widget -- that means lowercase, > underscore-separated method names. I'd say a good attempt would be > mimicing most of what CList provided: > > - Providing a list of headers to the constructor > - append()/insert() methods that takes a list of strings > - A clear() method that deletes all rows > - remove() method with removes a numbered row > - select/unselect_row() methods that take a numbered row > - set_data()/get_data() pairs and a find_row_from_data() > > You'd need to find out if freeze()/thaw() make sense in this new > context. > > You could from there work on the icing, which is backgrounds, controlled > sorting, column visibility width and title control, pixmap and `special > cell' support if necessary. > > I've heard Python is a good prototyping language, by the way <wink>.
I too got frustrated with trying to use a basic clist in the gtk 2.x. I don't completely understand all the details of the new widget, but I learned enough to do what I needed to do. I wrote this python wrapper (not a gtk widget) to help me use it. While it's tailored for my uses which involved a SQL database, it shouldn't be too difficult to clean up and extend. If anyone is interested, here it is. I use 4 spaces for indentation, but if it gets garbled, let me know and I can put it on a website for download. Dave ----------------------------------------------------------------- #!/usr/bin/env python #---------------------------------------------------------------------- # ListStoreComponent.py # Dave Reed # 12/17/2002 #---------------------------------------------------------------------- import sys import gtk, gobject import UtilPSQL #---------------------------------------------------------------------- class ListStoreComponent: #---------------------------------------------------------------------- def __init__(self, tree_view_widget, col_names, col_dict, selection_mode=None): """ __init__(self, tree_view_widget, col_names, col_dict): col_names = [ 'last_name', 'first_name', 'address1', 'birth_date', 'id' ] col_dict = { # (title, type, width, visible) 'last_name': ('Last Name', 'str', 120, 1), 'first_name': ('First Name', 'str', 120, 1), 'address1': ('Address1', 'str', 150, 1), 'birth_date': ('Birth Date', 'str', 70, 1), 'id': ('ID', 'int', 50, 1), } """ self.tree_view_widget = tree_view_widget self.col_names = col_names self.col_dict = col_dict self.selected_rows = {} self.unselect = None self.my_select = 0 self.changed_row = None # create list of types for calling gtk.ListStore with l = [] total_width = 0 for c in col_names: title, col_type, width, visible = col_dict[c] total_width = total_width + width if col_type == 'int': col_type = gobject.TYPE_INT else: # elif col_type == 'str': col_type = gobject.TYPE_STRING l.append(col_type) l = tuple(l) self.model = gtk.ListStore(*l) # append columns self.tree_view_cols = [] w = self.tree_view_widget for i in range(len(col_names)): c = col_names[i] cell = gtk.CellRendererText() title, col_type, width, visible = col_dict[c] col = gtk.TreeViewColumn(title, cell, text=i) self.tree_view_cols.append(col) w.append_column(col) # set visibility and size col.set_visible(visible) col.set_min_width(width) w.set_model(self.model) self.selection = w.get_selection() if selection_mode is not None: self.selection.set_mode(selection_mode) if selection_mode == gtk.SELECTION_MULTIPLE: self.handler = self.selection.connect( "changed", self.on_selection_changed) #---------------------------------------------------------------------- def clear(self): self.my_select = 1 self.model.clear() self.my_select = 0 #---------------------------------------------------------------------- def sql_populate(self, db, table, where_clause, order_clause, type_dict): com = ['select '] com.append(','.join(self.col_names)) com.append(' from %s %s %s;' % (table, where_clause, order_clause)) com = ''.join(com) self.sql_populate_cmd(db, com, type_dict) #---------------------------------------------------------------------- def sql_populate_cmd(self, db, com, type_dict): self.my_select = 1 # clear existing entries self.model.clear() db.execute(com) r = db.fetchall() for i in xrange(len(r)): line = r[i] for j in range(len(self.col_names)): c = self.col_names[j] if type_dict[c][:7] == 'numeric': dec = type_dict[c].split(',')[1][:-1] format = '%%0.%sf' % dec line[j] = format % line[j] iter = self.model.append(line) self.tree_view_widget.set_model(self.model) self.selected_rows = {} self.my_select = 0 #---------------------------------------------------------------------- def populate_with_list(self, row_list): self.my_select = 1 # clear existing entries self.model.clear() # new method for use with pygtk in CVS for i in xrange(len(row_list)): iter = self.model.append(row_list[i]) self.tree_view_widget.set_model(self.model) self.selected_rows = {} self.my_select = 0 #---------------------------------------------------------------------- def append_row(self, row_data): # new method for use with pygtk in CVS self.model.append(row_data) #---------------------------------------------------------------------- def get_row(self, row_num): if row_num < len(self.model): row = self.model[row_num] d = {} for i in range(len(self.col_names)): c = self.col_names[i] d[c] = row[i] return d else: return None #---------------------------------------------------------------------- # code for handling multi selection without having to also press # the control key def on_selection_changed(self, selection): if not self.my_select: selection.selected_foreach(self.select_row) r = self.changed_row self.my_select = 1 if self.selected_rows.has_key(r): del self.selected_rows[r] self.unselect = 1 selection.unselect_iter(self.model[r].iter) else: self.selected_rows[r] = r # select the appropriate rows selection.disconnect(self.handler) self.unselect = 0 for i in self.selected_rows: if i != r: selection.select_iter(self.model[i].iter) self.my_select = 0 self.handler = selection.connect( "changed", self.on_selection_changed) #---------------------------------------------------------------------- def select_row(self, list_store, row, iter): self.changed_row = row[0] #---------------------------------------------------------------------- def get_selected_row(self): try: selection = self.tree_view_widget.get_selection() model, iter = selection.get_selected() if selection.iter_is_selected(iter): row = model[iter] d = {} for i in range(len(self.col_names)): c = self.col_names[i] d[c] = row[i] return d else: print 'not selected' return None except: return None #---------------------------------------------------------------------- def get_selected_iter(self): try: selection = self.tree_view_widget.get_selection() model, iter = selection.get_selected() return iter except: None #---------------------------------------------------------------------- def select_iter(self, iter): selection = self.tree_view_widget.get_selection() selection.select_iter(iter) #---------------------------------------------------------------------- #---------------------------------------------------------------------- def main(argv): pass #---------------------------------------------------------------------- if __name__ == '__main__': main(sys.argv) _______________________________________________ pygtk mailing list [EMAIL PROTECTED] http://www.daa.com.au/mailman/listinfo/pygtk Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/