[pygtk] Problem with CellRendererToggle

Brian dol-sen at telus.net
Sat Nov 18 12:57:39 WST 2006


On Fri, 2006-17-11 at 18:28 +0100, Pipen wrote:
> Hi.
> 
> Each row in my TreeView contains a column with: toggle, pixbuf and
> text renderer respectively. If need to maintain the following
> situations:
> - user clicks on the toggle - toggle receives 'toggled' event;
> treeview row cursor should not change.
> - user clicks on the rest of the row (pixbuf, text) - treeview row
> cursor should change, toggle should not receive 'toggled' event.
> 
> The program does not work as I expected. I receive 'toggled' and
> 'cursor-changed' events no matter what part the user clicks. If the user
> clicks on the toggle, the treeview row cursor changes to the row clicked
> toggle is in.
> 
> The following code sets up the TreeView (SETS_COL_TOGGLE is 0,
> SETS_COL_ICON is 1, SETS_COL_NAME is 2).
> 
>         store = gtk.TreeStore( bool, gtk.gdk.Pixbuf, str, int )
>         col = gtk.TreeViewColumn( 'Sets' )
>         # Toggle.
>         cell = gtk.CellRendererToggle()
>         cell.set_property( 'activatable', True )
>         cell.connect_object( 'toggled', self.on_set_toggled, store )
>         col.pack_start( cell, False )
>         col.add_attribute( cell, 'active', SETS_COL_TOGGLE )
>         # Pixbuf.
>         cell = gtk.CellRendererPixbuf()
>         col.pack_start( cell, False )
>         col.add_attribute( cell, 'pixbuf', SETS_COL_ICON )
>         # Text.
>         cell = gtk.CellRendererText()
>         col.pack_start( cell, True )
>         col.add_attribute( cell, 'text', SETS_COL_NAME )
>         self.treesets.append_column( col )
>         self.treesets.set_model( store )
> 
> I successfuly set up this kind of tree behavior using Qt, I'm fighting
> Gtk right now.
> Any kind of suggestion would be appreciated.
> 

you need to check the path in the toggled callback to see if it is on
the toggle.

Here is some code from our app that uses several columns in a treeview,
one of which is a toggle (not always shown/used for some views).  Sorry,
I wasn't the one that originated this code and I have not worked on it
lately.  You should be able to figure out what you need from it and the
embedded comments.

class PackageView(CommonTreeView):
        # Note! this is a gtk.TreeView type class and swap out the treeview models
        # dependending on what we need to display at the time.

        # connect to clicked event
        self.connect("cursor_changed", self._clicked)
        self.connect("button_press_event", self.on_button_press)


    def on_button_press(self, treeview, event):
        utils.debug.dprint("VIEWS: Handling PackageView button press event")
        self.event = event # save the event so we can access it in _clicked()
        if event.type != gtk.gdk.BUTTON_PRESS:
            utils.debug.dprint("VIEWS: Strange event type got passed to on_button_press() callback...")
            utils.debug.dprint("VIEWS: event.type =  %s" %str(event.type))
        if event.button == 3: # secondary mouse button
            self.dopopup = True # indicate that the popup menu should be displayed.
        else:
            self.dopopup = False
        # Test to make sure something was clicked on:
        pathinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
        if pathinfo == None:
            self.dopopup = False
            return True
        else:
            path, col, cellx, celly = pathinfo
            utils.debug.dprint("VIEWS: pathinfo = %s" %str(pathinfo))
            #treeview.set_cursor(path, col, 0) # Note: sets off _clicked again
        return False

    def on_toggled(self, widget, path):
        self.toggle = path
        utils.debug.dprint("VIEWS: Toggle activated at path '%s'" % path)
        self.set_cursor(path) # sets off _clicked
        return True

    def _clicked(self, treeview, *args):
        """ Handles treeview clicks """
        utils.debug.dprint("VIEWS: Package view _clicked() signal caught")
        # get the selection
        package = get_treeview_selection(treeview, 2)
        #utils.debug.dprint("VIEWS: package = %s" % package.full_name)
        if (not package and not self.toggle) or package.full_name == "None":
            self.mainwindow_callback("package changed", None)
            return False
        if self.toggle != None : # for upgrade view
            iter = self.get_model().get_iter(self.toggle)
            #if self.upgrade_model.get_value(iter, 0) != "None":
            check = self.upgrade_model.get_value(iter, 1)
            check = not check
            self.upgrade_model.set_value(iter, 1, check)
            package.is_checked = check
            self.dopopup = False # don't popup menu if clicked on checkbox
            self.toggle = None
            return True # we've got it sorted
        else:
            #utils.debug.dprint("VIEWS: full_name != _last_package = %d" %(package.full_name != self._last_selected))
            self.mainwindow_callback("package changed", package)
        self._last_selected = package.full_name

        #pop up menu if was rmb-click
        if self.dopopup:
[snip]

-- 
Brian <dol-sen at telus.net>



More information about the pygtk mailing list