1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
//#define GI_INLINE 1
#include <gtk/gtk.hpp>
#include <iostream>
#include <tuple>
#include <vector>
namespace GLib = gi::repository::GLib;
namespace GObject_ = gi::repository::GObject;
namespace Gtk = gi::repository::Gtk;
static GLib::MainLoop loop;
// based on python-gtk3 example
// https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html
// list of tuples for each software,
// containing the software name, initial release, and main programming languages
const std::vector<std::tuple<std::string, int, std::string>> software_list{
std::make_tuple("Firefox", 2002, "C++"),
std::make_tuple("Eclipse", 2004, "Java"),
std::make_tuple("Pitivi", 2004, "Python"),
std::make_tuple("Netbeans", 1996, "Java"),
std::make_tuple("Chrome", 2008, "C++"),
std::make_tuple("Filezilla", 2001, "C++"),
std::make_tuple("Bazaar", 2005, "Python"),
std::make_tuple("Git", 2005, "C"),
std::make_tuple("Linux Kernel", 1991, "C"),
std::make_tuple("GCC", 1987, "C"),
std::make_tuple("Frostwire", 2004, "Java")};
class TreeViewFilterWindow : public Gtk::impl::WindowImpl
{
typedef TreeViewFilterWindow self_type;
Gtk::ListStore store_;
Gtk::TreeModelFilter language_filter_;
std::string current_filter_language_;
public:
TreeViewFilterWindow() : Gtk::impl::WindowImpl(this)
{
Gtk::Window &self = *(this);
self.set_title("TreeView filter demo");
self.set_border_width(10);
// set up the grid in which elements are positioned
auto grid = Gtk::Grid::new_();
grid.set_column_homogeneous(true);
grid.set_row_homogeneous(true);
self.add(grid);
// create ListStore model
store_ = Gtk::ListStore::new_type_<std::string, int, std::string>();
for (auto &e : software_list) {
auto it = store_.append();
GObject_::Value cols[] = {std::get<0>(e), std::get<1>(e), std::get<2>(e)};
for (unsigned i = 0; i < G_N_ELEMENTS(cols); ++i) {
store_.set_value(it, i, cols[i]);
}
}
// create the filter, feeding it with the liststore model
auto treemodel = store_.interface_(gi::interface_tag<Gtk::TreeModel>());
language_filter_ =
gi::object_cast<Gtk::TreeModelFilter>(treemodel.filter_new(nullptr));
// set the filter function
language_filter_.set_visible_func(
gi::mem_fun(&self_type::language_filter_func, this));
// create the treeview, make it use the filter as a model, and add
// columns
auto treeview = Gtk::TreeView::new_with_model(language_filter_);
int i = 0;
for (auto &e : {"Software", "Release Year", "Programming Language"}) {
auto renderer = Gtk::CellRendererText::new_();
auto column = Gtk::TreeViewColumn::new_(e, renderer, {{"text", i}});
treeview.append_column(column);
++i;
}
// create buttons to filter by programming language, and set up their
// events
std::vector<Gtk::Widget> buttons;
for (auto &prog_language : {"Java", "C", "C++", "Python", "None"}) {
auto button = Gtk::Button::new_with_label(prog_language);
buttons.push_back(button);
button.signal_clicked().connect(
gi::mem_fun(&self_type::on_selection_button_clicked, this));
}
// set up the layout;
// put the treeview in a scrollwindow, and the buttons in a row
auto scrollable_treelist = Gtk::ScrolledWindow::new_();
scrollable_treelist.set_vexpand(true);
grid.attach(scrollable_treelist, 0, 0, 8, 10);
grid.attach_next_to(
buttons[0], scrollable_treelist, Gtk::PositionType::BOTTOM_, 1, 1);
auto it = buttons.begin() + 1;
while (it != buttons.end()) {
grid.attach_next_to(*it, *(it - 1), Gtk::PositionType::RIGHT_, 1, 1);
++it;
}
scrollable_treelist.add(treeview);
self.show_all();
}
bool language_filter_func(Gtk::TreeModel filter, Gtk::TreeIter_Ref it) const
{
if (current_filter_language_.empty() || current_filter_language_ == "None")
return true;
return current_filter_language_ ==
filter.get_value(it, 2).get_value<std::string>();
}
void on_selection_button_clicked(Gtk::Button button)
{
// set the current language filter to the button's label
current_filter_language_ = button.get_label();
std::cout << current_filter_language_ << " language selected!" << std::endl;
// update the filter, which updates in turn the view
language_filter_.refilter();
}
};
int
main(int argc, char **argv)
{
gtk_init(&argc, &argv);
// recommended general approach iso stack based
// too much vmethod calling which is not safe for plain case
auto win = gi::make_ref<TreeViewFilterWindow>();
// TODO auto-handle arg ignore ??
win->signal_destroy().connect([](Gtk::Widget) { Gtk::main_quit(); });
win->show_all();
Gtk::main();
}
|