Imported Upstream version 1.2.0
[psensor-pkg-debian.git] / src / ui_sensorpref.c
1 /*
2  * Copyright (C) 2010-2016 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #include <stdlib.h>
20
21 #include <gtk/gtk.h>
22
23 #include <cfg.h>
24 #include <temperature.h>
25 #include <ui_appindicator.h>
26 #include <ui_color.h>
27 #include <ui_pref.h>
28 #include <ui_sensorlist.h>
29 #include <ui_sensorpref.h>
30
31 enum {
32         COL_NAME = 0,
33         COL_SENSOR_PREF
34 };
35
36 static GtkTreeView *w_sensors_list;
37 static GtkDialog *w_dialog;
38 static GtkLabel *w_sensor_id;
39 static GtkLabel *w_sensor_type;
40 static GtkLabel *w_sensor_chipname;
41 static GtkLabel *w_sensor_min;
42 static GtkLabel *w_sensor_max;
43 static GtkLabel *w_sensor_low_threshold_unit;
44 static GtkLabel *w_sensor_high_threshold_unit;
45 static GtkEntry *w_sensor_name;
46 static GtkToggleButton *w_sensor_draw;
47 static GtkToggleButton *w_sensor_display;
48 static GtkToggleButton *w_sensor_alarm;
49 static GtkToggleButton *w_appindicator_enabled;
50 static GtkToggleButton *w_appindicator_label_enabled;
51 static GtkColorButton *w_sensor_color;
52 static GtkSpinButton *w_sensor_high_threshold;
53 static GtkSpinButton *w_sensor_low_threshold;
54 static GtkListStore *store;
55
56 /* 'true' when the notifications of field changes are due to the change
57  * of the selected sensor.
58  */
59 static bool ignore_changes;
60
61 static struct psensor *get_selected_sensor(void)
62 {
63         GtkTreeModel *model;
64         GtkTreeIter iter;
65         struct psensor *s;
66         GtkTreeSelection *selection;
67
68         selection = gtk_tree_view_get_selection(w_sensors_list);
69
70         s = NULL;
71         if (gtk_tree_selection_get_selected(selection, &model, &iter))
72                 gtk_tree_model_get(model, &iter, COL_SENSOR_PREF, &s, -1);
73
74         return s;
75 }
76
77 static void apply_config(struct ui_psensor *ui)
78 {
79         config_sync();
80
81         ui_sensorlist_update(ui, 1);
82         ui_appindicator_update_menu(ui);
83 }
84
85 void ui_sensorpref_name_changed_cb(GtkEntry *entry, gpointer data)
86 {
87         struct psensor *s;
88
89         const gchar *str;
90
91         if (ignore_changes)
92                 return;
93
94         s = get_selected_sensor();
95
96         if (!s)
97                 return;
98
99         str = gtk_entry_get_text(entry);
100
101         if (strcmp(str, s->name)) {
102                 free(s->name);
103                 s->name = strdup(str);
104                 config_set_sensor_name(s->id, str);
105
106                 apply_config((struct ui_psensor *)data);
107         }
108 }
109
110 void ui_sensorpref_draw_toggled_cb(GtkToggleButton *btn, gpointer data)
111 {
112         gboolean active;
113         struct psensor *s;
114
115         if (ignore_changes)
116                 return;
117
118         s = get_selected_sensor();
119
120         if (!s)
121                 return;
122
123         active = gtk_toggle_button_get_active(btn);
124         config_set_sensor_graph_enabled(s->id, active);
125
126         apply_config((struct ui_psensor *)data);
127 }
128
129 void ui_sensorpref_display_toggled_cb(GtkToggleButton *btn, gpointer data)
130 {
131         gboolean active;
132         struct psensor *s;
133
134         if (ignore_changes)
135                 return;
136
137         s = get_selected_sensor();
138
139         if (!s)
140                 return;
141
142         active = gtk_toggle_button_get_active(btn);
143         config_set_sensor_enabled(s->id, active);
144
145         apply_config((struct ui_psensor *)data);
146 }
147
148 void ui_sensorpref_alarm_toggled_cb(GtkToggleButton *btn, gpointer data)
149 {
150         gboolean active;
151         struct psensor *s;
152
153         if (ignore_changes)
154                 return;
155
156         s = get_selected_sensor();
157
158         if (!s)
159                 return;
160
161         active = gtk_toggle_button_get_active(btn);
162         config_set_sensor_alarm_enabled(s->id, active);
163
164         apply_config((struct ui_psensor *)data);
165 }
166
167 void
168 ui_sensorpref_appindicator_menu_toggled_cb(GtkToggleButton *btn, gpointer data)
169 {
170         gboolean active;
171         struct psensor *s;
172
173         if (ignore_changes)
174                 return;
175
176         s = get_selected_sensor();
177
178         if (!s)
179                 return;
180
181         active = gtk_toggle_button_get_active(btn);
182         config_set_appindicator_enabled(s->id, active);
183
184         apply_config((struct ui_psensor *)data);
185 }
186
187 void
188 ui_sensorpref_appindicator_label_toggled_cb(GtkToggleButton *btn, gpointer data)
189 {
190         gboolean active;
191         struct psensor *s;
192
193         if (ignore_changes)
194                 return;
195
196         s = get_selected_sensor();
197
198         if (!s)
199                 return;
200
201         active = gtk_toggle_button_get_active(btn);
202         config_set_appindicator_label_enabled(s->id, active);
203
204         apply_config((struct ui_psensor *)data);
205 }
206
207 void ui_sensorpref_color_set_cb(GtkColorButton *widget, gpointer data)
208 {
209         struct psensor *s;
210         GdkRGBA color;
211
212         if (ignore_changes)
213                 return;
214
215         s = get_selected_sensor();
216         if (!s)
217                 return;
218
219         gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), &color);
220         config_set_sensor_color(s->id, &color);
221
222         apply_config((struct ui_psensor *)data);
223 }
224
225 void
226 ui_sensorpref_alarm_high_threshold_changed_cb(GtkSpinButton *btn, gpointer data)
227 {
228         struct psensor *s;
229         gdouble v;
230
231         if (ignore_changes)
232                 return;
233
234         s = get_selected_sensor();
235         if (!s)
236                 return;
237
238         v = gtk_spin_button_get_value(btn);
239         if (config_get_temperature_unit() == FAHRENHEIT)
240                 v = fahrenheit_to_celsius(v);
241
242         config_set_sensor_alarm_high_threshold(s->id, v);
243         s->alarm_high_threshold = v;
244
245         apply_config((struct ui_psensor *)data);
246 }
247
248 void
249 ui_sensorpref_alarm_low_threshold_changed_cb(GtkSpinButton *btn, gpointer data)
250 {
251         struct psensor *s;
252         gdouble v;
253
254         if (ignore_changes)
255                 return;
256
257         s = get_selected_sensor();
258         if (!s)
259                 return;
260
261         v = gtk_spin_button_get_value(btn);
262         if (config_get_temperature_unit() == FAHRENHEIT)
263                 v = fahrenheit_to_celsius(v);
264
265         config_set_sensor_alarm_low_threshold(s->id, v);
266         s->alarm_low_threshold = v;
267
268         apply_config((struct ui_psensor *)data);
269 }
270
271 static void update_pref(struct psensor *s)
272 {
273         int use_celsius, threshold;
274         GdkRGBA *color;
275         const char *chip;
276         char *smin, *smax;
277
278         if (!s)
279                 return;
280
281         ignore_changes = true;
282
283         gtk_label_set_text(w_sensor_id, s->id);
284         gtk_label_set_text(w_sensor_type, psensor_type_to_str(s->type));
285         gtk_entry_set_text(w_sensor_name, s->name);
286
287         if (s->chip)
288                 chip = s->chip;
289         else
290                 chip = _("Unknown");
291         gtk_label_set_text(w_sensor_chipname, chip);
292
293         use_celsius = config_get_temperature_unit() == CELSIUS ? 1 : 0;
294
295         if (s->min == UNKNOWN_DBL_VALUE)
296                 smin = strdup(_("Unknown"));
297         else
298                 smin = psensor_value_to_str(s->type, s->min, use_celsius);
299
300         gtk_label_set_text(w_sensor_min, smin);
301         free(smin);
302
303         if (s->max == UNKNOWN_DBL_VALUE)
304                 smax = strdup(_("Unknown"));
305         else
306                 smax = psensor_value_to_str(s->type, s->max, use_celsius);
307         gtk_label_set_text(w_sensor_max, smax);
308         free(smax);
309
310         gtk_toggle_button_set_active(w_sensor_draw,
311                                      config_is_sensor_graph_enabled(s->id));
312
313         gtk_toggle_button_set_active(w_sensor_display,
314                                      config_is_sensor_enabled(s->id));
315
316         color = config_get_sensor_color(s->id);
317         gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(w_sensor_color), color);
318         gdk_rgba_free(color);
319
320         gtk_label_set_text(w_sensor_high_threshold_unit,
321                            psensor_type_to_unit_str(s->type, use_celsius));
322         gtk_label_set_text(w_sensor_low_threshold_unit,
323                            psensor_type_to_unit_str(s->type, use_celsius));
324
325         if (is_appindicator_supported()) {
326                 gtk_widget_set_has_tooltip
327                         (GTK_WIDGET(w_appindicator_label_enabled), FALSE);
328                 gtk_widget_set_has_tooltip
329                         (GTK_WIDGET(w_appindicator_enabled), FALSE);
330         } else {
331                 gtk_widget_set_sensitive
332                         (GTK_WIDGET(w_appindicator_label_enabled), FALSE);
333                 gtk_widget_set_has_tooltip
334                         (GTK_WIDGET(w_appindicator_label_enabled), TRUE);
335                 gtk_widget_set_sensitive
336                         (GTK_WIDGET(w_appindicator_enabled), FALSE);
337                 gtk_widget_set_has_tooltip
338                         (GTK_WIDGET(w_appindicator_enabled), TRUE);
339         }
340
341         gtk_toggle_button_set_active(w_sensor_alarm,
342                                      config_get_sensor_alarm_enabled(s->id));
343
344         threshold = s->alarm_high_threshold;
345         if (!use_celsius)
346                 threshold = celsius_to_fahrenheit(threshold);
347         gtk_spin_button_set_value(w_sensor_high_threshold, threshold);
348
349         threshold = s->alarm_low_threshold;
350         if (!use_celsius)
351                 threshold = celsius_to_fahrenheit(threshold);
352         gtk_spin_button_set_value(w_sensor_low_threshold, threshold);
353
354         gtk_toggle_button_set_active(w_appindicator_enabled,
355                                      config_is_appindicator_enabled(s->id));
356
357         gtk_toggle_button_set_active
358                 (w_appindicator_label_enabled,
359                  config_is_appindicator_label_enabled(s->id));
360
361         ignore_changes = false;
362 }
363
364 void
365 ui_sensorpref_tree_selection_changed_cb(GtkTreeSelection *sel, gpointer data)
366 {
367         update_pref(get_selected_sensor());
368 }
369
370 static void select_sensor(struct psensor *s, struct psensor **sensors)
371 {
372         struct psensor **s_cur;
373         int i;
374         GtkTreePath *p;
375         GtkTreeSelection *sel;
376
377         for (s_cur = sensors, i = 0; *s_cur; s_cur++, i++)
378                 if (s == *s_cur) {
379                         p = gtk_tree_path_new_from_indices(i, -1);
380                         sel = gtk_tree_view_get_selection(w_sensors_list);
381                         gtk_tree_selection_select_path(sel, p);
382
383                         gtk_tree_path_free(p);
384
385                         update_pref(s);
386                         break;
387                 }
388 }
389
390 static void quit(void)
391 {
392         gtk_widget_destroy(GTK_WIDGET(w_dialog));
393         w_dialog = NULL;
394 }
395
396 static gboolean
397 on_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
398 {
399         quit();
400         return TRUE;
401 }
402
403 void ui_sensorpref_close_clicked_cb(GtkButton *btn, gpointer data)
404 {
405         quit();
406 }
407
408 static GtkBuilder *load_ui(struct ui_psensor *ui)
409 {
410         GtkBuilder *builder;
411         GError *error;
412         guint ok;
413
414         error = NULL;
415
416         builder = gtk_builder_new();
417         ok = gtk_builder_add_from_file
418                 (builder,
419                  PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "sensor-edit.glade",
420                  &error);
421
422         if (!ok) {
423                 log_printf(LOG_ERR, error->message);
424                 g_error_free(error);
425                 return NULL;
426         }
427
428         w_sensors_list = GTK_TREE_VIEW
429                 (gtk_builder_get_object(builder, "sensors_list"));
430         w_dialog = GTK_DIALOG(gtk_builder_get_object(builder, "dialog1"));
431         w_sensor_id = GTK_LABEL(gtk_builder_get_object(builder, "sensor_id"));
432         w_sensor_type = GTK_LABEL
433                 (gtk_builder_get_object(builder, "sensor_type"));
434         w_sensor_name = GTK_ENTRY
435                 (gtk_builder_get_object(builder, "sensor_name"));
436         w_sensor_chipname = GTK_LABEL
437                 (gtk_builder_get_object(builder, "chip_name"));
438         w_sensor_min = GTK_LABEL
439                 (gtk_builder_get_object(builder, "sensor_min"));
440         w_sensor_max = GTK_LABEL
441                 (gtk_builder_get_object(builder, "sensor_max"));
442         w_sensor_draw = GTK_TOGGLE_BUTTON
443                 (gtk_builder_get_object(builder, "sensor_draw"));
444         w_sensor_display = GTK_TOGGLE_BUTTON
445                 (gtk_builder_get_object(builder, "sensor_enable_checkbox"));
446         w_sensor_color = GTK_COLOR_BUTTON
447                 (gtk_builder_get_object(builder, "sensor_color"));
448         w_sensor_alarm = GTK_TOGGLE_BUTTON
449                 (gtk_builder_get_object(builder, "sensor_alarm"));
450         w_sensor_high_threshold
451                 = GTK_SPIN_BUTTON(gtk_builder_get_object
452                                   (builder, "sensor_alarm_high_threshold"));
453         w_sensor_low_threshold
454                 = GTK_SPIN_BUTTON(gtk_builder_get_object
455                                   (builder, "sensor_alarm_low_threshold"));
456         w_sensor_high_threshold_unit
457                 = GTK_LABEL(gtk_builder_get_object
458                             (builder, "sensor_alarm_high_threshold_unit"));
459         w_sensor_low_threshold_unit
460                 = GTK_LABEL(gtk_builder_get_object
461                             (builder, "sensor_alarm_low_threshold_unit"));
462         w_appindicator_enabled = GTK_TOGGLE_BUTTON
463                 (gtk_builder_get_object(builder, "indicator_checkbox"));
464         w_appindicator_label_enabled = GTK_TOGGLE_BUTTON
465                 (gtk_builder_get_object(builder, "indicator_label_checkbox"));
466
467         store = GTK_LIST_STORE(gtk_builder_get_object(builder,
468                                                       "sensors_liststore"));
469
470         gtk_window_set_transient_for(GTK_WINDOW(w_dialog),
471                                      GTK_WINDOW(ui->main_window));
472         gtk_builder_connect_signals(builder, ui);
473
474         g_signal_connect(w_dialog,
475                          "delete_event",
476                          G_CALLBACK(on_delete_event_cb),
477                          w_dialog);
478
479         return builder;
480 }
481
482 static void populate(struct psensor *sensor, struct psensor **sensors)
483 {
484         GtkTreeIter iter;
485         struct psensor **s_cur, **ordered_sensors, *s;
486
487         gtk_list_store_clear(store);
488
489         ordered_sensors = ui_get_sensors_ordered_by_position(sensors);
490         for (s_cur = ordered_sensors; *s_cur; s_cur++) {
491                 s = *s_cur;
492                 gtk_list_store_append(store, &iter);
493
494                 gtk_list_store_set(store, &iter,
495                                    COL_NAME, s->name,
496                                    COL_SENSOR_PREF, s,
497                                    -1);
498         }
499
500         select_sensor(sensor, ordered_sensors);
501
502         free(ordered_sensors);
503 }
504
505 void ui_sensorpref_dialog_run(struct psensor *sensor, struct ui_psensor *ui)
506 {
507         GtkBuilder *builder;
508
509         if (w_dialog == NULL) {
510                 builder = load_ui(ui);
511
512                 if (!builder)
513                         return;
514
515                 g_object_unref(G_OBJECT(builder));
516         }
517
518         populate(sensor, ui->sensors);
519
520         gtk_window_present(GTK_WINDOW(w_dialog));
521 }