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