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