1 #pragma once
2 #include <functional>
3 #include <gtkmm.h>
4 
5 #include "keychain.h"
6 
7 class SearchList : public Gtk::VBox {
8 public:
SearchList(std::function<void (const Glib::ustring &)> _selectionChangedCb,Keychain & keychain)9     SearchList(std::function<void(const Glib::ustring&)> _selectionChangedCb, Keychain& keychain)
10         : Gtk::VBox() {
11         selectionChangedCb = _selectionChangedCb;
12         set_spacing(5);
13         set_can_focus(false);
14 
15         pack_start(search_entry, false, true, 0);
16         pack_start(viewport, true, true, 0);
17 
18         viewport.add(item_list);
19         viewport.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
20 
21         item_list_model = Gtk::ListStore::create(columns);
22 
23         for (const auto& item : keychain) {
24             auto uuid = item.first;
25             auto title = item.second.title;
26 
27             auto new_row = *item_list_model->append();
28             new_row[columns.uuid] = uuid;
29             new_row[columns.name] = title;
30         }
31 
32         item_list_model->set_sort_column(columns.name, Gtk::SORT_ASCENDING);
33 
34         item_list_filter_model = Gtk::TreeModelFilter::create(item_list_model);
35         item_list_filter_model->set_visible_func(
36             [this](const Gtk::TreeModel::const_iterator& iter) -> bool {
37                 if (!iter)
38                     return true;
39                 auto row = *iter;
40                 Glib::ustring itemName = row[columns.name];
41                 auto searchText = search_entry.get_text();
42 
43                 if (itemName.casefold().find(searchText.casefold()) != Glib::ustring::npos)
44                     return true;
45                 return false;
46             });
47 
48         item_list.set_model(item_list_filter_model);
49         item_list.append_column("Name", columns.name);
50         item_list.set_headers_visible(false);
51 
52         item_list_selector = item_list.get_selection();
53         item_list_selector->set_mode(Gtk::SELECTION_BROWSE);
54         item_list_selector->signal_changed().connect([this]() {
55             auto row = *item_list.get_selection()->get_selected();
56             auto itemUUID = row[columns.uuid];
57 
58             selectionChangedCb(itemUUID);
59         });
60 
61         search_entry.signal_search_changed().connect(
62             [this]() { item_list_filter_model->refilter(); });
63     };
64 
~SearchList()65     virtual ~SearchList(){};
66 
67 protected:
68     class SearchListColumns : public Gtk::TreeModel::ColumnRecord {
69     public:
SearchListColumns()70         SearchListColumns() {
71             add(uuid);
72             add(name);
73         }
74 
75         Gtk::TreeModelColumn<Glib::ustring> uuid;
76         Gtk::TreeModelColumn<Glib::ustring> name;
77     };
78 
79     SearchListColumns columns;
80 
81     Gtk::ScrolledWindow viewport;
82     Gtk::SearchEntry search_entry;
83     Gtk::TreeView item_list;
84     Glib::RefPtr<Gtk::TreeSelection> item_list_selector;
85     Glib::RefPtr<Gtk::ListStore> item_list_model;
86     Glib::RefPtr<Gtk::TreeModelFilter> item_list_filter_model;
87     std::function<void(const Glib::ustring&)> selectionChangedCb;
88 };
89