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/