Initial import of ephy (rev# 7126) from svn
[ephy-soc.git] / src / .svn / text-base / prefs-dialog.c.svn-base
blob4d222fe48f80a5461ae4878377f3088152a92c23
1 /*
2  *  Copyright © 200-2003 Marco Pesenti Gritti
3  *  Copyright © 2003, 2004, 2005 Christian Persch
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  *  $Id$
20  */
22 #include "config.h"
24 #include "prefs-dialog.h"
25 #include "ephy-dialog.h"
26 #include "ephy-prefs.h"
27 #include "ephy-embed-shell.h"
28 #include "ephy-favicon-cache.h"
29 #include "ephy-session.h"
30 #include "ephy-embed-prefs.h"
31 #include "ephy-embed-single.h"
32 #include "ephy-shell.h"
33 #include "ephy-gui.h"
34 #include "eel-gconf-extensions.h"
35 #include "ephy-langs.h"
36 #include "ephy-encodings.h"
37 #include "ephy-debug.h"
38 #include "ephy-file-chooser.h"
39 #include "ephy-file-helpers.h"
40 #include "ephy-tree-model-node.h"
41 #include "ephy-tree-model-sort.h"
43 #include <glib/gi18n.h>
44 #include <gtk/gtklabel.h>
45 #include <gtk/gtkcellrenderertext.h>
46 #include <gtk/gtkcelllayout.h>
47 #include <gtk/gtktreeselection.h>
48 #include <gtk/gtkframe.h>
49 #include <gtk/gtkhbox.h>
50 #include <gtk/gtkvbox.h>
51 #include <gtk/gtkradiobutton.h>
52 #include <gtk/gtktogglebutton.h>
53 #include <gtk/gtkcombobox.h>
54 #include <gtk/gtktreemodel.h>
55 #include <gtk/gtkliststore.h>
56 #include <gtk/gtkimage.h>
57 #include <gtk/gtklabel.h>
58 #include <gtk/gtkstock.h>
59 #include <gtk/gtknotebook.h>
60 #include <gtk/gtkfilechooserbutton.h>
61 #include <gtk/gtkmain.h>
62 #include <string.h>
64 #include <libgnomevfs/gnome-vfs-utils.h>
66 #define CONF_FONTS_FOR_LANGUAGE "/apps/epiphany/dialogs/preferences_font_language"
67 #define DOWNLOAD_BUTTON_WIDTH   8
69 static void prefs_dialog_class_init     (PrefsDialogClass *klass);
70 static void prefs_dialog_init           (PrefsDialog *pd);
72 #include "languages.h"
74 static const char * const cookies_accept_enum [] =
76         "anywhere", "current site", "nowhere"
79 enum
81         FONT_TYPE_VARIABLE,
82         FONT_TYPE_MONOSPACE
85 static const char * const fonts_types[] =
87         "variable",
88         "monospace"
91 enum
93         FONT_SIZE_FIXED,
94         FONT_SIZE_VAR,
95         FONT_SIZE_MIN
98 static const char * const size_prefs [] =
100         CONF_RENDERING_FONT_FIXED_SIZE,
101         CONF_RENDERING_FONT_VAR_SIZE,
102         CONF_RENDERING_FONT_MIN_SIZE
105 static const int default_size [] =
107         10,
108         11,
109         7
112 enum
114         WINDOW_PROP,
115         NOTEBOOK_PROP,
117         /* General */
118         HOMEPAGE_ENTRY_PROP,
119         HOMEPAGE_CURRENT_PROP,
120         HOMEPAGE_BLANK_PROP,
121         AUTO_OPEN_PROP,
122         DOWNLOAD_PATH_HBOX_PROP,
123         DOWNLOAD_PATH_LABEL_PROP,
125         /* Fonts and Colors */
126         USE_FONTS_PROP,
127         MIN_SIZE_PROP,
128         FONT_PREFS_BUTTON_PROP,
129         USE_COLORS_PROP,
130         CSS_CONTAINER_PROP,
131         CSS_CHECKBOX_PROP,
132         CSS_EDIT_BOX_PROP,
133         CSS_EDIT_BUTTON_PROP,
135         /* Privacy */
136         ALLOW_POPUPS_PROP,
137         ALLOW_JAVA_PROP,
138         ALLOW_JS_PROP,
139         ACCEPT_COOKIES_PROP,
140         REMEMBER_PASSWORDS_PROP,
141         DISK_CACHE_PROP,
142         CLEAR_CACHE_BUTTON_PROP,
144         /* Language */
145         AUTO_ENCODING_PROP,
146         DEFAULT_ENCODING_PROP,
147         DEFAULT_ENCODING_LABEL_PROP,
148         AUTO_ENCODING_LABEL_PROP,
149         LANGUAGE_ADD_BUTTON_PROP,
150         LANGUAGE_REMOVE_BUTTON_PROP,
151         LANGUAGE_UP_BUTTON_PROP,
152         LANGUAGE_DOWN_BUTTON_PROP,
153         LANGUAGE_TREEVIEW_PROP
156 static const
157 EphyDialogProperty properties [] =
159         { "prefs_dialog",       NULL, PT_NORMAL, 0},
160         { "prefs_notebook",     NULL, PT_NORMAL, 0},
162         /* General */
163         { "homepage_entry",                     CONF_GENERAL_HOMEPAGE,    PT_AUTOAPPLY, G_TYPE_STRING },
164         { "homepage_current_button",            NULL,                     PT_NORMAL,    0 },
165         { "homepage_blank_button",              NULL,                     PT_NORMAL,    0 },
166         { "automatic_downloads_checkbutton",    CONF_AUTO_DOWNLOADS,      PT_AUTOAPPLY, 0 },
167         { "download_button_hbox",               NULL,                     PT_NORMAL,    0 },
168         { "download_button_label",              NULL,                     PT_NORMAL,    0 },
170         /* Fonts and Colors */
171         { "use_fonts_checkbutton",      CONF_RENDERING_USE_OWN_FONTS,   PT_AUTOAPPLY | PT_INVERTED,     0 },
172         { "min_size_spinbutton",        CONF_RENDERING_FONT_MIN_SIZE,   PT_AUTOAPPLY,   0 },
173         { "font_prefs_button",          NULL,                           PT_NORMAL,      0 },
174         { "use_colors_checkbutton",     CONF_RENDERING_USE_OWN_COLORS,  PT_AUTOAPPLY | PT_INVERTED,     0 },
175         { "css_container",              NULL,                           PT_NORMAL,      0 },
176         { "css_checkbox",               CONF_USER_CSS_ENABLED,          PT_AUTOAPPLY,   0 },
177         { "css_edit_box",               NULL,                           PT_NORMAL,      0 },
178         { "css_edit_button",            NULL,                           PT_NORMAL,      0 },
180         /* Privacy */
181         { "popups_allow_checkbutton",           CONF_SECURITY_ALLOW_POPUPS,       PT_AUTOAPPLY, 0 },
182         { "enable_java_checkbutton",            CONF_SECURITY_JAVA_ENABLED,       PT_AUTOAPPLY, 0 },
183         { "enable_javascript_checkbutton",      CONF_SECURITY_JAVASCRIPT_ENABLED, PT_AUTOAPPLY, 0 },
184         { "cookies_radiobutton",                CONF_SECURITY_COOKIES_ACCEPT,     PT_AUTOAPPLY, G_TYPE_STRING },
185         { "remember_passwords_checkbutton",     CONF_PRIVACY_REMEMBER_PASSWORDS,  PT_AUTOAPPLY, 0 },
186         { "disk_cache_spin",                    CONF_NETWORK_CACHE_SIZE,          PT_AUTOAPPLY, 0 },
187         { "clear_cache_button",                 NULL,                             PT_NORMAL,    0 },
189         /* Languages */
190         { "auto_encoding_combo",        CONF_LANGUAGE_AUTODETECT_ENCODING,      PT_AUTOAPPLY,   G_TYPE_STRING },
191         { "default_encoding_combo",     CONF_LANGUAGE_DEFAULT_ENCODING,         PT_AUTOAPPLY,   G_TYPE_STRING },
192         { "default_encoding_label",     NULL,                                   PT_NORMAL,      0 },
193         { "auto_encoding_label",        NULL,                                   PT_NORMAL,      0 },
194         { "lang_add_button",            NULL,                                   PT_NORMAL,      0 },
195         { "lang_remove_button",         NULL,                                   PT_NORMAL,      0 },
196         { "lang_up_button",             NULL,                                   PT_NORMAL,      0 },
197         { "lang_down_button",           NULL,                                   PT_NORMAL,      0 },
198         { "lang_treeview",              NULL,                                   PT_NORMAL,      0 },
200         { NULL }
203 enum
205         LANGUAGE_DIALOG,
206         LANGUAGE_PROP,
207         LANGUAGE_ACCEPT_BUTTON_PROP
210 static const
211 EphyDialogProperty add_lang_props [] =
213         { "add_language_dialog", NULL,  PT_NORMAL,      0 },
214         { "languages_treeview",  NULL,  PT_NORMAL,      G_TYPE_STRING },
215         { "add_button",          NULL,  PT_NORMAL,      0 },
217         { NULL }
220 enum
222         FONTS_WINDOW_PROP,
223         FONTS_LANGUAGE_PROP,
224         FONTS_VARIABLE_PROP,
225         FONTS_MONOSPACE_PROP,
226         FONTS_VARIABLE_SIZE_PROP,
227         FONTS_FIXED_SIZE_PROP,
228         FONTS_MIN_SIZE_PROP,
231 static const
232 EphyDialogProperty fonts_properties [] =
234         { "fonts_dialog",               NULL,                           PT_NORMAL, 0},
235         { "fonts_language_combo",       CONF_FONTS_FOR_LANGUAGE,        PT_AUTOAPPLY,   G_TYPE_STRING },
236         { "variable_combo",             NULL,                           PT_AUTOAPPLY,   G_TYPE_STRING },
237         { "monospace_combo",            NULL,                           PT_AUTOAPPLY,   G_TYPE_STRING },
238         { "variable_size_spinbutton",   NULL,                           PT_AUTOAPPLY,   0 },
239         { "fixed_size_spinbutton",      NULL,                           PT_AUTOAPPLY,   0 },
240         { "min_size_spinbutton",        NULL,                           PT_AUTOAPPLY,   0 },
242         { NULL }
245 enum
247         COL_FONTS_LANG_NAME,
248         COL_FONTS_LANG_CODE
251 enum
253         COL_FONT_NAME,
254         COL_FONT_DATA,
255         COL_FONT_IS_SEP
258 enum
260         COL_LANG_NAME,
261         COL_LANG_CODE
264 enum
266         COL_ENC_NAME,
267         COL_ENC_CODE
270 enum
272         COL_AUTODETECTOR_NAME,
273         COL_AUTODETECTOR_DATA,
274         COL_AUTODETECTOR_IS_SEP
277 #define EPHY_PREFS_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_PREFS_DIALOG, PrefsDialogPrivate))
279 struct PrefsDialogPrivate
281         GtkTreeView *lang_treeview;
282         GtkTreeModel *lang_model;
283         EphyDialog *fonts_dialog;
284         EphyDialog *add_lang_dialog;
285         GtkWidget *lang_add_button;
286         GtkWidget *lang_remove_button;
287         GtkWidget *lang_up_button;
288         GtkWidget *lang_down_button;
289         GHashTable *iso_639_table;
290         GHashTable *iso_3166_table;
293 static GObjectClass *parent_class = NULL;
295 GType
296 prefs_dialog_get_type (void)
298         static GType type = 0;
300         if (G_UNLIKELY (type == 0))
301         {
302                 const GTypeInfo our_info =
303                 {
304                         sizeof (PrefsDialogClass),
305                         NULL, /* base_init */
306                         NULL, /* base_finalize */
307                         (GClassInitFunc) prefs_dialog_class_init,
308                         NULL,
309                         NULL, /* class_data */
310                         sizeof (PrefsDialog),
311                         0, /* n_preallocs */
312                         (GInstanceInitFunc) prefs_dialog_init
313                 };
315                 type = g_type_register_static (EPHY_TYPE_DIALOG,
316                                                "PrefsDialog",
317                                                &our_info, 0);
318         }
320         return type;
323 static void
324 prefs_dialog_finalize (GObject *object)
326         PrefsDialog *dialog = EPHY_PREFS_DIALOG (object);
327         PrefsDialogPrivate *priv = dialog->priv;
329         if (priv->fonts_dialog != NULL)
330         {
331                 EphyDialog **fonts_dialog = &priv->fonts_dialog;
333                 g_object_remove_weak_pointer
334                         (G_OBJECT (priv->fonts_dialog),
335                         (gpointer *) fonts_dialog);
336                 g_object_unref (priv->fonts_dialog);
337         }
339         if (priv->add_lang_dialog != NULL)
340         {
341                 EphyDialog **add_lang_dialog = &priv->add_lang_dialog;
343                 g_object_remove_weak_pointer
344                                 (G_OBJECT (priv->add_lang_dialog),
345                                  (gpointer *) add_lang_dialog);
346                 g_object_unref (priv->add_lang_dialog);
347         }
349         g_hash_table_destroy (priv->iso_639_table);
350         g_hash_table_destroy (priv->iso_3166_table);
352         G_OBJECT_CLASS (parent_class)->finalize (object);
355 static void
356 prefs_dialog_class_init (PrefsDialogClass *klass)
358         GObjectClass *object_class = G_OBJECT_CLASS (klass);
360         parent_class = g_type_class_peek_parent (klass);
362         object_class->finalize = prefs_dialog_finalize;
364         g_type_class_add_private (object_class, sizeof(PrefsDialogPrivate));
367 static void
368 prefs_dialog_show_help (EphyDialog *dialog)
370         GtkWidget *window, *notebook;
371         int id;
373         static const char help_preferences[][28] = {
374                 "general-preferences",
375                 "fonts-and-style-preferences",
376                 "privacy-preferences",
377                 "language-preferences"
378         };
380         ephy_dialog_get_controls (dialog,
381                                   properties[WINDOW_PROP].id, &window,
382                                   properties[NOTEBOOK_PROP].id, &notebook,
383                                   NULL);
385         id = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
386         id = CLAMP (id, 0, 3);
388         ephy_gui_help (GTK_WINDOW (window), "epiphany", help_preferences[id]);
391 static void
392 setup_font_combo (EphyDialog *dialog,
393                   const char *type,
394                   const char *code,
395                   int prop)
397         GtkWidget *combo;
398         GtkListStore *store;
399         GtkTreeIter iter;
400         GList *fonts, *l;
401         char key[255];
402         EphyEmbedSingle *single;
404         single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
405         fonts = ephy_embed_single_get_font_list (single, code);
406         fonts = g_list_sort (fonts, (GCompareFunc) strcmp);
408         g_snprintf (key, 255, "%s_%s_%s", CONF_RENDERING_FONT, type, code);
410         combo = ephy_dialog_get_control (dialog, fonts_properties[prop].id);
411         store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
413         gtk_list_store_append (store, &iter);
414         gtk_list_store_set (store, &iter,
415                             COL_FONT_NAME, _("Default"),
416                             COL_FONT_DATA, NULL,
417                             COL_FONT_IS_SEP, FALSE,
418                             -1);
419         gtk_list_store_append (store, &iter);
420         gtk_list_store_set (store, &iter,
421                             COL_FONT_NAME, "",
422                             COL_FONT_DATA, "",
423                             COL_FONT_IS_SEP, TRUE,
424                             -1);
426         for (l = fonts; l != NULL; l = l->next)
427         {
428                 gtk_list_store_append (store, &iter);
429                 gtk_list_store_set (store, &iter,
430                                     COL_FONT_NAME, (char *) l->data,
431                                     COL_FONT_DATA, (char *) l->data,
432                                     COL_FONT_IS_SEP, FALSE,
433                                     -1);
434         }
435         g_list_foreach (fonts, (GFunc) g_free, NULL);
436         g_list_free (fonts);
438         ephy_dialog_set_pref (dialog, fonts_properties[prop].id, NULL);
440         gtk_combo_box_set_model (GTK_COMBO_BOX (combo), GTK_TREE_MODEL (store));
441         gtk_combo_box_set_active (GTK_COMBO_BOX (combo), -1);
443         ephy_dialog_set_pref (dialog, fonts_properties[prop].id, key);
445         g_object_unref (store);
448 static void
449 fonts_language_changed_cb (EphyDialog *dialog,
450                            const GValue *value,
451                            gpointer data)
453         const char *code;
454         char key[128];
455         int size;
457         code = g_value_get_string (value);
459         LOG ("fonts language combo changed, new code '%s'", code);
461         setup_font_combo (dialog, "variable", code, FONTS_VARIABLE_PROP);
462         setup_font_combo (dialog, "monospace", code, FONTS_MONOSPACE_PROP);
464         g_snprintf (key, sizeof (key), "%s_%s", size_prefs[FONT_SIZE_VAR], code);
465         size = eel_gconf_get_integer (key);
466         if (size <= 0)
467         {
468                 eel_gconf_set_integer (key, default_size[FONT_SIZE_VAR]);
469         }
470         ephy_dialog_set_pref (dialog, fonts_properties[FONTS_VARIABLE_SIZE_PROP].id, key);
472         g_snprintf (key, sizeof (key), "%s_%s", size_prefs[FONT_SIZE_FIXED], code);
473         size = eel_gconf_get_integer (key);
474         if (size <= 0)
475         {
476                 eel_gconf_set_integer (key, default_size[FONT_SIZE_FIXED]);
477         }
478         ephy_dialog_set_pref (dialog, fonts_properties[FONTS_FIXED_SIZE_PROP].id, key);
480         g_snprintf (key, sizeof (key), "%s_%s", size_prefs[FONT_SIZE_MIN], code);
481         size = eel_gconf_get_integer (key);
482         if (size <= 0)
483         {
484                 eel_gconf_set_integer (key, default_size[FONT_SIZE_MIN]);
485         }
486         ephy_dialog_set_pref (dialog, fonts_properties[FONTS_MIN_SIZE_PROP].id, key);
489 static void
490 font_prefs_dialog_response_cb (GtkWidget *widget,
491                                int response,
492                                EphyDialog *dialog)
494         if (response == GTK_RESPONSE_HELP)
495         {
496                 ephy_gui_help (GTK_WINDOW (widget), "epiphany", "fonts-and-style-preferences");
497                 return;
498         }
500         g_object_unref (dialog);
503 static gboolean
504 row_is_separator (GtkTreeModel *model,
505                   GtkTreeIter *iter,
506                   gpointer data)
508         int column = GPOINTER_TO_INT (data);
509         gboolean is_sep;
511         gtk_tree_model_get (model, iter, column, &is_sep, -1);
513         return is_sep;
516 static EphyDialog *
517 setup_fonts_dialog (PrefsDialog *pd)
519         EphyDialog *dialog;
520         GtkWidget *window, *parent, *variable_combo, *monospace_combo;
521         GtkWidget *combo;
522         GtkCellRenderer *renderer;
523         GtkListStore *store;
524         GtkTreeModel *sortmodel;
525         GtkTreeIter iter;
526         guint n_fonts_languages, i;
527         const EphyFontsLanguageInfo *fonts_languages;
529         parent = ephy_dialog_get_control (EPHY_DIALOG (pd),
530                                           properties[WINDOW_PROP].id);
532         dialog =  EPHY_DIALOG (g_object_new (EPHY_TYPE_DIALOG,
533                                              "parent-window", parent,
534                                              NULL));
536         ephy_dialog_construct (dialog, fonts_properties,
537                                ephy_file ("prefs-dialog.glade"),
538                                "fonts_dialog", NULL);
540         ephy_dialog_get_controls
541                 (dialog,
542                  fonts_properties[FONTS_WINDOW_PROP].id, &window,
543                  fonts_properties[FONTS_LANGUAGE_PROP].id, &combo,
544                  fonts_properties[FONTS_VARIABLE_PROP].id, &variable_combo,
545                  fonts_properties[FONTS_MONOSPACE_PROP].id, &monospace_combo,
546                  NULL);
548         gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (parent)),
549                                      GTK_WINDOW (window));
550         g_signal_connect (window, "response",
551                           G_CALLBACK (font_prefs_dialog_response_cb), dialog);
553         renderer = gtk_cell_renderer_text_new ();
554         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (variable_combo), renderer, TRUE);
555         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (variable_combo), renderer,
556                                         "text", COL_FONT_NAME,
557                                         NULL);
558         ephy_dialog_set_data_column (dialog, fonts_properties[FONTS_VARIABLE_PROP].id,
559                                      COL_FONT_DATA);
560         renderer = gtk_cell_renderer_text_new ();
561         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (monospace_combo), renderer, TRUE);
562         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (monospace_combo), renderer,
563                                         "text", COL_FONT_NAME,
564                                         NULL);
565         ephy_dialog_set_data_column (dialog, fonts_properties[FONTS_MONOSPACE_PROP].id,
566                                      COL_FONT_DATA);
568         gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (variable_combo),
569                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
570                                               GINT_TO_POINTER (COL_FONT_IS_SEP), NULL);
571         gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (monospace_combo),
572                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
573                                               GINT_TO_POINTER (COL_FONT_IS_SEP), NULL);
575         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
577         fonts_languages = ephy_font_languages ();
578         n_fonts_languages = ephy_font_n_languages ();
579         
580         for (i = 0; i < n_fonts_languages; i++)
581         {
582                 gtk_list_store_append (store, &iter);
583                 gtk_list_store_set (store, &iter,
584                                     COL_FONTS_LANG_NAME, Q_(fonts_languages[i].title),
585                                     COL_FONTS_LANG_CODE, fonts_languages[i].code,
586                                     -1);
587         }
589         sortmodel = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
590         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sortmodel),
591                                               COL_FONTS_LANG_NAME,
592                                               GTK_SORT_ASCENDING);
594         gtk_combo_box_set_model (GTK_COMBO_BOX (combo), sortmodel);
596         renderer = gtk_cell_renderer_text_new ();
597         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
598         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
599                                         "text", COL_FONTS_LANG_NAME,
600                                         NULL);
602         ephy_dialog_set_data_column (dialog, fonts_properties[FONTS_LANGUAGE_PROP].id, COL_FONTS_LANG_CODE);
604         g_signal_connect (dialog, "changed::fonts_language_combo",
605                           G_CALLBACK (fonts_language_changed_cb),
606                           NULL);
608         g_object_unref (store);
609         g_object_unref (sortmodel);
611         return dialog;
614 static void
615 font_prefs_button_clicked_cb (GtkWidget *button,
616                               PrefsDialog *pd)
618         PrefsDialogPrivate *priv = pd->priv;
620         if (priv->fonts_dialog == NULL)
621         {
622                 EphyDialog **fonts_dialog;
624                 priv->fonts_dialog = setup_fonts_dialog (pd);
626                 fonts_dialog = &priv->fonts_dialog;
628                 g_object_add_weak_pointer
629                         (G_OBJECT (priv->fonts_dialog),
630                         (gpointer *) fonts_dialog);
631         }
633         ephy_dialog_show (priv->fonts_dialog);
636 static void
637 css_checkbox_toggled (GtkToggleButton *button,
638                       GtkWidget *widget)
640         g_object_set (widget, "sensitive", gtk_toggle_button_get_active (button), NULL);
643 static void
644 css_edit_button_clicked_cb (GtkWidget *button,
645                             PrefsDialog *pd)
647         char *css_file, *uri;
649         css_file = g_build_filename (ephy_dot_dir (),
650                                      USER_STYLESHEET_FILENAME,
651                                      NULL);
652         uri = gnome_vfs_get_uri_from_local_path (css_file);
654         ephy_file_launch_handler ("text/plain", uri,
655                                   gtk_get_current_event_time ());
657         g_free (css_file);
658         g_free (uri);
661 static void
662 create_node_combo (EphyDialog *dialog,
663                    int prop,
664                    EphyEncodings *encodings,
665                    EphyNode *node,
666                    const char *key,
667                    const char *default_value)
669         EphyTreeModelNode *nodemodel;
670         GtkTreeModel *sortmodel;
671         GtkComboBox *combo;
672         GtkCellRenderer *renderer;
673         char *code;
674         int title_col, data_col;
676         code = eel_gconf_get_string (key);
677         if (code == NULL || ephy_encodings_get_node (encodings, code, FALSE) == NULL)
678         {
679                 /* safe default */
680                 eel_gconf_set_string (key, default_value);
681         }
682         g_free (code);
684         combo = GTK_COMBO_BOX (ephy_dialog_get_control (dialog, properties[prop].id));
686         nodemodel = ephy_tree_model_node_new (node);
688         title_col = ephy_tree_model_node_add_prop_column
689                         (nodemodel, G_TYPE_STRING, EPHY_NODE_ENCODING_PROP_TITLE_ELIDED);
690         data_col = ephy_tree_model_node_add_prop_column
691                         (nodemodel, G_TYPE_STRING, EPHY_NODE_ENCODING_PROP_ENCODING);
693         sortmodel = ephy_tree_model_sort_new (GTK_TREE_MODEL (nodemodel));
695         gtk_tree_sortable_set_sort_column_id
696                 (GTK_TREE_SORTABLE (sortmodel), title_col, GTK_SORT_ASCENDING);
698         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (sortmodel));
700         renderer = gtk_cell_renderer_text_new ();
701         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
702         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
703                                         "text", title_col,
704                                         NULL);
706         ephy_dialog_set_data_column (dialog, properties[prop].id, data_col);
708         g_object_unref (nodemodel);
709         g_object_unref (sortmodel);
712 static void
713 create_autodetectors_combo (EphyDialog *dialog,
714                             int prop,
715                             EphyEncodings *encodings,
716                             EphyNode *node,
717                             const char *key,
718                             const char *default_value)
720         GtkListStore *store;
721         GtkTreeIter iter;
722         GPtrArray *children;
723         GtkComboBox *combo;
724         GtkCellRenderer *renderer;
725         char *code;
726         const char *off_title = NULL;
727         guint i;
729         code = eel_gconf_get_string (key);
730         if (code == NULL || ephy_encodings_get_node (encodings, code, FALSE) == NULL)
731         {
732                 /* safe default */
733                 eel_gconf_set_string (key, default_value);
734         }
735         g_free (code);
737         combo = GTK_COMBO_BOX (ephy_dialog_get_control (dialog, properties[prop].id));
739         store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
741         children = ephy_node_get_children (node);
742         for (i = 0; i < children->len; ++i)
743         {
744                 EphyNode *kid = g_ptr_array_index (children, i);
745                 const char *code, *title;
747                 code = ephy_node_get_property_string (kid, EPHY_NODE_ENCODING_PROP_ENCODING);
748                 g_return_if_fail (code != NULL);
750                 title = ephy_node_get_property_string (kid, EPHY_NODE_ENCODING_PROP_TITLE_ELIDED);
751                 if (code[0] == '\0')
752                 {
753                         off_title = title;
754                 }
755                 else
756                 {       
757                         gtk_list_store_insert_with_values (store, &iter, -1,
758                                                            COL_AUTODETECTOR_NAME, title,
759                                                            COL_AUTODETECTOR_DATA, code,
760                                                            COL_AUTODETECTOR_IS_SEP, FALSE,
761                                                            -1);
762                 }
763         }
765         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
766                                               COL_AUTODETECTOR_NAME,
767                                               GTK_SORT_ASCENDING);
768         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
769                                               GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
770                                               GTK_SORT_ASCENDING);
772         g_assert (off_title != NULL);
774         gtk_list_store_insert_with_values (store, &iter, 0,
775                                            COL_AUTODETECTOR_NAME, off_title,
776                                            COL_AUTODETECTOR_DATA, "",
777                                            COL_AUTODETECTOR_IS_SEP, FALSE,
778                                            -1);
779         gtk_list_store_insert_with_values (store, &iter, 1,
780                                            COL_AUTODETECTOR_NAME, NULL,
781                                            COL_AUTODETECTOR_DATA, "",
782                                            COL_AUTODETECTOR_IS_SEP, TRUE,
783                                            -1);
785         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
786         g_object_unref (store);
788         gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
789                                               (GtkTreeViewRowSeparatorFunc) row_is_separator,
790                                               GINT_TO_POINTER (COL_AUTODETECTOR_IS_SEP), NULL);
793         renderer = gtk_cell_renderer_text_new ();
794         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
795         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer,
796                                         "text", COL_AUTODETECTOR_NAME,
797                                         NULL);
799         ephy_dialog_set_data_column (dialog, properties[prop].id, COL_AUTODETECTOR_DATA);
802 static void
803 language_editor_add (PrefsDialog *pd,
804                      const char *code,
805                      const char *desc)
807         GtkTreeIter iter;
809         g_return_if_fail (code != NULL && desc != NULL);
811         if (gtk_tree_model_get_iter_first (pd->priv->lang_model, &iter))
812         {
813                 do
814                 {
815                         char *c;
817                         gtk_tree_model_get (pd->priv->lang_model, &iter,
818                                             COL_LANG_CODE, &c,
819                                             -1);
821                         if (strcmp (code, c) == 0)
822                         {
823                                 g_free (c);
825                                 /* already in list, don't allow a duplicate */
826                                 return;
827                         }
828                         g_free (c);
829                 }
830                 while (gtk_tree_model_iter_next (pd->priv->lang_model, &iter));
831         }
833         gtk_list_store_append (GTK_LIST_STORE (pd->priv->lang_model), &iter);
834         
835         gtk_list_store_set (GTK_LIST_STORE (pd->priv->lang_model), &iter,
836                             COL_LANG_NAME, desc,
837                             COL_LANG_CODE, code,
838                             -1);
841 static void
842 language_editor_update_pref (PrefsDialog *pd)
844         GtkTreeIter iter;
845         GSList *codes = NULL;
847         if (gtk_tree_model_get_iter_first (pd->priv->lang_model, &iter))
848         {
849                 do
850                 {
851                         char *code;
852                 
853                         gtk_tree_model_get (pd->priv->lang_model, &iter,
854                                             COL_LANG_CODE, &code,
855                                             -1);
857                         codes = g_slist_prepend (codes, code);
858                 }
859                 while (gtk_tree_model_iter_next (pd->priv->lang_model, &iter));
860         }
862         codes = g_slist_reverse (codes);
863         eel_gconf_set_string_list (CONF_RENDERING_LANGUAGE, codes);
865         g_slist_foreach (codes, (GFunc) g_free, NULL);
866         g_slist_free (codes);
869 static void
870 language_editor_update_buttons (PrefsDialog *dialog)
872         GtkTreeSelection *selection;
873         GtkTreeModel *model;
874         GtkTreePath *path;
875         GtkTreeIter iter;
876         gboolean can_remove = FALSE, can_move_up = FALSE, can_move_down = FALSE;
877         int selected;
879         selection = gtk_tree_view_get_selection (dialog->priv->lang_treeview);
881         if (gtk_tree_selection_get_selected (selection, &model, &iter))
882         {
883                 path = gtk_tree_model_get_path (model, &iter);
884         
885                 selected = gtk_tree_path_get_indices (path)[0];
887                 can_remove = TRUE;
888                 can_move_up = selected > 0;
889                 can_move_down = 
890                         selected < gtk_tree_model_iter_n_children (model, NULL) - 1;
892                 gtk_tree_path_free (path);
893         }
895         gtk_widget_set_sensitive (dialog->priv->lang_remove_button, can_remove);
896         gtk_widget_set_sensitive (dialog->priv->lang_up_button, can_move_up);
897         gtk_widget_set_sensitive (dialog->priv->lang_down_button, can_move_down);
900 static void
901 add_lang_dialog_selection_changed (GtkTreeSelection *selection,
902                                    EphyDialog *dialog)
904         GtkWidget *button;
905         int n_selected;
907         button = ephy_dialog_get_control (dialog, add_lang_props[LANGUAGE_ACCEPT_BUTTON_PROP].id);
909         n_selected = gtk_tree_selection_count_selected_rows (selection);
910         gtk_widget_set_sensitive (button, n_selected > 0);
913 static void
914 add_lang_dialog_response_cb (GtkWidget *widget,
915                              int response,
916                              PrefsDialog *pd)
918         EphyDialog *dialog = pd->priv->add_lang_dialog;
919         GtkTreeView *treeview;
920         GtkTreeModel *model;
921         GtkTreeSelection *selection;
922         GtkTreeIter iter;
923         GList *rows, *r;
925         g_return_if_fail (dialog != NULL);
927         if (response == GTK_RESPONSE_ACCEPT)
928         {
929                 treeview = GTK_TREE_VIEW (ephy_dialog_get_control
930                                 (dialog, add_lang_props[LANGUAGE_PROP].id));
931                 selection = gtk_tree_view_get_selection (treeview);
933                 rows = gtk_tree_selection_get_selected_rows (selection, &model);
935                 for (r = rows; r != NULL; r = r->next)
936                 {
937                         GtkTreePath *path = (GtkTreePath *) r->data;
939                         if (gtk_tree_model_get_iter (model, &iter, path))
940                         {
941                                 char *code, *desc;
942                                 
943                                 gtk_tree_model_get (model, &iter,
944                                                     COL_LANG_NAME, &desc,
945                                                     COL_LANG_CODE, &code,
946                                                     -1);
948                                 language_editor_add (pd, code, desc);
949                 
950                                 g_free (desc);
951                                 g_free (code);
952                         }
953                 }                       
955                 g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL);
956                 g_list_free (rows);
958                 language_editor_update_pref (pd);
959                 language_editor_update_buttons (pd);
960         }
962         g_object_unref (dialog);
965 static char *
966 get_name_for_lang_code (PrefsDialog *pd,
967                         const char *code)
969         char **str;
970         char *name;
971         const char *langname, *localename;
972         int len;
974         str = g_strsplit (code, "-", -1);
975         len = g_strv_length (str);
976         g_return_val_if_fail (len != 0, NULL);
978         langname = (const char *) g_hash_table_lookup (pd->priv->iso_639_table, str[0]);
980         if (len == 1 && langname != NULL)
981         {
982                 name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
983         }
984         else if (len == 2 && langname != NULL)
985         {
986                 localename = (const char *) g_hash_table_lookup (pd->priv->iso_3166_table, str[1]);
988                 if (localename != NULL)
989                 {
990                         /* Translators: The text before the "|" is context to help you decide on
991                          * the correct translation. You MUST OMIT it in the translated string.
992                          * Translators: the first %s is the language name, and the
993                          * second %s is the locale name. Example:
994                          * "French (France)"
995                          */
996                         name = g_strdup_printf (Q_("language|%s (%s)"),
997                                                 dgettext (ISO_639_DOMAIN, langname),
998                                                 dgettext (ISO_3166_DOMAIN, localename));
999                 }
1000                 else
1001                 {
1002                         /* Translators: The text before the "|" is context to help you decide on
1003                          * the correct translation. You MUST OMIT it in the translated string. */
1004                         name = g_strdup_printf (Q_("language|%s (%s)"),
1005                                                 dgettext (ISO_639_DOMAIN, langname), str[1]);
1006                 }
1007         }
1008         else
1009         {
1010                 /* Translators: The text before the "|" is context to help you decide on
1011                  * the correct translation. You MUST OMIT it in the translated string.
1012                  * Translators: this refers to a user-define language code
1013                  * (one which isn't in our built-in list).
1014                  */
1015                 name = g_strdup_printf (Q_("language|User defined (%s)"), code);
1016         }
1018         g_strfreev (str);
1020         return name;
1023 static void
1024 add_system_language_entry (GtkListStore *store)
1026         GtkTreeIter iter;
1027         char **sys_langs;
1028         char *system, *text;
1029         int n_sys_langs;
1031         sys_langs = ephy_langs_get_languages ();
1032         n_sys_langs = g_strv_length (sys_langs);
1034         system = g_strjoinv (", ", sys_langs);
1036         text = g_strdup_printf
1037                 (ngettext ("System language (%s)",
1038                            "System languages (%s)", n_sys_langs), system);
1040         gtk_list_store_append (store, &iter);
1041         gtk_list_store_set (store, &iter,
1042                             COL_LANG_NAME, text,
1043                             COL_LANG_CODE, "system",
1044                             -1);
1046         g_strfreev (sys_langs);
1047         g_free (system);
1048         g_free (text);
1051 static EphyDialog *
1052 setup_add_language_dialog (PrefsDialog *pd)
1054         EphyDialog *dialog;
1055         GtkWidget *window, *parent;
1056         GtkListStore *store;
1057         GtkTreeModel *sortmodel;
1058         GtkTreeView *treeview;
1059         GtkCellRenderer *renderer;
1060         GtkTreeViewColumn *column;
1061         GtkTreeSelection *selection;
1062         GtkTreeIter iter;
1063         int i;
1065         parent = ephy_dialog_get_control (EPHY_DIALOG (pd), properties[WINDOW_PROP].id);
1067         dialog =  EPHY_DIALOG (g_object_new (EPHY_TYPE_DIALOG,
1068                                              "parent-window", parent,
1069                                              "default-width", 260,
1070                                              "default-height", 230,
1071                                              NULL));
1073         ephy_dialog_construct (dialog, 
1074                                add_lang_props,
1075                                ephy_file ("prefs-dialog.glade"),
1076                                "add_language_dialog",
1077                                NULL);
1079         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
1081         for (i = 0; i < G_N_ELEMENTS (languages); i++)
1082         {
1083                 const char *code = languages[i];
1084                 char *name;
1086                 name = get_name_for_lang_code (pd, code);
1087                 
1088                 gtk_list_store_append (store, &iter);
1089                 gtk_list_store_set (store, &iter,
1090                                     COL_LANG_NAME, name,
1091                                     COL_LANG_CODE, code,
1092                                     -1);
1093                 g_free (name);
1094         }
1096         add_system_language_entry (store);
1098         sortmodel = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
1099         gtk_tree_sortable_set_sort_column_id
1100                 (GTK_TREE_SORTABLE (sortmodel), COL_LANG_NAME, GTK_SORT_ASCENDING);
1102         ephy_dialog_get_controls (dialog,
1103                                   add_lang_props[LANGUAGE_PROP].id, &treeview,
1104                                   add_lang_props[LANGUAGE_DIALOG].id, &window,
1105                                   NULL);
1107         gtk_window_group_add_window (GTK_WINDOW (parent)->group, GTK_WINDOW (window));
1108         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
1110         gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), FALSE);
1112         gtk_tree_view_set_model (treeview, sortmodel);
1114         gtk_tree_view_set_headers_visible (treeview, FALSE);
1116         renderer = gtk_cell_renderer_text_new ();
1118         gtk_tree_view_insert_column_with_attributes (treeview,
1119                                                      0, "Language",
1120                                                      renderer,
1121                                                      "text", 0,
1122                                                      NULL);
1123         column = gtk_tree_view_get_column (treeview, 0);
1124         gtk_tree_view_column_set_resizable (column, TRUE);
1125         gtk_tree_view_column_set_sort_column_id (column, COL_LANG_NAME);
1127         selection = gtk_tree_view_get_selection (treeview);
1128         gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1129         
1130         add_lang_dialog_selection_changed (GTK_TREE_SELECTION (selection), dialog);
1131         g_signal_connect (selection, "changed",
1132                           G_CALLBACK (add_lang_dialog_selection_changed), dialog);
1134         g_signal_connect (window, "response",
1135                           G_CALLBACK (add_lang_dialog_response_cb), pd);
1137         g_object_unref (store);
1138         g_object_unref (sortmodel);
1140         return dialog;
1143 static void
1144 language_editor_add_button_clicked_cb (GtkWidget *button,
1145                                        PrefsDialog *pd)
1147         if (pd->priv->add_lang_dialog == NULL)
1148         {
1149                 EphyDialog **add_lang_dialog;
1151                 pd->priv->add_lang_dialog = setup_add_language_dialog (pd);
1153                 add_lang_dialog = &pd->priv->add_lang_dialog;
1155                 g_object_add_weak_pointer
1156                         (G_OBJECT (pd->priv->add_lang_dialog),
1157                         (gpointer *) add_lang_dialog);
1158         }
1160         ephy_dialog_show (pd->priv->add_lang_dialog);
1163 static void
1164 language_editor_remove_button_clicked_cb (GtkWidget *button,
1165                                           PrefsDialog *pd)
1167         GtkTreeSelection *selection;
1168         GtkTreeModel *model;
1169         GtkTreeIter iter;
1171         selection = gtk_tree_view_get_selection (pd->priv->lang_treeview);
1173         if (gtk_tree_selection_get_selected (selection, &model, &iter))
1174         {
1175                 gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1176         }
1178         language_editor_update_pref (pd);
1179         language_editor_update_buttons (pd);
1182 static void
1183 language_editor_up_button_clicked_cb (GtkWidget *button,
1184                                       PrefsDialog *pd)
1186         GtkTreeSelection *selection;
1187         GtkTreeModel *model;
1188         GtkTreeIter iter, iter_prev;
1189         GtkTreePath *path;
1191         selection = gtk_tree_view_get_selection (pd->priv->lang_treeview);
1193         if (gtk_tree_selection_get_selected (selection, &model, &iter))
1194         {
1195                 path = gtk_tree_model_get_path (model, &iter);
1197                 if (!gtk_tree_path_prev (path))
1198                 {
1199                         gtk_tree_path_free (path);
1200                         return;
1201                 }
1203                 gtk_tree_model_get_iter (model, &iter_prev, path);
1205                 gtk_list_store_swap (GTK_LIST_STORE (model), &iter_prev, &iter);
1207                 gtk_tree_path_free (path);
1208         }
1210         language_editor_update_pref (pd);
1211         language_editor_update_buttons (pd);
1214 static void
1215 language_editor_down_button_clicked_cb (GtkWidget *button,
1216                                         PrefsDialog *pd)
1218         GtkTreeSelection *selection;
1219         GtkTreeModel *model;
1220         GtkTreeIter iter, iter_next;
1221         GtkTreePath *path;
1224         selection = gtk_tree_view_get_selection (pd->priv->lang_treeview);
1226         if (gtk_tree_selection_get_selected (selection, &model, &iter))
1227         {
1228                 path = gtk_tree_model_get_path (model, &iter);
1230                 gtk_tree_path_next (path);
1232                 gtk_tree_model_get_iter (model, &iter_next, path);
1234                 gtk_list_store_swap (GTK_LIST_STORE (model), &iter, &iter_next);
1236                 gtk_tree_path_free (path);
1237         }
1239         language_editor_update_pref (pd);
1240         language_editor_update_buttons (pd);
1243 static void
1244 language_editor_treeview_drag_end_cb (GtkWidget *widget,
1245                                       GdkDragContext *context,
1246                                       PrefsDialog *dialog)
1248         language_editor_update_pref (dialog);
1249         language_editor_update_buttons (dialog);
1252 static void
1253 language_editor_selection_changed_cb (GtkTreeSelection *selection,
1254                                       PrefsDialog *dialog)
1256         language_editor_update_buttons (dialog);
1259 static void
1260 create_language_section (EphyDialog *dialog)
1262         PrefsDialog *pd = EPHY_PREFS_DIALOG (dialog);
1263         GtkListStore *store;
1264         GtkTreeView *treeview;
1265         GtkCellRenderer *renderer;
1266         GtkTreeViewColumn *column;
1267         GtkTreeSelection *selection;
1268         GSList *list, *l, *ulist = NULL;
1270         pd->priv->iso_639_table = ephy_langs_iso_639_table ();
1271         pd->priv->iso_3166_table = ephy_langs_iso_3166_table ();
1273         ephy_dialog_get_controls
1274                 (dialog,
1275                  properties[LANGUAGE_TREEVIEW_PROP].id, &treeview,
1276                  properties[LANGUAGE_ADD_BUTTON_PROP].id, &pd->priv->lang_add_button,
1277                  properties[LANGUAGE_REMOVE_BUTTON_PROP].id, &pd->priv->lang_remove_button,
1278                  properties[LANGUAGE_UP_BUTTON_PROP].id, &pd->priv->lang_up_button, 
1279                  properties[LANGUAGE_DOWN_BUTTON_PROP].id, &pd->priv->lang_down_button,
1280                  NULL);
1282         g_signal_connect (pd->priv->lang_add_button, "clicked",
1283                           G_CALLBACK (language_editor_add_button_clicked_cb), dialog);
1284         g_signal_connect (pd->priv->lang_remove_button, "clicked",
1285                           G_CALLBACK (language_editor_remove_button_clicked_cb), dialog);
1286         g_signal_connect (pd->priv->lang_up_button, "clicked",
1287                           G_CALLBACK (language_editor_up_button_clicked_cb), dialog);
1288         g_signal_connect (pd->priv->lang_down_button, "clicked",
1289                           G_CALLBACK (language_editor_down_button_clicked_cb), dialog);
1291         /* setup the languages treeview */
1292         pd->priv->lang_treeview = treeview;
1294         gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
1296         store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
1298         pd->priv->lang_model = GTK_TREE_MODEL (store);
1300         gtk_tree_view_set_model (treeview, pd->priv->lang_model);
1301         g_object_unref (store);
1303         gtk_tree_view_set_headers_visible (treeview, FALSE);
1305         renderer = gtk_cell_renderer_text_new ();
1307         gtk_tree_view_insert_column_with_attributes (treeview,
1308                                                      0, _("Language"),
1309                                                      renderer,
1310                                                      "text", 0,
1311                                                      NULL);
1312         column = gtk_tree_view_get_column (treeview, 0);
1313         gtk_tree_view_column_set_resizable (column, TRUE);
1314         gtk_tree_view_column_set_sort_column_id (column, COL_LANG_NAME);
1316         selection = gtk_tree_view_get_selection (treeview);
1317         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
1319         /* Connect treeview signals */
1320         g_signal_connect (G_OBJECT (treeview), "drag_end",
1321                           G_CALLBACK (language_editor_treeview_drag_end_cb), pd);
1322         g_signal_connect (G_OBJECT (selection), "changed",
1323                           G_CALLBACK (language_editor_selection_changed_cb), pd);
1325         list = eel_gconf_get_string_list (CONF_RENDERING_LANGUAGE);
1327         /* uniquify list */
1328         for (l = list; l != NULL; l = l->next)
1329         {
1330                 if (g_slist_find_custom (ulist, l->data, (GCompareFunc) strcmp) == NULL)
1331                 {
1332                         ulist = g_slist_prepend (ulist, g_strdup (l->data));
1333                 }
1334         }
1335         ulist = g_slist_reverse (ulist);
1337         /* if modified, write back */
1338         if (g_slist_length (ulist) != g_slist_length (list))
1339         {
1340                 eel_gconf_set_string_list (CONF_RENDERING_LANGUAGE, ulist);
1341         }
1343         /* Fill languages editor */
1344         for (l = ulist; l != NULL; l = l->next)
1345         {
1346                 const char *code = (const char *) l->data;
1348                 if (strcmp (code, "system") == 0)
1349                 {
1350                         add_system_language_entry (store);
1351                 }
1352                 else if (code[0] != '\0')
1353                 {
1354                         char *text;
1356                         text = get_name_for_lang_code (pd, code);
1357                         language_editor_add (pd, code, text);
1358                         g_free (text);
1359                 }
1360         }
1362         language_editor_update_buttons (pd);
1364         /* Lockdown if key is not writable */
1365         if (eel_gconf_key_is_writable (CONF_RENDERING_LANGUAGE) == FALSE)
1366         {
1367                 gtk_widget_set_sensitive (pd->priv->lang_add_button, FALSE);
1368                 gtk_widget_set_sensitive (pd->priv->lang_remove_button, FALSE);
1369                 gtk_widget_set_sensitive (pd->priv->lang_up_button, FALSE);
1370                 gtk_widget_set_sensitive (pd->priv->lang_down_button, FALSE);
1371                 gtk_widget_set_sensitive (GTK_WIDGET (pd->priv->lang_treeview), FALSE);
1372         }
1374         g_slist_foreach (list, (GFunc) g_free, NULL);
1375         g_slist_free (list);
1377         g_slist_foreach (ulist, (GFunc) g_free, NULL);
1378         g_slist_free (ulist);
1381 static void
1382 download_path_changed_cb (GtkFileChooser *button)
1384         char *dir, *downloads_dir, *desktop_dir;
1386         /* FIXME: use _uri variant when we support downloading 
1387          * to gnome-vfs remote locations
1388          */
1389         dir = gtk_file_chooser_get_filename (button);
1390         if (dir == NULL) return;
1392         downloads_dir = ephy_file_downloads_dir ();
1393         desktop_dir = ephy_file_desktop_dir ();
1394         g_return_if_fail (downloads_dir != NULL && desktop_dir != NULL);
1396         if (strcmp (dir, downloads_dir) == 0)
1397         {
1398                 eel_gconf_set_string (CONF_STATE_DOWNLOAD_DIR, "Downloads");
1399         }
1400         else if (strcmp (dir, desktop_dir) == 0)
1401         {
1402                 eel_gconf_set_string (CONF_STATE_DOWNLOAD_DIR, "Desktop");
1403         }
1404         else
1405         {
1406                 eel_gconf_set_path (CONF_STATE_DOWNLOAD_DIR, dir);
1407         }
1409         g_free (dir);
1410         g_free (downloads_dir);
1411         g_free (desktop_dir);
1414 static void
1415 create_download_path_button (EphyDialog *dialog)
1417         GtkWidget *parent, *hbox, *label, *button;
1418         EphyFileChooser *fc;
1419         char *dir;
1421         dir = ephy_file_get_downloads_dir ();
1423         ephy_dialog_get_controls (dialog,
1424                                   properties[DOWNLOAD_PATH_HBOX_PROP].id, &hbox,
1425                                   properties[DOWNLOAD_PATH_LABEL_PROP].id, &label,
1426                                   properties[WINDOW_PROP].id, &parent,
1427                                   NULL);
1429         fc = ephy_file_chooser_new (_("Select a Directory"),
1430                                     parent,
1431                                     GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1432                                     NULL, EPHY_FILE_FILTER_NONE);
1434         /* Unset the destroy-with-parent, since gtkfilechooserbutton doesn't expect this */
1435         gtk_window_set_destroy_with_parent (GTK_WINDOW (fc), FALSE);
1437         button = gtk_file_chooser_button_new_with_dialog (GTK_WIDGET (fc));
1438         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (button), dir);
1439         gtk_file_chooser_button_set_width_chars (GTK_FILE_CHOOSER_BUTTON (button),
1440                                                  DOWNLOAD_BUTTON_WIDTH);
1441         g_signal_connect (button, "current-folder-changed",
1442                           G_CALLBACK (download_path_changed_cb), dialog);
1443         gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
1444         gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1445         gtk_widget_show (button);
1447         gtk_widget_set_sensitive (button, eel_gconf_key_is_writable (CONF_STATE_DOWNLOAD_DIR));
1448         g_free (dir);
1451 static void
1452 prefs_dialog_response_cb (GtkDialog *widget,
1453                           int response,
1454                           EphyDialog *dialog)
1456         if (response == GTK_RESPONSE_HELP)
1457         {
1458                 prefs_dialog_show_help (dialog);
1459                 return;
1460         }
1461                 
1462         g_object_unref (dialog);
1465 static void
1466 prefs_clear_cache_button_clicked_cb (GtkWidget *button,
1467                                      PrefsDialog *dialog)
1469         EphyEmbedShell *shell;
1470         EphyEmbedSingle *single;
1471         EphyFaviconCache *cache;
1473         shell = ephy_embed_shell_get_default ();
1475         single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (shell));
1476         ephy_embed_single_clear_cache (single);
1478         cache = EPHY_FAVICON_CACHE (ephy_embed_shell_get_favicon_cache (shell));
1479         ephy_favicon_cache_clear (cache);
1482 static void
1483 set_homepage_entry (EphyDialog *dialog,
1484                     const char *new_location)
1486         GValue value = { 0, };
1488         g_value_init (&value, G_TYPE_STRING);
1489         g_value_set_string (&value, new_location);
1490         ephy_dialog_set_value (dialog, properties[HOMEPAGE_ENTRY_PROP].id, &value);
1491         g_value_unset (&value);
1494 static void
1495 prefs_homepage_current_button_clicked_cb (GtkWidget *button,
1496                                           EphyDialog *dialog)
1498         EphySession *session;
1499         EphyWindow *window;
1500         EphyTab *tab;
1502         session = EPHY_SESSION (ephy_shell_get_session (ephy_shell_get_default ()));
1503         window = ephy_session_get_active_window (session);
1505         /* can't do anything in this case */
1506         if (window == NULL) return;
1508         tab = ephy_window_get_active_tab (window);
1509         g_return_if_fail (tab != NULL);
1511         set_homepage_entry (dialog, ephy_tab_get_address (tab));
1514 static void
1515 prefs_homepage_blank_button_clicked_cb (GtkWidget *button,
1516                                         EphyDialog *dialog)
1518         set_homepage_entry (dialog, NULL);
1520 static void
1521 prefs_dialog_init (PrefsDialog *pd)
1523         EphyDialog *dialog = EPHY_DIALOG (pd);
1524         EphyEncodings *encodings;
1525         GtkWidget *window, *curr_button, *blank_button;
1526         GtkWidget *clear_cache_button, *font_prefs_button;
1527         GtkWidget *css_checkbox, *css_edit_box, *css_edit_button, *css_container;
1528         gboolean sensitive;
1530         pd->priv = EPHY_PREFS_DIALOG_GET_PRIVATE (pd);
1532         ephy_dialog_construct (dialog,
1533                                properties,
1534                                ephy_file ("prefs-dialog.glade"),
1535                                "prefs_dialog",
1536                                NULL);
1538         ephy_dialog_add_enum (dialog, properties[ACCEPT_COOKIES_PROP].id,
1539                               G_N_ELEMENTS (cookies_accept_enum), cookies_accept_enum);
1541         ephy_dialog_get_controls
1542                 (dialog,
1543                  properties[WINDOW_PROP].id, &window,
1544                  properties[HOMEPAGE_CURRENT_PROP].id, &curr_button,
1545                  properties[HOMEPAGE_BLANK_PROP].id, &blank_button,
1546                  properties[FONT_PREFS_BUTTON_PROP].id, &font_prefs_button,
1547                  properties[CSS_CHECKBOX_PROP].id, &css_checkbox,
1548                  properties[CSS_EDIT_BOX_PROP].id, &css_edit_box,
1549                  properties[CSS_EDIT_BUTTON_PROP].id, &css_edit_button,
1550                  properties[CSS_CONTAINER_PROP].id, &css_container,
1551                  properties[CLEAR_CACHE_BUTTON_PROP].id, &clear_cache_button,
1552                  NULL);
1554         ephy_gui_ensure_window_group (GTK_WINDOW (window));
1556         g_signal_connect (window, "response",
1557                           G_CALLBACK (prefs_dialog_response_cb), dialog);
1559         g_signal_connect (curr_button, "clicked",
1560                           G_CALLBACK (prefs_homepage_current_button_clicked_cb), dialog);
1561         g_signal_connect (blank_button, "clicked",
1562                           G_CALLBACK (prefs_homepage_blank_button_clicked_cb), dialog);
1564         /* set homepage button sensitivity */
1565         sensitive = eel_gconf_key_is_writable (CONF_GENERAL_HOMEPAGE);
1566         gtk_widget_set_sensitive (curr_button, sensitive);
1567         gtk_widget_set_sensitive (blank_button, sensitive);
1569         g_signal_connect (font_prefs_button, "clicked",
1570                           G_CALLBACK (font_prefs_button_clicked_cb), dialog);
1572         css_checkbox_toggled (GTK_TOGGLE_BUTTON (css_checkbox), css_edit_box);
1573         g_signal_connect (css_checkbox, "toggled",
1574                           G_CALLBACK (css_checkbox_toggled), css_edit_box);
1576         g_signal_connect (css_edit_button, "clicked",
1577                           G_CALLBACK (css_edit_button_clicked_cb), dialog);
1579         g_signal_connect (clear_cache_button, "clicked",
1580                           G_CALLBACK (prefs_clear_cache_button_clicked_cb), dialog);
1582         encodings = EPHY_ENCODINGS (ephy_embed_shell_get_encodings
1583                                         (EPHY_EMBED_SHELL (ephy_shell)));
1585         create_node_combo (dialog, DEFAULT_ENCODING_PROP, encodings,
1586                            ephy_encodings_get_all (encodings),
1587                            CONF_LANGUAGE_DEFAULT_ENCODING, "ISO-8859-1");
1588         create_autodetectors_combo (dialog, AUTO_ENCODING_PROP, encodings,
1589                                     ephy_encodings_get_detectors (encodings),
1590                                     CONF_LANGUAGE_AUTODETECT_ENCODING, "");
1592         create_language_section (dialog);
1594         create_download_path_button (dialog);