Revert "Take a different approach to detecting MicroB browser window close"
[browser-switch] / config-ui / browser-switchboard-cp.c
1 /*
2  * browser-switchboard-cp.c -- a hildon-control-panel applet for
3  * selecting the default browser for Browser Switchboard
4  * 
5  * Copyright (C) 2009-2010 Steven Luo
6  * Copyright (C) 2009-2010 Faheem Pervez
7  * 
8  * Derived from services-cp.c from maemo-control-services
9  * Copyright (c) 2008 Janne Kataja <janne.kataja@iki.fi>
10  * Copyright (c) 2008 Nokia Corporation
11  * 
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25  * USA.
26  */
27
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include <gtk/gtk.h>
37
38 #ifdef HILDON
39 #include <hildon/hildon-banner.h>
40 #include <hildon/hildon-program.h>
41
42 #ifdef FREMANTLE
43 #include <hildon/hildon-touch-selector.h>
44 #include <hildon/hildon-picker-button.h>
45 #include <hildon/hildon-caption.h>
46 #include <hildon/hildon-entry.h>
47 #endif /* FREMANTLE */
48
49 #ifdef HILDON_CP_APPLET
50 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
51 #endif /* HILDON_CP_APPLET */
52 #endif /* HILDON */
53
54 #include "configfile.h"
55
56 #define CONTINUOUS_MODE_DEFAULT 0
57
58 #if defined(HILDON) && defined(FREMANTLE)
59 #define _HILDON_SIZE_DEFAULT (HILDON_SIZE_AUTO_WIDTH|HILDON_SIZE_FINGER_HEIGHT)
60 #endif
61
62 struct browser_entry {
63         char *config;
64         char *displayname;
65 };
66 struct browser_entry browsers[] = {
67         { "microb", "MicroB" }, /* First entry is the default! */
68         { "tear", "Tear" },
69         { "fennec", "Mobile Firefox (Fennec)" },
70         { "midori", "Midori" },
71         { "other", "Other" },
72         { NULL, NULL },
73 };
74
75 struct config_widgets {
76 #if defined(HILDON) && defined(FREMANTLE)
77         GtkWidget *continuous_mode_selector;
78         GtkWidget *default_browser_selector;
79 #else
80         GtkWidget *continuous_mode_off_radio;
81         GtkWidget *continuous_mode_on_radio;
82         GtkWidget *default_browser_combo;
83 #endif
84         GtkWidget *other_browser_cmd_entry;
85         GtkWidget *other_browser_cmd_entry_label;
86 };
87 struct config_widgets cw;
88 GtkWidget *dialog;
89
90
91 /**********************************************************************
92  * Configuration routines
93  **********************************************************************/
94
95 #if defined(HILDON) && defined(FREMANTLE)
96
97 static inline int get_continuous_mode(void) {
98         return hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0);
99 }
100 static inline void set_continuous_mode(int state) {
101         hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0, state);
102 }
103
104 static inline char *get_default_browser(void) {
105         return browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
106 }
107
108 #else /* !defined(HILDON) || !defined(FREMANTLE) */
109
110 static inline int get_continuous_mode(void) {
111         return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio));
112 }
113 static inline void set_continuous_mode(int state) {
114         if (state)
115                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio), TRUE);
116         else
117                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_off_radio), TRUE);
118 }
119
120 static inline char *get_default_browser(void) {
121         return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
122 }
123
124 #endif /* defined(HILDON) && defined(FREMANTLE) */
125
126 static void set_default_browser(char *browser) {
127         gint i;
128
129         /* Loop through browsers looking for a match */
130         for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
131                         ++i);
132
133         if (!browsers[i].config)
134                 /* No match found, set to the default browser */
135                 i = 0;
136
137 #if defined(HILDON) && defined(FREMANTLE)
138         hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, i);
139 #else
140         gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), i);
141 #endif
142 }
143
144 static inline char *get_other_browser_cmd(void) {
145         return (char *)gtk_entry_get_text(GTK_ENTRY(cw.other_browser_cmd_entry));
146 }
147 static inline void set_other_browser_cmd(char *cmd) {
148         gtk_entry_set_text(GTK_ENTRY(cw.other_browser_cmd_entry), cmd);
149 }
150
151 static void load_config(void) {
152         FILE *fp;
153         int continuous_mode_seen = 0;
154         int default_browser_seen = 0;
155         int other_browser_cmd_seen = 0;
156         struct swb_config_line line;
157
158         if (!(fp = open_config_file()))
159                 return;
160
161         /* Parse the config file
162            TODO: should we handle errors differently than EOF? */
163         if (!parse_config_file_begin())
164                 goto out;
165         while (!parse_config_file_line(fp, &line)) {
166                 if (line.parsed) {
167                         if (!strcmp(line.key, "continuous_mode")) {
168                                 if (!continuous_mode_seen) {
169                                         set_continuous_mode(atoi(line.value));
170                                         continuous_mode_seen = 1;
171                                 }
172                         } else if (!strcmp(line.key, "default_browser")) {
173                                 if (!default_browser_seen) {
174                                         set_default_browser(line.value);
175                                         default_browser_seen = 1;
176                                 }
177                         } else if (!strcmp(line.key, "other_browser_cmd")) {
178                                 if (!other_browser_cmd_seen) {
179                                         set_other_browser_cmd(line.value);
180                                         other_browser_cmd_seen = 1;
181                                 }
182                         }
183                 }
184                 free(line.key);
185                 free(line.value);
186         }
187         parse_config_file_end();
188
189 out:
190         fclose(fp);
191         return;
192 }
193
194 static void save_config(void) {
195         FILE *fp = NULL, *tmpfp = NULL;
196         char *homedir, *tempfile, *newfile;
197         size_t len;
198         int continuous_mode_seen = 0;
199         int default_browser_seen = 0;
200         int other_browser_cmd_seen = 0;
201         struct swb_config_line line;
202
203         /* If CONFIGFILE_DIR doesn't exist already, try to create it */
204         if (!(homedir = getenv("HOME")))
205                 homedir = DEFAULT_HOMEDIR;
206         len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1;
207         if (!(newfile = calloc(len, sizeof(char))))
208                 return;
209         snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR);
210         if (access(newfile, F_OK) == -1 && errno == ENOENT) {
211                 mkdir(newfile, 0750);
212         }
213         free(newfile);
214
215         /* Put together the path to the new config file and the tempfile */
216         len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1;
217         if (!(newfile = calloc(len, sizeof(char))))
218                 return;
219         /* 4 = strlen(".tmp") */
220         if (!(tempfile = calloc(len+4, sizeof(char)))) {
221                 free(newfile);
222                 return;
223         }
224         snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC);
225         snprintf(tempfile, len+4, "%s%s", newfile, ".tmp");
226
227         /* Open the temporary file for writing */
228         if (!(tmpfp = fopen(tempfile, "w")))
229                 /* TODO: report the error somehow? */
230                 goto out;
231
232         /* Open the old config file, if it exists */
233         if ((fp = open_config_file()) && parse_config_file_begin()) {
234                 /* Copy the old config file over to the new one line by line,
235                    replacing old config values with new ones
236                    TODO: should we handle errors differently than EOF? */
237                 while (!parse_config_file_line(fp, &line)) {
238                         if (line.parsed) {
239                                 /* Is a config line, print the new value here */
240                                 if (!strcmp(line.key, "continuous_mode")) {
241                                         if (!continuous_mode_seen) {
242                                                 fprintf(tmpfp, "%s = %d\n",
243                                                         line.key,
244                                                         get_continuous_mode());
245                                                 continuous_mode_seen = 1;
246                                         }
247                                 } else if (!strcmp(line.key,
248                                                         "default_browser")) {
249                                         if (!default_browser_seen) {
250                                                 fprintf(tmpfp, "%s = \"%s\"\n",
251                                                         line.key,
252                                                         get_default_browser());
253                                                 default_browser_seen = 1;
254                                         }
255                                 } else if (!strcmp(line.key,
256                                                         "other_browser_cmd")) {
257                                         if (!other_browser_cmd_seen &&
258                                             strlen(get_other_browser_cmd())>0) {
259                                                 fprintf(tmpfp, "%s = \"%s\"\n",
260                                                         line.key,
261                                                         get_other_browser_cmd());
262                                                 other_browser_cmd_seen = 1;
263                                         }
264                                 }
265                         } else {
266                                 /* Just copy the old line over */
267                                 fprintf(tmpfp, "%s\n", line.key);
268                         }
269                         free(line.key);
270                         free(line.value);
271                 }
272                 parse_config_file_end();
273         }
274
275         /* If we haven't written them yet, write out the new config values */
276         if (!continuous_mode_seen)
277                 fprintf(tmpfp, "%s = %d\n",
278                         "continuous_mode", get_continuous_mode());
279         if (!default_browser_seen)
280                 fprintf(tmpfp, "%s = \"%s\"\n",
281                         "default_browser", get_default_browser());
282         if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0)
283                 fprintf(tmpfp, "%s = \"%s\"\n",
284                         "other_browser_cmd", get_other_browser_cmd());
285
286         /* Replace the old config file with the new one */
287         fclose(tmpfp);
288         tmpfp = NULL;
289         rename(tempfile, newfile);
290
291 out:
292         free(newfile);
293         free(tempfile);
294         if (tmpfp)
295                 fclose(tmpfp);
296         if (fp)
297                 fclose(fp);
298         return;
299 }
300
301 static void do_reconfig(void) {
302         save_config();
303
304         /* Try to send SIGHUP to any running browser-switchboard process
305            This causes it to reread config files if in continuous_mode, or
306            die so that the config will be reloaded on next start otherwise */
307         system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
308 }
309
310
311 /**********************************************************************
312  * Callbacks
313  **********************************************************************/
314
315 #if defined(HILDON) && defined(FREMANTLE)
316 static void default_browser_selector_callback(GtkWidget *widget,
317                 gint column, gpointer data) {
318 #else
319 static void default_browser_combo_callback(GtkWidget *widget, gpointer data) {
320 #endif
321         if (!strcmp(get_default_browser(), "other")) {
322                 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), TRUE);
323                 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, TRUE);
324                 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, TRUE);
325         } else {
326                 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), FALSE); /* FREMANTLE: give the text the greyed-out look */
327                 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
328                 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
329         }
330 }
331
332
333 /**********************************************************************
334  * Interface
335  **********************************************************************/
336
337 #if defined(HILDON) && defined(FREMANTLE)
338 /*
339  * Fremantle Hildon dialog
340  */
341 static GtkDialog *swb_config_dialog(gpointer cp_window) {
342         GtkWidget *dialog_vbox;
343
344         GtkWidget *default_browser_selector_button;
345         GtkWidget *continuous_mode_selector_button;
346         int i;
347         HildonGtkInputMode input_mode;
348
349         dialog = gtk_dialog_new_with_buttons(
350                 "Browser Switchboard",
351                 GTK_WINDOW(cp_window),
352                 GTK_DIALOG_MODAL,
353                 GTK_STOCK_OK,
354                 GTK_RESPONSE_OK,
355                 GTK_STOCK_CANCEL,
356                 GTK_RESPONSE_CANCEL,
357                 NULL);
358
359         dialog_vbox = GTK_DIALOG(dialog)->vbox;
360
361         /* Config options */
362         cw.default_browser_selector = hildon_touch_selector_new_text();
363         for (i = 0; browsers[i].config; ++i)
364                 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), browsers[i].displayname);
365         hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, 0);
366         default_browser_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
367         hildon_button_set_title(HILDON_BUTTON(default_browser_selector_button),
368                                 "Default browser:");
369         hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(default_browser_selector_button), HILDON_TOUCH_SELECTOR(cw.default_browser_selector));
370         hildon_button_set_alignment(HILDON_BUTTON(default_browser_selector_button),
371                                     0, 0.5, 0, 0);
372         g_signal_connect(G_OBJECT(cw.default_browser_selector), "changed",
373                          G_CALLBACK(default_browser_selector_callback), NULL);
374         gtk_box_pack_start(GTK_BOX(dialog_vbox),
375                            default_browser_selector_button, FALSE, FALSE, 0);
376
377         cw.other_browser_cmd_entry = hildon_entry_new(_HILDON_SIZE_DEFAULT);
378         /* Disable autocapitalization and dictionary features for the entry */
379         input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
380         input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
381                         HILDON_GTK_INPUT_MODE_DICTIONARY);
382         hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
383
384         cw.other_browser_cmd_entry_label = hildon_caption_new(NULL,
385                         "Command (%s for URI):",
386                         cw.other_browser_cmd_entry,
387                         NULL, HILDON_CAPTION_OPTIONAL);
388         gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
389         gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
390         hildon_gtk_widget_set_theme_size(cw.other_browser_cmd_entry_label, _HILDON_SIZE_DEFAULT);
391         gtk_box_pack_start(GTK_BOX(dialog_vbox),
392                            cw.other_browser_cmd_entry_label, FALSE, FALSE, 0);
393
394         cw.continuous_mode_selector = hildon_touch_selector_new_text();
395         hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Lower memory usage");
396         hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Faster browser startup time");
397
398         continuous_mode_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
399         hildon_button_set_title(HILDON_BUTTON(continuous_mode_selector_button),
400                                 "Optimize Browser Switchboard for:");
401         hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(continuous_mode_selector_button), HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector));
402         hildon_button_set_alignment(HILDON_BUTTON(continuous_mode_selector_button),
403                                     0, 0, 0, 0);
404         set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
405         gtk_box_pack_start(GTK_BOX(dialog_vbox),
406                            continuous_mode_selector_button, FALSE, FALSE, 0);
407
408         gtk_widget_show_all(dialog);
409         return GTK_DIALOG(dialog);
410 }
411
412 #else /* !defined(HILDON) || !defined(FREMANTLE) */
413 /*
414  * GTK+/Diablo Hildon dialog
415  */
416 static GtkDialog *swb_config_dialog(gpointer cp_window) {
417         GtkWidget *dialog_vbox;
418
419         GtkWidget *options_table;
420         GtkWidget *default_browser_combo_label;
421         GtkWidget *continuous_mode_label;
422         int i;
423 #ifdef HILDON
424         HildonGtkInputMode input_mode;
425 #endif
426
427         dialog = gtk_dialog_new_with_buttons(
428                 "Browser Switchboard",
429                 GTK_WINDOW(cp_window),
430                 GTK_DIALOG_MODAL,
431                 GTK_STOCK_OK,
432                 GTK_RESPONSE_OK,
433                 GTK_STOCK_CANCEL,
434                 GTK_RESPONSE_CANCEL,
435                 NULL);
436
437         dialog_vbox = GTK_DIALOG(dialog)->vbox;
438
439         /* Config options */
440         options_table = gtk_table_new(3, 2, FALSE);
441         gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
442         gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
443
444         cw.default_browser_combo = gtk_combo_box_new_text();
445         for (i = 0; browsers[i].config; ++i)
446                 gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
447                                           browsers[i].displayname);
448         gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
449         default_browser_combo_label = gtk_label_new("Default browser:");
450         gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
451         g_signal_connect(G_OBJECT(cw.default_browser_combo), "changed",
452                          G_CALLBACK(default_browser_combo_callback), NULL);
453         gtk_table_attach(GTK_TABLE(options_table),
454                         default_browser_combo_label,
455                         0, 1,
456                         0, 1,
457                         GTK_FILL, GTK_FILL|GTK_EXPAND,
458                         5, 0);
459         gtk_table_attach(GTK_TABLE(options_table),
460                         cw.default_browser_combo,
461                         1, 2,
462                         0, 1,
463                         GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
464                         5, 0);
465
466         cw.other_browser_cmd_entry = gtk_entry_new();
467 #ifdef HILDON
468         /* Disable autocapitalization and dictionary features for the entry */
469         input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
470         input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
471                         HILDON_GTK_INPUT_MODE_DICTIONARY);
472         hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
473 #endif
474         cw.other_browser_cmd_entry_label = gtk_label_new("Command (%s for URI):");
475         gtk_misc_set_alignment(GTK_MISC(cw.other_browser_cmd_entry_label), 1, 0.5);
476         gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
477         gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
478         gtk_table_attach(GTK_TABLE(options_table),
479                         cw.other_browser_cmd_entry_label,
480                         0, 1,
481                         1, 2,
482                         GTK_FILL, GTK_FILL|GTK_EXPAND,
483                         5, 0);
484         gtk_table_attach(GTK_TABLE(options_table),
485                         cw.other_browser_cmd_entry,
486                         1, 2,
487                         1, 2,
488                         GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
489                         5, 0);
490         gtk_table_set_row_spacing(GTK_TABLE(options_table), 1, 15);
491
492         continuous_mode_label = gtk_label_new("Optimize Browser Switchboard for:");
493         gtk_misc_set_alignment(GTK_MISC(continuous_mode_label), 0, 0.5);
494         cw.continuous_mode_off_radio = gtk_radio_button_new_with_label(NULL,
495                         "Lower memory usage");
496         cw.continuous_mode_on_radio = gtk_radio_button_new_with_label_from_widget(
497                         GTK_RADIO_BUTTON(cw.continuous_mode_off_radio),
498                         "Faster browser startup time");
499         set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
500         gtk_table_attach(GTK_TABLE(options_table),
501                         continuous_mode_label,
502                         0, 2,
503                         2, 3,
504                         GTK_FILL, GTK_FILL|GTK_EXPAND,
505                         5, 0);
506         gtk_table_attach(GTK_TABLE(options_table),
507                         cw.continuous_mode_off_radio,
508                         0, 2,
509                         3, 4,
510                         GTK_FILL, GTK_FILL|GTK_EXPAND,
511                         20, 0);
512         gtk_table_attach(GTK_TABLE(options_table),
513                         cw.continuous_mode_on_radio,
514                         0, 2,
515                         4, 5,
516                         GTK_FILL, GTK_FILL|GTK_EXPAND,
517                         20, 5);
518         gtk_table_set_row_spacing(GTK_TABLE(options_table), 3, 0);
519
520
521         gtk_widget_show_all(dialog);
522         return GTK_DIALOG(dialog);
523 }
524
525 #endif /* defined(HILDON) && defined(FREMANTLE) */
526
527
528 /**********************************************************************
529  * Entry
530  **********************************************************************/
531
532 #ifdef HILDON_CP_APPLET
533 /*
534  * Application was started from control panel.
535  */
536 osso_return_t execute(osso_context_t *osso,
537                       gpointer userdata, gboolean user_activated) {
538         GtkDialog *dialog;
539         gint response;
540
541         if (osso == NULL)
542                 return OSSO_ERROR;
543
544         dialog = GTK_DIALOG(swb_config_dialog(userdata));
545         load_config();
546
547         response = gtk_dialog_run(dialog);
548         if (response == GTK_RESPONSE_OK)
549                 do_reconfig();
550
551         gtk_widget_destroy(GTK_WIDGET(dialog));
552
553         return OSSO_OK;
554 }
555 #else
556 /*
557  * Application was started from command line.
558  */
559 int main(int argc, char *argv[]) {
560         GtkDialog *dialog;
561         gint response;
562 #ifdef HILDON
563         HildonProgram *program = NULL;
564 #endif
565
566         gtk_init(&argc, &argv);
567 #ifdef HILDON
568         program = HILDON_PROGRAM(hildon_program_get_instance());
569 #endif
570
571         g_set_application_name("Browser Switchboard");
572
573         dialog = GTK_DIALOG(swb_config_dialog(NULL));
574         load_config();
575
576         response = gtk_dialog_run(dialog);
577         if (response == GTK_RESPONSE_OK)
578                 do_reconfig();
579
580         gtk_widget_destroy(GTK_WIDGET(dialog));
581
582         exit(0);
583 }
584 #endif /* HILDON_CP_APPLET */