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 { "midori", "Midori" },
75 char *logger_name = NULL;
77 struct config_widgets {
78 #if defined(HILDON) && defined(FREMANTLE)
79 GtkWidget *continuous_mode_selector;
80 GtkWidget *default_browser_selector;
82 GtkWidget *continuous_mode_off_radio;
83 GtkWidget *continuous_mode_on_radio;
84 GtkWidget *default_browser_combo;
86 GtkWidget *other_browser_cmd_entry;
87 GtkWidget *other_browser_cmd_entry_label;
89 struct config_widgets cw;
93 /**********************************************************************
94 * Configuration routines
95 **********************************************************************/
97 #if defined(HILDON) && defined(FREMANTLE)
99 static inline int get_continuous_mode(void) {
100 return hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0);
102 static inline void set_continuous_mode(int state) {
103 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0, state);
106 static inline char *get_default_browser(void) {
107 return browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
110 #else /* !defined(HILDON) || !defined(FREMANTLE) */
112 static inline int get_continuous_mode(void) {
113 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio));
115 static inline void set_continuous_mode(int state) {
117 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio), TRUE);
119 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_off_radio), TRUE);
122 static inline char *get_default_browser(void) {
123 return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
126 #endif /* defined(HILDON) && defined(FREMANTLE) */
128 static void set_default_browser(char *browser) {
131 /* Loop through browsers looking for a match */
132 for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
135 if (!browsers[i].config)
136 /* No match found, set to the default browser */
139 #if defined(HILDON) && defined(FREMANTLE)
140 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, i);
142 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), i);
146 static inline char *get_other_browser_cmd(void) {
147 return (char *)gtk_entry_get_text(GTK_ENTRY(cw.other_browser_cmd_entry));
149 static inline void set_other_browser_cmd(char *cmd) {
150 gtk_entry_set_text(GTK_ENTRY(cw.other_browser_cmd_entry), cmd);
153 static void load_config(void) {
155 int continuous_mode_seen = 0;
156 int default_browser_seen = 0;
157 int other_browser_cmd_seen = 0;
158 struct swb_config_line line;
160 if (!(fp = open_config_file()))
163 /* Parse the config file
164 TODO: should we handle errors differently than EOF? */
165 if (!parse_config_file_begin())
167 while (!parse_config_file_line(fp, &line)) {
169 if (!strcmp(line.key, "continuous_mode")) {
170 if (!continuous_mode_seen) {
171 set_continuous_mode(atoi(line.value));
172 continuous_mode_seen = 1;
175 } else if (!strcmp(line.key, "default_browser")) {
176 if (!default_browser_seen) {
177 set_default_browser(line.value);
178 default_browser_seen = 1;
181 } else if (!strcmp(line.key, "other_browser_cmd")) {
182 if (!other_browser_cmd_seen) {
183 set_other_browser_cmd(line.value);
184 other_browser_cmd_seen = 1;
187 } else if (!strcmp(line.key, "logging")) {
189 logger_name = line.value;
194 parse_config_file_end();
201 static void save_config(void) {
202 FILE *fp = NULL, *tmpfp = NULL;
203 char *homedir, *tempfile, *newfile;
205 int continuous_mode_seen = 0;
206 int default_browser_seen = 0;
207 int other_browser_cmd_seen = 0;
208 struct swb_config_line line;
210 /* If CONFIGFILE_DIR doesn't exist already, try to create it */
211 if (!(homedir = getenv("HOME")))
212 homedir = DEFAULT_HOMEDIR;
213 len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1;
214 if (!(newfile = calloc(len, sizeof(char))))
216 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR);
217 if (access(newfile, F_OK) == -1 && errno == ENOENT) {
218 mkdir(newfile, 0750);
222 /* Put together the path to the new config file and the tempfile */
223 len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1;
224 if (!(newfile = calloc(len, sizeof(char))))
226 /* 4 = strlen(".tmp") */
227 if (!(tempfile = calloc(len+4, sizeof(char)))) {
231 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC);
232 snprintf(tempfile, len+4, "%s%s", newfile, ".tmp");
234 /* Open the temporary file for writing */
235 if (!(tmpfp = fopen(tempfile, "w")))
236 /* TODO: report the error somehow? */
239 /* Open the old config file, if it exists */
240 if ((fp = open_config_file()) && parse_config_file_begin()) {
241 /* Copy the old config file over to the new one line by line,
242 replacing old config values with new ones
243 TODO: should we handle errors differently than EOF? */
244 while (!parse_config_file_line(fp, &line)) {
246 /* Is a config line, print the new value here */
247 if (!strcmp(line.key, "continuous_mode")) {
248 if (!continuous_mode_seen) {
249 fprintf(tmpfp, "%s = %d\n",
251 get_continuous_mode());
252 continuous_mode_seen = 1;
254 } else if (!strcmp(line.key,
255 "default_browser")) {
256 if (!default_browser_seen) {
257 fprintf(tmpfp, "%s = \"%s\"\n",
259 get_default_browser());
260 default_browser_seen = 1;
262 } else if (!strcmp(line.key,
263 "other_browser_cmd")) {
264 if (!other_browser_cmd_seen &&
265 strlen(get_other_browser_cmd())>0) {
266 fprintf(tmpfp, "%s = \"%s\"\n",
268 get_other_browser_cmd());
269 other_browser_cmd_seen = 1;
271 } else if (!strcmp(line.key,
274 fprintf(tmpfp, "%s = \"%s\"\n",
282 /* Just copy the old line over */
283 fprintf(tmpfp, "%s\n", line.key);
288 parse_config_file_end();
291 /* If we haven't written them yet, write out the new config values */
292 if (!continuous_mode_seen)
293 fprintf(tmpfp, "%s = %d\n",
294 "continuous_mode", get_continuous_mode());
295 if (!default_browser_seen)
296 fprintf(tmpfp, "%s = \"%s\"\n",
297 "default_browser", get_default_browser());
298 if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0)
299 fprintf(tmpfp, "%s = \"%s\"\n",
300 "other_browser_cmd", get_other_browser_cmd());
302 fprintf(tmpfp, "%s = \"%s\"\n",
303 "logging", logger_name);
305 /* Replace the old config file with the new one */
308 rename(tempfile, newfile);
320 static void do_reconfig(void) {
323 /* Try to send SIGHUP to any running browser-switchboard process
324 This causes it to reread config files if in continuous_mode, or
325 die so that the config will be reloaded on next start otherwise */
326 system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
330 /**********************************************************************
332 **********************************************************************/
334 #if defined(HILDON) && defined(FREMANTLE)
335 static void default_browser_selector_callback(GtkWidget *widget,
336 gint column, gpointer data) {
338 static void default_browser_combo_callback(GtkWidget *widget, gpointer data) {
340 if (!strcmp(get_default_browser(), "other")) {
341 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), TRUE);
342 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, TRUE);
343 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, TRUE);
345 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), FALSE); /* FREMANTLE: give the text the greyed-out look */
346 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
347 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
352 /**********************************************************************
354 **********************************************************************/
356 #if defined(HILDON) && defined(FREMANTLE)
358 * Fremantle Hildon dialog
360 static GtkDialog *swb_config_dialog(gpointer cp_window) {
361 GtkWidget *dialog_vbox;
363 GtkWidget *default_browser_selector_button;
364 GtkWidget *continuous_mode_selector_button;
366 HildonGtkInputMode input_mode;
368 dialog = gtk_dialog_new_with_buttons(
369 "Browser Switchboard",
370 GTK_WINDOW(cp_window),
378 dialog_vbox = GTK_DIALOG(dialog)->vbox;
381 cw.default_browser_selector = hildon_touch_selector_new_text();
382 for (i = 0; browsers[i].config; ++i)
383 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), browsers[i].displayname);
384 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, 0);
385 default_browser_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
386 hildon_button_set_title(HILDON_BUTTON(default_browser_selector_button),
388 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(default_browser_selector_button), HILDON_TOUCH_SELECTOR(cw.default_browser_selector));
389 hildon_button_set_alignment(HILDON_BUTTON(default_browser_selector_button),
391 g_signal_connect(G_OBJECT(cw.default_browser_selector), "changed",
392 G_CALLBACK(default_browser_selector_callback), NULL);
393 gtk_box_pack_start(GTK_BOX(dialog_vbox),
394 default_browser_selector_button, FALSE, FALSE, 0);
396 cw.other_browser_cmd_entry = hildon_entry_new(_HILDON_SIZE_DEFAULT);
397 /* Disable autocapitalization and dictionary features for the entry */
398 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
399 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
400 HILDON_GTK_INPUT_MODE_DICTIONARY);
401 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
403 cw.other_browser_cmd_entry_label = hildon_caption_new(NULL,
404 "Command (%s for URI):",
405 cw.other_browser_cmd_entry,
406 NULL, HILDON_CAPTION_OPTIONAL);
407 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
408 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
409 hildon_gtk_widget_set_theme_size(cw.other_browser_cmd_entry_label, _HILDON_SIZE_DEFAULT);
410 gtk_box_pack_start(GTK_BOX(dialog_vbox),
411 cw.other_browser_cmd_entry_label, FALSE, FALSE, 0);
413 cw.continuous_mode_selector = hildon_touch_selector_new_text();
414 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Lower memory usage");
415 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Faster browser startup time");
417 continuous_mode_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
418 hildon_button_set_title(HILDON_BUTTON(continuous_mode_selector_button),
419 "Optimize Browser Switchboard for:");
420 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(continuous_mode_selector_button), HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector));
421 hildon_button_set_alignment(HILDON_BUTTON(continuous_mode_selector_button),
423 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
424 gtk_box_pack_start(GTK_BOX(dialog_vbox),
425 continuous_mode_selector_button, FALSE, FALSE, 0);
427 gtk_widget_show_all(dialog);
428 return GTK_DIALOG(dialog);
431 #else /* !defined(HILDON) || !defined(FREMANTLE) */
433 * GTK+/Diablo Hildon dialog
435 static GtkDialog *swb_config_dialog(gpointer cp_window) {
436 GtkWidget *dialog_vbox;
438 GtkWidget *options_table;
439 GtkWidget *default_browser_combo_label;
440 GtkWidget *continuous_mode_label;
443 HildonGtkInputMode input_mode;
446 dialog = gtk_dialog_new_with_buttons(
447 "Browser Switchboard",
448 GTK_WINDOW(cp_window),
456 dialog_vbox = GTK_DIALOG(dialog)->vbox;
459 options_table = gtk_table_new(3, 2, FALSE);
460 gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
461 gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
463 cw.default_browser_combo = gtk_combo_box_new_text();
464 for (i = 0; browsers[i].config; ++i)
465 gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
466 browsers[i].displayname);
467 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
468 default_browser_combo_label = gtk_label_new("Default browser:");
469 gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
470 g_signal_connect(G_OBJECT(cw.default_browser_combo), "changed",
471 G_CALLBACK(default_browser_combo_callback), NULL);
472 gtk_table_attach(GTK_TABLE(options_table),
473 default_browser_combo_label,
476 GTK_FILL, GTK_FILL|GTK_EXPAND,
478 gtk_table_attach(GTK_TABLE(options_table),
479 cw.default_browser_combo,
482 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
485 cw.other_browser_cmd_entry = gtk_entry_new();
487 /* Disable autocapitalization and dictionary features for the entry */
488 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
489 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
490 HILDON_GTK_INPUT_MODE_DICTIONARY);
491 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
493 cw.other_browser_cmd_entry_label = gtk_label_new("Command (%s for URI):");
494 gtk_misc_set_alignment(GTK_MISC(cw.other_browser_cmd_entry_label), 1, 0.5);
495 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
496 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
497 gtk_table_attach(GTK_TABLE(options_table),
498 cw.other_browser_cmd_entry_label,
501 GTK_FILL, GTK_FILL|GTK_EXPAND,
503 gtk_table_attach(GTK_TABLE(options_table),
504 cw.other_browser_cmd_entry,
507 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
509 gtk_table_set_row_spacing(GTK_TABLE(options_table), 1, 15);
511 continuous_mode_label = gtk_label_new("Optimize Browser Switchboard for:");
512 gtk_misc_set_alignment(GTK_MISC(continuous_mode_label), 0, 0.5);
513 cw.continuous_mode_off_radio = gtk_radio_button_new_with_label(NULL,
514 "Lower memory usage");
515 cw.continuous_mode_on_radio = gtk_radio_button_new_with_label_from_widget(
516 GTK_RADIO_BUTTON(cw.continuous_mode_off_radio),
517 "Faster browser startup time");
518 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
519 gtk_table_attach(GTK_TABLE(options_table),
520 continuous_mode_label,
523 GTK_FILL, GTK_FILL|GTK_EXPAND,
525 gtk_table_attach(GTK_TABLE(options_table),
526 cw.continuous_mode_off_radio,
529 GTK_FILL, GTK_FILL|GTK_EXPAND,
531 gtk_table_attach(GTK_TABLE(options_table),
532 cw.continuous_mode_on_radio,
535 GTK_FILL, GTK_FILL|GTK_EXPAND,
537 gtk_table_set_row_spacing(GTK_TABLE(options_table), 3, 0);
540 gtk_widget_show_all(dialog);
541 return GTK_DIALOG(dialog);
544 #endif /* defined(HILDON) && defined(FREMANTLE) */
547 /**********************************************************************
549 **********************************************************************/
551 #ifdef HILDON_CP_APPLET
553 * Application was started from control panel.
555 osso_return_t execute(osso_context_t *osso,
556 gpointer userdata, gboolean user_activated) {
563 dialog = GTK_DIALOG(swb_config_dialog(userdata));
566 response = gtk_dialog_run(dialog);
567 if (response == GTK_RESPONSE_OK)
570 gtk_widget_destroy(GTK_WIDGET(dialog));
576 * Application was started from command line.
578 int main(int argc, char *argv[]) {
582 HildonProgram *program = NULL;
585 gtk_init(&argc, &argv);
587 program = HILDON_PROGRAM(hildon_program_get_instance());
590 g_set_application_name("Browser Switchboard");
592 dialog = GTK_DIALOG(swb_config_dialog(NULL));
595 response = gtk_dialog_run(dialog);
596 if (response == GTK_RESPONSE_OK)
599 gtk_widget_destroy(GTK_WIDGET(dialog));
603 #endif /* HILDON_CP_APPLET */