I'm using PyGTK 2.0's TreeView backed by a ListStore to create a table of selectable items. I need to select and deselect individual rows by single clicking anywhere on the row. Clicking a row should toggle the highlight and the value of a checkbox only for that row.
I've created the TreeView with multiple selection and a column for the checkboxes, but I can't toggle the selection on an individual row without holding Control. I tried to connect a select function to the view so that it would at least toggle the checkboxes, but the function does not work as described in the tutorial:
self.dataview = gtk.TreeView(store)
self.dataview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.dataview.get_selection().set_select_function(self.on_row_selected, None)
def on_row_selected(self, selection, model, path, is_selected, data):
print selection
print model
print path
print is_selected
print data
model.set_value(path, 0, is_selected)
Triggering the select function produces an error:
TypeError: on_row_selected() takes exactly 6 arguments (3 given)
Replacing the function arguments with *args
shows that only path
and data
are provided.
Besides the behavior of set_select_function
, what's the best approach to toggling row selection with single clicks, and how do I sync that with a column in my data model?
This isn't exactly what I asked for but I finally got the interaction I wanted using gtk.TreeViewColumn.set_cell_data_func
. This allows me to specify a function that will be called whenever a cell is to be rendered. I used it to apply a custom style across the whole row based on its data, and then used single-selection clicks just to toggle the value.
self.view = gtk.TreeView(store)
self.view.get_selection().set_mode(gtk.SELECTION_SINGLE)
self.view.get_selection().set_select_function(self.on_row_selected)
...
renderer = gtk.CellRendererText()
for idx, heading in enumerate(heading_list):
col = gtk.TreeViewColumn(None, renderer, text=idx)
col.set_cell_data_func(renderer, self.cell_data_func)
...
def cell_data_func(self, column, cell, model, it):
if model.get(it, self.select_index)[0]:
# apply selected style
else:
# apply normal style
def on_row_selected(self, data):
path = data[0]
iter = self.model.get_iter(path)
val = self.model.get_value(iter, self.select_index)
self.model.set_value(iter, self.select_index, not val)