1 #pragma once 2 #include <gtkmm.h> 3 4 #include "helper.h" 5 #include "keychain.h" 6 7 class ItemView : public Gtk::Grid { 8 public: ItemView(const KeychainItem & data)9 ItemView(const KeychainItem& data) : Gtk::Grid() { 10 set_row_spacing(5); 11 set_column_spacing(3); 12 set_margin_end(5); 13 set_margin_start(5); 14 15 if (data.sections.size() > 0) { 16 for (const auto& section : data.sections) { 17 attachSectionTitle(section.first); 18 for (const auto& field : section.second) { 19 processSingleField(field); 20 } 21 } 22 } 23 24 if (!data.notes.empty()) { 25 attachSectionTitle("Notes"); 26 auto notes_buffer = Gtk::TextBuffer::create(); 27 notes_buffer->set_text(data.notes); 28 29 auto notes_field = Gtk::manage(new Gtk::TextView(notes_buffer)); 30 notes_field->set_hexpand(true); 31 notes_field->set_vexpand(true); 32 notes_field->set_editable(false); 33 notes_field->set_wrap_mode(Gtk::WRAP_WORD); 34 attach(*notes_field, 0, row_index++, 4, 1); 35 } 36 37 if (data.URLs.size() > 0) { 38 attachSectionTitle("URLs"); 39 for (auto& url : data.URLs) { 40 auto url_button = Gtk::manage(new Gtk::LinkButton(url, url)); 41 attach(*url_button, 0, row_index++, 4, 1); 42 } 43 } 44 45 show_all_children(); 46 } ~ItemView()47 virtual ~ItemView() {} 48 49 protected: attachSectionTitle(std::string label)50 void attachSectionTitle(std::string label) { 51 auto label_widget = Gtk::manage(new Gtk::Label(label)); 52 attach(*label_widget, 0, row_index++, 4, 1); 53 } 54 processSingleField(const KeychainField & field)55 void processSingleField(const KeychainField& field) { 56 processSingleField(field.name, field.value, field.password); 57 } 58 processSingleField(std::string label,std::string value,bool conceal)59 void processSingleField(std::string label, std::string value, bool conceal) { 60 auto my_index = row_index++; 61 62 auto label_widget = Gtk::manage(new Gtk::Label(label)); 63 label_widget->set_halign(Gtk::ALIGN_END); 64 label_widget->set_margin_end(5); 65 attach(*label_widget, 0, my_index, 1, 1); 66 67 auto value_widget = Gtk::manage(new Gtk::Entry()); 68 value_widget->set_hexpand(true); 69 value_widget->set_editable(false); 70 71 const auto isTOTP = isTOTPURI(value); 72 if (isTOTP) { 73 try { 74 value_widget->set_text(calculateTOTP(value)); 75 } catch (std::exception& e) { 76 errorDialog(e.what()); 77 } 78 } else { 79 value_widget->set_text(value); 80 } 81 82 if (conceal && !isTOTP) 83 value_widget->set_visibility(false); 84 attach(*value_widget, 1, my_index, conceal ? 1 : 3, 1); 85 86 if (conceal) { 87 auto copy_button = Gtk::manage(new Gtk::Button("_Copy", true)); 88 copy_button->signal_clicked().connect([value_widget]() { 89 auto valueText = value_widget->get_text(); 90 auto clipboard = Gtk::Clipboard::get(); 91 clipboard->set_text(valueText); 92 clipboard->store(); 93 }); 94 attach(*copy_button, 2, my_index, 1, 1); 95 if (isTOTP) { 96 auto calculate_button = Gtk::manage(new Gtk::Button("_Calculate", true)); 97 calculate_button->signal_clicked().connect([value, value_widget]() { 98 try { 99 value_widget->set_text(calculateTOTP(value)); 100 } catch (std::exception& e) { 101 errorDialog(e.what()); 102 } 103 }); 104 attach(*calculate_button, 3, my_index, 1, 1); 105 } else { 106 auto reveal_button = Gtk::manage(new Gtk::Button("_Reveal", true)); 107 reveal_button->signal_clicked().connect([reveal_button, value_widget]() { 108 bool visible = value_widget->get_visibility(); 109 visible = !visible; 110 111 value_widget->set_visibility(visible); 112 reveal_button->set_label(visible ? "_Hide" : "_Reveal"); 113 }); 114 attach(*reveal_button, 3, my_index, 1, 1); 115 } 116 } 117 } 118 int row_index = 0; 119 }; 120