2 * browser-switchboard-cp.c -- a hildon-control-panel applet for
3 * selecting the default browser for Browser Switchboard
5 * Copyright (C) 2009 Steven Luo
7 * Derived from services-cp.c from maemo-control-services
8 * Copyright (c) 2008 Janne Kataja <janne.kataja@iki.fi>
9 * Copyright (c) 2008 Nokia Corporation
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
34 #include <glib/gstdio.h>
38 #include <hildon/hildon-banner.h>
39 #include <hildon/hildon-program.h>
42 #include <hildon/hildon-touch-selector.h>
43 #include <hildon/hildon-picker-button.h>
44 #include <hildon/hildon-caption.h>
45 #include <hildon/hildon-entry.h>
46 #endif /* FREMANTLE */
48 #ifdef HILDON_CP_APPLET
49 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
50 #endif /* HILDON_CP_APPLET */
53 #include "configfile.h"
55 #define CONTINUOUS_MODE_DEFAULT 0
57 #if defined(HILDON) && defined(FREMANTLE)
58 #define _HILDON_SIZE_DEFAULT (HILDON_SIZE_AUTO_WIDTH|HILDON_SIZE_FINGER_HEIGHT)
61 struct browser_entry {
65 struct browser_entry browsers[] = {
66 { "microb", "MicroB" }, /* First entry is the default! */
68 { "fennec", "Mobile Firefox (Fennec)" },
69 { "midori", "Midori" },
74 struct config_widgets {
75 #if defined(HILDON) && defined(FREMANTLE)
76 GtkWidget *continuous_mode_selector;
77 GtkWidget *default_browser_selector;
79 GtkWidget *continuous_mode_off_radio;
80 GtkWidget *continuous_mode_on_radio;
81 GtkWidget *default_browser_combo;
83 GtkWidget *other_browser_cmd_entry;
84 GtkWidget *other_browser_cmd_entry_label;
86 struct config_widgets cw;
90 /**********************************************************************
91 * Configuration routines
92 **********************************************************************/
94 #if defined(HILDON) && defined(FREMANTLE)
96 static inline int get_continuous_mode(void) {
97 return hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0);
99 static inline void set_continuous_mode(int state) {
100 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), 0, state);
103 static inline char *get_default_browser(void) {
104 return browsers[hildon_touch_selector_get_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0)].config;
107 #else /* !defined(HILDON) || !defined(FREMANTLE) */
109 static inline int get_continuous_mode(void) {
110 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio));
112 static inline void set_continuous_mode(int state) {
114 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio), TRUE);
116 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_off_radio), TRUE);
119 static inline char *get_default_browser(void) {
120 return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
123 #endif /* defined(HILDON) && defined(FREMANTLE) */
125 static void set_default_browser(char *browser) {
128 /* Loop through browsers looking for a match */
129 for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
132 if (!browsers[i].config)
133 /* No match found, set to the default browser */
136 #if defined(HILDON) && defined(FREMANTLE)
137 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, i);
139 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), i);
143 static inline char *get_other_browser_cmd(void) {
144 return (char *)gtk_entry_get_text(GTK_ENTRY(cw.other_browser_cmd_entry));
146 static inline void set_other_browser_cmd(char *cmd) {
147 gtk_entry_set_text(GTK_ENTRY(cw.other_browser_cmd_entry), cmd);
150 static void load_config(void) {
152 int continuous_mode_seen = 0;
153 int default_browser_seen = 0;
154 int other_browser_cmd_seen = 0;
155 struct swb_config_line line;
157 if (!(fp = open_config_file()))
160 /* Parse the config file
161 TODO: should we handle errors differently than EOF? */
162 if (!parse_config_file_begin())
164 while (!parse_config_file_line(fp, &line)) {
166 if (!strcmp(line.key, "continuous_mode")) {
167 if (!continuous_mode_seen) {
168 set_continuous_mode(atoi(line.value));
169 continuous_mode_seen = 1;
171 } else if (!strcmp(line.key, "default_browser")) {
172 if (!default_browser_seen) {
173 set_default_browser(line.value);
174 default_browser_seen = 1;
176 } else if (!strcmp(line.key, "other_browser_cmd")) {
177 if (!other_browser_cmd_seen) {
178 set_other_browser_cmd(line.value);
179 other_browser_cmd_seen = 1;
186 parse_config_file_end();
193 static void save_config(void) {
194 FILE *fp = NULL, *tmpfp = NULL;
195 char *homedir, *tempfile, *newfile;
197 int continuous_mode_seen = 0;
198 int default_browser_seen = 0;
199 int other_browser_cmd_seen = 0;
200 struct swb_config_line line;
202 /* If CONFIGFILE_DIR doesn't exist already, try to create it */
203 if (!(homedir = getenv("HOME")))
204 homedir = DEFAULT_HOMEDIR;
205 len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1;
206 if (!(newfile = calloc(len, sizeof(char))))
208 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR);
209 if (access(newfile, F_OK) == -1 && errno == ENOENT) {
210 mkdir(newfile, 0750);
214 /* Put together the path to the new config file and the tempfile */
215 len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1;
216 if (!(newfile = calloc(len, sizeof(char))))
218 /* 4 = strlen(".tmp") */
219 if (!(tempfile = calloc(len+4, sizeof(char)))) {
223 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC);
224 snprintf(tempfile, len+4, "%s%s", newfile, ".tmp");
226 /* Open the temporary file for writing */
227 if (!(tmpfp = fopen(tempfile, "w")))
228 /* TODO: report the error somehow? */
231 /* Open the old config file, if it exists */
232 if ((fp = open_config_file()) && parse_config_file_begin()) {
233 /* Copy the old config file over to the new one line by line,
234 replacing old config values with new ones
235 TODO: should we handle errors differently than EOF? */
236 while (!parse_config_file_line(fp, &line)) {
238 /* Is a config line, print the new value here */
239 if (!strcmp(line.key, "continuous_mode")) {
240 if (!continuous_mode_seen) {
241 fprintf(tmpfp, "%s = %d\n",
243 get_continuous_mode());
244 continuous_mode_seen = 1;
246 } else if (!strcmp(line.key,
247 "default_browser")) {
248 if (!default_browser_seen) {
249 fprintf(tmpfp, "%s = \"%s\"\n",
251 get_default_browser());
252 default_browser_seen = 1;
254 } else if (!strcmp(line.key,
255 "other_browser_cmd")) {
256 if (!other_browser_cmd_seen &&
257 strlen(get_other_browser_cmd())>0) {
258 fprintf(tmpfp, "%s = \"%s\"\n",
260 get_other_browser_cmd());
261 other_browser_cmd_seen = 1;
265 /* Just copy the old line over */
266 fprintf(tmpfp, "%s\n", line.key);
271 parse_config_file_end();
274 /* If we haven't written them yet, write out the new config values */
275 if (!continuous_mode_seen)
276 fprintf(tmpfp, "%s = %d\n",
277 "continuous_mode", get_continuous_mode());
278 if (!default_browser_seen)
279 fprintf(tmpfp, "%s = \"%s\"\n",
280 "default_browser", get_default_browser());
281 if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0)
282 fprintf(tmpfp, "%s = \"%s\"\n",
283 "other_browser_cmd", get_other_browser_cmd());
285 /* Replace the old config file with the new one */
288 rename(tempfile, newfile);
300 static void do_reconfig(void) {
303 /* Try to send SIGHUP to any running browser-switchboard process
304 This causes it to reread config files if in continuous_mode, and
305 die so that the config will be reloaded on next start otherwise */
306 system("kill -HUP `pidof browser-switchboard` > /dev/null 2>&1");
310 /**********************************************************************
312 **********************************************************************/
314 #if defined(HILDON) && defined(FREMANTLE)
315 static void default_browser_selector_callback(GtkWidget *widget,
316 gint column, gpointer data) {
318 static void default_browser_combo_callback(GtkWidget *widget, gpointer data) {
320 if (!strcmp(get_default_browser(), "other")) {
321 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), TRUE);
322 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, TRUE);
323 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, TRUE);
325 gtk_editable_set_editable(GTK_EDITABLE(cw.other_browser_cmd_entry), FALSE); /* FREMANTLE: give the text the greyed-out look */
326 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
327 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
332 /**********************************************************************
334 **********************************************************************/
336 #if defined(HILDON) && defined(FREMANTLE)
338 * Fremantle Hildon dialog
340 static GtkDialog *swb_config_dialog(gpointer cp_window) {
341 GtkWidget *dialog_vbox;
343 GtkWidget *default_browser_selector_button;
344 GtkWidget *continuous_mode_selector_button;
346 HildonGtkInputMode input_mode;
348 dialog = gtk_dialog_new_with_buttons(
349 "Browser Switchboard",
350 GTK_WINDOW(cp_window),
358 dialog_vbox = GTK_DIALOG(dialog)->vbox;
361 cw.default_browser_selector = hildon_touch_selector_new_text();
362 for (i = 0; browsers[i].config; ++i)
363 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), browsers[i].displayname);
364 hildon_touch_selector_set_active(HILDON_TOUCH_SELECTOR(cw.default_browser_selector), 0, 0);
365 default_browser_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_HORIZONTAL);
366 hildon_button_set_title(HILDON_BUTTON(default_browser_selector_button),
368 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(default_browser_selector_button), HILDON_TOUCH_SELECTOR(cw.default_browser_selector));
369 hildon_button_set_alignment(HILDON_BUTTON(default_browser_selector_button),
371 g_signal_connect(G_OBJECT(cw.default_browser_selector), "changed",
372 G_CALLBACK(default_browser_selector_callback), NULL);
373 gtk_box_pack_start(GTK_BOX(dialog_vbox),
374 default_browser_selector_button, FALSE, FALSE, 0);
376 cw.other_browser_cmd_entry = hildon_entry_new(_HILDON_SIZE_DEFAULT);
377 /* Disable autocapitalization and dictionary features for the entry */
378 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
379 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
380 HILDON_GTK_INPUT_MODE_DICTIONARY);
381 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
383 cw.other_browser_cmd_entry_label = hildon_caption_new(NULL,
384 "Command (%s for URI):",
385 cw.other_browser_cmd_entry,
386 NULL, HILDON_CAPTION_OPTIONAL);
387 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
388 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
389 hildon_gtk_widget_set_theme_size(cw.other_browser_cmd_entry_label, _HILDON_SIZE_DEFAULT);
390 gtk_box_pack_start(GTK_BOX(dialog_vbox),
391 cw.other_browser_cmd_entry_label, FALSE, FALSE, 0);
393 cw.continuous_mode_selector = hildon_touch_selector_new_text();
394 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Lower memory usage");
395 hildon_touch_selector_append_text(HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector), "Faster browser startup time");
397 continuous_mode_selector_button = hildon_picker_button_new(_HILDON_SIZE_DEFAULT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
398 hildon_button_set_title(HILDON_BUTTON(continuous_mode_selector_button),
399 "Optimize Browser Switchboard for:");
400 hildon_picker_button_set_selector(HILDON_PICKER_BUTTON(continuous_mode_selector_button), HILDON_TOUCH_SELECTOR(cw.continuous_mode_selector));
401 hildon_button_set_alignment(HILDON_BUTTON(continuous_mode_selector_button),
403 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
404 gtk_box_pack_start(GTK_BOX(dialog_vbox),
405 continuous_mode_selector_button, FALSE, FALSE, 0);
407 gtk_widget_show_all(dialog);
408 return GTK_DIALOG(dialog);
411 #else /* !defined(HILDON) || !defined(FREMANTLE) */
413 * GTK+/Diablo Hildon dialog
415 static GtkDialog *swb_config_dialog(gpointer cp_window) {
416 GtkWidget *dialog_vbox;
418 GtkWidget *options_table;
419 GtkWidget *default_browser_combo_label;
420 GtkWidget *continuous_mode_label;
423 HildonGtkInputMode input_mode;
426 dialog = gtk_dialog_new_with_buttons(
427 "Browser Switchboard",
428 GTK_WINDOW(cp_window),
436 dialog_vbox = GTK_DIALOG(dialog)->vbox;
439 options_table = gtk_table_new(3, 2, FALSE);
440 gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
441 gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
443 cw.default_browser_combo = gtk_combo_box_new_text();
444 for (i = 0; browsers[i].config; ++i)
445 gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
446 browsers[i].displayname);
447 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
448 default_browser_combo_label = gtk_label_new("Default browser:");
449 gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
450 g_signal_connect(G_OBJECT(cw.default_browser_combo), "changed",
451 G_CALLBACK(default_browser_combo_callback), NULL);
452 gtk_table_attach(GTK_TABLE(options_table),
453 default_browser_combo_label,
456 GTK_FILL, GTK_FILL|GTK_EXPAND,
458 gtk_table_attach(GTK_TABLE(options_table),
459 cw.default_browser_combo,
462 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
465 cw.other_browser_cmd_entry = gtk_entry_new();
467 /* Disable autocapitalization and dictionary features for the entry */
468 input_mode = hildon_gtk_entry_get_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry));
469 input_mode &= ~(HILDON_GTK_INPUT_MODE_AUTOCAP |
470 HILDON_GTK_INPUT_MODE_DICTIONARY);
471 hildon_gtk_entry_set_input_mode(GTK_ENTRY(cw.other_browser_cmd_entry), input_mode);
473 cw.other_browser_cmd_entry_label = gtk_label_new("Command (%s for URI):");
474 gtk_misc_set_alignment(GTK_MISC(cw.other_browser_cmd_entry_label), 1, 0.5);
475 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
476 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
477 gtk_table_attach(GTK_TABLE(options_table),
478 cw.other_browser_cmd_entry_label,
481 GTK_FILL, GTK_FILL|GTK_EXPAND,
483 gtk_table_attach(GTK_TABLE(options_table),
484 cw.other_browser_cmd_entry,
487 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
489 gtk_table_set_row_spacing(GTK_TABLE(options_table), 1, 15);
491 continuous_mode_label = gtk_label_new("Optimize Browser Switchboard for:");
492 gtk_misc_set_alignment(GTK_MISC(continuous_mode_label), 0, 0.5);
493 cw.continuous_mode_off_radio = gtk_radio_button_new_with_label(NULL,
494 "Lower memory usage");
495 cw.continuous_mode_on_radio = gtk_radio_button_new_with_label_from_widget(
496 GTK_RADIO_BUTTON(cw.continuous_mode_off_radio),
497 "Faster browser startup time");
498 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
499 gtk_table_attach(GTK_TABLE(options_table),
500 continuous_mode_label,
503 GTK_FILL, GTK_FILL|GTK_EXPAND,
505 gtk_table_attach(GTK_TABLE(options_table),
506 cw.continuous_mode_off_radio,
509 GTK_FILL, GTK_FILL|GTK_EXPAND,
511 gtk_table_attach(GTK_TABLE(options_table),
512 cw.continuous_mode_on_radio,
515 GTK_FILL, GTK_FILL|GTK_EXPAND,
517 gtk_table_set_row_spacing(GTK_TABLE(options_table), 3, 0);
520 gtk_widget_show_all(dialog);
521 return GTK_DIALOG(dialog);
524 #endif /* defined(HILDON) && defined(FREMANTLE) */
527 /**********************************************************************
529 **********************************************************************/
531 #ifdef HILDON_CP_APPLET
533 * Application was started from control panel.
535 osso_return_t execute(osso_context_t *osso,
536 gpointer userdata, gboolean user_activated) {
543 dialog = GTK_DIALOG(swb_config_dialog(userdata));
546 response = gtk_dialog_run(dialog);
547 if (response == GTK_RESPONSE_OK)
550 gtk_widget_destroy(GTK_WIDGET(dialog));
556 * Application was started from command line.
558 int main(int argc, char *argv[]) {
562 HildonProgram *program = NULL;
565 gtk_init(&argc, &argv);
567 program = HILDON_PROGRAM(hildon_program_get_instance());
570 g_set_application_name("Browser Switchboard");
572 dialog = GTK_DIALOG(swb_config_dialog(NULL));
575 response = gtk_dialog_run(dialog);
576 if (response == GTK_RESPONSE_OK)
579 gtk_widget_destroy(GTK_WIDGET(dialog));
583 #endif /* HILDON_CP_APPLET */