Fixed bug 6755: First application is forcefully checked to the applications-list...
[cl-launcher] / src / cl-cpapplet.c
1 /*
2  *  Camera Launcher for Maemo.
3  *  Copyright (C) 2010 Roman Moravcik
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25
26 #include <glib.h>
27 #include <glib/gi18n-lib.h>
28
29 #include <gtk/gtk.h>
30 #include <hildon/hildon.h>
31 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
32
33 #include <gconf/gconf-client.h>
34
35 #include "cl-utils.h"
36
37 #define _HL(str) dgettext("hildon-libs",str)
38
39 typedef struct {
40         int index;
41         const char *text;
42 } Action;
43
44 static Action actions[] = {
45         {CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION,   N_("Automatically run prefered application")},
46         {CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP,        N_("Show application selector pop-up window")},
47         {CL_LAUNCHER_ACTION_DO_NOTHING,                 N_("Do nothing")}
48 };
49
50 typedef struct _CLLauncherAppletData CLLauncherAppletData;
51 struct _CLLauncherAppletData {
52         GtkWidget *action;
53         GtkWidget *prefered_application;
54         GtkWidget *application_list;
55
56
57         GConfClient *gconf_client;
58 };
59
60 static gboolean
61 gconf_get_bool (GConfClient *client,
62                 const gchar *key)
63 {
64         gboolean value = FALSE;
65         gchar *tmp = NULL;
66
67         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
68
69         value = gconf_client_get_bool (client, tmp, NULL);
70
71         if (tmp)
72                 g_free (tmp);
73
74         return value;
75 }
76
77 static void
78 gconf_set_bool (GConfClient *client,
79                 const gchar *key,
80                 gboolean value)
81 {
82         gchar *tmp = NULL;
83
84         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
85
86         gconf_client_set_bool (client, tmp, value, NULL);
87
88         if (tmp)
89                 g_free (tmp);
90 }
91
92 static gint
93 gconf_get_int (GConfClient *client,
94                 const gchar *key)
95 {
96         gint value = 0;
97         gchar *tmp = NULL;
98
99         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
100
101         value = gconf_client_get_int (client, tmp, NULL);
102
103         if (tmp)
104                 g_free (tmp);
105
106         return value;
107 }
108
109 static void
110 gconf_set_int (GConfClient *client,
111                 const gchar *key,
112                 gint value)
113 {
114         gchar *tmp = NULL;
115
116         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
117
118         gconf_client_set_int (client, tmp, value, NULL);
119
120         if (tmp)
121                 g_free (tmp);
122 }
123
124 static gchar *
125 gconf_get_string (GConfClient *client,
126                   gchar *key)
127 {
128         gchar *value = NULL;
129         gchar *tmp = NULL;
130
131         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
132
133         value = gconf_client_get_string (client, tmp, NULL);
134
135         if (tmp)
136                 g_free (tmp);
137
138         return value;
139 }
140
141 static void
142 gconf_set_string (GConfClient *client,
143                 gchar *key,
144                 const gchar *value)
145 {
146         gchar *tmp = NULL;
147
148         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
149
150         if (value)
151                 gconf_client_set_string (client, tmp, value, NULL);
152         else
153                 gconf_client_unset (client, tmp, NULL);
154
155         if (tmp)
156                 g_free (tmp);
157 }
158
159 static GSList *
160 gconf_get_string_list (GConfClient *client,
161                   gchar *key)
162 {
163         GSList *value = NULL;
164         gchar *tmp = NULL;
165
166         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
167
168         value = gconf_client_get_list (client, tmp, GCONF_VALUE_STRING, NULL);
169
170         if (tmp)
171                 g_free (tmp);
172
173         return value;
174 }
175
176 static void
177 gconf_set_string_list (GConfClient *client,
178                 gchar *key,
179                 GSList *value)
180 {
181         gchar *tmp = NULL;
182
183         tmp = g_strdup_printf ("%s/%s", GCONF_CL_LAUNCHER, key);
184
185         if (value)
186                 gconf_client_set_list (client, tmp, GCONF_VALUE_STRING, value, NULL);
187         else
188                 gconf_client_unset (client, tmp, NULL);
189
190         if (tmp)
191                 g_free (tmp);
192 }
193
194 static GtkWidget *
195 create_action_selector (CLLauncherAppletData *data)
196 {
197         GtkWidget *button, *selector;
198         CLLauncherAction action;
199         gint index = 0;
200
201         g_return_val_if_fail (data, NULL);
202
203         button = hildon_picker_button_new (HILDON_SIZE_FINGER_HEIGHT,
204                                            HILDON_BUTTON_ARRANGEMENT_VERTICAL);
205         hildon_button_set_title (HILDON_BUTTON (button), _("Opening of lens cover will"));
206         hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 0.0);
207         hildon_button_set_title_alignment (HILDON_BUTTON(button), 0.0, 0.5);
208         hildon_button_set_value_alignment (HILDON_BUTTON (button), 0.0, 0.5);
209
210         selector = hildon_touch_selector_new_text ();
211         while (index < CL_LAUNCHER_ACTION_LAST) {
212                 hildon_touch_selector_insert_text (HILDON_TOUCH_SELECTOR (selector),
213                                                    actions[index].index,
214                                                    _(actions[index].text));
215                 index++;
216         }
217
218         hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
219                                            HILDON_TOUCH_SELECTOR (selector));
220
221         return button;
222 }
223
224 static GtkWidget *
225 create_prefered_application_selector (CLLauncherAppletData *data)
226 {
227         GtkWidget *button, *selector;
228         GtkCellRenderer *renderer;
229         HildonTouchSelectorColumn *column;
230         GtkListStore *application_list;
231         gint index = 0;
232
233         g_return_val_if_fail (data, NULL);
234
235         button = hildon_picker_button_new (HILDON_SIZE_FINGER_HEIGHT,
236                                            HILDON_BUTTON_ARRANGEMENT_VERTICAL);
237         hildon_button_set_title (HILDON_BUTTON (button), _("Prefered application"));
238         hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 0.0);
239         hildon_button_set_title_alignment (HILDON_BUTTON(button), 0.0, 0.5);
240         hildon_button_set_value_alignment (HILDON_BUTTON (button), 0.0, 0.5);
241
242         application_list = gtk_list_store_new (NUM_COLS,
243                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_FILENAME */
244                                                GDK_TYPE_PIXBUF, /* SELECTOR_COLUMN_ICON */
245                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_NAME */
246                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_OSSO_SERVICE */
247                                                G_TYPE_STRING);  /* SELECTOR_COLUMN_EXEC */
248         get_application_list (application_list);
249
250         /* sort list of applications */
251         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (application_list),
252                                               SELECTOR_COLUMN_NAME, GTK_SORT_ASCENDING);
253
254         /* create selector */
255         selector = hildon_touch_selector_new ();
256
257         renderer = gtk_cell_renderer_text_new ();
258         column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
259                                                      GTK_TREE_MODEL (application_list),
260                                                      renderer,
261                                                      "text", SELECTOR_COLUMN_NAME,
262                                                      NULL);
263         hildon_touch_selector_column_set_text_column (column, SELECTOR_COLUMN_NAME);
264
265         g_object_unref (application_list);
266
267         hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
268                                            HILDON_TOUCH_SELECTOR (selector));
269
270         return button;
271 }
272
273 static GtkWidget *
274 create_application_list_selector (CLLauncherAppletData *data)
275 {
276         GtkWidget *button, *selector;
277         GtkCellRenderer *renderer;
278         HildonTouchSelectorColumn *column;
279         GtkListStore *application_list;
280         gint index = 0;
281
282         g_return_val_if_fail (data, NULL);
283
284         button = hildon_picker_button_new (HILDON_SIZE_FINGER_HEIGHT,
285                                            HILDON_BUTTON_ARRANGEMENT_VERTICAL);
286         hildon_button_set_title (HILDON_BUTTON (button), _("Application selector pop-up window"));
287         hildon_button_set_alignment (HILDON_BUTTON (button), 0.0, 0.5, 1.0, 0.0);
288         hildon_button_set_title_alignment (HILDON_BUTTON(button), 0.0, 0.5);
289         hildon_button_set_value_alignment (HILDON_BUTTON (button), 0.0, 0.5);
290
291         application_list = gtk_list_store_new (NUM_COLS,
292                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_FILENAME */
293                                                GDK_TYPE_PIXBUF, /* SELECTOR_COLUMN_ICON */
294                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_NAME */
295                                                G_TYPE_STRING,   /* SELECTOR_COLUMN_OSSO_SERVICE */
296                                                G_TYPE_STRING);  /* SELECTOR_COLUMN_EXEC */
297         get_application_list (application_list);
298
299         /* sort list of applications */
300         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (application_list),
301                                               SELECTOR_COLUMN_NAME, GTK_SORT_ASCENDING);
302
303         /* create selector */
304         selector = hildon_touch_selector_new ();
305
306         renderer = gtk_cell_renderer_text_new ();
307         column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
308                                                      GTK_TREE_MODEL (application_list),
309                                                      renderer,
310                                                      "text", SELECTOR_COLUMN_NAME,
311                                                      NULL);
312         hildon_touch_selector_column_set_text_column (column, SELECTOR_COLUMN_NAME);
313         hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
314                                                          HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE);
315
316         g_object_unref (application_list);
317
318         hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
319                                            HILDON_TOUCH_SELECTOR (selector));
320
321         return button;
322 }
323
324 static void
325 load_configuration (CLLauncherAppletData *data)
326 {
327         HildonTouchSelector *selector;
328         CLLauncherAction action;
329         gchar *prefered_application = NULL;
330         GSList *application_list = NULL, *entry = NULL;
331         GtkTreeModel *tree_model;
332         GtkTreeIter iter;
333         gboolean iter_valid = TRUE;
334
335         g_return_if_fail (data);
336
337         /* read action from gconf */
338         action = gconf_get_int (data->gconf_client, "action");
339
340         if ((action < CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION) ||
341             (action > CL_LAUNCHER_ACTION_DO_NOTHING))
342                 action = CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION;
343
344         hildon_picker_button_set_active (HILDON_PICKER_BUTTON (data->action),
345                                          action);
346
347         /* read prefered application from gconf */
348         prefered_application = gconf_get_string (data->gconf_client, "prefered_application");
349         if (prefered_application == NULL)
350                 prefered_application = g_strdup (CAMERA_APPLICATION_DESKTOP_FILE);
351
352         selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (data->prefered_application));
353         tree_model = hildon_touch_selector_get_model (selector, SELECTOR_COLUMN_NAME);
354         for (iter_valid = gtk_tree_model_get_iter_first (tree_model, &iter); iter_valid;
355              iter_valid = gtk_tree_model_iter_next (tree_model, &iter)) {
356                 const gchar *filename;
357
358                 gtk_tree_model_get (tree_model, &iter, SELECTOR_COLUMN_FILENAME, &filename, -1);
359                 if (!strcmp (prefered_application, filename)) {
360                         hildon_touch_selector_select_iter(selector, SELECTOR_COLUMN_NAME, &iter, FALSE);
361                         break;
362                 }
363         }
364
365         /* read aplication list from gconf */
366         application_list = gconf_get_string_list (data->gconf_client, "application_list");
367         if (application_list == NULL) {
368                 application_list = g_slist_append (application_list, g_strdup (CAMERA_APPLICATION_DESKTOP_FILE));
369                 application_list = g_slist_append (application_list, g_strdup (FLASHLIGHT_APPLET_DESKTOP_FILE));
370         }
371
372         selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (data->application_list));
373         tree_model = hildon_touch_selector_get_model (selector, SELECTOR_COLUMN_NAME);
374         hildon_touch_selector_unselect_all(selector, SELECTOR_COLUMN_NAME);
375         for (entry = application_list; entry; entry = entry->next) {
376                 for (iter_valid = gtk_tree_model_get_iter_first (tree_model, &iter); iter_valid;
377                      iter_valid = gtk_tree_model_iter_next (tree_model, &iter)) {
378                         const gchar *filename;
379
380                         gtk_tree_model_get (tree_model, &iter, SELECTOR_COLUMN_FILENAME, &filename, -1);
381                         if (!strcmp (entry->data, filename)) {
382                                 hildon_touch_selector_select_iter(selector, SELECTOR_COLUMN_NAME, &iter, FALSE);
383                                 break;
384                         }
385                 }
386         }
387
388         /* free prefered application */
389         if (prefered_application)
390                 g_free (prefered_application);
391
392         /* free list of applications */
393         if (application_list) {
394                 g_slist_foreach (application_list, (GFunc) g_free, NULL);
395                 g_slist_free (application_list);
396         }
397 }
398
399 static void
400 save_configuration (CLLauncherAppletData *data)
401 {
402         HildonTouchSelector *selector;
403         CLLauncherAction action;
404         gchar *prefered_application = NULL;
405         GSList *application_list = NULL;
406         GList *selected_rows = NULL, *entry = NULL;
407         GtkTreeIter iter;
408
409         g_return_if_fail (data);
410
411         /* action */
412         action = hildon_picker_button_get_active (HILDON_PICKER_BUTTON (data->action));
413
414         /* if nothing was selected, set action to CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION */
415         if (action == -1)
416                 action = CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION;
417
418         /* prefered application */
419         if (hildon_picker_button_get_active (HILDON_PICKER_BUTTON (data->prefered_application)) > -1) {
420                 selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (data->prefered_application));
421                 if (hildon_touch_selector_get_selected (selector, SELECTOR_COLUMN_NAME, &iter)) {
422                         gtk_tree_model_get (hildon_touch_selector_get_model (selector, SELECTOR_COLUMN_NAME),
423                                             &iter, SELECTOR_COLUMN_FILENAME, &prefered_application, -1);
424                 }
425         }
426
427         /* if nothing was selected, set prefered application to CAMERA_APPLICATION_DESKTOP_FILE */
428         if (prefered_application == NULL)
429                 prefered_application = g_strdup (CAMERA_APPLICATION_DESKTOP_FILE);
430
431         /* application list */
432         selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (data->application_list));
433         selected_rows = hildon_touch_selector_get_selected_rows (selector, SELECTOR_COLUMN_NAME);
434         if (selected_rows) {
435                 for (entry = selected_rows; entry; entry = entry->next) {
436                         const gchar *filename;
437
438                         gtk_tree_model_get_iter (hildon_touch_selector_get_model (selector, SELECTOR_COLUMN_NAME),
439                                                  &iter, (GtkTreePath *) (entry->data));
440
441                         gtk_tree_model_get (hildon_touch_selector_get_model (selector, SELECTOR_COLUMN_NAME),
442                                             &iter, SELECTOR_COLUMN_FILENAME, &filename, -1);
443
444                         application_list = g_slist_append (application_list, g_strdup (filename));
445                 }
446                 g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
447                 g_list_free (selected_rows);
448         }
449
450         gconf_set_int (data->gconf_client, "action", action);
451         gconf_set_string (data->gconf_client, "prefered_application", prefered_application);
452         gconf_set_string_list (data->gconf_client, "application_list", application_list);
453
454         /* free prefered application */
455         if (prefered_application)
456                 g_free (prefered_application);
457
458         /* free list of applications */
459         if (application_list) {
460                 g_slist_foreach (application_list, (GFunc) g_free, NULL);
461                 g_slist_free (application_list);
462         }
463 }
464
465 osso_return_t
466 execute (osso_context_t *osso,
467          gpointer data,
468          gboolean user_activated)
469 {
470         CLLauncherAppletData *priv;
471         GtkWidget *dialog, *vbox;
472
473         /* allocate cllauncherappletdata */
474         priv = g_new0 (CLLauncherAppletData, 1);
475
476         /* initialize gconf */
477         priv->gconf_client = gconf_client_get_default ();
478         if (priv->gconf_client == NULL) {
479                 return OSSO_ERROR;
480         }
481
482         /* main dialog */
483         dialog = gtk_dialog_new ();
484         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
485         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data));
486         gtk_window_set_title (GTK_WINDOW (dialog), _("Camera Lens Launcher"));
487         gtk_dialog_add_button(GTK_DIALOG (dialog), _HL("wdgt_bd_save"), GTK_RESPONSE_ACCEPT);
488
489         vbox = gtk_vbox_new (FALSE, 0);
490         gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox);
491
492         /* action selector button */
493         priv->action = create_action_selector (priv);
494         gtk_box_pack_start (GTK_BOX (vbox), priv->action, TRUE, TRUE, 0);
495
496         /* prefered application selector */
497         priv->prefered_application = create_prefered_application_selector (priv);
498         gtk_box_pack_start (GTK_BOX (vbox), priv->prefered_application, TRUE, TRUE, 0);
499
500         /* application list selector */
501         priv->application_list = create_application_list_selector (priv);
502         gtk_box_pack_start (GTK_BOX (vbox), priv->application_list, TRUE, TRUE, 0);
503
504         /* load configuration */
505         load_configuration (priv);
506
507         /* Run the dialog */
508         gtk_widget_show_all (GTK_WIDGET (dialog));
509         if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
510                 /* save configuration */
511                 save_configuration (priv);
512         }
513         gtk_widget_destroy (GTK_WIDGET (dialog));
514
515         /* free cllauncherdata */
516         if (priv) {
517                 g_free (priv);
518         }
519
520         return OSSO_OK;
521 }
522
523 osso_return_t
524 save_state (osso_context_t *osso,
525             gpointer data)
526 {
527         return OSSO_OK;
528 }
529