diff options
Diffstat (limited to 'frontends/gtk/preferences.c')
-rw-r--r-- | frontends/gtk/preferences.c | 1030 |
1 files changed, 1030 insertions, 0 deletions
diff --git a/frontends/gtk/preferences.c b/frontends/gtk/preferences.c new file mode 100644 index 000000000..3efb9eddd --- /dev/null +++ b/frontends/gtk/preferences.c @@ -0,0 +1,1030 @@ +/* + * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org> + * + * This file is part of NetSurf, http://www.netsurf-browser.org/ + * + * NetSurf is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * NetSurf is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <math.h> +#include <string.h> + +#include "utils/messages.h" +#include "utils/nsoption.h" +#include "utils/file.h" +#include "utils/log.h" +#include "utils/nsurl.h" +#include "desktop/browser.h" +#include "desktop/searchweb.h" + +#include "gtk/compat.h" +#include "gtk/window.h" +#include "gtk/gui.h" +#include "gtk/scaffolding.h" +#include "gtk/resources.h" +#include "gtk/preferences.h" + +/* private prefs */ +struct ppref { + /** dialog handle created when window first accessed */ + GObject *dialog; + + struct browser_window *bw; + + /* widgets which are accessed from outside their own signal handlers */ + GtkEntry *entryHomePageURL; + GtkEntry *entryProxyHost; + GtkEntry *entryProxyUser; + GtkEntry *entryProxyPassword; + GtkEntry *entryProxyNoproxy; + GtkSpinButton *spinProxyPort; + + /* dynamic list stores */ + GtkListStore *content_language; + GtkListStore *search_providers; +}; + +static struct ppref ppref; + + +/* Set netsurf option based on toggle button state + * + * This works for any widget which subclasses togglebutton (checkbox, + * radiobutton etc.) + */ +#define TOGGLEBUTTON_SIGNALS(WIDGET, OPTION) \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_toggled(GtkToggleButton *togglebutton, \ + struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_toggled(GtkToggleButton *togglebutton, \ + struct ppref *priv) \ +{ \ + nsoption_set_bool(OPTION, \ + gtk_toggle_button_get_active(togglebutton)); \ +} \ + \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, \ + struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, \ + struct ppref *priv) \ +{ \ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), \ + nsoption_bool(OPTION)); \ +} + +#define SPINBUTTON_SIGNALS(WIDGET, OPTION, MULTIPLIER) \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \ + struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \ + struct ppref *priv) \ +{ \ + nsoption_set_int(OPTION, \ + round(gtk_spin_button_get_value(spinbutton) * MULTIPLIER)); \ +} \ + \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \ +{ \ + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), \ + ((gdouble)nsoption_int(OPTION)) / MULTIPLIER); \ +} + +#define SPINBUTTON_UINT_SIGNALS(WIDGET, OPTION, MULTIPLIER) \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \ + struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_valuechanged(GtkSpinButton *spinbutton, \ + struct ppref *priv) \ +{ \ + nsoption_set_uint(OPTION, \ + round(gtk_spin_button_get_value(spinbutton) * MULTIPLIER)); \ +} \ + \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \ +{ \ + gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), \ + ((gdouble)nsoption_uint(OPTION)) / MULTIPLIER); \ +} + +#define ENTRY_SIGNALS(WIDGET, OPTION) \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_changed(GtkEditable *editable, struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_changed(GtkEditable *editable, struct ppref *priv)\ +{ \ + nsoption_set_charp(OPTION, \ + strdup(gtk_entry_get_text(GTK_ENTRY(editable)))); \ +} \ + \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv); \ +G_MODULE_EXPORT void \ +nsgtk_preferences_##WIDGET##_realize(GtkWidget *widget, struct ppref *priv) \ +{ \ + const char *OPTION; \ + OPTION = nsoption_charp(OPTION); \ + if (OPTION != NULL) { \ + gtk_entry_set_text(GTK_ENTRY(widget), OPTION); \ + } \ +} + +/* GTK module requires these to be exported symbols so these all need + * forward declaring to avoid warnings + */ +G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_changed(GtkComboBox *combo, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboProxyType_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboDefault_changed(GtkComboBox *combo, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboDefault_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_changed(GtkComboBox *combo, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboboxLanguage_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_checkShowSingleTab_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboTabPosition_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_changed(GtkComboBox *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboDeveloperView_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboButtonType_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_setDefaultPage_clicked(GtkButton *button, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_selectionchanged(GtkFileChooser *chooser, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_fileChooserDownloads_realize(GtkWidget *widget, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_response(GtkDialog *dlg, gint resid); +G_MODULE_EXPORT gboolean nsgtk_preferences_dialogPreferences_deleteevent(GtkDialog *dlg, struct ppref *priv); +G_MODULE_EXPORT void nsgtk_preferences_dialogPreferences_destroy(GtkDialog *dlg, struct ppref *priv); + + +/********* PDF **********/ + +/* Appearance */ + +/* no images in output */ +TOGGLEBUTTON_SIGNALS(checkSuppressImages, suppress_images) + +/* no background images */ +TOGGLEBUTTON_SIGNALS(checkRemoveBackgrounds, remove_backgrounds) + +/* scale to fit page */ +TOGGLEBUTTON_SIGNALS(checkFitPage, enable_loosening) + +/* port */ +SPINBUTTON_SIGNALS(spinExportScale, export_scale, 1.0) + +/* Margins */ +SPINBUTTON_SIGNALS(spinMarginTop, margin_top, 1.0) +SPINBUTTON_SIGNALS(spinMarginBottom, margin_bottom, 1.0) +SPINBUTTON_SIGNALS(spinMarginLeft, margin_left, 1.0) +SPINBUTTON_SIGNALS(spinMarginRight, margin_right, 1.0) + + +/* Generation */ + +/* output is compressed */ +TOGGLEBUTTON_SIGNALS(checkCompressPDF, enable_PDF_compression) + +/* output has a password */ +TOGGLEBUTTON_SIGNALS(checkPasswordPDF, enable_PDF_password) + +/********* Network **********/ + +/* HTTP proxy */ +static void set_proxy_widgets_sensitivity(int proxyval, struct ppref *priv) +{ + gboolean host; + gboolean port; + gboolean user; + gboolean pass; + gboolean noproxy; + + switch (proxyval) { + case 0: /* no proxy */ + host = FALSE; + port = FALSE; + user = FALSE; + pass = FALSE; + noproxy = FALSE; + break; + + case 1: /* proxy with no auth */ + host = TRUE; + port = TRUE; + user = FALSE; + pass = FALSE; + noproxy = TRUE; + break; + + case 2: /* proxy with basic auth */ + host = TRUE; + port = TRUE; + user = TRUE; + pass = TRUE; + noproxy = TRUE; + break; + + case 3: /* proxy with ntlm auth */ + host = TRUE; + port = TRUE; + user = TRUE; + pass = TRUE; + noproxy = TRUE; + break; + + case 4: /* system proxy */ + host = FALSE; + port = FALSE; + user = FALSE; + pass = FALSE; + noproxy = FALSE; + break; + + default: + return; + } + + gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyHost), host); + gtk_widget_set_sensitive(GTK_WIDGET(priv->spinProxyPort), port); + gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyUser), user); + gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyPassword), pass); + gtk_widget_set_sensitive(GTK_WIDGET(priv->entryProxyNoproxy), noproxy); + +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboProxyType_changed(GtkComboBox *combo, struct ppref *priv) +{ + int proxy_sel; + proxy_sel = gtk_combo_box_get_active(combo); + + switch (proxy_sel) { + case 0: /* no proxy */ + nsoption_set_bool(http_proxy, false); + break; + + case 1: /* proxy with no auth */ + nsoption_set_bool(http_proxy, true); + nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_NONE); + break; + + case 2: /* proxy with basic auth */ + nsoption_set_bool(http_proxy, true); + nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_BASIC); + break; + + case 3: /* proxy with ntlm auth */ + nsoption_set_bool(http_proxy, true); + nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_NTLM); + break; + + case 4: /* system proxy */ + nsoption_set_bool(http_proxy, true); + nsoption_set_int(http_proxy_auth, OPTION_HTTP_PROXY_AUTH_NONE); + break; + } + + set_proxy_widgets_sensitivity(proxy_sel, priv); +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboProxyType_realize(GtkWidget *widget, struct ppref *priv) +{ + int proxytype = 0; /* no proxy by default */ + + if (nsoption_bool(http_proxy) == true) { + /* proxy type combo box starts with disabled, to allow + * for this the http_proxy option needs combining with + * the http_proxy_auth option + */ + proxytype = nsoption_int(http_proxy_auth) + 1; + if (nsoption_charp(http_proxy_host) == NULL) { + /* set to use a proxy without a host, turn proxy off */ + proxytype = 0; + } else if (((proxytype == 2) || + (proxytype == 3)) && + ((nsoption_charp(http_proxy_auth_user) == NULL) || + (nsoption_charp(http_proxy_auth_pass) == NULL))) { + /* authentication selected with empty credentials, turn proxy off */ + proxytype = 0; + } + } + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), proxytype); + + set_proxy_widgets_sensitivity(proxytype, priv); +} + +/* host */ +ENTRY_SIGNALS(entryProxyHost, http_proxy_host) + +/* port */ +SPINBUTTON_SIGNALS(spinProxyPort, http_proxy_port, 1.0) + +/* user */ +ENTRY_SIGNALS(entryProxyUser, http_proxy_auth_user) + +/* password */ +ENTRY_SIGNALS(entryProxyPassword, http_proxy_auth_pass) + +/* no proxy */ +ENTRY_SIGNALS(entryProxyNoproxy, http_proxy_noproxy) + +/* Fetching */ + +/* maximum fetchers */ +SPINBUTTON_SIGNALS(spinMaxFetchers, max_fetchers, 1.0) + +/* fetches per host */ +SPINBUTTON_SIGNALS(spinFetchesPerHost, max_fetchers_per_host, 1.0) + +/* cached connections */ +SPINBUTTON_SIGNALS(spinCachedConnections, max_cached_fetch_handles, 1.0) + + +/********* Privacy **********/ + +/* General */ + +/* enable referral submission */ +TOGGLEBUTTON_SIGNALS(checkSendReferer, send_referer) + +/* send do not track */ +TOGGLEBUTTON_SIGNALS(checkSendDNT, do_not_track) + +/* History */ + +/* local history shows url tooltips */ +TOGGLEBUTTON_SIGNALS(checkHoverURLs, hover_urls) + +/* remember browsing history */ +SPINBUTTON_SIGNALS(spinHistoryAge, history_age, 1.0) + +/* Cache */ + +/* memory cache size */ +SPINBUTTON_SIGNALS(spinMemoryCacheSize, memory_cache_size, (1024*1024)) + +/* disc cache size */ +SPINBUTTON_UINT_SIGNALS(spinDiscCacheSize, disc_cache_size, (1024*1024)) + + +/* disc cache age */ +SPINBUTTON_SIGNALS(spinDiscCacheAge, disc_cache_age, 1.0) + + +/********* Content **********/ + +/* Control */ + + +/* prevent popups */ +TOGGLEBUTTON_SIGNALS(checkDisablePopups, disable_popups) + +/* hide adverts */ +TOGGLEBUTTON_SIGNALS(checkHideAdverts, block_advertisements) + +/* enable javascript */ +TOGGLEBUTTON_SIGNALS(checkEnableJavascript, enable_javascript) + +/* disable plugins */ +TOGGLEBUTTON_SIGNALS(checkDisablePlugins, disable_plugins) + +/* high quality image scaling */ +TOGGLEBUTTON_SIGNALS(checkResampleImages, render_resample) + +/* load and display of images */ +G_MODULE_EXPORT void +nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo, + struct ppref *priv) +{ + int img_sel; + /* get the row number for the selection */ + img_sel = gtk_combo_box_get_active(combo); + switch (img_sel) { + case 0: + /* background and foreground */ + nsoption_set_bool(foreground_images, true); + nsoption_set_bool(background_images, true); + break; + + case 1: + /* foreground only */ + nsoption_set_bool(foreground_images, true); + nsoption_set_bool(background_images, false); + break; + + case 2: + /* background only */ + nsoption_set_bool(foreground_images, false); + nsoption_set_bool(background_images, true); + break; + + case 3: + /* no images */ + nsoption_set_bool(foreground_images, false); + nsoption_set_bool(background_images, false); + break; + } +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget, + struct ppref *priv) +{ + if (nsoption_bool(foreground_images)) { + if (nsoption_bool(background_images)) { + /* background and foreground */ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 0); + } else { + /* foreground only */ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 1); + } + } else { + if (nsoption_bool(background_images)) { + /* background only */ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 2); + } else { + /* no images */ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), 3); + } + } +} + +/* Animation */ + +/* enable animation */ +TOGGLEBUTTON_SIGNALS(checkEnableAnimations, animate_images) + +/* frame time */ +SPINBUTTON_SIGNALS(spinAnimationSpeed, minimum_gif_delay, 100.0) + +/* Fonts */ + +/* default font */ +G_MODULE_EXPORT void +nsgtk_preferences_comboDefault_changed(GtkComboBox *combo, struct ppref *priv) +{ + int font_sel; + /* get the row number for the selection */ + font_sel = gtk_combo_box_get_active(combo); + if ((font_sel >= 0) && (font_sel <= 4)) { + nsoption_set_int(font_default, font_sel); + } +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboDefault_realize(GtkWidget *widget, struct ppref *priv) +{ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + nsoption_int(font_default)); +} + +/* default font size */ +SPINBUTTON_SIGNALS(spinDefaultSize, font_size, 10.0) + +/* preview - actually reflow all views */ +G_MODULE_EXPORT void +nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv) +{ + nsgtk_reflow_all_windows(); +} + + +/* Language */ + +/* accept language */ +G_MODULE_EXPORT void +nsgtk_preferences_comboboxLanguage_changed(GtkComboBox *combo, + struct ppref *priv) +{ + gchar *lang = NULL; + GtkTreeIter iter; + GtkTreeModel *model; + + /* Obtain currently selected item from combo box. + * If nothing is selected, do nothing. + */ + if (gtk_combo_box_get_active_iter(combo, &iter)) { + /* Obtain data model from combo box. */ + model = gtk_combo_box_get_model(combo); + + /* Obtain string from model. */ + gtk_tree_model_get(model, &iter, 0, &lang, -1); + } + + if (lang != NULL) { + nsoption_set_charp(accept_language, strdup(lang)); + g_free(lang); + } +} + +/** + * populate language combo from data + */ +static nserror +comboboxLanguage_add_from_data(GtkListStore *liststore, + GtkComboBox *combobox, + const char *accept_language, + const uint8_t *data, + size_t data_size) +{ + int active_language = -1; + GtkTreeIter iter; + int combo_row_count = 0; + const uint8_t *s; + const uint8_t *nl; + char buf[50]; + int bufi = 0; + + gtk_list_store_clear(liststore); + s = data; + + while (s < (data + data_size)) { + /* find nl and copy buffer */ + for (nl = s; nl < data + data_size; nl++) { + if ((*nl == '\n') || (bufi == (sizeof(buf) - 2))) { + buf[bufi] = 0; /* null terminate */ + break; + } + buf[bufi++] = *nl; + } + if (bufi > 0) { + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, buf, -1 ); + + if (strcmp(buf, accept_language) == 0) { + active_language = combo_row_count; + } + + combo_row_count++; + } + bufi = 0; + s = nl + 1; /* skip newline */ + } + + /* if configured language was not in list, add it */ + if (active_language == -1) { + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, accept_language, -1); + active_language = combo_row_count; + } + + gtk_combo_box_set_active(combobox, active_language); + + return NSERROR_OK; +} + +/** + * populate language combo from file + */ +static nserror +comboboxLanguage_add_from_file(GtkListStore *liststore, + GtkComboBox *combobox, + const char *accept_language, + const char *file_location) +{ + int active_language = -1; + GtkTreeIter iter; + int combo_row_count = 0; + FILE *fp; + char buf[50]; + + fp = fopen(file_location, "r"); + if (fp == NULL) { + return NSERROR_NOT_FOUND; + } + + gtk_list_store_clear(liststore); + + LOG("Used %s for languages", file_location); + while (fgets(buf, sizeof(buf), fp)) { + /* Ignore blank lines */ + if (buf[0] == '\0') + continue; + + /* Remove trailing \n */ + buf[strlen(buf) - 1] = '\0'; + + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, buf, -1 ); + + if (strcmp(buf, accept_language) == 0) { + active_language = combo_row_count; + } + + combo_row_count++; + } + + /* if configured language was not in list, add it */ + if (active_language == -1) { + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, accept_language, -1); + active_language = combo_row_count; + } + + fclose(fp); + + gtk_combo_box_set_active(combobox, active_language); + + return NSERROR_OK; +} + +/** + * Fill content language list store. + */ +G_MODULE_EXPORT void +nsgtk_preferences_comboboxLanguage_realize(GtkWidget *widget, + struct ppref *priv) +{ + nserror res; + const uint8_t *data; + size_t data_size; + const char *languages_file; + const char *accept_language; + + if (priv->content_language == NULL) { + LOG("content language list store unavailable"); + return; + } + + /* get current accept language */ + accept_language = nsoption_charp(accept_language); + if (accept_language == NULL) { + accept_language = "en"; + } + + /* attempt to read languages from inline resource */ + res = nsgtk_data_from_resname("languages", &data, &data_size); + if (res == NSERROR_OK) { + res = comboboxLanguage_add_from_data(priv->content_language, + GTK_COMBO_BOX(widget), + accept_language, + data, + data_size); + } else { + /* attempt to read languages from file */ + res = nsgtk_path_from_resname("languages", &languages_file); + if (res == NSERROR_OK) { + res = comboboxLanguage_add_from_file(priv->content_language, + GTK_COMBO_BOX(widget), + accept_language, + languages_file); + } + } + if (res != NSERROR_OK) { + LOG("error populatiung languages combo"); + } +} + + +/********* Apperance **********/ + +/* Tabs */ + +/* always show tab bar */ +G_MODULE_EXPORT void +nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton, + struct ppref *priv) +{ + nsoption_set_bool(show_single_tab, + gtk_toggle_button_get_active(togglebutton)); + nsgtk_reflow_all_windows(); +} + +G_MODULE_EXPORT void +nsgtk_preferences_checkShowSingleTab_realize(GtkWidget *widget, + struct ppref *priv) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), + nsoption_bool(show_single_tab)); +} + +/* switch to newly opened tabs immediately */ +TOGGLEBUTTON_SIGNALS(checkFocusNew, focus_new) + +/* newly opened tabs are blank */ +TOGGLEBUTTON_SIGNALS(checkNewBlank, new_blank) + +/* tab position */ +G_MODULE_EXPORT void +nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget, + struct ppref *priv) +{ + struct nsgtk_scaffolding *current; + + /* set the option */ + nsoption_set_int(position_tab, gtk_combo_box_get_active(widget)); + + /* update all notebooks in all scaffolds */ + current = nsgtk_scaffolding_iterate(NULL); + while (current) { + nsgtk_scaffolding_reset_offset(current); + + nsgtk_reflow_all_windows(); + + current = nsgtk_scaffolding_iterate(current); + } +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboTabPosition_realize(GtkWidget *widget, + struct ppref *priv) +{ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + nsoption_int(position_tab)); +} + +/* Tools */ + +/* developer view opening */ +G_MODULE_EXPORT void +nsgtk_preferences_comboDeveloperView_changed(GtkComboBox *widget, + struct ppref *priv) +{ + /* set the option */ + nsoption_set_int(developer_view, gtk_combo_box_get_active(widget)); +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboDeveloperView_realize(GtkWidget *widget, + struct ppref *priv) +{ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + nsoption_int(developer_view)); +} + + +/* URLbar */ + +/* show recently visited urls as you type */ +TOGGLEBUTTON_SIGNALS(checkDisplayRecentURLs, url_suggestion) + +/* Toolbar */ + +/* button position */ +G_MODULE_EXPORT void +nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget, + struct ppref *priv) +{ + struct nsgtk_scaffolding *current; + + nsoption_set_int(button_type, gtk_combo_box_get_active(widget) + 1); + + current = nsgtk_scaffolding_iterate(NULL); + while (current != NULL) { + nsgtk_scaffolding_reset_offset(current); + + nsgtk_scaffolding_toolbars(current, nsoption_int(button_type)); + + current = nsgtk_scaffolding_iterate(current); + } +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboButtonType_realize(GtkWidget *widget, + struct ppref *priv) +{ + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), + nsoption_int(button_type) - 1); +} + + + +/************ Main ************/ + +/* Startup */ + +/* entry HomePageURL widget */ +ENTRY_SIGNALS(entryHomePageURL, homepage_url) + +/* put current page into homepage url */ +G_MODULE_EXPORT void +nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv) +{ + const gchar *url = nsurl_access(browser_window_get_url(priv->bw)); + + if (priv->entryHomePageURL != NULL) { + gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url); + nsoption_set_charp(homepage_url, strdup(url)); + } +} + +/* put default page into homepage */ +G_MODULE_EXPORT void +nsgtk_preferences_setDefaultPage_clicked(GtkButton *button, struct ppref *priv) +{ + const gchar *url = NETSURF_HOMEPAGE; + + if (priv->entryHomePageURL != NULL) { + gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url); + nsoption_set_charp(homepage_url, strdup(url)); + } +} + +/* Search */ + +/* Url Search widget */ +TOGGLEBUTTON_SIGNALS(checkUrlSearch, search_url_bar) + +/* provider combo */ +G_MODULE_EXPORT void +nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv) +{ + int provider; + + provider = gtk_combo_box_get_active(widget); + + /* set the option */ + nsoption_set_int(search_provider, provider); + + /* set search provider */ + search_web_select_provider(provider); +} + +G_MODULE_EXPORT void +nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv) +{ + int iter; + const char *name; + int provider = nsoption_int(search_provider); + + if (priv->search_providers != NULL) { + gtk_list_store_clear(priv->search_providers); + for (iter = search_web_iterate_providers(0, &name); + iter != -1; + iter = search_web_iterate_providers(iter, &name)) { + gtk_list_store_insert_with_values(priv->search_providers, + NULL, -1, + 0, name, -1); + } + } + + gtk_combo_box_set_active(GTK_COMBO_BOX(widget), provider); +} + + +/* Downloads */ + +/* clear downloads */ +TOGGLEBUTTON_SIGNALS(checkClearDownloads, downloads_clear) + +/* request overwite */ +TOGGLEBUTTON_SIGNALS(checkRequestOverwrite, request_overwrite) + +/* download location + * + * note selection-changed is used instead of file-set as the returned + * filename when that signal are used is incorrect. Though this signal + * does update frequently often with the same data. + */ +G_MODULE_EXPORT void +nsgtk_preferences_fileChooserDownloads_selectionchanged(GtkFileChooser *chooser, + struct ppref *priv) +{ + gchar *dir; + dir = gtk_file_chooser_get_filename(chooser); + nsoption_set_charp(downloads_directory, strdup(dir)); + g_free(dir); +} + +G_MODULE_EXPORT void +nsgtk_preferences_fileChooserDownloads_realize(GtkWidget *widget, + struct ppref *priv) +{ + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(widget), + nsoption_charp(downloads_directory)); +} + + +/************* Dialog window ***********/ + +/* dialog close and destroy events */ +G_MODULE_EXPORT void +nsgtk_preferences_dialogPreferences_response(GtkDialog *dlg, gint resid) +{ + char *choices = NULL; + + if (resid == GTK_RESPONSE_CLOSE) { + netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices"); + if (choices != NULL) { + nsoption_write(choices, NULL, NULL); + free(choices); + } + gtk_widget_hide(GTK_WIDGET(dlg)); + } +} + +G_MODULE_EXPORT gboolean +nsgtk_preferences_dialogPreferences_deleteevent(GtkDialog *dlg, + struct ppref *priv) +{ + char *choices = NULL; + + netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices"); + if (choices != NULL) { + nsoption_write(choices, NULL, NULL); + free(choices); + } + + gtk_widget_hide(GTK_WIDGET(dlg)); + + /* Delt with it by hiding window, no need to destory widget by + * default. + */ + return TRUE; +} + +G_MODULE_EXPORT void +nsgtk_preferences_dialogPreferences_destroy(GtkDialog *dlg, struct ppref *priv) +{ + char *choices = NULL; + + netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices"); + if (choices != NULL) { + nsoption_write(choices, NULL, NULL); + free(choices); + } +} + + +/* exported interface documented in gtk/preferences.h */ +GtkWidget* nsgtk_preferences(struct browser_window *bw, GtkWindow *parent) +{ + GtkBuilder *preferences_builder; + struct ppref *priv = &ppref; + nserror res; + + priv->bw = bw; /* for setting "current" page */ + + /* memoised dialog creation */ + if (priv->dialog != NULL) { + gtk_window_set_transient_for(GTK_WINDOW(priv->dialog), parent); + return GTK_WIDGET(priv->dialog); + } + + res = nsgtk_builder_new_from_resname("options", &preferences_builder); + if (res != NSERROR_OK) { + LOG("Preferences UI builder init failed"); + return NULL; + } + + priv->dialog = gtk_builder_get_object(preferences_builder, + "dialogPreferences"); + if (priv->dialog == NULL) { + LOG("Unable to get object for preferences dialog"); + /* release builder as were done with it */ + g_object_unref(G_OBJECT(preferences_builder)); + return NULL; + } + + /* need to explicitly obtain handles for some widgets enabling + * updates by other widget events + */ +#define GB(TYPE, NAME) GTK_##TYPE(gtk_builder_get_object(preferences_builder, #NAME)) + priv->entryHomePageURL = GB(ENTRY, entryHomePageURL); + priv->content_language = GB(LIST_STORE, liststore_content_language); + priv->search_providers = GB(LIST_STORE, liststore_search_provider); + priv->entryProxyHost = GB(ENTRY, entryProxyHost); + priv->spinProxyPort = GB(SPIN_BUTTON, spinProxyPort); + priv->entryProxyUser = GB(ENTRY, entryProxyUser); + priv->entryProxyPassword = GB(ENTRY, entryProxyPassword); + priv->entryProxyNoproxy = GB(ENTRY, entryProxyNoproxy); +#undef GB + + /* connect all signals ready to use */ + gtk_builder_connect_signals(preferences_builder, priv); + + /* release builder as were done with it */ + g_object_unref(G_OBJECT(preferences_builder)); + + /* mark dialog as transient on parent */ + gtk_window_set_transient_for(GTK_WINDOW(priv->dialog), parent); + + return GTK_WIDGET(priv->dialog); +} + |