GtkTreeView filtering and selecting

918 views Asked by At

I have a simple GtkTreeView and a GtkEntry used to filter the model. When I type somehing into the entry, software_list is filtered by language.

software_list = [("Firefox", 2002,  "C++"),
                 ("Eclipse", 2004, "Java" ),
                 ("Netbeans", 1996, "Java"),
                 ("Chrome", 2008, "C++"),
                 ("GCC", 1987, "C"),
                 ("Frostwire", 2004, "Java")]

class TreeViewFilterWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        self.curr_filter = ''

        self.entry = Gtk.Entry()
        self.entry.connect('changed', self.on_text_change)

        self.software_liststore = Gtk.ListStore(str, int, str)
        for software_ref in software_list:
            self.software_liststore.append(list(software_ref))

        self.filter = self.software_liststore.filter_new()
        self.filter.set_visible_func(self.filter_func)

        self.treeview = Gtk.TreeView.new_with_model(self.filter)
        for i, column_title in enumerate(["Software", "Release Year", "Programming Language"]):
            renderer = Gtk.CellRendererText()
            column = Gtk.TreeViewColumn(column_title, renderer, text=i)
            self.treeview.append_column(column)
        self.treeview.get_selection().connect('changed', self.on_row_select) 

        # packing into boxes, showing components, starting main loop goes here

    def on_text_change(self, entry):
        self.curr_filter = entry.get_text()
        self.filter.refilter()

    def filter_func(self, model, iter, data):
        if self.curr_filter:
            return re.search(re.escape(self.curr_filter), model[iter][2])
        else:
            return True

The problem is, when I select i.e. "Chrome" from the list and then type "Java" into the entry, then, obviously, "Chrome" gets hidden but selection changes to some other, random row. I'd prefer TreeView unselected hidden elements instead of changing the selection. How can I do this?

1

There are 1 answers

0
lxop On

This just works as expected in Gtk2, but in Gtk3 you need to deselect the row if it disappears. The appropriate code is

class TreeViewFilterWindow(Gtk.Window):

    def __init__(...):
        ...
        self.selection = self.treeview.get_selection()
        self.filter.connect('row-deleted', self.on_row_deleted)

    def on_row_deleted(self, model, path):
        if self.selection.path_is_selected(path):
            GObject.idle_add(self.selection.unselect_path, path)

I found that calling self.selection.unselect_path(path) directly didn't seem to work for some reason, but deferring it with idle_add sorted it out.