31c2651da9891c4c4255f38976210956328e7af5
[tweakr] / modules / tweakr-mce.c
1 /*
2  * vim:ts=4:sw=4:et:cindent:cino=(0
3  */ 
4
5 #include <config.h>
6 #include <glib/gi18n-lib.h>
7
8 #include <gtk/gtk.h>
9 #include <hildon/hildon-picker-button.h>
10 #include <hildon/hildon-touch-selector.h>
11 #include <hildon/hildon-note.h>
12 #include <hildon/hildon-check-button.h>
13
14 #include "libtweakr-section/tweakr-section.h"
15 #include "libtweakr-section/tweakr-module.h"
16
17
18 #define TWEAKR_TYPE_MCE_SECTION \
19         (tweakr_mce_section_type)
20 #define TWEAKR_MCE_SECTION(obj) \
21         (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
22         TWEAKR_TYPE_MCE_SECTION, \
23         TweakrMceSection))
24 #define TWEAKR_MCE_SECTION_CLASS(k) \
25         (G_TYPE_CHECK_CLASS_CAST((k), \
26         TWEAKR_TYPE_MCE_SECTION, \
27         TweakrMceSectionClass))
28 #define TWEAKR_IS_MCE_SECTION(obj) \
29         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
30         TWEAKR_TYPE_MCE_SECTION))
31
32 #define DISABLE_LABEL _("Do nothing")
33 #define SHOW_MENU_LABEL _("Show menu")
34 #define POWER_OFF_LABEL _("Power off")
35 #define LOCK_LABEL _("Lock device")
36
37 enum {
38     SHORT_POWER_KEY_DISABLED,
39     SHORT_POWER_KEY_MENU,
40     SHORT_POWER_KEY_OFF,
41     SHORT_POWER_KEY_N
42 };
43
44 enum {
45     LONG_POWER_KEY_DISABLED,
46     LONG_POWER_KEY_MENU,
47     LONG_POWER_KEY_OFF,
48     LONG_POWER_KEY_N
49 };
50
51 enum {
52     DOUBLE_POWER_KEY_DISABLED,
53     DOUBLE_POWER_KEY_MENU,
54     DOUBLE_POWER_KEY_OFF,
55     DOUBLE_POWER_KEY_LOCK,
56     DOUBLE_POWER_KEY_N
57 };
58
59
60 typedef struct _picker_t
61 {
62     guint index;
63     const gchar *value;
64     const gchar *label;
65 } picker_t;
66
67 static picker_t spk [SHORT_POWER_KEY_N];
68 static picker_t lpk [LONG_POWER_KEY_N];
69 static picker_t dpk [DOUBLE_POWER_KEY_N];
70
71 typedef struct _TweakrMceSection TweakrMceSection;
72 typedef struct _TweakrMceSectionClass
73                TweakrMceSectionClass;
74
75 struct _TweakrMceSection
76 {
77     TweakrSection parent_instance;
78
79     GKeyFile *ini;
80     GtkWidget *short_power_key;
81     GtkWidget *long_power_key;
82     GtkWidget *double_power_key;
83     GtkWidget *lens_cover;
84
85     guint value_changed : 1;
86 };
87
88 struct _TweakrMceSectionClass
89 {
90     TweakrSectionClass parent_class;
91 };
92
93
94 static GType tweakr_mce_section_get_type (GTypeModule *module);
95 static void tweakr_mce_section_class_init
96     (TweakrMceSectionClass *class);
97 static void tweakr_mce_section_init
98     (TweakrMceSection *section);
99 static void tweakr_mce_section_dispose (GObject *obj);
100
101 static gboolean _save (TweakrSection *section,
102                        gboolean *requires_restart);
103
104 static GType tweakr_mce_section_type = 0;
105 static TweakrSectionClass *
106     tweakr_mce_section_parent_class = NULL;
107
108
109 G_MODULE_EXPORT void
110 tweakr_module_load (TweakrModule *module)
111 {
112     tweakr_mce_section_get_type (G_TYPE_MODULE (module));
113 }
114
115 G_MODULE_EXPORT void
116 tweakr_module_unload (TweakrModule *module)
117 {
118 }
119
120 static GType
121 tweakr_mce_section_get_type (GTypeModule *module)
122 {
123     if (!tweakr_mce_section_type)
124     {
125         static const GTypeInfo section_info =
126         {
127             sizeof (TweakrMceSectionClass),
128             (GBaseInitFunc) NULL,
129             (GBaseFinalizeFunc) NULL,
130             (GClassInitFunc) tweakr_mce_section_class_init,
131             NULL,           /* class_finalize */
132             NULL,           /* class_data     */
133             sizeof (TweakrMceSection),
134             0,              /* n_preallocs    */
135             (GInstanceInitFunc) tweakr_mce_section_init
136         };
137
138         tweakr_mce_section_type =
139             g_type_module_register_type (module, TWEAKR_TYPE_SECTION,
140                                          "TweakrMceSection",
141                                          &section_info, 0);
142     }
143
144     return tweakr_mce_section_type;
145 }
146
147 static void
148 tweakr_mce_section_class_init
149     (TweakrMceSectionClass *klass)
150 {
151     GObjectClass *object_class = G_OBJECT_CLASS (klass);
152     TweakrSectionClass *section_class =
153         TWEAKR_SECTION_CLASS (klass);
154
155     tweakr_mce_section_parent_class =
156         g_type_class_peek_parent (klass);
157
158     section_class->name   = "_Mce";
159     section_class->save = _save;
160
161     object_class->dispose = tweakr_mce_section_dispose;
162 }
163
164 static void _value_changed (HildonPickerButton *b, gpointer user_data)
165 {
166     TweakrMceSection *section = TWEAKR_MCE_SECTION (user_data);
167
168     section->value_changed = TRUE;
169 }
170
171 static void _lens_cover_changed (HildonCheckButton *b, gpointer user_data)
172 {
173     TweakrMceSection *section = TWEAKR_MCE_SECTION (user_data);
174
175     section->value_changed = TRUE;
176 }
177
178 GtkWidget * _build_short_power_key (TweakrMceSection *section)
179 {
180     gint i;
181     GtkWidget *button, *selector;
182
183     spk[0].index = SHORT_POWER_KEY_DISABLED;
184     spk[0].value = "disabled";
185     spk[0].label = DISABLE_LABEL;
186
187     spk[1].index = SHORT_POWER_KEY_MENU;
188     spk[1].value = "menu";
189     spk[1].label = SHOW_MENU_LABEL;
190
191     spk[2].index = SHORT_POWER_KEY_OFF;
192     spk[2].value = "poweroff";
193     spk[2].label = POWER_OFF_LABEL;
194
195     selector = hildon_touch_selector_new_text ();
196     for (i = 0; i < SHORT_POWER_KEY_N; i++)
197     {
198         hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
199                                            spk[i].label);
200     }
201
202     button = hildon_picker_button_new (HILDON_SIZE_AUTO,
203                                        HILDON_BUTTON_ARRANGEMENT_VERTICAL);
204     hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
205
206     hildon_button_set_title (HILDON_BUTTON (button),
207                              _("Power key short press"));
208     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
209     hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
210                                        HILDON_TOUCH_SELECTOR (selector));
211
212     g_signal_connect (G_OBJECT (button), "value-changed",
213                       G_CALLBACK (_value_changed), section);
214
215     gtk_widget_show (button);
216     return button;
217 }
218
219 GtkWidget * _build_long_power_key (TweakrMceSection *section)
220 {
221     gint i;
222     GtkWidget *button, *selector;
223     
224     lpk[0].index = LONG_POWER_KEY_DISABLED;
225     lpk[0].value = "disabled";
226     lpk[0].label = DISABLE_LABEL;
227
228     lpk[1].index = LONG_POWER_KEY_MENU;
229     lpk[1].value = "menu";
230     lpk[1].label = SHOW_MENU_LABEL;
231
232     lpk[2].index = LONG_POWER_KEY_OFF;
233     lpk[2].value = "poweroff";
234     lpk[2].label = POWER_OFF_LABEL;
235
236     selector = hildon_touch_selector_new_text ();
237     for (i = 0; i < LONG_POWER_KEY_N; i++)
238     {
239         hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
240                                            lpk[i].label);
241     }
242
243     button = hildon_picker_button_new (HILDON_SIZE_AUTO,
244                                        HILDON_BUTTON_ARRANGEMENT_VERTICAL);
245     hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
246
247     hildon_button_set_title (HILDON_BUTTON (button),
248                              _("Power key long press"));
249     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
250     hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
251                                        HILDON_TOUCH_SELECTOR (selector));
252
253     g_signal_connect (G_OBJECT (button), "value-changed",
254                       G_CALLBACK (_value_changed), section);
255
256     gtk_widget_show (button);
257     return button;
258 }
259
260 GtkWidget * _build_double_power_key (TweakrMceSection *section)
261 {
262     gint i;
263     GtkWidget *button, *selector;
264
265     dpk[0].index = DOUBLE_POWER_KEY_DISABLED;
266     dpk[0].value = "disabled";
267     dpk[0].label = DISABLE_LABEL;
268
269     dpk[1].index = DOUBLE_POWER_KEY_MENU;
270     dpk[1].value = "menu";
271     dpk[1].label = SHOW_MENU_LABEL;
272
273     dpk[2].index = DOUBLE_POWER_KEY_OFF;
274     dpk[2].value = "poweroff";
275     dpk[2].label = POWER_OFF_LABEL;
276
277     dpk[3].index = DOUBLE_POWER_KEY_LOCK;
278     dpk[3].value = "tklock";
279     dpk[3].label = LOCK_LABEL;
280
281     selector = hildon_touch_selector_new_text ();
282     for (i = 0; i < DOUBLE_POWER_KEY_N; i++)
283     {
284         hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
285                                            dpk[i].label);
286     }
287
288     button = hildon_picker_button_new (HILDON_SIZE_AUTO,
289                                        HILDON_BUTTON_ARRANGEMENT_VERTICAL);
290     hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
291
292     hildon_button_set_title (HILDON_BUTTON (button),
293                              _("Power key long press"));
294     gtk_button_set_alignment (GTK_BUTTON (button), 0.0f, 0.5f);
295     hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
296                                        HILDON_TOUCH_SELECTOR (selector));
297
298     g_signal_connect (G_OBJECT (button), "value-changed",
299                       G_CALLBACK (_value_changed), section);
300
301     gtk_widget_show (button);
302     return button;
303 }
304
305 GtkWidget *_build_lens_cover (TweakrMceSection *section)
306 {
307     GtkWidget *button;
308
309     button = hildon_check_button_new (HILDON_SIZE_AUTO);
310     hildon_gtk_widget_set_theme_size (button, HILDON_SIZE_FINGER_HEIGHT);
311     gtk_button_set_label (GTK_BUTTON (button),
312                           _("Opening camera lens cover unlocks device"));
313
314     g_signal_connect (G_OBJECT (button), "toggled",
315                       G_CALLBACK (_lens_cover_changed), section);
316
317     gtk_widget_show (button);
318     return button;
319 }
320
321 static void
322 tweakr_mce_section_init (TweakrMceSection *section)
323 {
324     TweakrSection *iface;
325     gchar *short_power_key_value;
326     gchar *long_power_key_value;
327     gchar *double_power_key_value;
328     gint i;
329     gboolean lens_cover_value;
330
331     section->short_power_key = _build_short_power_key (section);
332     section->long_power_key = _build_long_power_key (section);
333     section->double_power_key = _build_double_power_key (section);
334     section->lens_cover = _build_lens_cover (section);
335
336     section->ini = g_key_file_new ();
337
338     if (!g_key_file_load_from_file (section->ini, MCE,
339                                     G_KEY_FILE_NONE, NULL))
340     {
341         g_warning ("%s: failed to load %s", G_STRFUNC, MCE);
342         return;
343     }
344
345     short_power_key_value = g_key_file_get_string (section->ini, "PowerKey",
346                                                    "PowerKeyShortAction",
347                                                    NULL);
348     long_power_key_value = g_key_file_get_string (section->ini, "PowerKey",
349                                                   "PowerKeyLongAction",
350                                                   NULL);
351     double_power_key_value = g_key_file_get_string (section->ini, "PowerKey",
352                                                     "PowerKeyDoubleAction",
353                                                     NULL);
354     lens_cover_value = g_key_file_get_boolean (section->ini, "TKLock",
355                                                 "LensCoverUnlock", NULL);
356
357     for (i = 0; i < SHORT_POWER_KEY_N; i++)
358     {
359         if (g_strcmp0 (short_power_key_value, spk[i].value) == 0)
360         {
361             hildon_picker_button_set_active
362                 (HILDON_PICKER_BUTTON (section->short_power_key), i);
363         }
364     }
365
366     for (i = 0; i < LONG_POWER_KEY_N; i++)
367     {
368         if (g_strcmp0 (long_power_key_value, lpk[i].value) == 0)
369         {
370             hildon_picker_button_set_active
371                 (HILDON_PICKER_BUTTON (section->long_power_key), i);
372         }
373     }
374
375     for (i = 0; i < DOUBLE_POWER_KEY_N; i++)
376     {
377         if (g_strcmp0 (double_power_key_value, dpk[i].value) == 0)
378         {
379             hildon_picker_button_set_active
380                 (HILDON_PICKER_BUTTON (section->double_power_key), i);
381         }
382     }
383
384     hildon_check_button_set_active
385         (HILDON_CHECK_BUTTON (section->lens_cover), lens_cover_value);
386
387     section->value_changed = FALSE;
388
389     iface = TWEAKR_SECTION (section);
390     iface->name = _("Hardware keys");
391     iface->widget = gtk_vbox_new (FALSE, 0);
392     gtk_box_pack_start (GTK_BOX (iface->widget), section->short_power_key,
393                         FALSE, FALSE, 0);
394     gtk_box_pack_start (GTK_BOX (iface->widget), section->long_power_key,
395                         FALSE, FALSE, 0);
396     gtk_box_pack_start (GTK_BOX (iface->widget), section->double_power_key,
397                         FALSE, FALSE, 0);
398     gtk_box_pack_start (GTK_BOX (iface->widget), section->lens_cover,
399                         FALSE, FALSE, 0);
400 }
401
402 static void
403 tweakr_mce_section_dispose (GObject *obj)
404 {
405     TweakrMceSection *section = TWEAKR_MCE_SECTION (obj);
406     if (section->ini)
407     {
408         g_key_file_free (section->ini);
409         section->ini = NULL;
410     }
411
412     G_OBJECT_CLASS (tweakr_mce_section_parent_class)->dispose
413         (obj);
414 }
415
416 static gboolean _save (TweakrSection *section,
417                        gboolean *requires_restart)
418 {
419     gchar *argv[6];
420     gint short_active, long_active, double_active;
421     gint i;
422     gboolean lens_cover_value;
423
424     if (!TWEAKR_MCE_SECTION (section)->value_changed)
425         return TRUE;
426
427     short_active = hildon_picker_button_get_active
428         (HILDON_PICKER_BUTTON (TWEAKR_MCE_SECTION
429                                (section)->short_power_key));
430
431     long_active = hildon_picker_button_get_active
432         (HILDON_PICKER_BUTTON (TWEAKR_MCE_SECTION
433                                (section)->long_power_key));
434
435     double_active = hildon_picker_button_get_active
436         (HILDON_PICKER_BUTTON (TWEAKR_MCE_SECTION
437                                (section)->double_power_key));
438
439     lens_cover_value = hildon_check_button_get_active
440         (HILDON_CHECK_BUTTON (TWEAKR_MCE_SECTION (section)->lens_cover));
441
442     if (short_active  == SHORT_POWER_KEY_DISABLED &&
443         long_active   == LONG_POWER_KEY_DISABLED  &&
444         double_active == DOUBLE_POWER_KEY_DISABLED)
445     {
446         GtkWidget *note;
447         gint retcode;
448
449         note = hildon_note_new_confirmation
450             (NULL,
451              _("Setting all Power Key options to \"Do nothing\" means "
452                "that the only way to turn the device off is the removal of "
453                "the battery. Do you want to continue?"));
454         retcode = gtk_dialog_run (GTK_DIALOG (note));
455         gtk_widget_destroy (note);
456
457         if (retcode == GTK_RESPONSE_CANCEL)
458             return FALSE;
459     }
460
461     *requires_restart = TRUE;
462
463     argv[0] = g_strdup ("/usr/bin/tweakr-mce-save");
464     argv[1] = g_strdup_printf ("%s", spk[short_active].value);
465     argv[2] = g_strdup_printf ("%s", lpk[long_active].value);
466     argv[3] = g_strdup_printf ("%s", dpk[double_active].value);
467     argv[4] = g_strdup_printf ("%d", lens_cover_value);
468     argv[5] = NULL;
469
470     g_spawn_sync ("/home/user", argv, NULL,
471                   G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
472                   NULL, NULL, NULL, NULL, NULL, NULL);
473
474     for (i = 0; i < (sizeof (argv) / sizeof (gchar *)) - 1; i++)
475         g_free (argv[i]);
476
477     return TRUE;
478 }
479