2 * browser-switchboard-cp.c -- a hildon-control-panel applet for
3 * selecting the default browser for Browser Switchboard
5 * Copyright (C) 2009-2010 Steven Luo
6 * Copyright (C) 2009-2010 Faheem Pervez
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
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)
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.
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,
35 #include <glib/gstdio.h>
39 #include <hildon/hildon-banner.h>
40 #include <hildon/hildon-program.h>
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 */
49 #ifdef HILDON_CP_APPLET
50 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
51 #endif /* HILDON_CP_APPLET */
54 #include "configfile.h"
56 #define CONTINUOUS_MODE_DEFAULT 0
58 #if defined(HILDON) && defined(FREMANTLE)
59 #define _HILDON_SIZE_DEFAULT (HILDON_SIZE_AUTO_WIDTH|HILDON_SIZE_FINGER_HEIGHT)
62 struct browser_entry {
66 struct browser_entry browsers[] = {
67 { "microb", "MicroB" }, /* First entry is the default! */
69 { "fennec", "Mobile Firefox (Fennec)" },
70 { "opera", "Opera Mobile" },
71 { "midori", "Midori" },
76 char *logger_name = NULL;
78 struct config_widgets {
79 #if defined(HILDON) && defined(FREMANTLE)
80 GtkWidget *continuous_mode_selector;
81 GtkWidget *default_browser_selector;
83 GtkWidget *continuous_mode_off_radio;
84 GtkWidget *continuous_mode_on_radio;
85 GtkWidget *default_browser_combo;
87 GtkWidget *other_browser_cmd_entry;
88 GtkWidget *other_browser_cmd_entry_label;
90 struct config_widgets cw;
94 /**********************************************************************
95 * Configuration routines
96 **********************************************************************/
98 #if defined(HILDON) && defined(FREMANTLE)
100 static inline int get_continuous_mode(void) {
101 return hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0);
103 static inline void set_continuous_mode(int state) {
104 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0, state);
107 static inline char *get_default_browser(void) {
108 return browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
111 #else /* !defined(HILDON) || !defined(FREMANTLE) */
113 static inline int get_continuous_mode(void) {
114 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio));
116 static inline void set_continuous_mode(int state) {
118 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio), TRUE);
120 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_off_radio), TRUE);
123 static inline char *get_default_browser(void) {
124 return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
127 #endif /* defined(HILDON) && defined(FREMANTLE) */
129 static void set_default_browser(char *browser) {
132 /* Loop through browsers looking for a match */
133 for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
136 if (!browsers[i].config)
137 /* No match found, set to the default browser */
140 #if defined(HILDON) && defined(FREMANTLE)
141 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, i);
143 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), i);
147 static inline char *get_other_browser_cmd(void) {
148 return (char *)gtk_entry_get_text(GTK_ENTRY(cw.other_browser_cmd_entry));
150 static inline void set_other_browser_cmd(char *cmd) {
151 gtk_entry_set_text(GTK_ENTRY(cw.other_browser_cmd_entry), cmd);
154 static void load_config(void) {
156 int continuous_mode_seen = 0;
157 int default_browser_seen = 0;
158 int other_browser_cmd_seen = 0;
159 struct swb_config_line line;
161 if (!(fp = open_config_file()))
164 /* Parse the config file
165 TODO: should we handle errors differently than EOF? */
166 if (!parse_config_file_begin())
168 while (!parse_config_file_line(fp, &line)) {
170 if (!strcmp(line.key, "continuous_mode")) {
171 if (!continuous_mode_seen) {
172 set_continuous_mode(atoi(line.value));
173 continuous_mode_seen = 1;
176 } else if (!strcmp(line.key, "default_browser")) {
177 if (!default_browser_seen) {
178 set_default_browser(line.value);
179 default_browser_seen = 1;
182 } else if (!strcmp(line.key, "other_browser_cmd")) {
183 if (!other_browser_cmd_seen) {
184 set_other_browser_cmd(line.value);
185 other_browser_cmd_seen = 1;
188 } else if (!strcmp(line.key, "logging")) {
190 logger_name = line.value;
195 parse_config_file_end();
202 static void save_config(void) {
203 FILE *fp = NULL, *tmpfp = NULL;
204 char *homedir, *tempfile, *newfile;
206 int continuous_mode_seen = 0;
207 int default_browser_seen = 0;
208 int other_browser_cmd_seen = 0;
209 struct swb_config_line line;
211 /* If CONFIGFILE_DIR doesn't exist already, try to create it */
212 if (!(homedir = getenv("HOME")))
213 homedir = DEFAULT_HOMEDIR;
214 len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1;
215 if (!(newfile = calloc(len, sizeof(char))))
217 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR);
218 if (access(newfile, F_OK) == -1 && errno == ENOENT) {
219 mkdir(newfile, 0750);
223 /* Put together the path to the new config file and the tempfile */
224 len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1;
225 if (!(newfile = calloc(len, sizeof(char))))
227 /* 4 = strlen(".tmp") */
228 if (!(tempfile = calloc(len+4, sizeof(char)))) {
232 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC);
233 snprintf(tempfile, len+4, "%s%s", newfile, ".tmp");
235 /* Open the temporary file for writing */
236 if (!(tmpfp = fopen(tempfile, "w")))
237 /* TODO: report the error somehow? */
240 /* Open the old config file, if it exists */
241 if ((fp = open_config_file()) && parse_config_file_begin()) {
242 /* Copy the old config file over to the new one line by line,
243 replacing old config values with new ones
244 TODO: should we handle errors differently than EOF? */
245 while (!parse_config_file_line(fp, &line)) {
247 /* Is a config line, print the new value here */
248 if (!strcmp(line.key, "continuous_mode")) {
249 if (!continuous_mode_seen) {
250 fprintf(tmpfp, "%s = %d\n",
252 get_continuous_mode());
253 continuous_mode_seen = 1;
255 } else if (!strcmp(line.key,
256 "default_browser")) {
257 if (!default_browser_seen) {
258 fprintf(tmpfp, "%s = \"%s\"\n",
260 get_default_browser());
261 default_browser_seen = 1;
263 } else if (!strcmp(line.key,
264 "other_browser_cmd")) {
265 if (!other_browser_cmd_seen &&
266 strlen(get_other_browser_cmd())>0) {
267 fprintf(tmpfp, "%s = \"%s\"\n",
269 get_other_browser_cmd());
270 other_browser_cmd_seen = 1;
272 } else if (!strcmp(line.key,
275 fprintf(tmpfp, "%s = \"%s\"\n",
283 /* Just copy the old line over */
284 fprintf(tmpfp, "%s\n", line.key);
289 parse_config_file_end();
292 /* If we haven't written them yet, write out the new config values */
293 if (!continuous_mode_seen)
294 fprintf(tmpfp, "%s = %d\n",
295 "continuous_mode", get_continuous_mode());
296 if (!default_browser_seen)
297 fprintf(tmpfp, "%s = \"%s\"\n",
298 "default_browser", get_default_browser());
299 if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0)
300 fprintf(tmpfp, "%s = \"%s\"\n",
301 "other_browser_cmd", get_other_browser_cmd());
303 fprintf(tmpfp, "%s = \"%s\"\n",
304 "logging", logger_name);
306 /* Replace the old config file with the new one */
309 rename(tempfile, newfile);
321 static void do_reconfig(void) {
324 /* Try to send SIGHUP to any running browser-switchboard process
325 This causes it to reread config files if in continuous_mode, or
326 die so that the config will be reloaded on next start otherwise */
327 system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
331 /**********************************************************************
333 **********************************************************************/
335 #if defined(HILDON) && defined(FREMANTLE)
336 static void default_browser_selector_callback(GtkWidget *widget,
337 gint column, gpointer data) {
339 static void default_browser_combo_callback(GtkWidget *widget, gpointer data) {
341 if (!strcmp(get_default_browser(), "other")) {
342 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), TRUE);
343 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, TRUE);
344 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, TRUE);
346 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), FALSE); /* FREMANTLE: give the text the greyed-out look */
347 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
348 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
353 /**********************************************************************
355 **********************************************************************/
357 #if defined(HILDON) && defined(FREMANTLE)
359 * Fremantle Hildon dialog
361 static GtkDialog *swb_config_dialog(gpointer cp_window) {
362 GtkWidget *dialog_vbox;
364 GtkWidget *default_browser_selector_button;
365 GtkWidget *continuous_mode_selector_button;
367 HildonGtkInputMode input_mode;
369 dialog = gtk_dialog_new_with_buttons(
370 "Browser Switchboard",
371 GTK_WINDOW(cp_window),
379 dialog_vbox = GTK_DIALOG(dialog)->vbox;
382 cw.default_browser_selector = hildon_touch_selector_new_text();
383 for (i = 0; browsers[i].config; ++i)
384 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), browsers[i].displayname);
385 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, 0);
386 default_browser_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
387 hildon_button_set_title(HILDON_BUTTON(default_browser_selector_button),
389 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(default_browser_selector_button), HILDON_TOUCH_SELECTOR(cw.default_browser_selector));
390 hildon_button_set_alignment(HILDON_BUTTON(default_browser_selector_button),
392 g_signal_connect(G_OBJECT(cw.default_browser_selector), "changed",
393 G_CALLBACK(default_browser_selector_callback), NULL);
394 gtk_box_pack_start(GTK_BOX(dialog_vbox),
395 default_browser_selector_button, FALSE, FALSE, 0);
397 cw.other_browser_cmd_entry = hildon_entry_new(_HILDON_SIZE_DEFAULT);
398 /* Disable autocapitalization and dictionary features for the entry */
399 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
400 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
401 HILDON_GTK_INPUT_MODE_DICTIONARY);
402 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
404 cw.other_browser_cmd_entry_label = hildon_caption_new(NULL,
405 "Command (%s for URI):",
406 cw.other_browser_cmd_entry,
407 NULL, HILDON_CAPTION_OPTIONAL);
408 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
409 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
410 hildon_gtk_widget_set_theme_size(cw.other_browser_cmd_entry_label, _HILDON_SIZE_DEFAULT);
411 gtk_box_pack_start(GTK_BOX(dialog_vbox),
412 cw.other_browser_cmd_entry_label, FALSE, FALSE, 0);
414 cw.continuous_mode_selector = hildon_touch_selector_new_text();
415 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Lower memory usage");
416 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Faster browser startup time");
418 continuous_mode_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
419 hildon_button_set_title(HILDON_BUTTON(continuous_mode_selector_button),
420 "Optimize Browser Switchboard for:");
421 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(continuous_mode_selector_button), HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector));
422 hildon_button_set_alignment(HILDON_BUTTON(continuous_mode_selector_button),
424 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
425 gtk_box_pack_start(GTK_BOX(dialog_vbox),
426 continuous_mode_selector_button, FALSE, FALSE, 0);
428 gtk_widget_show_all(dialog);
429 return GTK_DIALOG(dialog);
432 #else /* !defined(HILDON) || !defined(FREMANTLE) */
434 * GTK+/Diablo Hildon dialog
436 static GtkDialog *swb_config_dialog(gpointer cp_window) {
437 GtkWidget *dialog_vbox;
439 GtkWidget *options_table;
440 GtkWidget *default_browser_combo_label;
441 GtkWidget *continuous_mode_label;
444 HildonGtkInputMode input_mode;
447 dialog = gtk_dialog_new_with_buttons(
448 "Browser Switchboard",
449 GTK_WINDOW(cp_window),
457 dialog_vbox = GTK_DIALOG(dialog)->vbox;
460 options_table = gtk_table_new(3, 2, FALSE);
461 gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
462 gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
464 cw.default_browser_combo = gtk_combo_box_new_text();
465 for (i = 0; browsers[i].config; ++i)
466 gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
467 browsers[i].displayname);
468 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
469 default_browser_combo_label = gtk_label_new("Default browser:");
470 gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
471 g_signal_connect(G_OBJECT(cw.default_browser_combo), "changed",
472 G_CALLBACK(default_browser_combo_callback), NULL);
473 gtk_table_attach(GTK_TABLE(options_table),
474 default_browser_combo_label,
477 GTK_FILL, GTK_FILL|GTK_EXPAND,
479 gtk_table_attach(GTK_TABLE(options_table),
480 cw.default_browser_combo,
483 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
486 cw.other_browser_cmd_entry = gtk_entry_new();
488 /* Disable autocapitalization and dictionary features for the entry */
489 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
490 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
491 HILDON_GTK_INPUT_MODE_DICTIONARY);
492 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
494 cw.other_browser_cmd_entry_label = gtk_label_new("Command (%s for URI):");
495 gtk_misc_set_alignment(GTK_MISC(cw.other_browser_cmd_entry_label), 1, 0.5);
496 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
497 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
498 gtk_table_attach(GTK_TABLE(options_table),
499 cw.other_browser_cmd_entry_label,
502 GTK_FILL, GTK_FILL|GTK_EXPAND,
504 gtk_table_attach(GTK_TABLE(options_table),
505 cw.other_browser_cmd_entry,
508 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
510 gtk_table_set_row_spacing(GTK_TABLE(options_table), 1, 15);
512 continuous_mode_label = gtk_label_new("Optimize Browser Switchboard for:");
513 gtk_misc_set_alignment(GTK_MISC(continuous_mode_label), 0, 0.5);
514 cw.continuous_mode_off_radio = gtk_radio_button_new_with_label(NULL,
515 "Lower memory usage");
516 cw.continuous_mode_on_radio = gtk_radio_button_new_with_label_from_widget(
517 GTK_RADIO_BUTTON(cw.continuous_mode_off_radio),
518 "Faster browser startup time");
519 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
520 gtk_table_attach(GTK_TABLE(options_table),
521 continuous_mode_label,
524 GTK_FILL, GTK_FILL|GTK_EXPAND,
526 gtk_table_attach(GTK_TABLE(options_table),
527 cw.continuous_mode_off_radio,
530 GTK_FILL, GTK_FILL|GTK_EXPAND,
532 gtk_table_attach(GTK_TABLE(options_table),
533 cw.continuous_mode_on_radio,
536 GTK_FILL, GTK_FILL|GTK_EXPAND,
538 gtk_table_set_row_spacing(GTK_TABLE(options_table), 3, 0);
541 gtk_widget_show_all(dialog);
542 return GTK_DIALOG(dialog);
545 #endif /* defined(HILDON) && defined(FREMANTLE) */
548 /**********************************************************************
550 **********************************************************************/
552 #ifdef HILDON_CP_APPLET
554 * Application was started from control panel.
556 osso_return_t execute(osso_context_t *osso,
557 gpointer userdata, gboolean user_activated) {
564 dialog = GTK_DIALOG(swb_config_dialog(userdata));
567 response = gtk_dialog_run(dialog);
568 if (response == GTK_RESPONSE_OK)
571 gtk_widget_destroy(GTK_WIDGET(dialog));
577 * Application was started from command line.
579 int main(int argc, char *argv[]) {
583 HildonProgram *program = NULL;
586 gtk_init(&argc, &argv);
588 program = HILDON_PROGRAM(hildon_program_get_instance());
591 g_set_application_name("Browser Switchboard");
593 dialog = GTK_DIALOG(swb_config_dialog(NULL));
596 response = gtk_dialog_run(dialog);
597 if (response == GTK_RESPONSE_OK)
600 gtk_widget_destroy(GTK_WIDGET(dialog));
604 #endif /* HILDON_CP_APPLET */