aboutsummaryrefslogblamecommitdiffstats
path: root/src/ephy-encoding-dialog.c
blob: de15cbae3b00192c883cee2f761b67c4dd844a5d (plain) (tree)
1
2
3
4
5
                                                                           
  

                                                            
                                 












                                                                        
                                                                                  
  

   
                   
                                 

                       
                                 
                             
                             

                           
                              
                     
                       
 
                       
                    


                            
                          
      
 

                                                                                                                                              
                                 



                                 
                            
                            
                                

  





                         
                                                                                
 
           




































                                                                          
                                                        

                         


                                    
                          
                             
                                      
                            
                           





                                                                         
                                                           



                                                             
                                                              





                                                               
      
 

                                                                                     
 

                                                                           







                                                                                 







                                                                                     

         

                                                               

                                                                                


                                         

           
                                     

                                              
 
                                                     
                                                     














                                                                                     
                                                                                            





                                                                  




                                                                                   
                                                                                                    




                                                               
                                                                                     
 





                                                        
                                                                           


                                                           




                                                   
                                                                    






                                                                

                              
                            
 


                                                                         

                                                               

                                                                                 

                                                           

                         


                                                                
                                                                 
      
         
                                                         


                                 
                                                       
 


                                                                
                                                                 
      
 
                                                                          
         

 
           
                                                    
                                               

                                                             

                                          
                                                        


                       



                                

                                                  
 
                          


                                                       
 










                                                                       
 

                                      
 
                                                                                 
                                                                        

                                 


           



                                                  
 
                          



                                                       
 
                                                   
 









                                                     
 
                                                                                 




                                                                        


           









                                                                          

                                                      
                                                                 
                                    



                                  




                                                                 
                                                                                
 
                                                    
                                                                 

                                                 
 

                                                               


                                                                                 
















                                                                              
 

                                                                                          
 

                                                 
 






                                                                                   
 



                                                                           

                                                            
                                  

                                                             



                                   

                                                                 

                                                               

                                                               
                                                     
                                                           


                                                                     
                                                                                 
                                                     
                                                           
 

                                          
                                                                     
                                                                    















                                                                                   

                                
                                                                                                    



                                                                                     
                                                 
 
                                                                              


           



                                                                
                                                               







                                                                                   
                                                     

                                                   

                                   
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 *  Copyright © 2000, 2001, 2002, 2003 Marco Pesenti Gritti
 *  Copyright © 2003, 2004 Christian Persch
 *  Copyright © 2012 Igalia S.L.
 *
 *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "ephy-encoding-dialog.h"

#include "ephy-debug.h"
#include "ephy-embed-container.h"
#include "ephy-embed-shell.h"
#include "ephy-embed-utils.h"
#include "ephy-embed.h"
#include "ephy-encodings.h"
#include "ephy-file-helpers.h"
#include "ephy-gui.h"
#include "ephy-shell.h"

#include <glib/gi18n.h>
#include <gtk/gtk.h>
#ifdef HAVE_WEBKIT2
#include <webkit2/webkit2.h>
#else
#include <webkit/webkit.h>
#endif

#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 *enc_view;
    gboolean update_tag;
    char *selected_encoding;
};

enum {
    COL_TITLE_ELIDED,
    COL_ENCODING,
    NUM_COLS
};
    
G_DEFINE_TYPE (EphyEncodingDialog, ephy_encoding_dialog, EPHY_TYPE_EMBED_DIALOG)

static void
select_encoding_row (GtkTreeView *view, EphyEncoding *encoding)
{
    GtkTreeIter iter;
    GtkTreeModel *model;
    gboolean valid_iter = FALSE;
    const char *target_encoding;

    model = gtk_tree_view_get_model (view);
    valid_iter = gtk_tree_model_get_iter_first (model, &iter);

    target_encoding = ephy_encoding_get_encoding (encoding);

    while (valid_iter)
    {
        char *encoding_string = NULL;

        gtk_tree_model_get (model, &iter,
                    COL_ENCODING, &encoding_string, -1);

        if (g_str_equal (encoding_string,
                 target_encoding))
        {
            GtkTreeSelection *selection;

            selection = gtk_tree_view_get_selection (view);
            gtk_tree_selection_select_iter (selection, &iter);
            g_free (encoding_string);

            return;
        }

        g_free (encoding_string);
        valid_iter = gtk_tree_model_iter_next (model, &iter);
    }
}

static void
sync_encoding_against_embed (EphyEncodingDialog *dialog)
{
    EphyEmbed *embed;
        GtkTreeSelection *selection;
        GtkTreeModel *model;
        GList *rows;
    GtkWidget *button;
    const char *encoding;
    gboolean is_automatic = FALSE;
    WebKitWebView *view;
    EphyEncoding *node;

    dialog->priv->update_tag = TRUE;

    embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog));
    g_return_if_fail (EPHY_IS_EMBED (embed));

    view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
