1 #include "preferences_window_stock_info_digikey.hpp"
2 #include "common/common.hpp"
3 #include "util/gtk_util.hpp"
4 #include "util/util.hpp"
5 #include "preferences/preferences.hpp"
6 #include <set>
7 #include <iostream>
8 #include "util/stock_info_provider_digikey.hpp"
9 #include "util/sqlite.hpp"
10 #include "util/win32_undef.hpp"
11 #include "digikey_auth_window.hpp"
12 
13 namespace horizon {
14 
populate_and_bind_combo(Gtk::ComboBoxText & combo,const std::vector<std::pair<std::string,std::string>> & items,std::string & value)15 void DigiKeyApiPreferencesEditor::populate_and_bind_combo(Gtk::ComboBoxText &combo,
16                                                           const std::vector<std::pair<std::string, std::string>> &items,
17                                                           std::string &value)
18 {
19     for (const auto &[code, name] : items)
20         combo.append(code, name + " (" + code + ")");
21     combo.set_active_id(value);
22     combo.signal_changed().connect([this, &combo, &value] {
23         value = combo.get_active_id();
24         preferences.signal_changed().emit();
25     });
26 }
27 
DigiKeyApiPreferencesEditor(BaseObjectType * cobject,const Glib::RefPtr<Gtk::Builder> & x,Preferences & prefs)28 DigiKeyApiPreferencesEditor::DigiKeyApiPreferencesEditor(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &x,
29                                                          Preferences &prefs)
30     : Gtk::Box(cobject), preferences(prefs), digikey_preferences(preferences.digikey_api),
31       db(StockInfoProviderDigiKey::get_db_filename(), SQLITE_OPEN_READWRITE)
32 {
33     GET_WIDGET(digikey_client_id_entry);
34     GET_WIDGET(digikey_client_secret_entry);
35     GET_WIDGET(digikey_max_price_breaks_sp);
36     GET_WIDGET(digikey_site_combo);
37     GET_WIDGET(digikey_currency_combo);
38     GET_WIDGET(digikey_token_label);
39 
40     bind_widget(digikey_client_id_entry, digikey_preferences.client_id, [this](std::string &v) {
41         update_warnings();
42         preferences.signal_changed().emit();
43     });
44     bind_widget(digikey_client_secret_entry, digikey_preferences.client_secret, [this](std::string &v) {
45         update_warnings();
46         preferences.signal_changed().emit();
47     });
48 
49 
50     digikey_max_price_breaks_sp->set_value(digikey_preferences.max_price_breaks);
51     digikey_max_price_breaks_sp->signal_changed().connect([this] {
52         digikey_preferences.max_price_breaks = digikey_max_price_breaks_sp->get_value_as_int();
53         preferences.signal_changed().emit();
54     });
55 
56     {
57         const std::vector<std::pair<std::string, std::string>> sites = {
58                 {"AU", "Australia"},
59                 {"AT", "Austria"},
60                 {"BE", "Belgium"},
61                 {"BG", "Bulgaria"},
62                 {"CA", "Canada"},
63                 {"CN", "China"},
64                 {"CZ", "Czech Republic"},
65                 {"DK", "Denmark"},
66                 {"EE", "Estonia"},
67                 {"FI", "Finland"},
68                 {"FR", "France"},
69                 {"DE", "Germany"},
70                 {"GR", "Greece"},
71                 {"HK", "Hong Kong"},
72                 {"HU", "Hungary"},
73                 {"IN", "India"},
74                 {"IE", "Ireland"},
75                 {"IL", "Israel"},
76                 {"IT", "Italy"},
77                 {"JP", "Japan"},
78                 {"KR", "Korea, Republic of"},
79                 {"LV", "Latvia"},
80                 {"LT", "Lithuania"},
81                 {"LU", "Luxembourg"},
82                 {"MY", "Malaysia"},
83                 {"MX", "Mexico"},
84                 {"NL", "Netherlands"},
85                 {"NZ", "New Zealand"},
86                 {"NO", "Norway"},
87                 {"PH", "Philippines"},
88                 {"PL", "Poland"},
89                 {"PT", "Portugal"},
90                 {"RO", "Romania"},
91                 {"SG", "Singapore"},
92                 {"SK", "Slovakia"},
93                 {"SI", "Slovenia"},
94                 {"ZA", "South Africa"},
95                 {"ES", "Spain"},
96                 {"SE", "Sweden"},
97                 {"CH", "Switzerland"},
98                 {"TW", "Taiwan, Province of China"},
99                 {"TH", "Thailand"},
100                 {"UK", "United Kingdom"},
101                 {"US", "United States"},
102         };
103         populate_and_bind_combo(*digikey_site_combo, sites, digikey_preferences.site);
104     }
105 
106     {
107         const std::vector<std::pair<std::string, std::string>> currencies = {
108                 {"AUD", "Australian Dollar"},
109                 {"THB", "Baht"},
110                 {"CAD", "Canadian Dollar"},
111                 {"CZK", "Czech Koruna"},
112                 {"DKK", "Danish Krone"},
113                 {"EUR", "Euro"},
114                 {"HUF", "Forint"},
115                 {"HKD", "Hong Kong Dollar"},
116                 {"INR", "Indian Rupee"},
117                 {"MYR", "Malaysian Ringgit"},
118                 {"ILS", "New Israeli Sheqel"},
119                 {"RON", "New Romanian Leu"},
120                 {"TWD", "New Taiwan Dollar"},
121                 {"NZD", "New Zealand Dollar"},
122                 {"NOK", "Norwegian Krone"},
123                 {"PHP", "Philippine Piso"},
124                 {"GBP", "Pound Sterling"},
125                 {"ZAR", "Rand"},
126                 {"SGD", "Singapore Dollar"},
127                 {"SEK", "Swedish Krona"},
128                 {"CHF", "Swiss Franc"},
129                 {"USD", "US Dollar"},
130                 {"KRW", "Won"},
131                 {"JPY", "Yen"},
132                 {"CNY", "Yuan Renminbi"},
133                 {"PLN", "Zloty"},
134         };
135         populate_and_bind_combo(*digikey_currency_combo, currencies, digikey_preferences.currency);
136     }
137 
138     {
139         Gtk::Button *digikey_sign_in_button;
140         GET_WIDGET(digikey_sign_in_button);
141         digikey_sign_in_button->signal_clicked().connect([this] {
142             auto top = dynamic_cast<Gtk::Window *>(get_ancestor(GTK_TYPE_WINDOW));
143             auto win = DigiKeyAuthWindow::create();
144             win->set_transient_for(*top);
145             win->present();
146             win->signal_hide().connect(sigc::mem_fun(*this, &DigiKeyApiPreferencesEditor::update_token), false);
147         });
148     }
149 
150     update_warnings();
151     update_token();
152 }
153 
needs_trim(const std::string & s)154 static bool needs_trim(const std::string &s)
155 {
156     return s.size() && (isspace(s.front()) || isspace(s.back()));
157 }
158 
update_warnings()159 void DigiKeyApiPreferencesEditor::update_warnings()
160 {
161     for (auto entry : {digikey_client_id_entry, digikey_client_secret_entry}) {
162         const std::string txt = entry->get_text();
163         if (txt.size() == 0) {
164             entry_set_warning(entry, "Required");
165         }
166         else if (needs_trim(txt)) {
167             entry_set_warning(entry, "Has trailing/leading whitespace");
168         }
169         else {
170             entry_set_warning(entry, "");
171         }
172     }
173 }
174 
175 
update_token()176 void DigiKeyApiPreferencesEditor::update_token()
177 {
178     SQLite::Query q(db, "SELECT datetime(valid_until, 'localtime') FROM tokens WHERE key = 'refresh'");
179     if (q.step()) {
180         digikey_token_label->set_text("Token valid until " + q.get<std::string>(0)
181                                       + "\nThe token will automatically be refreshed.");
182     }
183     else {
184         digikey_token_label->set_text("No token, log in to obtain one.");
185     }
186 }
187 
create(Preferences & prefs)188 DigiKeyApiPreferencesEditor *DigiKeyApiPreferencesEditor::create(Preferences &prefs)
189 {
190     DigiKeyApiPreferencesEditor *w;
191     Glib::RefPtr<Gtk::Builder> x = Gtk::Builder::create();
192     std::vector<Glib::ustring> widgets = {"digikey_box", "adjustment10", "adjustment11"};
193     x->add_from_resource("/org/horizon-eda/horizon/pool-prj-mgr/preferences/preferences.ui", widgets);
194     x->get_widget_derived("digikey_box", w, prefs);
195     w->reference();
196     return w;
197 }
198 
199 } // namespace horizon
200