diff options
Diffstat (limited to 'src/ephy-encoding-dialog.c')
-rw-r--r-- | src/ephy-encoding-dialog.c | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/src/ephy-encoding-dialog.c b/src/ephy-encoding-dialog.c new file mode 100644 index 000000000..5f7e653a1 --- /dev/null +++ b/src/ephy-encoding-dialog.c @@ -0,0 +1,489 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Marco Pesenti Gritti + * Copyright (C) 2003 Christian Persch + * + * This program 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; either version 2, or (at your option) + * any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ephy-encoding-dialog.h" +#include "ephy-encodings.h" +#include "ephy-embed.h" +#include "ephy-embed-shell.h" +#include "ephy-shell.h" +#include "ephy-gui.h" +#include "ephy-node.h" +#include "ephy-node-view.h" +#include "ephy-debug.h" + +#include <gtk/gtklabel.h> +#include <gtk/gtkbutton.h> +#include <gtk/gtktreeview.h> +#include <gtk/gtktreeselection.h> +#include <bonobo/bonobo-i18n.h> +#include <string.h> + +enum +{ + CATEGORIES_SCROLLER_PROP, + LIST_SCROLLER_PROP +}; + +static const +EphyDialogProperty properties [] = +{ + { CATEGORIES_SCROLLER_PROP, "categories_scroller", NULL, PT_NORMAL, NULL }, + { LIST_SCROLLER_PROP, "list_scroller", NULL, PT_NORMAL, NULL }, + + { -1, NULL, NULL } +}; + +#define EPHY_ENCODING_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ENCODING_DIALOG, EphyEncodingDialogPrivate)) + +struct EphyEncodingDialogPrivate +{ + EphyEncodings *encodings; + EphyWindow *window; + EphyEmbed *embed; + GtkWidget *cat_view; + GtkWidget *enc_view; + EphyNodeFilter *filter; + EphyNode *selected_node; + gboolean update_tag; +}; + +static void ephy_encoding_dialog_class_init (EphyEncodingDialogClass *klass); +static void ephy_encoding_dialog_init (EphyEncodingDialog *ge); +void ephy_encoding_dialog_response_cb (GtkWidget *widget, + gint response, + EphyEncodingDialog *dialog); + +enum +{ + PROP_0, + PROP_WINDOW +}; + +static GObjectClass *parent_class = NULL; + +GType +ephy_encoding_dialog_get_type (void) +{ + static GType ephy_type_encoding_dialog = 0; + + if (ephy_type_encoding_dialog == 0) + { + static const GTypeInfo our_info = + { + sizeof (EphyEncodingDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) ephy_encoding_dialog_class_init, + NULL, + NULL, /* class_data */ + sizeof (EphyEncodingDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) ephy_encoding_dialog_init + }; + + ephy_type_encoding_dialog = g_type_register_static (EPHY_TYPE_EMBED_DIALOG, + "EphyEncodingDialog", + &our_info, 0); + } + + return ephy_type_encoding_dialog; +} + +static void +setup_filter (EphyEncodingDialog *dialog, EphyNode *category) +{ + ephy_node_filter_empty (dialog->priv->filter); + + ephy_node_filter_add_expression (dialog->priv->filter, + ephy_node_filter_expression_new (EPHY_NODE_FILTER_EXPRESSION_HAS_PARENT, + category), + 0); + + ephy_node_filter_done_changing (dialog->priv->filter); +} + +static void +sync_embed_cb (EphyEncodingDialog *dialog, GParamSpec *pspec, gpointer dummy) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + EphyNode *node, *categories; + gresult result; + GtkTreeSelection *selection; + GtkTreeModel *model; + GList *rows; + GPtrArray *children; + int i; + + dialog->priv->update_tag = TRUE; + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + node = ephy_encodings_get_node (dialog->priv->encodings, info->encoding); + g_return_if_fail (EPHY_IS_NODE (node)); + + /* select the correct category in the left pane ... */ + categories = ephy_encodings_get_categories (dialog->priv->encodings); + + children = ephy_node_get_children (categories); + for (i = 0; i < children->len; i++) + { + EphyNode *kid; + + kid = g_ptr_array_index (children, i); + if (ephy_node_has_child (kid, node)) + { + ephy_node_view_select_node (EPHY_NODE_VIEW (dialog->priv->cat_view), + kid); + break; + } + } + ephy_node_thaw (categories); + + /* ... and the active encoding in the right pane */ + ephy_node_view_select_node (EPHY_NODE_VIEW (dialog->priv->enc_view), + node); + + /* scroll the view so the active encoding is visible */ + selection = gtk_tree_view_get_selection + (GTK_TREE_VIEW (dialog->priv->enc_view)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->enc_view)); + rows = gtk_tree_selection_get_selected_rows (selection, &model); + if (rows != NULL) + { + gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->priv->enc_view), + (GtkTreePath *)rows->data, + NULL, FALSE); + g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL); + g_list_free (rows); + } + + ephy_encoding_info_free (info); + + dialog->priv->update_tag = FALSE; +} + +static void +sync_active_tab (EphyWindow *window, GParamSpec *pspec, EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + + embed = ephy_window_get_active_embed (dialog->priv->window); + + g_object_set (G_OBJECT (dialog), "embed", embed, NULL); +} + +static void +ephy_encoding_dialog_set_window (EphyEncodingDialog *dialog, EphyWindow *window) +{ + g_return_if_fail (EPHY_IS_WINDOW (window)); + + dialog->priv->window = window; + + sync_active_tab (window, NULL, dialog); + g_signal_connect (G_OBJECT (window), "notify::active-tab", + G_CALLBACK (sync_active_tab), dialog); +} + +static void +activate_choice (EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + gresult result; + + LOG ("going manual") + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + if (dialog->priv->selected_node != NULL) + { + const char *code; + + code = ephy_node_get_property_string (dialog->priv->selected_node, + EPHY_NODE_ENCODING_PROP_ENCODING); + + /* only force it if it's different from active */ + if (info->encoding && strcmp (info->encoding, code) != 0) + { + ephy_embed_set_encoding (embed, code); + + ephy_encodings_add_recent (dialog->priv->encodings, code); + } + } + + ephy_encoding_info_free (info); +} + +static void +activate_automatic (EphyEncodingDialog *dialog) +{ + EphyEmbed *embed; + EphyEncodingInfo *info; + gresult result; + + LOG ("going automatic") + + embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog)); + g_return_if_fail (EPHY_IS_EMBED (embed)); + + result = ephy_embed_get_encoding_info (embed, &info); + if (result != G_OK || info == NULL) return; + + if ((info->forced_encoding != NULL && info->forced_encoding[0] != '\0') + || info->encoding_source >= EMBED_ENCODING_PARENT_FORCED) + { + /* clear forced encoding */ + ephy_embed_set_encoding (embed, ""); + } + + ephy_encoding_info_free (info); +} + +void +ephy_encoding_dialog_response_cb (GtkWidget *widget, + gint response, + EphyEncodingDialog *dialog) +{ + switch (response) + { + case GTK_RESPONSE_OK: + activate_choice (dialog); + break; + case -11: /* Automatic */ + activate_automatic (dialog); + break; + default: + break; + } + + g_object_unref (dialog); +} + +static void +category_node_selected_cb (EphyNodeView *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + setup_filter (dialog, node); +} + +static void +view_node_selected_cb (EphyNodeView *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + dialog->priv->selected_node = node; +} + +static void +view_node_activated_cb (GtkWidget *view, + EphyNode *node, + EphyEncodingDialog *dialog) +{ + dialog->priv->selected_node = node; + + if (dialog->priv->update_tag == FALSE) + { + activate_choice (dialog); + + g_object_unref (dialog); + } +} + +static void +ephy_encoding_dialog_init (EphyEncodingDialog *dialog) +{ + GtkWidget *treeview, *scroller; + GtkTreeSelection *selection; + EphyNode *node; + + dialog->priv = EPHY_ENCODING_DIALOG_GET_PRIVATE (dialog); + + dialog->priv->encodings = + EPHY_ENCODINGS (ephy_embed_shell_get_encodings + (EPHY_EMBED_SHELL (ephy_shell))); + + dialog->priv->update_tag = FALSE; + dialog->priv->selected_node = NULL; + + ephy_dialog_construct (EPHY_DIALOG (dialog), + properties, + "epiphany.glade", + "encoding_dialog"); + + node = ephy_encodings_get_categories (dialog->priv->encodings); + treeview = ephy_node_view_new (node, dialog->priv->filter); + + ephy_node_view_add_column (EPHY_NODE_VIEW (treeview), _("Location"), + G_TYPE_STRING, + EPHY_NODE_ENCODING_PROP_TITLE, + -1, + EPHY_NODE_VIEW_AUTO_SORT | + EPHY_NODE_VIEW_SEARCHABLE, + NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + g_signal_connect (G_OBJECT (treeview), + "node_selected", + G_CALLBACK (category_node_selected_cb), + dialog); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); + gtk_widget_show (treeview); + + scroller = ephy_dialog_get_control + (EPHY_DIALOG (dialog), CATEGORIES_SCROLLER_PROP); + gtk_container_add (GTK_CONTAINER (scroller), treeview); + + dialog->priv->cat_view = treeview; + + dialog->priv->filter = ephy_node_filter_new (); + + node = ephy_encodings_get_all (dialog->priv->encodings); + treeview = ephy_node_view_new (node, dialog->priv->filter); + + ephy_node_view_add_column (EPHY_NODE_VIEW (treeview), _("Encodings"), + G_TYPE_STRING, + EPHY_NODE_ENCODING_PROP_TITLE_ELIDED, + -1, + EPHY_NODE_VIEW_AUTO_SORT | + EPHY_NODE_VIEW_SEARCHABLE, + NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), FALSE); + + g_signal_connect (G_OBJECT (treeview), + "node_selected", + G_CALLBACK (view_node_selected_cb), + dialog); + g_signal_connect (G_OBJECT (treeview), + "node_activated", + G_CALLBACK (view_node_activated_cb), + dialog); + + gtk_widget_show (treeview); + + scroller = ephy_dialog_get_control + (EPHY_DIALOG (dialog), LIST_SCROLLER_PROP); + gtk_container_add (GTK_CONTAINER (scroller), treeview); + + dialog->priv->enc_view = treeview; + + g_signal_connect (G_OBJECT (dialog), "notify::embed", + G_CALLBACK (sync_embed_cb), NULL); +} + +static void +ephy_encoding_dialog_finalize (GObject *object) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + if (dialog->priv->window != NULL) + { + g_signal_handlers_disconnect_by_func (dialog->priv->window, + G_CALLBACK (sync_active_tab), + dialog); + } + + g_object_unref (dialog->priv->filter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +ephy_encoding_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + switch (prop_id) + { + case PROP_WINDOW: + ephy_encoding_dialog_set_window (dialog, g_value_get_object (value)); + break; + } +} + +static void +ephy_encoding_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyEncodingDialog *dialog = EPHY_ENCODING_DIALOG (object); + + switch (prop_id) + { + case PROP_WINDOW: + g_value_set_object (value, dialog->priv->window); + break; + } +} + +static void +ephy_encoding_dialog_class_init (EphyEncodingDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = ephy_encoding_dialog_finalize; + object_class->get_property = ephy_encoding_dialog_get_property; + object_class->set_property = ephy_encoding_dialog_set_property; + + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "Parent window", + EPHY_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof(EphyEncodingDialogPrivate)); +} + +EphyEncodingDialog * +ephy_encoding_dialog_new (EphyWindow *parent) +{ + return g_object_new (EPHY_TYPE_ENCODING_DIALOG, + "window", parent, + NULL); +} |