<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Thank you Paul.</p>
<p>I implemented your suggestion and the code now works. I just
didn't quite understand what the online tutorial at
<a class="moz-txt-link-freetext" href="https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html">https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html</a>
meant by the following: "Instances of <a class="reference
external"
href="https://lazka.github.io/pgi-docs/Gtk-3.0/classes/TreeModelFilter.html#Gtk.TreeModelFilter"
title="(in Gtk 3.0 v3.0)"><code class="xref py py-class docutils
literal notranslate"><span class="pre">Gtk.TreeModelFilter</span></code></a>
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.<br>
</p>
""" Sorted and Filtered TreeView Demo Program. Filters on
programming language and year<br>
columns and sorts the filtered rows. Extends on the program in
section 13.5 of<br>
<a class="moz-txt-link-freetext" href="https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html">https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html</a>.
"""<br>
<br>
import gi<br>
<br>
gi.require_version("Gtk", "3.0")<br>
from gi.repository import Gtk<br>
<br>
# list of tuples for each software<br>
SOFTWARE_LIST = [<br>
("Firefox", 2002, "C++"),<br>
("Eclipse", 2004, "Java"),<br>
("Pitivi", 2004, "Python"),<br>
("Netbeans", 1996, "Java"),<br>
("Chrome", 2008, "C++"),<br>
("Filezilla", 2001, "C++"),<br>
("Bazaar", 2005, "Python"),<br>
("Git", 2005, "C"),<br>
("Linux Kernel", 1991, "C"),<br>
("GCC", 1987, "C"),<br>
("Frostwire", 2004, "Java"),<br>
("Homebank", 1995, "C"),<br>
("Tellico", 2001, "C++"),<br>
("gLabels", 2001, "C++"),<br>
("Deluge", 2007, "Python"),<br>
]<br>
<br>
class TreeViewFilterWindow(Gtk.Window):<br>
""" TreeViewFilterWindow class """<br>
def __init__(self):<br>
Gtk.Window.__init__(self, title="Treeview Filter Demo")<br>
self.set_border_width(10)<br>
<br>
# Setting up the self.grid in which the elements are to be
positioned<br>
self.grid = Gtk.Grid()<br>
self.grid.set_column_homogeneous(True)<br>
self.grid.set_row_homogeneous(True)<br>
self.add(self.grid)<br>
<br>
# Creating the ListStore model<br>
self.software_liststore = Gtk.ListStore(str, int, str)<br>
for software_ref in SOFTWARE_LIST:<br>
self.software_liststore.append(list(software_ref))<br>
<br>
self.current_filter_language = None<br>
self.current_filter_year = None<br>
<br>
# Create the language filter, feeding it with the liststore
model<br>
self.language_filter = self.software_liststore.filter_new()<br>
# Create the year filter, feeding it with the language
filter<br>
self.year_filter = self.language_filter.filter_new()<br>
# Setting the filter functions<br>
self.language_filter.set_visible_func(self.language_filter_func)<br>
self.year_filter.set_visible_func(self.year_filter_func)<br>
<br>
# Create the sorted filtered tree model, feeding it with the
year filter<br>
self.sortedandfilteredtreemodel =
Gtk.TreeModelSort(model=self.year_filter)<br>
# Creating the treeview, using the sorted filter as a model
and adding the columns<br>
self.sortedtreeview =
Gtk.TreeView.new_with_model(self.sortedandfilteredtreemodel)<br>
for i, column_title in enumerate(["Software", "Release
Year", "Programming Language"]):<br>
renderer = Gtk.CellRendererText()<br>
column = Gtk.TreeViewColumn(column_title, renderer,
text=i)<br>
column.set_sort_order(Gtk.SortType.ASCENDING)<br>
column.set_sort_column_id(i)<br>
self.sortedtreeview.append_column(column)<br>
<br>
# Creating buttons to filter by programming language and
setting up their events<br>
self.language_buttons = list()<br>
for prog_language in ["Java", "C", "C++", "Python", "None"]:<br>
button = Gtk.Button(label=prog_language)<br>
self.language_buttons.append(button)<br>
button.connect("clicked",
self.on_language_selection_button_clicked)<br>
<br>
# Creating buttons to filter by release year and setting up
their events<br>
self.year_buttons = list()<br>
for year in [1987, 1991, 1995, 1996, 2001, 2002, 2004, 2005,
2007, 2008, "None"]:<br>
button = Gtk.Button(label=year)<br>
self.year_buttons.append(button)<br>
button.connect("clicked",
self.on_year_selection_button_clicked)<br>
<br>
# Setting up the layout, putting the treeview in a
scrollwindow, and the buttons in a<br>
# set_row_homogeneous<br>
self.scrollable_treelist = Gtk.ScrolledWindow()<br>
self.scrollable_treelist.set_vexpand(True)<br>
self.grid.attach(self.scrollable_treelist, 0, 0, 8, 10)<br>
self.grid.attach_next_to(self.language_buttons[0],
self.scrollable_treelist,<br>
Gtk.PositionType.BOTTOM, 1, 1)<br>
<br>
# Layout language selection buttons<br>
for i, button in enumerate(self.language_buttons[1:]):<br>
self.grid.attach_next_to(button,
self.language_buttons[i], Gtk.PositionType.RIGHT, 1, 1)<br>
<br>
self.grid.attach_next_to(self.year_buttons[0],
self.language_buttons[0],<br>
Gtk.PositionType.BOTTOM, 1, 1)<br>
<br>
# Layout year selection buttons<br>
for i, button in enumerate(self.year_buttons[1:]):<br>
self.grid.attach_next_to(button, self.year_buttons[i],
Gtk.PositionType.RIGHT, 1, 1)<br>
<br>
self.scrollable_treelist.add(self.sortedtreeview)<br>
<br>
self.show_all()<br>
<br>
def language_filter_func(self, model, iter, data):<br>
""" Tests if the language in the row is the one in the
filter. """<br>
if self.current_filter_language is None:<br>
return True<br>
else:<br>
return model[iter][2] == self.current_filter_language<br>
<br>
def year_filter_func(self, model, iter, data):<br>
""" Tests if the year in the row is the one in the filter.
"""<br>
if self.current_filter_year is None:<br>
return True<br>
else:<br>
return model[iter][1] == self.current_filter_year<br>
<br>
def on_language_selection_button_clicked(self, widget):<br>
""" Called on any of the language button clicks """<br>
# Set the current language filter to the button's
scrollable_treelist<br>
if (widget.get_label() == "None"):<br>
self.current_filter_language = None<br>
else:<br>
self.current_filter_language = widget.get_label()<br>
print("%s language selected!" %
self.current_filter_language)<br>
# Update the filter, which updates the view in turn<br>
self.language_filter.refilter()<br>
<br>
def on_year_selection_button_clicked(self, widget):<br>
""" Called on any of the year selection button clicks. """<br>
if (widget.get_label() == "None"):<br>
self.current_filter_year = None<br>
else:<br>
self.current_filter_year = int(widget.get_label())<br>
print("year %s selected!" % self.current_filter_year)<br>
# Update the filter, which updates the view in turn<br>
self.year_filter.refilter()<br>
<br>
TV_WIN = TreeViewFilterWindow()<br>
TV_WIN.connect("destroy", Gtk.main_quit)<br>
TV_WIN.show_all()<br>
Gtk.main()<br>
<p><br>
</p>
<p>John Driezen</p>
<p>jdriezen at sympatico.ca<br>
</p>
</body>
</html>