Filtering
| Chapter 10. ListView, GridView, ColumnView |

## Filtering

The list can be filtered by wrapping it in a `FilterListModel`. Set a `Filter` such as a `StringFilter` or a `BoolFilter` to the `FilterListModel`.

FilterListModel Reference

StringFilter Reference

BoolFilter Reference

### Example

Figure 10.5. FilterListModel

Source Code

File: `examplewindow.h` (For use with gtkmm 4)

    #ifndef GTKMM_EXAMPLEWINDOW_H
    #define GTKMM_EXAMPLEWINDOW_H

    #include <gtkmm.h>

    class ExampleWindow : public Gtk::Window
    {
    public:
      ExampleWindow();
      ~ExampleWindow() override;

    protected:
      // Signal handlers:
      void on_button_showall();
      void on_button_showj();
      void on_button_showm();
      void on_button_quit();
      void on_setup_label(const Glib::RefPtr<Gtk::ListItem>& list_item, Gtk::Align halign);
      void on_bind_id(const Glib::RefPtr<Gtk::ListItem>& list_item);
      void on_bind_name(const Glib::RefPtr<Gtk::ListItem>& list_item);

      // A Gio::ListStore item.
      class ModelColumns : public Glib::Object
      {
      public:
        unsigned int m_col_id;
        Glib::ustring m_col_name;

        static Glib::RefPtr<ModelColumns> create(int col_id, const Glib::ustring& col_name)
        {
          return Glib::make_refptr_for_instance<ModelColumns>(
            new ModelColumns(col_id, col_name));
        }

      protected:
        ModelColumns(int col_id, const Glib::ustring& col_name)
        : m_col_id(col_id), m_col_name(col_name)
        {}
      }; // ModelColumns

      // Child widgets:
      Gtk::Box m_VBox;
      Gtk::ScrolledWindow m_ScrolledWindow;
      Gtk::ColumnView m_ColumnView;
      Gtk::Box m_ButtonBox;
      Gtk::ToggleButton m_Button_ShowAll;
      Gtk::ToggleButton m_Button_ShowJ;
      Gtk::ToggleButton m_Button_ShowM;
      Gtk::Button m_Button_Quit;

      Glib::RefPtr<Gtk::SingleSelection> m_SelectionModel;
      Glib::RefPtr<Gio::ListStore<ModelColumns>> m_ListStore;
      Glib::RefPtr<Gtk::FilterListModel> m_FilterListModel;
      Glib::RefPtr<Gtk::StringFilter> m_StringFilter;
    };

    #endif //GTKMM_EXAMPLEWINDOW_H