#ifdef HAVE_WEBKIT2
    encoding = webkit_web_view_get_custom_charset (view);
    if (encoding == NULL) return;
#else
    encoding = webkit_web_view_get_custom_encoding (view);
    if (encoding == NULL)
    {
        encoding = webkit_web_view_get_encoding (view);
        if (encoding == NULL) return;
        is_automatic = TRUE;
    }
#endif

    node = ephy_encodings_get_encoding (dialog->priv->encodings, encoding, TRUE);
    g_assert (EPHY_IS_ENCODING (node));

    /* Select the current encoding in the list view. */
    select_encoding_row (GTK_TREE_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_scroll_to_cell (GTK_TREE_VIEW (dialog->priv->enc_view),
                          (GtkTreePath *) rows->data,
                          NULL, /* column */
                          TRUE,
                          0.5,
                          0.0);
        g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
        g_list_free (rows);
    }

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog),
                      "automatic_button");
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), is_automatic);

    dialog->priv->update_tag = FALSE;
}


static void
embed_net_stop_cb (EphyWebView *view,
           GParamSpec *pspec,
           EphyEncodingDialog *dialog)
{
    if (ephy_web_view_is_loading (view) == FALSE)
        sync_encoding_against_embed (dialog);
}

static void
sync_embed_cb (EphyEncodingDialog *dialog, GParamSpec *pspec, gpointer dummy)
{
    EphyEmbed *embed;
    embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog));

    if (dialog->priv->embed != NULL)
    {
        g_signal_handlers_disconnect_by_func (dialog->priv->embed,
                              G_CALLBACK (embed_net_stop_cb),
                              dialog);
    }

    g_signal_connect (G_OBJECT (ephy_embed_get_web_view (embed)), "notify::load-status",
              G_CALLBACK (embed_net_stop_cb), dialog);
    dialog->priv->embed = embed;

    sync_encoding_against_embed (dialog);
}

static void
sync_active_tab (EphyWindow *window, GParamSpec *pspec, EphyEncodingDialog *dialog)
{
    EphyEmbed *embed;

    embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (dialog->priv->window));

    g_object_set (G_OBJECT (dialog), "embed", embed, NULL);
}

static void
sync_parent_window_cb (EphyEncodingDialog *dialog, GParamSpec *pspec, gpointer dummy)
{
    EphyWindow *window;
    GValue value = { 0, };

    g_return_if_fail (dialog->priv->window == NULL);

    g_value_init (&value, GTK_TYPE_WIDGET);
    g_object_get_property (G_OBJECT (dialog), "parent-window", &value);
    window = EPHY_WINDOW (g_value_get_object (&value));
    g_value_unset (&value);

    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-child",
              G_CALLBACK (sync_active_tab), dialog);
}

static void
activate_choice (EphyEncodingDialog *dialog)
{
    EphyEmbed *embed;
    GtkWidget *button;
    gboolean is_automatic;
    WebKitWebView *view;

    embed = ephy_embed_dialog_get_embed (EPHY_EMBED_DIALOG (dialog));
    g_return_if_fail (EPHY_IS_EMBED (embed));

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog),
                      "automatic_button");
    is_automatic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));

    view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);

    if (is_automatic)
    {
#ifdef HAVE_WEBKIT2
        webkit_web_view_set_custom_charset (view, NULL);
#else
        webkit_web_view_set_custom_encoding (view, NULL);
#endif
    }
    else if (dialog->priv->selected_encoding != NULL)
    {
        const char *code;

        code = dialog->priv->selected_encoding;

#ifdef HAVE_WEBKIT2
        webkit_web_view_set_custom_charset (view, code);
#else
        webkit_web_view_set_custom_encoding (view, code);
#endif

        ephy_encodings_add_recent (dialog->priv->encodings, code);
    }
}

static void
ephy_encoding_dialog_response_cb (GtkWidget *widget,
                  int response,
                  EphyEncodingDialog *dialog)
{
    if (response == GTK_RESPONSE_HELP)
    {
        ephy_gui_help (widget, "text-encoding");
        return;
    }

    g_object_unref (dialog);
}

static void
view_row_selected_cb (GtkTreeSelection *selection,
              EphyEncodingDialog *dialog)
{
    GtkWidget *button;
    GtkTreeModel *model;
    GtkTreeIter iter;
    EphyEncodingDialogPrivate *priv = dialog->priv;

    if (gtk_tree_selection_get_selected (selection, &model, &iter))
    {
        char *encoding;

        gtk_tree_model_get (model, &iter,
                    COL_ENCODING, &encoding,
                    -1);

        g_free (priv->selected_encoding);
        priv->selected_encoding = encoding;
    }

    if (dialog->priv->update_tag) 
        return;

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog), "manual_button");
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);

    activate_choice (dialog);
}

