[kwlug-disc] Filtering on Two Columns in Gtk+ v3 and Python.

John Driezen jdriezen at sympatico.ca
Sun Jun 13 04:44:30 EDT 2021


Thank you Paul.

I implemented your suggestion and the code now works.  I just didn't 
quite understand what the online tutorial at 
https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html 
meant by the following:   "Instances of |Gtk.TreeModelFilter| 
<https://lazka.github.io/pgi-docs/Gtk-3.0/classes/TreeModelFilter.html#Gtk.TreeModelFilter> 
can be stacked one onto another, to use multiple filters on the same 
model (in the same way you’d use “AND” clauses in a SQL request)."  Your 
suggestion was a simple solution.  For those interested the working code 
follows.

""" Sorted and Filtered TreeView Demo Program. Filters on programming 
language and year
columns and sorts the filtered rows. Extends on the program in section 
13.5 of
https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html. """

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

# list of tuples for each software
SOFTWARE_LIST = [
     ("Firefox", 2002, "C++"),
     ("Eclipse", 2004, "Java"),
     ("Pitivi", 2004, "Python"),
     ("Netbeans", 1996, "Java"),
     ("Chrome", 2008, "C++"),
     ("Filezilla", 2001, "C++"),
     ("Bazaar", 2005, "Python"),
     ("Git", 2005, "C"),
     ("Linux Kernel", 1991, "C"),
     ("GCC", 1987, "C"),
     ("Frostwire", 2004, "Java"),
     ("Homebank", 1995, "C"),
     ("Tellico", 2001, "C++"),
     ("gLabels", 2001, "C++"),
     ("Deluge", 2007, "Python"),
]

class TreeViewFilterWindow(Gtk.Window):
     """ TreeViewFilterWindow class """
     def __init__(self):
         Gtk.Window.__init__(self, title="Treeview Filter Demo")
         self.set_border_width(10)

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

         # Creating the ListStore model
         self.software_liststore = Gtk.ListStore(str, int, str)
         for software_ref in SOFTWARE_LIST:
             self.software_liststore.append(list(software_ref))

         self.current_filter_language = None
         self.current_filter_year = None

         # Create the language filter, feeding it with the liststore model
         self.language_filter = self.software_liststore.filter_new()
         # Create the year filter, feeding it with the language filter
         self.year_filter = self.language_filter.filter_new()
         # Setting the filter functions
self.language_filter.set_visible_func(self.language_filter_func)
         self.year_filter.set_visible_func(self.year_filter_func)

         # Create the sorted filtered tree model, feeding it with the 
year filter
         self.sortedandfilteredtreemodel = 
Gtk.TreeModelSort(model=self.year_filter)
         # Creating the treeview, using the sorted filter as a model and 
adding the columns
         self.sortedtreeview = 
Gtk.TreeView.new_with_model(self.sortedandfilteredtreemodel)
         for i, column_title in enumerate(["Software", "Release Year", 
"Programming Language"]):
             renderer = Gtk.CellRendererText()
             column = Gtk.TreeViewColumn(column_title, renderer, text=i)
             column.set_sort_order(Gtk.SortType.ASCENDING)
             column.set_sort_column_id(i)
             self.sortedtreeview.append_column(column)

         # Creating buttons to filter by programming language and 
setting up their events
         self.language_buttons = list()
         for prog_language in ["Java", "C", "C++", "Python", "None"]:
             button = Gtk.Button(label=prog_language)
             self.language_buttons.append(button)
             button.connect("clicked", 
self.on_language_selection_button_clicked)

         # Creating buttons to filter by release year and setting up 
their events
         self.year_buttons = list()
         for year in [1987, 1991, 1995, 1996, 2001, 2002, 2004, 2005, 
2007, 2008, "None"]:
             button = Gtk.Button(label=year)
             self.year_buttons.append(button)
             button.connect("clicked", 
self.on_year_selection_button_clicked)

         # Setting up the layout, putting the treeview in a 
scrollwindow, and the buttons in a
         # set_row_homogeneous
         self.scrollable_treelist = Gtk.ScrolledWindow()
         self.scrollable_treelist.set_vexpand(True)
         self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10)
         self.grid.attach_next_to(self.language_buttons[0], 
self.scrollable_treelist,
                                  Gtk.PositionType.BOTTOM, 1, 1)

         # Layout language selection buttons
         for i, button in enumerate(self.language_buttons[1:]):
             self.grid.attach_next_to(button, self.language_buttons[i], 
Gtk.PositionType.RIGHT, 1, 1)

         self.grid.attach_next_to(self.year_buttons[0], 
self.language_buttons[0],
                                  Gtk.PositionType.BOTTOM, 1, 1)

         # Layout year selection buttons
         for i, button in enumerate(self.year_buttons[1:]):
             self.grid.attach_next_to(button, self.year_buttons[i], 
Gtk.PositionType.RIGHT, 1, 1)

         self.scrollable_treelist.add(self.sortedtreeview)

         self.show_all()

     def language_filter_func(self, model, iter, data):
         """ Tests if the language in the row is the one in the filter. """
         if self.current_filter_language is None:
             return True
         else:
             return model[iter][2] == self.current_filter_language

     def year_filter_func(self, model, iter, data):
         """ Tests if the year in the row is the one in the filter. """
         if self.current_filter_year is None:
             return True
         else:
             return model[iter][1] == self.current_filter_year

     def on_language_selection_button_clicked(self, widget):
         """ Called on any of the language button clicks """
         # Set the current language filter to the button's 
scrollable_treelist
         if (widget.get_label() == "None"):
             self.current_filter_language = None
         else:
             self.current_filter_language = widget.get_label()
         print("%s language selected!" % self.current_filter_language)
         # Update the filter, which updates the view in turn
         self.language_filter.refilter()

     def on_year_selection_button_clicked(self, widget):
         """ Called on any of the year selection button clicks. """
         if (widget.get_label() == "None"):
             self.current_filter_year = None
         else:
             self.current_filter_year = int(widget.get_label())
         print("year %s selected!" % self.current_filter_year)
         # Update the filter, which updates the view in turn
         self.year_filter.refilter()

TV_WIN = TreeViewFilterWindow()
TV_WIN.connect("destroy", Gtk.main_quit)
TV_WIN.show_all()
Gtk.main()


John Driezen

jdriezen at sympatico.ca

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://kwlug.org/pipermail/kwlug-disc_kwlug.org/attachments/20210613/c8b3e0ec/attachment.htm>


More information about the kwlug-disc mailing list