1 /**
2  * @file preferences_dialog.c Liferea preferences
3  *
4  * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
5  * Copyright (C) 2004-2018 Lars Windolf <lars.windolf@gmx.de>
6  * Copyright (C) 2009 Hubert Figuiere <hub@figuiere.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include "ui/preferences_dialog.h"
24 
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28 
29 #include <webkit2/webkit2.h>
30 
31 #include "common.h"
32 #include "conf.h"
33 #include "enclosure.h"
34 #include "favicon.h"
35 #include "feedlist.h"
36 #include "folder.h"
37 #include "itemlist.h"
38 #include "social.h"
39 #include "ui/enclosure_list_view.h"
40 #include "ui/item_list_view.h"
41 #include "ui/liferea_dialog.h"
42 #include "ui/liferea_shell.h"
43 #include "ui/ui_common.h"
44 #include "ui/itemview.h"
45 
46 /** common private structure for all subscription dialogs */
47 struct PreferencesDialogPrivate {
48 	GtkWidget	*dialog;	/**< the GtkDialog widget */
49 };
50 
51 #define PREFERENCES_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), PREFERENCES_DIALOG_TYPE, PreferencesDialogPrivate))
52 
53 static GObjectClass *parent_class = NULL;
54 
55 G_DEFINE_TYPE (PreferencesDialog, preferences_dialog, G_TYPE_OBJECT);
56 
57 /* file type tree store column ids */
58 enum fts_columns {
59 	FTS_TYPE,	/* file type name */
60 	FTS_CMD,	/* file cmd name */
61 	FTS_PTR,	/* pointer to config entry */
62 	FTS_LEN
63 };
64 
65 extern GSList *bookmarkSites;	/* from social.c */
66 
67 static PreferencesDialog *prefdialog = NULL;
68 
69 /** download tool commands need to take an URI as %s */
70 static const gchar * enclosure_download_commands[] = {
71 	"steadyflow add %s",
72 	"dbus-send --session --print-reply --dest=org.gnome.gwget.ApplicationService /org/gnome/gwget/Gwget org.gnome.gwget.Application.OpenURI string:%s uint32:0",
73 	"kget %s",
74 	"uget-gtk %s",
75 	"transmission-gtk %s",
76 	"aria2 %s"
77 };
78 
79 /** order must match enclosure_download_commands[] */
80 static const gchar *enclosure_download_tool_options[] = { "Steadyflow", "gwget", "KGet", "uGet", "Transmission (Gtk)", "aria2", NULL };
81 
82 /** GConf representation of toolbar styles */
83 static const gchar * gui_toolbar_style_values[] = { "", "both", "both-horiz", "icons", "text", NULL };
84 
85 static const gchar * gui_toolbar_style_options[] = {
86 	N_("GNOME default"),
87 	N_("Text below icons"),
88 	N_("Text beside icons"),
89 	N_("Icons only"),
90 	N_("Text only"),
91 	NULL
92 };
93 
94 /* Note: these update interval literal should be kept in sync with the
95    ones in ui_subscription.c! */
96 
97 static const gchar * default_update_interval_unit_options[] = {
98 	N_("minutes"),
99 	N_("hours"),
100 	N_("days"),
101 	NULL
102 };
103 
104 static const gchar * browser_skim_key_options[] = {
105 	N_("Space"),
106 	N_("<Ctrl> Space"),
107 	N_("<Alt> Space"),
108 	NULL
109 };
110 
111 static const gchar * default_view_mode_options[] = {
112 	N_("Normal View"),
113 	N_("Wide View"),
114 	N_("Combined View"),
115 	NULL
116 };
117 
118 gchar *
prefs_get_download_command(void)119 prefs_get_download_command (void)
120 {
121 	gboolean 	use_custom_command;
122 	gchar 		*result = NULL;
123 
124 	conf_get_bool_value (DOWNLOAD_USE_CUSTOM_COMMAND, &use_custom_command);
125 	if (use_custom_command)
126 		conf_get_str_value (DOWNLOAD_CUSTOM_COMMAND, &result);
127 	else {
128 		gint	enclosure_download_tool;
129 		conf_get_int_value (DOWNLOAD_TOOL, &enclosure_download_tool);
130 		/* FIXME: array boundary check */
131 		result = g_strdup (enclosure_download_commands[enclosure_download_tool]);
132 	}
133 	return result;
134 }
135 
136 /* Preference dialog class */
137 
138 static void
preferences_dialog_finalize(GObject * object)139 preferences_dialog_finalize (GObject *object)
140 {
141 	PreferencesDialog *pd = PREFERENCES_DIALOG (object);
142 
143 	gtk_widget_destroy (pd->priv->dialog);
144 	prefdialog = NULL;
145 
146 	G_OBJECT_CLASS (parent_class)->finalize (object);
147 }
148 
149 static void
preferences_dialog_class_init(PreferencesDialogClass * klass)150 preferences_dialog_class_init (PreferencesDialogClass *klass)
151 {
152 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
153 
154 	parent_class = g_type_class_peek_parent (klass);
155 
156 	object_class->finalize = preferences_dialog_finalize;
157 
158 	g_type_class_add_private (object_class, sizeof (PreferencesDialogPrivate));
159 }
160 
161 /* Preference callbacks */
162 
163 void
on_folderdisplaybtn_toggled(GtkToggleButton * togglebutton,gpointer user_data)164 on_folderdisplaybtn_toggled (GtkToggleButton *togglebutton, gpointer user_data)
165 {
166 	gboolean enabled = gtk_toggle_button_get_active(togglebutton);
167 	conf_set_int_value(FOLDER_DISPLAY_MODE, (TRUE == enabled)?1:0);
168 }
169 
170 /**
171  * The "Hide read items" button has been clicked. Here we change the
172  * preference and, if the selected node is a folder, we reload the
173  * itemlist. The item selection is lost by this.
174  */
175 void
on_folderhidereadbtn_toggled(GtkToggleButton * togglebutton,gpointer user_data)176 on_folderhidereadbtn_toggled (GtkToggleButton *togglebutton, gpointer user_data)
177 {
178 	nodePtr		displayedNode;
179 	gboolean	enabled;
180 
181 	displayedNode = itemlist_get_displayed_node ();
182 
183 	enabled = gtk_toggle_button_get_active (togglebutton);
184 	conf_set_bool_value (FOLDER_DISPLAY_HIDE_READ, enabled);
185 
186 	if (displayedNode && IS_FOLDER (displayedNode)) {
187 		itemlist_unload (FALSE);
188 		itemlist_load (displayedNode);
189 
190 		/* Note: For simplicity when toggling this preference we
191 		   accept that the current item selection is lost. */
192 	}
193 }
194 
195 void
on_startupactionbtn_toggled(GtkButton * button,gpointer user_data)196 on_startupactionbtn_toggled (GtkButton *button, gpointer user_data)
197 {
198 	gboolean enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
199 	conf_set_int_value (STARTUP_FEED_ACTION, enabled?0:1);
200 }
201 
202 void
on_browsercmd_changed(GtkEditable * editable,gpointer user_data)203 on_browsercmd_changed (GtkEditable *editable, gpointer user_data)
204 {
205 	conf_set_str_value (BROWSER_COMMAND, gtk_editable_get_chars (editable,0,-1));
206 }
207 
208 static void
on_browser_changed(GtkComboBox * optionmenu,gpointer user_data)209 on_browser_changed (GtkComboBox *optionmenu, gpointer user_data)
210 {
211 	GtkTreeIter		iter;
212 	gint			num = -1;
213 
214 	if (gtk_combo_box_get_active_iter (optionmenu, &iter)) {
215 		gtk_tree_model_get (gtk_combo_box_get_model (optionmenu), &iter, 1, &num, -1);
216 
217 		gtk_widget_set_sensitive (liferea_dialog_lookup (prefdialog->priv->dialog, "browsercmd"), num != 0);
218 		gtk_widget_set_sensitive (liferea_dialog_lookup (prefdialog->priv->dialog, "manuallabel"), num != 0);
219 		gtk_widget_set_sensitive (liferea_dialog_lookup (prefdialog->priv->dialog, "urlhintlabel"), num != 0);
220 
221 		if (!num)
222 			conf_set_str_value (BROWSER_ID, "default");
223 		else
224 			conf_set_str_value (BROWSER_ID, "manual");
225 	}
226 }
227 
228 void
on_openlinksinsidebtn_clicked(GtkToggleButton * button,gpointer user_data)229 on_openlinksinsidebtn_clicked (GtkToggleButton *button, gpointer user_data)
230 {
231 	conf_set_bool_value (BROWSE_INSIDE_APPLICATION, gtk_toggle_button_get_active (button));
232 }
233 
234 void
on_disablejavascript_toggled(GtkToggleButton * togglebutton,gpointer user_data)235 on_disablejavascript_toggled (GtkToggleButton *togglebutton, gpointer user_data)
236 {
237 	conf_set_bool_value (DISABLE_JAVASCRIPT, gtk_toggle_button_get_active (togglebutton));
238 }
239 
240 void
on_enableplugins_toggled(GtkToggleButton * togglebutton,gpointer user_data)241 on_enableplugins_toggled (GtkToggleButton *togglebutton, gpointer user_data)
242 {
243 	conf_set_bool_value (ENABLE_PLUGINS, gtk_toggle_button_get_active (togglebutton));
244 }
245 
246 static void
on_socialsite_changed(GtkComboBox * optionmenu,gpointer user_data)247 on_socialsite_changed (GtkComboBox *optionmenu, gpointer user_data)
248 {
249 	GtkTreeIter iter;
250 	if (gtk_combo_box_get_active_iter (optionmenu, &iter)) {
251 		gchar * site;
252 		gtk_tree_model_get (gtk_combo_box_get_model (optionmenu), &iter, 0, &site, -1);
253 		social_set_bookmark_site (site);
254 	}
255 }
256 
257 static void
on_gui_toolbar_style_changed(gpointer user_data)258 on_gui_toolbar_style_changed (gpointer user_data)
259 {
260 	gchar *style;
261 	gint value = gtk_combo_box_get_active (GTK_COMBO_BOX (user_data));
262 	conf_set_str_value (TOOLBAR_STYLE, gui_toolbar_style_values[value]);
263 
264 	style = conf_get_toolbar_style ();
265 	liferea_shell_set_toolbar_style (style);
266 	g_free (style);
267 }
268 
269 void
on_itemCountBtn_value_changed(GtkSpinButton * spinbutton,gpointer user_data)270 on_itemCountBtn_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
271 {
272 	GtkAdjustment	*itemCount;
273 
274 	itemCount = gtk_spin_button_get_adjustment (spinbutton);
275 	conf_set_int_value (DEFAULT_MAX_ITEMS, gtk_adjustment_get_value (itemCount));
276 }
277 
278 void
on_default_update_interval_value_changed(GtkSpinButton * spinbutton,gpointer user_data)279 on_default_update_interval_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
280 {
281 	gint			updateInterval, intervalUnit;
282 	GtkWidget		*unitWidget, *valueWidget;
283 
284 	unitWidget = liferea_dialog_lookup (prefdialog->priv->dialog, "globalRefreshIntervalUnitComboBox");
285 	valueWidget = liferea_dialog_lookup (prefdialog->priv->dialog, "globalRefreshIntervalSpinButton");
286 	intervalUnit = gtk_combo_box_get_active (GTK_COMBO_BOX (unitWidget));
287 	updateInterval = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (valueWidget));
288 
289 	if (intervalUnit == 1)
290 		updateInterval *= 60;		/* hours */
291 	else if (intervalUnit == 2)
292 		updateInterval *= 1440;		/* days */
293 
294 	conf_set_int_value (DEFAULT_UPDATE_INTERVAL, updateInterval);
295 }
296 
297 static void
on_default_update_interval_unit_changed(gpointer user_data)298 on_default_update_interval_unit_changed (gpointer user_data)
299 {
300 	on_default_update_interval_value_changed (NULL, prefdialog);
301 }
302 
303 static void
on_updateallfavicons_clicked(GtkButton * button,gpointer user_data)304 on_updateallfavicons_clicked (GtkButton *button, gpointer user_data)
305 {
306 	feedlist_foreach (node_update_favicon);
307 }
308 
309 static void
on_proxyAutoDetect_clicked(GtkButton * button,gpointer user_data)310 on_proxyAutoDetect_clicked (GtkButton *button, gpointer user_data)
311 {
312 	conf_set_int_value (PROXY_DETECT_MODE, 0);
313 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (prefdialog->priv->dialog, "proxybox")), FALSE);
314 }
315 
316 static void
on_noProxy_clicked(GtkButton * button,gpointer user_data)317 on_noProxy_clicked (GtkButton *button, gpointer user_data)
318 {
319 	conf_set_int_value (PROXY_DETECT_MODE, 1);
320 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (prefdialog->priv->dialog, "proxybox")), FALSE);
321 }
322 
323 static void
on_manualProxy_clicked(GtkButton * button,gpointer user_data)324 on_manualProxy_clicked (GtkButton *button, gpointer user_data)
325 {
326 	conf_set_int_value (PROXY_DETECT_MODE, 2);
327 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (prefdialog->priv->dialog, "proxybox")), TRUE);
328 }
329 
330 void
on_useProxyAuth_toggled(GtkToggleButton * button,gpointer user_data)331 on_useProxyAuth_toggled (GtkToggleButton *button, gpointer user_data)
332 {
333 	gboolean enabled = gtk_toggle_button_get_active (button);
334 
335 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (prefdialog->priv->dialog, "proxyauthtable")), enabled);
336 	conf_set_bool_value (PROXY_USEAUTH, enabled);
337 }
338 
339 static void
on_proxyhostentry_changed(GtkEditable * editable,gpointer user_data)340 on_proxyhostentry_changed (GtkEditable *editable, gpointer user_data)
341 {
342 	conf_set_str_value (PROXY_HOST, gtk_editable_get_chars (editable,0,-1));
343 }
344 
345 static void
on_proxyportentry_changed(GtkEditable * editable,gpointer user_data)346 on_proxyportentry_changed (GtkEditable *editable, gpointer user_data)
347 {
348 	conf_set_int_value (PROXY_PORT, atoi (gtk_editable_get_chars (editable,0,-1)));
349 }
350 
351 static void
on_proxyusernameentry_changed(GtkEditable * editable,gpointer user_data)352 on_proxyusernameentry_changed (GtkEditable *editable, gpointer user_data)
353 {
354 	conf_set_str_value (PROXY_USER, gtk_editable_get_chars (editable,0,-1));
355 }
356 
357 static void
on_proxypasswordentry_changed(GtkEditable * editable,gpointer user_data)358 on_proxypasswordentry_changed (GtkEditable *editable, gpointer user_data)
359 {
360 	conf_set_str_value (PROXY_PASSWD, gtk_editable_get_chars (editable,0,-1));
361 }
362 
363 static void
on_skim_key_changed(gpointer user_data)364 on_skim_key_changed (gpointer user_data)
365 {
366 	conf_set_int_value (BROWSE_KEY_SETTING, gtk_combo_box_get_active (GTK_COMBO_BOX (user_data)));
367 }
368 
369 static void
on_default_view_mode_changed(gpointer user_data)370 on_default_view_mode_changed (gpointer user_data)
371 {
372 	conf_set_int_value (DEFAULT_VIEW_MODE, gtk_combo_box_get_active (GTK_COMBO_BOX (user_data)));
373 }
374 
375 void
on_enclosure_download_predefined_toggled(GtkToggleButton * button,gpointer user_data)376 on_enclosure_download_predefined_toggled (GtkToggleButton *button, gpointer user_data)
377 {
378 	gboolean is_active = gtk_toggle_button_get_active (button);
379 
380 	gtk_widget_set_sensitive (liferea_dialog_lookup (prefdialog->priv->dialog, "customDownloadEntry"), !is_active);
381 	gtk_widget_set_sensitive (liferea_dialog_lookup (prefdialog->priv->dialog, "downloadToolCombo"), is_active);
382 	conf_set_bool_value (DOWNLOAD_USE_CUSTOM_COMMAND, !is_active);
383 }
384 
385 static void
on_enclosure_download_tool_changed(gpointer user_data)386 on_enclosure_download_tool_changed (gpointer user_data)
387 {
388 	conf_set_int_value (DOWNLOAD_TOOL, gtk_combo_box_get_active (GTK_COMBO_BOX (user_data)));
389 }
390 
391 void
on_enclosure_download_custom_command_changed(GtkEditable * entry,gpointer user_data)392 on_enclosure_download_custom_command_changed (GtkEditable *entry, gpointer user_data)
393 {
394 	conf_set_str_value (DOWNLOAD_CUSTOM_COMMAND, gtk_entry_get_text (GTK_ENTRY (entry)));
395 }
396 
397 void
on_enc_action_change_btn_clicked(GtkButton * button,gpointer user_data)398 on_enc_action_change_btn_clicked (GtkButton *button, gpointer user_data)
399 {
400 	GtkTreeModel		*model;
401 	GtkTreeSelection	*selection;
402 	GtkTreeIter		iter;
403 	gpointer		type;
404 
405 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (liferea_dialog_lookup (prefdialog->priv->dialog, "enc_action_view")));
406 	if(gtk_tree_selection_get_selected (selection, &model, &iter)) {
407 		gtk_tree_model_get (model, &iter, FTS_PTR, &type, -1);
408 		ui_enclosure_change_type (type);
409 		gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
410 		                    FTS_CMD, ((encTypePtr)type)->cmd, -1);
411 	}
412 }
413 
414 void
on_enc_action_remove_btn_clicked(GtkButton * button,gpointer user_data)415 on_enc_action_remove_btn_clicked (GtkButton *button, gpointer user_data)
416 {
417 	GtkTreeModel		*model;
418 	GtkTreeSelection	*selection;
419 	GtkTreeIter		iter;
420 	gpointer		type;
421 
422 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (liferea_dialog_lookup (prefdialog->priv->dialog, "enc_action_view")));
423 	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
424 		gtk_tree_model_get (model, &iter, FTS_PTR, &type, -1);
425 		gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
426 		enclosure_mime_type_remove (type);
427 	}
428 }
429 
430 void
on_hidetoolbar_toggled(GtkToggleButton * button,gpointer user_data)431 on_hidetoolbar_toggled (GtkToggleButton *button, gpointer user_data)
432 {
433 	conf_set_bool_value (DISABLE_TOOLBAR, gtk_toggle_button_get_active (button));
434 	liferea_shell_update_toolbar ();
435 }
436 
437 void
on_donottrackbtn_toggled(GtkToggleButton * button,gpointer user_data)438 on_donottrackbtn_toggled (GtkToggleButton *button, gpointer user_data)
439 {
440 	conf_set_bool_value (DO_NOT_TRACK, gtk_toggle_button_get_active (button));
441 }
442 
443 static void
preferences_dialog_destroy_cb(GtkWidget * widget,PreferencesDialog * pd)444 preferences_dialog_destroy_cb (GtkWidget *widget, PreferencesDialog *pd)
445 {
446 	g_object_unref (pd);
447 }
448 
449 void
preferences_dialog_init(PreferencesDialog * pd)450 preferences_dialog_init (PreferencesDialog *pd)
451 {
452 	GtkWidget		*widget, *entry;
453 	GtkComboBox		*combo;
454 	GtkListStore		*store;
455 	GtkTreeIter		treeiter;
456 	GtkAdjustment		*itemCount;
457 	GtkTreeStore		*treestore;
458 	GtkTreeViewColumn 	*column;
459 	GSList			*list;
460 	gchar			*proxyport;
461 	gchar			*configuredBrowser, *name;
462 	gboolean		enabled;
463 	gint			tmp, i, iSetting, proxy_port;
464 	gboolean		bSetting, manualBrowser;
465 	gchar			*proxy_host, *proxy_user, *proxy_passwd;
466 	gchar			*browser_command;
467 	gchar 			*custom_download_command;
468 
469 	prefdialog = pd;
470 	pd->priv = PREFERENCES_DIALOG_GET_PRIVATE (pd);
471 	pd->priv->dialog = liferea_dialog_new ("prefs");
472 
473 	/* Set up browser selection popup */
474 	store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
475 	gtk_list_store_append (store, &treeiter);
476 	gtk_list_store_set (store, &treeiter, 0, _("Default Browser"), 1, 0, -1);
477 	gtk_list_store_append (store, &treeiter);
478 	gtk_list_store_set (store, &treeiter, 0, _("Manual"), 1, 1, -1);
479 
480 	combo = GTK_COMBO_BOX (liferea_dialog_lookup (pd->priv->dialog, "browserpopup"));
481 	gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
482 	ui_common_setup_combo_text (combo, 0);
483 	g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(on_browser_changed), pd);
484 
485 	/* ================== panel 1 "feeds" ==================== */
486 
487 	/* check box for feed startup update */
488 	conf_get_int_value (STARTUP_FEED_ACTION, &iSetting);
489 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "startupactionbtn")), (iSetting == 0));
490 
491 	/* cache size setting */
492 	widget = liferea_dialog_lookup (pd->priv->dialog, "itemCountBtn");
493 	itemCount = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget));
494 	conf_get_int_value (DEFAULT_MAX_ITEMS, &iSetting);
495 	gtk_adjustment_set_value (itemCount, iSetting);
496 
497 	/* set default update interval spin button and unit combo box */
498 	ui_common_setup_combo_menu (liferea_dialog_lookup (pd->priv->dialog, "globalRefreshIntervalUnitComboBox"),
499 	                            default_update_interval_unit_options,
500 	                            G_CALLBACK (on_default_update_interval_unit_changed),
501 				    -1);
502 
503 	widget = liferea_dialog_lookup (pd->priv->dialog, "globalRefreshIntervalUnitComboBox");
504 	conf_get_int_value (DEFAULT_UPDATE_INTERVAL, &tmp);
505 	if (tmp % 1440 == 0) {		/* days */
506 		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 2);
507 		tmp /= 1440;
508 	} else if (tmp % 60 == 0) {	/* hours */
509 		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
510 		tmp /= 60;
511 	} else {			/* minutes */
512 		gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
513 	}
514 	widget = liferea_dialog_lookup (pd->priv->dialog,"globalRefreshIntervalSpinButton");
515 	gtk_spin_button_set_range (GTK_SPIN_BUTTON (widget), 0, 1000000000);
516 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), tmp);
517 	g_signal_connect (G_OBJECT (widget), "changed", G_CALLBACK (on_default_update_interval_value_changed), pd);
518 
519 	/* ================== panel 2 "folders" ==================== */
520 
521 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "updateAllFavicons")), "clicked", G_CALLBACK(on_updateallfavicons_clicked), pd);
522 
523 	conf_get_int_value (FOLDER_DISPLAY_MODE, &iSetting);
524 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "folderdisplaybtn")), iSetting?TRUE:FALSE);
525 	conf_get_bool_value (FOLDER_DISPLAY_HIDE_READ, &bSetting);
526 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "hidereadbtn")), bSetting?TRUE:FALSE);
527 
528 	/* ================== panel 3 "headlines" ==================== */
529 
530 	conf_get_int_value (BROWSE_KEY_SETTING, &iSetting);
531 	ui_common_setup_combo_menu (liferea_dialog_lookup (pd->priv->dialog, "skimKeyCombo"),
532 	                            browser_skim_key_options,
533 	                            G_CALLBACK (on_skim_key_changed),
534 	                            iSetting);
535 
536 	conf_get_int_value (DEFAULT_VIEW_MODE, &iSetting);
537 	ui_common_setup_combo_menu (liferea_dialog_lookup (pd->priv->dialog, "defaultViewModeCombo"),
538 	                            default_view_mode_options,
539 	                            G_CALLBACK (on_default_view_mode_changed),
540 	                            iSetting);
541 
542 	/* Setup social bookmarking list */
543 	i = 0;
544 	conf_get_str_value (SOCIAL_BM_SITE, &name);
545 	store = gtk_list_store_new (1, G_TYPE_STRING);
546 	list = bookmarkSites;
547 	while (list) {
548 		socialSitePtr siter = list->data;
549 		if (name && !strcmp (siter->name, name))
550 			tmp = i;
551 		gtk_list_store_append (store, &treeiter);
552 		gtk_list_store_set (store, &treeiter, 0, siter->name, -1);
553 		list = g_slist_next (list);
554 		i++;
555 	}
556 
557 	combo = GTK_COMBO_BOX (liferea_dialog_lookup (pd->priv->dialog, "socialpopup"));
558 	g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (on_socialsite_changed), pd);
559 	gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
560 	ui_common_setup_combo_text (combo, 0);
561 	gtk_combo_box_set_active (combo, tmp);
562 
563 	/* ================== panel 4 "browser" ==================== */
564 
565 	/* set the inside browsing flag */
566 	widget = liferea_dialog_lookup(pd->priv->dialog, "browseinwindow");
567 	conf_get_bool_value(BROWSE_INSIDE_APPLICATION, &bSetting);
568 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), bSetting);
569 
570 	/* set the javascript-disabled flag */
571 	widget = liferea_dialog_lookup(pd->priv->dialog, "disablejavascript");
572 	conf_get_bool_value(DISABLE_JAVASCRIPT, &bSetting);
573 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), bSetting);
574 
575 	/* set the enable Plugins flag */
576 	widget = liferea_dialog_lookup(pd->priv->dialog, "enableplugins");
577 	conf_get_bool_value(ENABLE_PLUGINS, &bSetting);
578 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), bSetting);
579 
580 	conf_get_str_value (BROWSER_ID, &configuredBrowser);
581 	manualBrowser = !strcmp (configuredBrowser, "manual");
582 	g_free (configuredBrowser);
583 
584 	gtk_combo_box_set_active (GTK_COMBO_BOX (liferea_dialog_lookup (pd->priv->dialog, "browserpopup")), manualBrowser);
585 
586 	conf_get_str_value (BROWSER_COMMAND, &browser_command);
587 	entry = liferea_dialog_lookup (pd->priv->dialog, "browsercmd");
588 	gtk_entry_set_text (GTK_ENTRY(entry), browser_command);
589 	g_free (browser_command);
590 
591 	gtk_widget_set_sensitive (GTK_WIDGET (entry), manualBrowser);
592 	gtk_widget_set_sensitive (liferea_dialog_lookup (pd->priv->dialog, "manuallabel"), manualBrowser);
593 	gtk_widget_set_sensitive (liferea_dialog_lookup (pd->priv->dialog, "urlhintlabel"), manualBrowser);
594 
595 	/* ================== panel 4 "GUI" ================ */
596 
597 	/* tool bar settings */
598 	widget = liferea_dialog_lookup (pd->priv->dialog, "hidetoolbarbtn");
599 	conf_get_bool_value(DISABLE_TOOLBAR, &bSetting);
600 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), bSetting);
601 
602 	/* select currently active toolbar style option */
603 	conf_get_str_value (TOOLBAR_STYLE, &name);
604 	for (i = 0; gui_toolbar_style_values[i] != NULL; ++i) {
605 		if (strcmp (name, gui_toolbar_style_values[i]) == 0)
606 			break;
607 	}
608 	g_free (name);
609 
610 	/* On invalid key value: revert to default */
611 	if (gui_toolbar_style_values[i] == NULL)
612 		i = 0;
613 
614 	/* create toolbar style menu */
615 	ui_common_setup_combo_menu (liferea_dialog_lookup (pd->priv->dialog, "toolbarCombo"),
616 	                            gui_toolbar_style_options,
617 	                            G_CALLBACK (on_gui_toolbar_style_changed),
618 	                            i);
619 
620 	conf_bind (CONFIRM_MARK_ALL_READ, liferea_dialog_lookup (pd->priv->dialog, "confirmMarkAllReadButton"), "active", G_SETTINGS_BIND_DEFAULT);
621 
622 	/* ================= panel 5 "proxy" ======================== */
623 
624 #if WEBKIT_CHECK_VERSION (2, 15, 3)
625 	gtk_widget_destroy (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "proxyDisabledInfobar")));
626 	conf_get_str_value (PROXY_HOST, &proxy_host);
627 	gtk_entry_set_text (GTK_ENTRY (liferea_dialog_lookup (pd->priv->dialog, "proxyhostentry")), proxy_host);
628 	g_free (proxy_host);
629 
630 	conf_get_int_value (PROXY_PORT, &proxy_port);
631 	proxyport = g_strdup_printf ("%d", proxy_port);
632 	gtk_entry_set_text (GTK_ENTRY (liferea_dialog_lookup (pd->priv->dialog, "proxyportentry")), proxyport);
633 	g_free (proxyport);
634 
635 	conf_get_bool_value (PROXY_USEAUTH, &enabled);
636 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "useProxyAuth")), enabled);
637 
638 	conf_get_str_value (PROXY_USER, &proxy_user);
639 	gtk_entry_set_text (GTK_ENTRY (liferea_dialog_lookup (pd->priv->dialog, "proxyusernameentry")), proxy_user);
640 	g_free (proxy_user);
641 
642 	conf_get_str_value (PROXY_PASSWD, &proxy_passwd);
643 	gtk_entry_set_text (GTK_ENTRY (liferea_dialog_lookup (pd->priv->dialog, "proxypasswordentry")), proxy_passwd);
644 	g_free (proxy_passwd);
645 
646 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup(pd->priv->dialog, "proxyauthtable")), enabled);
647 
648 	conf_get_int_value (PROXY_DETECT_MODE, &i);
649 	switch (i) {
650 		default:
651 		case 0: /* proxy auto detect */
652 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "proxyAutoDetectRadio")), TRUE);
653 			enabled = FALSE;
654 			break;
655 		case 1: /* no proxy */
656 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "noProxyRadio")), TRUE);
657 			enabled = FALSE;
658 			break;
659 		case 2: /* manual proxy */
660 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (pd->priv->dialog, "manualProxyRadio")), TRUE);
661 			enabled = TRUE;
662 			break;
663 	}
664 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "proxybox")), enabled);
665 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "proxyAutoDetectRadio")), "clicked", G_CALLBACK (on_proxyAutoDetect_clicked), pd);
666 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "noProxyRadio")), "clicked", G_CALLBACK (on_noProxy_clicked), pd);
667 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "manualProxyRadio")), "clicked", G_CALLBACK (on_manualProxy_clicked), pd);
668 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "proxyhostentry")), "changed", G_CALLBACK (on_proxyhostentry_changed), pd);
669 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "proxyportentry")), "changed", G_CALLBACK (on_proxyportentry_changed), pd);
670 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "proxyusernameentry")), "changed", G_CALLBACK (on_proxyusernameentry_changed), pd);
671 	g_signal_connect (G_OBJECT (liferea_dialog_lookup (pd->priv->dialog, "proxypasswordentry")), "changed", G_CALLBACK (on_proxypasswordentry_changed), pd);
672 #else
673 	gtk_widget_show (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "proxyDisabledInfobar")));
674 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "proxybox")), FALSE);
675 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "proxyAutoDetectRadio")), TRUE);
676 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "noProxyRadio")), FALSE);
677 	gtk_widget_set_sensitive (GTK_WIDGET (liferea_dialog_lookup (pd->priv->dialog, "manualProxyRadio")), FALSE);
678 #endif
679 
680 	/* ================= panel 6 "Privacy" ======================== */
681 
682 	widget = liferea_dialog_lookup (pd->priv->dialog, "donottrackbtn");
683 	conf_get_bool_value (DO_NOT_TRACK, &bSetting);
684 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), bSetting);
685 
686 	/* ================= panel 7 "Enclosures" ======================== */
687 
688 	/* menu for download tool */
689 	conf_get_int_value (DOWNLOAD_TOOL, &iSetting);
690 	ui_common_setup_combo_menu (liferea_dialog_lookup (pd->priv->dialog, "downloadToolCombo"),
691 	                            enclosure_download_tool_options,
692 	                            G_CALLBACK (on_enclosure_download_tool_changed),
693 	                            iSetting);
694 
695 	/* restore toggle */
696 	conf_get_bool_value (DOWNLOAD_USE_CUSTOM_COMMAND, &bSetting);
697 	widget = liferea_dialog_lookup (pd->priv->dialog, "customDownload");
698 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), bSetting);
699 	gtk_widget_set_sensitive (liferea_dialog_lookup (pd->priv->dialog, "customDownloadEntry"), bSetting);
700 	gtk_widget_set_sensitive (liferea_dialog_lookup (pd->priv->dialog, "downloadToolCombo"), !bSetting);
701 
702 	/* restore custom command */
703 	conf_get_str_value (DOWNLOAD_CUSTOM_COMMAND, &custom_download_command);
704 	widget = liferea_dialog_lookup (pd->priv->dialog, "customDownloadEntry");
705 	gtk_entry_set_text (GTK_ENTRY (widget), custom_download_command);
706 	g_free (custom_download_command);
707 
708 	/* set up list of configured enclosure types */
709 	treestore = gtk_tree_store_new (FTS_LEN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
710 	list = (GSList *)enclosure_mime_types_get ();
711 	while (list) {
712 		GtkTreeIter *newIter = g_new0 (GtkTreeIter, 1);
713 		gtk_tree_store_append (treestore, newIter, NULL);
714 		gtk_tree_store_set (treestore, newIter,
715 	                	    FTS_TYPE, (NULL != ((encTypePtr)(list->data))->mime)?((encTypePtr)(list->data))->mime:((encTypePtr)(list->data))->extension,
716 	                	    FTS_CMD, ((encTypePtr)(list->data))->cmd,
717 	                	    FTS_PTR, list->data,
718 				    -1);
719 		list = g_slist_next (list);
720 	}
721 
722 	widget = liferea_dialog_lookup (pd->priv->dialog, "enc_action_view");
723 	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), GTK_TREE_MODEL (treestore));
724 
725 	column = gtk_tree_view_column_new_with_attributes (_("Type"), gtk_cell_renderer_text_new (), "text", FTS_TYPE, NULL);
726 	gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column);
727 	gtk_tree_view_column_set_sort_column_id (column, FTS_TYPE);
728 	column = gtk_tree_view_column_new_with_attributes (_("Program"), gtk_cell_renderer_text_new (), "text", FTS_CMD, NULL);
729 	gtk_tree_view_column_set_sort_column_id (column, FTS_CMD);
730 	gtk_tree_view_append_column (GTK_TREE_VIEW(widget), column);
731 
732 	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW(widget)), GTK_SELECTION_SINGLE);
733 
734 	g_signal_connect_object (pd->priv->dialog, "destroy", G_CALLBACK (preferences_dialog_destroy_cb), pd, 0);
735 
736 	gtk_widget_show_all (pd->priv->dialog);
737 
738 	gtk_window_present (GTK_WINDOW (pd->priv->dialog));
739 }
740 
741 void
preferences_dialog_open(void)742 preferences_dialog_open (void)
743 {
744 	if (prefdialog) {
745 		gtk_widget_show (prefdialog->priv->dialog);
746 		return;
747 	}
748 
749 	g_object_new (PREFERENCES_DIALOG_TYPE, NULL);
750 }
751