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>
37 #include <hildon/hildon-banner.h>
38 #include <hildon/hildon-program.h>
39 #ifdef HILDON_CP_APPLET
40 #include <hildon-cp-plugin/hildon-cp-plugin-interface.h>
44 #include "configfile.h"
46 #define CONTINUOUS_MODE_DEFAULT 0
48 struct browser_entry {
52 struct browser_entry browsers[] = {
53 { "microb", "MicroB" }, /* First entry is the default! */
55 { "fennec", "Mobile Firefox (Fennec)" },
56 { "midori", "Midori" },
61 struct config_widgets {
62 GtkWidget *continuous_mode_off_radio;
63 GtkWidget *continuous_mode_on_radio;
64 GtkWidget *default_browser_combo;
65 GtkWidget *other_browser_cmd_entry;
66 GtkWidget *other_browser_cmd_entry_label;
68 struct config_widgets cw;
72 /**********************************************************************
73 * Configuration routines
74 **********************************************************************/
76 static inline int get_continuous_mode(void) {
77 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio));
79 static inline void set_continuous_mode(int state) {
81 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_on_radio), TRUE);
83 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cw.continuous_mode_off_radio), TRUE);
86 static inline char *get_default_browser(void) {
87 return browsers[gtk_combo_box_get_active(GTK_COMBO_BOX(cw.default_browser_combo))].config;
89 static void set_default_browser(char *browser) {
92 /* Loop through browsers looking for a match */
93 for (i = 0; browsers[i].config && strcmp(browsers[i].config, browser);
96 if (!browsers[i].config)
97 /* No match found, set to the default browser */
100 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), i);
103 static inline char *get_other_browser_cmd(void) {
104 return (char *)gtk_entry_get_text(GTK_ENTRY(cw.other_browser_cmd_entry));
106 static inline void set_other_browser_cmd(char *cmd) {
107 gtk_entry_set_text(GTK_ENTRY(cw.other_browser_cmd_entry), cmd);
110 static void load_config(void) {
112 int continuous_mode_seen = 0;
113 int default_browser_seen = 0;
114 int other_browser_cmd_seen = 0;
115 struct swb_config_line line;
117 if (!(fp = open_config_file()))
120 /* Parse the config file
121 TODO: should we handle errors differently than EOF? */
122 if (!parse_config_file_begin())
124 while (!parse_config_file_line(fp, &line)) {
126 if (!strcmp(line.key, "continuous_mode")) {
127 if (!continuous_mode_seen) {
128 set_continuous_mode(atoi(line.value));
129 continuous_mode_seen = 1;
131 } else if (!strcmp(line.key, "default_browser")) {
132 if (!default_browser_seen) {
133 set_default_browser(line.value);
134 default_browser_seen = 1;
136 } else if (!strcmp(line.key, "other_browser_cmd")) {
137 if (!other_browser_cmd_seen) {
138 set_other_browser_cmd(line.value);
139 other_browser_cmd_seen = 1;
146 parse_config_file_end();
153 static void save_config(void) {
154 FILE *fp = NULL, *tmpfp = NULL;
155 char *homedir, *tempfile, *newfile;
157 int continuous_mode_seen = 0;
158 int default_browser_seen = 0;
159 int other_browser_cmd_seen = 0;
160 struct swb_config_line line;
162 /* If CONFIGFILE_DIR doesn't exist already, try to create it */
163 if (!(homedir = getenv("HOME")))
164 homedir = DEFAULT_HOMEDIR;
165 len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1;
166 if (!(newfile = calloc(len, sizeof(char))))
168 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR);
169 if (access(newfile, F_OK) == -1 && errno == ENOENT) {
170 mkdir(newfile, 0750);
174 /* Put together the path to the new config file and the tempfile */
175 len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1;
176 if (!(newfile = calloc(len, sizeof(char))))
178 /* 4 = strlen(".tmp") */
179 if (!(tempfile = calloc(len+4, sizeof(char)))) {
183 snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC);
184 snprintf(tempfile, len+4, "%s%s", newfile, ".tmp");
186 /* Open the temporary file for writing */
187 if (!(tmpfp = fopen(tempfile, "w")))
188 /* TODO: report the error somehow? */
191 /* Open the old config file, if it exists */
192 if ((fp = open_config_file()) && parse_config_file_begin()) {
193 /* Copy the old config file over to the new one line by line,
194 replacing old config values with new ones
195 TODO: should we handle errors differently than EOF? */
196 while (!parse_config_file_line(fp, &line)) {
198 /* Is a config line, print the new value here */
199 if (!strcmp(line.key, "continuous_mode")) {
200 if (!continuous_mode_seen) {
201 fprintf(tmpfp, "%s = %d\n",
203 get_continuous_mode());
204 continuous_mode_seen = 1;
206 } else if (!strcmp(line.key,
207 "default_browser")) {
208 if (!default_browser_seen) {
209 fprintf(tmpfp, "%s = \"%s\"\n",
211 get_default_browser());
212 default_browser_seen = 1;
214 } else if (!strcmp(line.key,
215 "other_browser_cmd")) {
216 if (!other_browser_cmd_seen &&
217 strlen(get_other_browser_cmd())>0) {
218 fprintf(tmpfp, "%s = \"%s\"\n",
220 get_other_browser_cmd());
221 other_browser_cmd_seen = 1;
225 /* Just copy the old line over */
226 fprintf(tmpfp, "%s\n", line.key);
231 parse_config_file_end();
234 /* If we haven't written them yet, write out the new config values */
235 if (!continuous_mode_seen)
236 fprintf(tmpfp, "%s = %d\n",
237 "continuous_mode", get_continuous_mode());
238 if (!default_browser_seen)
239 fprintf(tmpfp, "%s = \"%s\"\n",
240 "default_browser", get_default_browser());
241 if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0)
242 fprintf(tmpfp, "%s = \"%s\"\n",
243 "other_browser_cmd", get_other_browser_cmd());
245 /* Replace the old config file with the new one */
248 rename(tempfile, newfile);
260 /**********************************************************************
262 **********************************************************************/
264 static void default_browser_combo_callback(GtkWidget *widget, gpointer data) {
265 if (!strcmp(get_default_browser(), "other")) {
266 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, TRUE);
267 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, TRUE);
269 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
270 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
274 static inline void close_dialog(void) {
275 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_NONE);
278 static void ok_callback(GtkWidget *widget, gpointer data) {
280 /* TODO: is there any cleanup necessary? */
284 static void cancel_callback(GtkWidget *widget, gpointer data) {
285 /* TODO: is there any cleanup necessary? */
290 /**********************************************************************
292 **********************************************************************/
294 static GtkDialog *swb_config_dialog(void) {
295 GtkWidget *dialog_vbox;
297 GtkWidget *options_table;
298 GtkWidget *default_browser_combo_label;
299 GtkWidget *continuous_mode_label;
302 GtkWidget *action_area;
303 GtkWidget *okbutton, *cancelbutton;
305 dialog = gtk_dialog_new();
306 /* Doesn't seem to be necessary?
307 gtk_widget_set_size_request(GTK_WIDGET(dialog), 580, 180); */
308 gtk_window_set_title (GTK_WINDOW(dialog), "Browser Switchboard");
309 gtk_window_set_type_hint (GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
311 dialog_vbox = GTK_DIALOG(dialog)->vbox;
314 options_table = gtk_table_new(3, 2, FALSE);
315 gtk_table_set_row_spacings(GTK_TABLE(options_table), 5);
316 gtk_box_pack_start(GTK_BOX(dialog_vbox), options_table, FALSE, FALSE, 0);
318 cw.default_browser_combo = gtk_combo_box_new_text();
319 for (i = 0; browsers[i].config; ++i)
320 gtk_combo_box_append_text(GTK_COMBO_BOX(cw.default_browser_combo),
321 browsers[i].displayname);
322 gtk_combo_box_set_active(GTK_COMBO_BOX(cw.default_browser_combo), 0);
323 default_browser_combo_label = gtk_label_new("Default browser:");
324 gtk_misc_set_alignment(GTK_MISC(default_browser_combo_label), 1, 0.5);
325 g_signal_connect(G_OBJECT(cw.default_browser_combo), "changed",
326 G_CALLBACK(default_browser_combo_callback), NULL);
327 gtk_table_attach(GTK_TABLE(options_table),
328 default_browser_combo_label,
331 GTK_FILL, GTK_FILL|GTK_EXPAND,
333 gtk_table_attach(GTK_TABLE(options_table),
334 cw.default_browser_combo,
337 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
340 cw.other_browser_cmd_entry = gtk_entry_new();
341 cw.other_browser_cmd_entry_label = gtk_label_new("Command (%s for URI):");
342 gtk_misc_set_alignment(GTK_MISC(cw.other_browser_cmd_entry_label), 1, 0.5);
343 gtk_widget_set_sensitive(cw.other_browser_cmd_entry, FALSE);
344 gtk_widget_set_sensitive(cw.other_browser_cmd_entry_label, FALSE);
345 gtk_table_attach(GTK_TABLE(options_table),
346 cw.other_browser_cmd_entry_label,
349 GTK_FILL, GTK_FILL|GTK_EXPAND,
351 gtk_table_attach(GTK_TABLE(options_table),
352 cw.other_browser_cmd_entry,
355 GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,
357 gtk_table_set_row_spacing(GTK_TABLE(options_table), 1, 15);
359 continuous_mode_label = gtk_label_new("Optimize Browser Switchboard for:");
360 gtk_misc_set_alignment(GTK_MISC(continuous_mode_label), 0, 0.5);
361 cw.continuous_mode_off_radio = gtk_radio_button_new_with_label(NULL,
362 "Lower memory usage");
363 cw.continuous_mode_on_radio = gtk_radio_button_new_with_label_from_widget(
364 GTK_RADIO_BUTTON(cw.continuous_mode_off_radio),
365 "Faster browser startup time");
366 set_continuous_mode(CONTINUOUS_MODE_DEFAULT);
367 gtk_table_attach(GTK_TABLE(options_table),
368 continuous_mode_label,
371 GTK_FILL, GTK_FILL|GTK_EXPAND,
373 gtk_table_attach(GTK_TABLE(options_table),
374 cw.continuous_mode_off_radio,
377 GTK_FILL, GTK_FILL|GTK_EXPAND,
379 gtk_table_attach(GTK_TABLE(options_table),
380 cw.continuous_mode_on_radio,
383 GTK_FILL, GTK_FILL|GTK_EXPAND,
385 gtk_table_set_row_spacing(GTK_TABLE(options_table), 3, 0);
389 action_area = GTK_DIALOG(dialog)->action_area;
391 okbutton = gtk_button_new_from_stock(GTK_STOCK_OK);
392 g_signal_connect(G_OBJECT(okbutton), "clicked",
393 G_CALLBACK(ok_callback), NULL);
394 gtk_box_pack_start(GTK_BOX(action_area), okbutton, FALSE, FALSE, 0);
396 cancelbutton = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
397 g_signal_connect(G_OBJECT(cancelbutton), "clicked",
398 G_CALLBACK(cancel_callback), NULL);
399 gtk_box_pack_start(GTK_BOX(action_area), cancelbutton, FALSE, FALSE, 0);
401 gtk_widget_show_all(dialog);
402 return GTK_DIALOG(dialog);
406 /**********************************************************************
408 **********************************************************************/
410 #ifdef HILDON_CP_APPLET
412 * Application was started from control panel.
414 osso_return_t execute(osso_context_t *osso,
415 gpointer userdata, gboolean user_activated) {
416 HildonProgram *program;
419 program = HILDON_PROGRAM(hildon_program_get_instance());
423 dialog = GTK_DIALOG(swb_config_dialog());
425 gtk_dialog_run(dialog);
426 gtk_widget_destroy(GTK_WIDGET(dialog));
432 * Application was started from command line.
434 int main(int argc, char *argv[]) {
437 HildonProgram *program = NULL;
440 gtk_init(&argc, &argv);
442 program = HILDON_PROGRAM(hildon_program_get_instance());
445 g_set_application_name("Browser Switchboard");
447 dialog = GTK_DIALOG(swb_config_dialog());
449 gtk_dialog_run(dialog);
450 gtk_widget_destroy(GTK_WIDGET(dialog));