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