[kwlug-disc] A Sorted and Filtered Treeview Model in GTK3 and Python

John Driezen jdriezen at sympatico.ca
Wed Jun 2 20:50:39 EDT 2021


On 2021-06-01 9:14 p.m., John Driezen wrote:
> I am trying to expand upon a tutorial example located at 
> https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html 
> in section 13.5.  I wish to sort the filtered rows by column.  The 
> tutorial suggests that this is possible, and the Homebank program 
> (written in C and GTK3) contains many examples of this.  My attempt at 
> sorting the filtered rows follows.   The demo program works just fine 
> as is, but when I attempt to sort the filtered rows I get a blank 
> scrolled window.  Anyone have any suggestions?
>
I solved my issue with the help of the following two stackoverflow.com 
questions and answers.

https://stackoverflow.com/questions/52843937/cannot-sort-columns-in-gtk-textview-i-python-3 
and

https://stackoverflow.com/questions/55167884/python-gtk-3-sorting-a-treeview-by-clicking-on-column

For those interested, the working code resulting in a sorted and 
filtered treeview follows.

I can now sort the filtered rows by each column.  I really wish tutorial 
examples would go a bit further :(

""" Sorted and Filtered TreeView Demo Program """
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"),
]

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

         # Creating the filter, feeding it with the liststore model
         self.language_filter = self.software_liststore.filter_new()
         # Setting the filter function
self.language_filter.set_visible_func(self.language_filter_func)

         # Creating the treeview, using the sorted filter as a model and 
adding the columns

         self.sortedandfilteredtree = 
Gtk.TreeModelSort(model=self.language_filter)
         self.sortedtreeview = 
Gtk.TreeView.new_with_model(self.sortedandfilteredtree)
         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.buttons = list()
         for prog_language in ["Java", "C", "C++", "Python", "None"]:
             button = Gtk.Button(label=prog_language)
             self.buttons.append(button)
             button.connect("clicked", self.on_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.buttons[0], self.scrollable_treelist,
                                  Gtk.PositionType.BOTTOM, 1, 1)

         for i, button in enumerate(self.buttons[1:]):
             self.grid.attach_next_to(button, self.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 or 
self.current_filter_language == "None":
             return True
         else:
             return model[iter][2] == self.current_filter_language

     def on_selection_button_clicked(self, widget):
         """ Called on any of the button clicks """
         # Set the current language filter to the button's 
scrollable_treelist
         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()

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

Applying this idea to my scrap metal pricing program will be a weekend 
project sometime soon.

John Driezen

jdriezen at sympatico.ca






More information about the kwlug-disc mailing list