<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>