File: `examplewindow.cc` (For use with gtkmm 4)

    #include "examplewindow.h"

    ExampleWindow::ExampleWindow()
    : m_VBox(Gtk::Orientation::VERTICAL),
      m_Button_ShowAll("Show All"),
      m_Button_ShowJ("Show J"),
      m_Button_ShowM("Show M"),
      m_Button_Quit("Quit")
    {
      set_title("Gtk::ColumnView (Gtk::FilterListModel) example");
      set_default_size(400, 350);

      m_VBox.set_margin(5);
      set_child(m_VBox);

      // Add the ColumnView, inside a ScrolledWindow, with the buttons underneath:
      m_ScrolledWindow.set_child(m_ColumnView);

      // Only show the scrollbars when they are necessary:
      m_ScrolledWindow.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
      m_ScrolledWindow.set_expand();

      m_VBox.append(m_ScrolledWindow);
      m_VBox.append(m_ButtonBox);

      m_ButtonBox.set_margin(5);
      m_ButtonBox.set_spacing(10);
      m_ButtonBox.append(m_Button_ShowAll);
      m_ButtonBox.append(m_Button_ShowJ);
      m_ButtonBox.append(m_Button_ShowM);
      m_ButtonBox.append(m_Button_Quit);
      m_Button_ShowAll.signal_toggled().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_button_showall));
      m_Button_ShowJ.signal_toggled().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_button_showj));
      m_Button_ShowM.signal_toggled().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_button_showm));
      m_Button_Quit.set_hexpand(true);
      m_Button_Quit.set_halign(Gtk::Align::END);
      m_Button_Quit.signal_clicked().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_button_quit));

      // Gtk::CheckButton and Gtk::ToggleButton have set_group() methods.
      // They act as radio buttons, if they are included in a group.
      m_Button_ShowJ.set_group(m_Button_ShowAll);
      m_Button_ShowM.set_group(m_Button_ShowAll);

      // Create the List model.
      m_ListStore = Gio::ListStore<ModelColumns>::create();
      m_ListStore->append(ModelColumns::create(1, "Billy Bob"));
      m_ListStore->append(ModelColumns::create(11, "Billy Bob Junior"));
      m_ListStore->append(ModelColumns::create(12, "Sue Bob"));
      m_ListStore->append(ModelColumns::create(2, "Joey Jojo"));
      m_ListStore->append(ModelColumns::create(3, "Rob McRoberts"));
      m_ListStore->append(ModelColumns::create(31, "Xavier McRoberts"));

      // Create the filter model.
      auto expression = Gtk::ClosureExpression<Glib::ustring>::create(
        [](const Glib::RefPtr<Glib::ObjectBase>& item)->Glib::ustring
        {
          const auto col = std::dynamic_pointer_cast<ModelColumns>(item);
          return col ? col->m_col_name : "";
        });
      m_StringFilter = Gtk::StringFilter::create(expression);
      m_StringFilter->set_ignore_case(false);
      m_StringFilter->set_match_mode(Gtk::StringFilter::MatchMode::SUBSTRING);
      m_FilterListModel = Gtk::FilterListModel::create(m_ListStore, m_StringFilter);

      // Set list model and selection model.
      m_SelectionModel = Gtk::SingleSelection::create(m_ListStore);
      m_SelectionModel->set_autoselect(false);
      m_SelectionModel->set_can_unselect(true);
      m_ColumnView.set_model(m_SelectionModel);
      m_ColumnView.add_css_class("data-table"); // high density table

      // Make the columns reorderable.
      // This is not necessary, but it's nice to show the feature.
      m_ColumnView.set_reorderable(true);

      // Add the ColumnView's columns:

      // Id column
      auto factory = Gtk::SignalListItemFactory::create();
      factory->signal_setup().connect(sigc::bind(sigc::mem_fun(*this,
        &ExampleWindow::on_setup_label), Gtk::Align::END));
      factory->signal_bind().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_bind_id));
      auto column = Gtk::ColumnViewColumn::create("ID", factory);
      m_ColumnView.append_column(column);

      // Name column
      factory = Gtk::SignalListItemFactory::create();
      factory->signal_setup().connect(sigc::bind(sigc::mem_fun(*this,
        &ExampleWindow::on_setup_label), Gtk::Align::START));
      factory->signal_bind().connect(
        sigc::mem_fun(*this, &ExampleWindow::on_bind_name));
      column = Gtk::ColumnViewColumn::create("Name", factory);
      m_ColumnView.append_column(column);

      // Show the list model without filtering.
      m_Button_ShowAll.set_active(true);
    }

    ExampleWindow::~ExampleWindow()
    {
    }

    void ExampleWindow::on_button_showall()
    {
      if (m_Button_ShowAll.get_active())
        m_SelectionModel->set_model(m_ListStore);
    }

    void ExampleWindow::on_button_showj()
    {
      if (m_Button_ShowJ.get_active())
      {
       m_StringFilter->set_search("J");
        m_SelectionModel->set_model(m_FilterListModel);
      }
    }

    void ExampleWindow::on_button_showm()
    {
      if (m_Button_ShowM.get_active())
      {
       m_StringFilter->set_search("M");
        m_SelectionModel->set_model(m_FilterListModel);
      }
    }

    void ExampleWindow::on_button_quit()
    {
      close();
    }

    void ExampleWindow::on_setup_label(
      const Glib::RefPtr<Gtk::ListItem>& list_item, Gtk::Align halign)
    {
      list_item->set_child(*Gtk::make_managed<Gtk::Label>("", halign));
    }

    void ExampleWindow::on_bind_id(const Glib::RefPtr<Gtk::ListItem>& list_item)
    {
      auto col = std::dynamic_pointer_cast<ModelColumns>(list_item->get_item());
      if (!col)
        return;
      auto label = dynamic_cast<Gtk::Label*>(list_item->get_child());
      if (!label)
        return;
      label->set_text(Glib::ustring::format(col->m_col_id));
    }

    void ExampleWindow::on_bind_name(const Glib::RefPtr<Gtk::ListItem>& list_item)
    {
      auto col = std::dynamic_pointer_cast<ModelColumns>(list_item->get_item());
      if (!col)
        return;
      auto label = dynamic_cast<Gtk::Label*>(list_item->get_child());
      if (!label)
        return;
      label->set_text(col->m_col_name);
    }

File: `main.cc` (For use with gtkmm 4)

    #include "examplewindow.h"
    #include <gtkmm/application.h>

    int main(int argc, char* argv[])
    {
      auto app = Gtk::Application::create("org.gtkmm.example");

      // Shows the window and returns when it is closed.
      return app->make_window_and_run<ExampleWindow>(argc, argv);
    }

Sorting |  | Displaying Trees