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