File: gtk.cpp

package info (click to toggle)
cppgir 2.0%2Bgit20240928.c8bb1c6%2Breally2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,228 kB
  • sloc: cpp: 14,307; ansic: 339; makefile: 11; sh: 9
file content (139 lines) | stat: -rw-r--r-- 4,793 bytes parent folder | download | duplicates (2)
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();
}