The list can be filtered by wrapping it in a FilterListModel
.
Set a Filter
such as a StringFilter
or a BoolFilter
to the FilterListModel
.
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()
{
set_visible(false);
}
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);
}