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