pythoneventspygtkgtktreeview

How to assign “hidden data” to Gtk.TreeView row in order to catch them with Gtk.TreeView.connect("row-activated")?


In Python, I have a class person witch contain firstName and lastName and also country attributes (actually their is much more other data, but I simplify it for the example).

So, I generate a table witch should only show firstName and lastName (the user shouldn’t see the country). But when the user click on a specific row, I want to get the the full person object.

This is my code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# MWE for hidden data in Gtk.TreeView

import sys
import os
import gi

gi.require_version('Gtk', '3.0')

from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Gio
from gi.repository import Pango


class person():
    def __init__(self, firstName, lastName, country):
        self.firstName=firstName
        self.lastName=lastName
        self.country=country

personsList=[
    person("Ada",   "Lovelace", "UK"),
    person("Alan",  "Turing",   "UK"),
    person("Denis", "Richie",   "USA")
]

def onRowChange(widget, row, col):
    # This function is executed when a user click on a row
    print(widget)
    print(row)
    print(col)
    pass


class GridWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="TreeView MWE")
        self.connect("destroy", Gtk.main_quit)

        # Setting up the self.grid in which the elements are to be positionned
        self.grid = Gtk.Grid()
        self.grid.set_column_homogeneous(True)
        self.grid.set_row_homogeneous(True)
        self.add(self.grid)

        # Preparing the list store
        listStore=Gtk.ListStore(str, str)
        for aPerson in personsList:
            listStore.append([aPerson.firstName, aPerson.lastName])

        # Seting up the TreeView and given the ListStore to the Treeview
        treeView=Gtk.TreeView(model=listStore)
        renderer_text = Gtk.CellRendererText()

        # Preparing the headers
        column_text = Gtk.TreeViewColumn("First Name", renderer_text, text=0)
        treeView.append_column(column_text)
        column_text = Gtk.TreeViewColumn("Last Name", renderer_text, text=1)
        treeView.append_column(column_text)

        # Setting the event connection
        treeView.connect("row-activated", onRowChange)


        # Attaching the treeView to the Gride
        self.grid.add(treeView)




screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()


win = GridWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

And here is the rendering:

enter image description here

As you can see, the onRowChange() function can only get the TreeView and the TreeViewColumn objects when the user click on it, according to the row_activated signal’s documentation.

I know I can get the row number and search in the list witch object has this row number but it’s too much hazardous and a little bit hacky.

So, is their a way to include in the Gtk.ListStore a user’s hidden data and catch back this data with row-activated signal?


Solution

  • You can just add data to your liststore without showing it in the treeview. The following code snippet shows the necessary changes:

    ...
    def onRowChange(widget, row, col):
        # This function is executed when a user click on a row
        model = widget.get_model()
        iter_ = model.get_iter(row)
        person = model.get_value(iter_, 2)
        print(person.country)
    
    
    class GridWindow(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="TreeView MWE")
            self.connect("destroy", Gtk.main_quit)
    
            # Setting up the self.grid in which the elements are to be positionned
            self.grid = Gtk.Grid()
            self.grid.set_column_homogeneous(True)
            self.grid.set_row_homogeneous(True)
            self.add(self.grid)
    
            # Preparing the list store
            listStore=Gtk.ListStore(str, str, object)
            for aPerson in personsList:
                listStore.append([aPerson.firstName, aPerson.lastName, aPerson])
    ...