static void
view_row_activated_cb (GtkTreeView *treeview,
               GtkTreePath *path,
               GtkTreeViewColumn *column,
               EphyEncodingDialog *dialog)
{
    GtkWidget *button;
    GtkTreeIter iter;
    char *encoding;
    GtkTreeModel *model;
    EphyEncodingDialogPrivate *priv = dialog->priv;

    model = gtk_tree_view_get_model (treeview);

    gtk_tree_model_get_iter (model, &iter, path);
    gtk_tree_model_get (model, &iter,
                COL_ENCODING, &encoding,
                -1);

    g_free (priv->selected_encoding);
    priv->selected_encoding = encoding;

    if (dialog->priv->update_tag) 
        return;

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog), "manual_button");
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);

    activate_choice (dialog);

    g_object_unref (dialog);
}

static void
automatic_toggled_cb (GtkToggleButton *button, EphyEncodingDialog *dialog)
{
    if (gtk_toggle_button_get_active (button)
        && dialog->priv->update_tag == FALSE)
    {
        activate_choice (dialog);
    }
}

static void
ephy_encoding_dialog_init (EphyEncodingDialog *dialog)
{
    GtkWidget *treeview, *scroller, *button, *window, *child;
    GtkTreeSelection *selection;
    GList *encodings, *p;
    GtkListStore *store;
    GtkTreeIter iter;
    GtkCellRenderer *renderer;

    dialog->priv = EPHY_ENCODING_DIALOG_GET_PRIVATE (dialog);

    dialog->priv->encodings =
        EPHY_ENCODINGS (ephy_embed_shell_get_encodings
                (EPHY_EMBED_SHELL (ephy_shell_get_default ())));

    ephy_dialog_construct (EPHY_DIALOG (dialog),
                   "/org/gnome/epiphany/epiphany.ui",
                   "encoding_dialog",
                   NULL);

    window = ephy_dialog_get_control (EPHY_DIALOG (dialog),
                      "encoding_dialog");
    g_signal_connect (window, "response",
              G_CALLBACK (ephy_encoding_dialog_response_cb), dialog);

    encodings = ephy_encodings_get_all (dialog->priv->encodings);
    store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
    for (p = encodings; p; p = p->next) 
    {
        EphyEncoding *encoding = EPHY_ENCODING (p->data);

        gtk_list_store_append (store, &iter);
        gtk_list_store_set (store, &iter,
                    COL_TITLE_ELIDED, 
                    ephy_encoding_get_title_elided (encoding),
                    -1);
        gtk_list_store_set (store, &iter,
                    COL_ENCODING, 
                    ephy_encoding_get_encoding (encoding),
                    -1);
    }
    g_list_free (encodings);

    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), COL_TITLE_ELIDED,
                          GTK_SORT_ASCENDING);

    treeview = gtk_tree_view_new ();
    renderer = gtk_cell_renderer_text_new ();

    gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
                             -1,
                             _("Encodings"),
                             renderer,
                             "text", COL_TITLE_ELIDED,
                             NULL);
    gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));

    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 (selection, "changed",
              G_CALLBACK (view_row_selected_cb),
              dialog);
    g_signal_connect (treeview, "row-activated",
              G_CALLBACK (view_row_activated_cb),
              dialog);

    gtk_widget_show (treeview);

    scroller = ephy_dialog_get_control (EPHY_DIALOG (dialog),
                        "scrolled_window");
    gtk_container_add (GTK_CONTAINER (scroller), treeview);

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog),
                      "automatic_button");
    child = gtk_bin_get_child (GTK_BIN (button));
    gtk_label_set_use_markup (GTK_LABEL (child), TRUE);
    g_signal_connect (button, "toggled",
              G_CALLBACK (automatic_toggled_cb), dialog);

    button = ephy_dialog_get_control (EPHY_DIALOG (dialog), "manual_button");
    child = gtk_bin_get_child (GTK_BIN (button));
    gtk_label_set_use_markup (GTK_LABEL (child), TRUE);

    dialog->priv->enc_view = treeview;

    g_signal_connect (G_OBJECT (dialog), "notify::parent-window",
              G_CALLBACK (sync_parent_window_cb), NULL);
    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);
    }

    if (dialog->priv->embed)
    {
        g_signal_handlers_disconnect_by_func (ephy_embed_get_web_view (dialog->priv->embed),
                              G_CALLBACK (embed_net_stop_cb),
                              dialog);
    }

    g_free (dialog->priv->selected_encoding);

    G_OBJECT_CLASS (ephy_encoding_dialog_parent_class)->finalize (object);
}

static void
ephy_encoding_dialog_class_init (EphyEncodingDialogClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);

    object_class->finalize = ephy_encoding_dialog_finalize;

    g_type_class_add_private (object_class, sizeof(EphyEncodingDialogPrivate));
}
        
EphyEncodingDialog *
ephy_encoding_dialog_new (EphyWindow *parent)
{
    return g_object_new (EPHY_TYPE_ENCODING_DIALOG,
                 "parent-window", parent,
                 "default-width", 350,
                     "default-height", 420,
                 NULL);
}