(no commit message)
[psensor.git] / src / ui_pref.c
1 /*
2     Copyright (C) 2010-2011 wpitchoune@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU 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
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "ui.h"
24 #include "cfg.h"
25 #include "ui_pref.h"
26 #include "ui_color.h"
27 #include "compat.h"
28
29 struct ui_pref {
30         /* Main container widget */
31         GtkWidget *widget;
32
33         GtkWidget *w_opacity;
34
35         GtkWidget *w_graph_fgcolor;
36         GtkWidget *w_graph_bgcolor;
37
38         GtkWidget *w_sensorlist_position;
39
40         GtkWidget *w_window_decoration_enabled;
41         GtkWidget *w_window_keep_below_enabled;
42
43         GtkWidget *w_graph_update_interval;
44         GtkWidget *w_graph_monitoring_duration;
45
46         GtkWidget *w_sensor_update_interval;
47 };
48
49 GdkColor *color_to_gdkcolor(struct color *color)
50 {
51         GdkColor *c = malloc(sizeof(GdkColor));
52
53         c->red = color->red;
54         c->green = color->green;
55         c->blue = color->blue;
56
57         return c;
58 }
59
60 void ui_pref_add_label(GtkWidget *table,
61                        const char *text, guint col, guint row)
62 {
63         GtkWidget *alig;
64         guint xpad;
65
66         alig = gtk_alignment_new(0, 0.5, 0, 0);
67
68         if (col == 0)
69                 xpad = 24;
70         else
71                 xpad = 4;
72
73         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 4, 4, xpad, 4);
74
75         gtk_container_add(GTK_CONTAINER(alig), GTK_WIDGET(gtk_label_new(text)));
76
77         gtk_table_attach(GTK_TABLE(table),
78                          alig,
79                          col, col + 1,
80                          row, row + 1,
81                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
82 }
83
84 GtkWidget *ui_pref_add_check_button(GtkWidget * table,
85                                     const char *text, int enabled, guint row)
86 {
87         GtkWidget *btn, *alig;
88
89         btn = gtk_check_button_new_with_label(text);
90         if (enabled)
91                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(btn), TRUE);
92
93         alig = gtk_alignment_new(0, 0.5, 0, 0);
94         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 4, 4, 24, 4);
95         gtk_container_add(GTK_CONTAINER(alig), GTK_WIDGET(btn));
96
97         gtk_table_attach(GTK_TABLE(table),
98                          alig,
99                          0, 2,
100                          row, row + 1,
101                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
102
103         return btn;
104 }
105
106 void ui_pref_add_section_title(GtkWidget *table, const char *title, guint row)
107 {
108         char *markup;
109         GtkWidget *alig, *label;
110
111         markup = malloc(3 + strlen(title) + 4 + 1);
112         sprintf(markup, "<b>%s</b>", title);
113
114         alig = gtk_alignment_new(0, 0, 0, 0);
115         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 8, 4, 8, 4);
116
117         label = gtk_label_new(NULL);
118         gtk_label_set_markup(GTK_LABEL(label), markup);
119         gtk_container_add(GTK_CONTAINER(alig), label);
120
121         gtk_table_attach(GTK_TABLE(table),
122                          alig,
123                          0, 2,
124                          row, row + 1,
125                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
126
127         free(markup);
128 }
129
130 GtkWidget *ui_pref_add_color_button(GtkWidget * table,
131                                     const char *text,
132                                     struct color *color, guint row)
133 {
134         GtkWidget *alig, *btn;
135         GdkColor *gdkcolor;
136
137         ui_pref_add_label(table, text, 0, row);
138
139         alig = gtk_alignment_new(0, 0.5, 0, 0);
140         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 4, 4, 4, 4);
141         gdkcolor = color_to_gdkcolor(color);
142         btn = ui_pref_create_color_button(gdkcolor);
143         free(gdkcolor);
144
145         gtk_container_add(GTK_CONTAINER(alig), btn);
146
147         gtk_table_attach(GTK_TABLE(table),
148                          alig,
149                          1, 2,
150                          row, row + 1,
151                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
152
153         return btn;
154 }
155
156 GtkWidget *ui_pref_add_spin_button(GtkWidget * table,
157                                    int value, int min, int max, guint row)
158 {
159         GtkWidget *alig;
160         GtkSpinButton *spin_button;
161
162         spin_button = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(min,
163                                                                      max, 1));
164
165         gtk_widget_set_sensitive(GTK_WIDGET(spin_button), TRUE);
166         gtk_spin_button_set_value(spin_button, value);
167         alig = gtk_alignment_new(0, 0.5, 0, 0);
168         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 4, 4, 4, 4);
169         gtk_container_add(GTK_CONTAINER(alig), GTK_WIDGET(spin_button));
170         gtk_table_attach(GTK_TABLE(table),
171                          alig,
172                          1, 2,
173                          row, row + 1,
174                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
175         return GTK_WIDGET(spin_button);
176 }
177
178 GtkWidget *ui_pref_create_color_button(GdkColor * color)
179 {
180         return gtk_color_button_new_with_color(color);
181 }
182
183 struct ui_pref *ui_pref_create_main_widget(struct ui_psensor *ui_psensor)
184 {
185         GtkWidget *table, *w_opacity, *label, *hbox, *alig;
186         struct ui_pref *pref;
187         struct config *cfg;
188         guint row;
189
190         cfg = ui_psensor->config;
191
192         pref = malloc(sizeof(struct ui_pref));
193
194         table = gtk_table_new(14, 2, FALSE);
195         gtk_table_set_col_spacing(GTK_TABLE(table), 0, 8);
196
197         row = 0;
198
199         /* Graph Colors section */
200         ui_pref_add_section_title(table, _("Graph Colors"), row++);
201
202         pref->w_graph_fgcolor
203             = ui_pref_add_color_button(table,
204                                        _("Foreground:"),
205                                        cfg->graph_fgcolor, row++);
206
207         pref->w_graph_bgcolor
208             = ui_pref_add_color_button(table,
209                                        _("Background:"),
210                                        cfg->graph_bgcolor, row++);
211
212         ui_pref_add_label(table, _("Background opacity:"), 0, row++);
213
214         w_opacity = gtk_hscale_new_with_range(0, 1, 0.1);
215         gtk_scale_set_draw_value(GTK_SCALE(w_opacity), FALSE);
216         gtk_range_set_value(GTK_RANGE(w_opacity), cfg->graph_bg_alpha);
217
218         hbox = gtk_hbox_new(FALSE, 0);
219         label = gtk_label_new(NULL);
220         gtk_label_set_markup(GTK_LABEL(label), _("<i>Min</i>"));
221         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
222         gtk_box_pack_start(GTK_BOX(hbox), w_opacity, TRUE, TRUE, 0);
223         label = gtk_label_new(NULL);
224         gtk_label_set_markup(GTK_LABEL(label), _("<i>Max</i>"));
225         gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
226         gtk_table_attach(GTK_TABLE(table),
227                          hbox,
228                          0, 2,
229                          row, row + 1,
230                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 28, 4);
231         row++;
232
233         /* Graph section */
234         ui_pref_add_section_title(table, _("Graph"), row++);
235
236         ui_pref_add_label(table, _("Graph update interval:"), 0, row);
237         pref->w_graph_update_interval
238             = ui_pref_add_spin_button(table,
239                                       cfg->graph_update_interval, 1, 60, row++);
240
241         ui_pref_add_label(table, _("Graph monitoring duration:"), 0, row);
242         pref->w_graph_monitoring_duration
243                 = ui_pref_add_spin_button(table,
244                                           cfg->graph_monitoring_duration,
245                                           1, 24 * 60,   /* 24h */
246                                           row++);
247
248         /* Sensor section */
249         ui_pref_add_section_title(table, _("Sensor"), row++);
250
251         ui_pref_add_label(table, _("Measure update interval:"), 0, row);
252         pref->w_sensor_update_interval
253             = ui_pref_add_spin_button(table,
254                                       cfg->sensor_update_interval,
255                                       1, 60, row++);
256
257         /* Interface section */
258         ui_pref_add_section_title(table, _("Interface"), row++);
259
260         ui_pref_add_label(table, _("Position of sensors table:"), 0, row);
261         pref->w_sensorlist_position = gtk_combo_box_new_text();
262         gtk_combo_box_append_text(GTK_COMBO_BOX(pref->w_sensorlist_position),
263                                   _("Right"));
264         gtk_combo_box_append_text(GTK_COMBO_BOX(pref->w_sensorlist_position),
265                                   _("Left"));
266         gtk_combo_box_append_text(GTK_COMBO_BOX(pref->w_sensorlist_position),
267                                   _("Top"));
268         gtk_combo_box_append_text(GTK_COMBO_BOX(pref->w_sensorlist_position),
269                                   _("Bottom"));
270         gtk_combo_box_set_active(GTK_COMBO_BOX(pref->w_sensorlist_position),
271                                  cfg->sensorlist_position);
272
273         alig = gtk_alignment_new(0, 0.5, 0, 0);
274         gtk_alignment_set_padding(GTK_ALIGNMENT(alig), 4, 4, 4, 4);
275         gtk_container_add(GTK_CONTAINER(alig), pref->w_sensorlist_position);
276         gtk_table_attach(GTK_TABLE(table),
277                          alig,
278                          1, 2,
279                          row, row + 1,
280                          GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
281         row++;
282
283         pref->w_window_decoration_enabled = ui_pref_add_check_button
284                 (table, _("Hide window decoration"),
285                  !cfg->window_decoration_enabled, row++);
286
287         pref->w_window_keep_below_enabled = ui_pref_add_check_button
288                 (table,
289                  _("Keep window below"),
290                  cfg->window_keep_below_enabled, row++);
291
292         pref->widget = table;
293         pref->w_opacity = w_opacity;
294
295         return pref;
296 }
297
298 void ui_pref_dialog_run(struct ui_psensor *ui)
299 {
300         GtkWidget *diag, *content_area;
301         gint result;
302         struct ui_pref *pref;
303         struct config *cfg;
304
305         cfg = ui->config;
306
307         diag = gtk_dialog_new_with_buttons(_("Edit Preferences"),
308                                            GTK_WINDOW(ui->main_window),
309                                            GTK_DIALOG_MODAL |
310                                            GTK_DIALOG_DESTROY_WITH_PARENT,
311                                            GTK_STOCK_OK,
312                                            GTK_RESPONSE_ACCEPT,
313                                            GTK_STOCK_CANCEL,
314                                            GTK_RESPONSE_REJECT, NULL);
315
316         content_area = gtk_dialog_get_content_area(GTK_DIALOG(diag));
317
318         pref = ui_pref_create_main_widget(ui);
319
320         gtk_container_add(GTK_CONTAINER(content_area), pref->widget);
321         gtk_widget_show_all(content_area);
322
323         result = gtk_dialog_run(GTK_DIALOG(diag));
324
325         if (result == GTK_RESPONSE_ACCEPT) {
326                 double value;
327                 GdkColor color;
328
329                 gtk_color_button_get_color
330                     (GTK_COLOR_BUTTON(pref->w_graph_fgcolor), &color);
331                 color_set(cfg->graph_fgcolor,
332                           color.red, color.green, color.blue);
333
334                 gtk_color_button_get_color
335                     (GTK_COLOR_BUTTON(pref->w_graph_bgcolor), &color);
336                 color_set(cfg->graph_bgcolor,
337                           color.red, color.green, color.blue);
338
339                 value = gtk_range_get_value(GTK_RANGE(pref->w_opacity));
340                 cfg->graph_bg_alpha = value;
341
342                 if (value == 1.0)
343                         cfg->alpha_channel_enabled = 0;
344                 else
345                         cfg->alpha_channel_enabled = 1;
346
347                 cfg->sensorlist_position
348                     = gtk_combo_box_get_active
349                     (GTK_COMBO_BOX(pref->w_sensorlist_position));
350
351                 cfg->window_decoration_enabled = !gtk_toggle_button_get_active
352                     GTK_TOGGLE_BUTTON(pref->w_window_decoration_enabled);
353
354                 cfg->window_keep_below_enabled
355                     = gtk_toggle_button_get_active
356                     (GTK_TOGGLE_BUTTON(pref->w_window_keep_below_enabled));
357
358                 gtk_window_set_decorated(GTK_WINDOW(ui->main_window),
359                                          cfg->window_decoration_enabled);
360
361                 gtk_window_set_keep_below(GTK_WINDOW(ui->main_window),
362                                           cfg->window_keep_below_enabled);
363
364                 cfg->sensor_update_interval
365                     = gtk_spin_button_get_value_as_int
366                     (GTK_SPIN_BUTTON(pref->w_sensor_update_interval));
367
368                 cfg->graph_update_interval
369                     = gtk_spin_button_get_value_as_int
370                     (GTK_SPIN_BUTTON(pref->w_graph_update_interval));
371
372                 cfg->graph_monitoring_duration
373                     = gtk_spin_button_get_value_as_int
374                     (GTK_SPIN_BUTTON(pref->w_graph_monitoring_duration));
375
376                 cfg->sensor_values_max_length
377                     =
378                     (cfg->graph_monitoring_duration * 60) /
379                     cfg->sensor_update_interval;
380
381                 ui_main_box_create(ui);
382
383                 config_save(cfg);
384         }
385
386         gtk_widget_destroy(diag);
387
388         free(pref);
389 }