Search code examples
pythongtkpygtkpygobject

How do you attach a popup menu to a column header button in GTK2 using PyGObject?


I want to popup a context menu when the user right-clicks on the header row of a Gtk.TreeView. In GTK3, Gtk.TreeViewColumn has a get_button() method, which makes this easy; simply attach the menu to the button and connect it to a 'clicked' event. However, in GTK2, this won't work. You can only call a get_widget() method, which returns None if you haven't set a widget via set_widget(). I've tried putting a Gtk.Label with the column name into a Gtk.EventBox and set that as the widget After connecting the EventBox to a callback for the 'button_press_event', clicking on it doesn't generate the event.

I tried to do something like what's listed here but doing get_parent() on the column widget returns None, and never reaches the button as their code implies.

What solutions have people found for this?


Solution

  • This is pretty easy actually, but you need a couple of hacks.

    First you need to force Gtk to create a header button for the GtkTreeViewColumn:

        label = gtk.Label("Column title")
        label.show()
        treeview_column.set_widget(label)
    

    After that you need to fetch the internal GtkButton of the header:

        widget = treeview_column.get_widget()
        while not isinstance(widget, gtk.Button):
            widget = widget.get_parent()
    

    Finally with a button reference you can do something useful:

        def button_release_event(button, event):
            if event.button == 3:
               menu.popup(event)
    
        widget.connect('button-release-event', button_release_event)
    

    This was taken from the kiwi library which has an ObjectList which provides a python list like api for creating GtkTreeViews.