aboutsummaryrefslogblamecommitdiffstats
path: root/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
blob: 58969a6b191815bdabb0ca03758a89432bcb238c (plain) (tree)































                                                                             



                                                                                    







                                     
  
 
                                           
                                     
  
 

                                                       

                                                
                                                                                      




































                                                                                                       

                               
                                                   













                                                                                                

                                            


                                                     




                                                 


































                                                                                
                                                                


                                                           
                                   






                                                          
                                  




                                                
                       




















                                                                                    

                                   


                                                                            

                                   

                                                     

















                                                                                           
                                                                             








































































































































                                                                                       
















                                                                         







                                                               



                                                                         


           
                                                                                       

                                         
                                   
 
                                                    
                                                               
 
                                              
                                                                          
                                                                            








                                                                                          
                                                                                           



 







                                                                                
/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) version 3.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "e-mail-display-popup-prefer-plain.h"
#include "mail/e-mail-display-popup-extension.h"
#include "mail/e-mail-display.h"
#include <shell/e-shell.h>
#include <shell/e-shell-window.h>
#include "mail/e-mail-browser.h"

#include <libebackend/libebackend.h>

#include <glib/gi18n-lib.h>

#define d(x)

typedef struct _EMailDisplayPopupPreferPlain EMailDisplayPopupPreferPlain;
typedef struct _EMailDisplayPopupPreferPlainClass EMailDisplayPopupPreferPlainClass;

struct _EMailDisplayPopupPreferPlain {
    EExtension parent;

    WebKitDOMDocument *document;
    gchar *text_plain_id;
    gchar *text_html_id;

    GtkActionGroup *action_group;

};

struct _EMailDisplayPopupPreferPlainClass {
    EExtensionClass parent_class;
};

#define E_TYPE_MAIL_DISPLAY_POPUP_PREFER_PLAIN \
    (e_mail_display_popup_prefer_plain_get_type ())
#define E_MAIL_DISPLAY_POPUP_PREFER_PLAIN(obj) \
    (G_TYPE_CHECK_INSTANCE_CAST \
    ((obj), E_TYPE_MAIL_DISPLAY_POPUP_PREFER_PLAIN, EMailDisplayPopupPreferPlain))

GType e_mail_display_popup_prefer_plain_get_type (void);
static void e_mail_display_popup_extension_interface_init (EMailDisplayPopupExtensionInterface *iface);

G_DEFINE_DYNAMIC_TYPE_EXTENDED (
    EMailDisplayPopupPreferPlain,
    e_mail_display_popup_prefer_plain,
    E_TYPE_EXTENSION,
    0,
    G_IMPLEMENT_INTERFACE_DYNAMIC (
        E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION,
        e_mail_display_popup_extension_interface_init));

static const gchar *ui_webview =
"<ui>"
"  <popup name='context'>"
"    <placeholder name='custom-actions-2'>"
"      <separator/>"
"      <menuitem action='show-plain-text-part'/>"
"      <menuitem action='show-text-html-part'/>"
"      <separator/>"
"    </placeholder>"
"  </popup>"
"</ui>";

static const gchar *ui_reader =
"<ui>"
"  <popup name='mail-preview-popup'>"
"    <placeholder name='mail-preview-popup-actions'>"
"      <separator/>"
"      <menuitem action='show-plain-text-part'/>"
"      <menuitem action='show-text-html-part'/>"
"      <separator/>"
"    </placeholder>"
"  </popup>"
"</ui>";

static void
toggle_part (GtkAction *action,
             EMailDisplayPopupExtension *extension)
{
    EMailDisplayPopupPreferPlain *pp_extension = (EMailDisplayPopupPreferPlain *) extension;
    WebKitDOMDocument *doc = pp_extension->document;
    WebKitDOMDOMWindow *window;
    WebKitDOMElement *frame_element;
    SoupURI *soup_uri;
    GHashTable *query;
    gchar *uri;

    uri = webkit_dom_document_get_document_uri (doc);
    soup_uri = soup_uri_new (uri);
    g_free (uri);

    query = soup_form_decode (soup_uri->query);
    g_hash_table_replace (
        query, g_strdup ("part_id"),
        pp_extension->text_html_id ?
            pp_extension->text_html_id :
            pp_extension->text_plain_id);
    g_hash_table_replace (
        query, g_strdup ("mime_type"),
        pp_extension->text_html_id ?
            (gpointer) "text/html" :
            (gpointer) "text/plain");

    soup_uri_set_query_from_form (soup_uri, query);
    g_hash_table_destroy (query);

    uri = soup_uri_to_string (soup_uri, FALSE);
    soup_uri_free (soup_uri);

    /* Get frame's window and from the window the actual <iframe> element */
    window = webkit_dom_document_get_default_view (doc);
    frame_element = webkit_dom_dom_window_get_frame_element (window);
    webkit_dom_html_iframe_element_set_src (
        WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame_element), uri);

    g_free (uri);
}

GtkActionEntry entries[] = {

    { "show-plain-text-part",
       NULL,
       N_("Display plain text version"),
       NULL,
       N_("Display plain text version of multipart/alternative message"),
       NULL
    },

    { "show-text-html-part",
      NULL,
      N_("Display HTML version"),
      NULL,
      N_("Display HTML version of multipart/alternative message"),
      NULL
    }
};

const gint ID_LEN = G_N_ELEMENTS (".alternative-prefer-plain.");

static void
set_text_plain_id (EMailDisplayPopupPreferPlain *extension,
                   const gchar *id)
{
    g_free (extension->text_plain_id);
    extension->text_plain_id = g_strdup (id);
}

static void
set_text_html_id (EMailDisplayPopupPreferPlain *extension,
                  const gchar *id)
{
    g_free (extension->text_html_id);
    extension->text_html_id = g_strdup (id);
}

static GtkActionGroup *
create_group (EMailDisplayPopupExtension *extension)
{
    EExtensible *extensible;
    EWebView *web_view;
    GtkUIManager *ui_manager;
    GtkActionGroup *group;
    GtkAction *action;
    EShell *shell;
    GtkWindow *shell_window;

    extensible = e_extension_get_extensible (E_EXTENSION (extension));
    web_view = E_WEB_VIEW (extensible);

    group = gtk_action_group_new ("prefer-plain");
    gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), NULL);

    ui_manager = e_web_view_get_ui_manager (web_view);
    gtk_ui_manager_insert_action_group (ui_manager, group, 0);
    gtk_ui_manager_add_ui_from_string (ui_manager, ui_webview, -1, NULL);

    action = gtk_action_group_get_action (group, "show-plain-text-part");
    g_signal_connect (
        action, "activate",
        G_CALLBACK (toggle_part), extension);

    action = gtk_action_group_get_action (group, "show-text-html-part");
    g_signal_connect (
        action, "activate",
        G_CALLBACK (toggle_part), extension);

    shell = e_shell_get_default ();
    shell_window = e_shell_get_active_window (shell);
    if (E_IS_SHELL_WINDOW (shell_window)) {
        ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (shell_window));
    } else if (E_IS_MAIL_BROWSER (shell_window)) {
        ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (shell_window));
    } else {
        return NULL;
    }

    gtk_ui_manager_insert_action_group (ui_manager, group, 0);
    gtk_ui_manager_add_ui_from_string (ui_manager, ui_reader, -1, NULL);

    return group;
}

static void
mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *extension,
                                                WebKitHitTestResult *context)
{
    EMailDisplay *display;
    GtkAction *action;
    WebKitDOMNode *node;
    gchar *uri, *part_id, *pos, *prefix;
    SoupURI *soup_uri;
    GHashTable *query;
    EMailPartList *part_list;
    GSList *iter;
    gboolean is_text_plain;
    const gchar *action_name;
    EMailDisplayPopupPreferPlain *pp_extension;

    display = E_MAIL_DISPLAY (e_extension_get_extensible (
            E_EXTENSION (extension)));

    pp_extension = E_MAIL_DISPLAY_POPUP_PREFER_PLAIN (extension);

    if (!pp_extension->action_group)
        pp_extension->action_group = create_group (extension);

    g_object_get (context, "inner-node", &node, NULL);

    if (!node) {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
        return;
    }

    pp_extension->document = webkit_dom_node_get_owner_document (node);
    uri = webkit_dom_document_get_document_uri (pp_extension->document);

    soup_uri = soup_uri_new (uri);
    if (!soup_uri || !soup_uri->query) {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
        if (soup_uri)
            soup_uri_free (soup_uri);
        g_free (uri);
        return;
    }

    query = soup_form_decode (soup_uri->query);
    part_id = g_hash_table_lookup (query, "part_id");
    if (part_id == NULL) {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
        g_hash_table_destroy (query);
        soup_uri_free (soup_uri);
        g_free (uri);
        return;
    }

    pos = strstr (part_id, ".alternative-prefer-plain.");
    if (!pos) {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
        g_hash_table_destroy (query);
        soup_uri_free (soup_uri);
        g_free (uri);
        return;
    }

    /* Don't display the actions on any other than text/plain or text/html parts */
    if (!strstr (pos, "plain_text") && !strstr (pos, "text_html")) {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
        g_hash_table_destroy (query);
        soup_uri_free (soup_uri);
        g_free (uri);
        return;
    }

    /* Check whether the displayed part is text_plain */
    is_text_plain = (strstr (pos + ID_LEN, "plain_text") != NULL);

    /* It is! Hide the menu action */
    if (is_text_plain) {
        action = gtk_action_group_get_action (
            pp_extension->action_group, "show-plain-text-part");
        gtk_action_set_visible (action, FALSE);
    } else {
        action = gtk_action_group_get_action (
            pp_extension->action_group, "show-text-html-part");
        gtk_action_set_visible (action, FALSE);
    }

    /* Now check whether HTML version exists, if it does enable the action */
    prefix = g_strndup (part_id, (pos - part_id) + ID_LEN - 1);

    action_name = NULL;
    part_list = e_mail_display_get_parts_list (display);
    for (iter = part_list->list; iter; iter = g_slist_next (iter)) {
        EMailPart *p = iter->data;
        if (!p)
            continue;

        if (g_str_has_prefix (p->id, prefix) &&
            (strstr (p->id, "text_html") || strstr (p->id, "plain_text"))) {

            pos = strstr (p->id, ".alternative-prefer-plain.");

            if (is_text_plain) {
                if (strstr (pos + ID_LEN, "text_html") != NULL) {
                    action_name = "show-text-html-part";
                    set_text_html_id (pp_extension, p->id);
                    set_text_plain_id (pp_extension, NULL);
                    break;
                }
            } else {
                if (strstr (pos + ID_LEN, "plain_text") != NULL) {
                    action_name = "show-plain-text-part";
                    set_text_html_id (pp_extension, NULL);
                    set_text_plain_id (pp_extension, p->id);
                    break;
                }
            }
        }
    }

    if (action_name) {
        action = gtk_action_group_get_action (
            pp_extension->action_group, action_name);
        gtk_action_group_set_visible (pp_extension->action_group, TRUE);
        gtk_action_set_visible (action, TRUE);
    } else {
        gtk_action_group_set_visible (pp_extension->action_group, FALSE);
    }

    g_free (prefix);
    g_hash_table_destroy (query);
    soup_uri_free (soup_uri);
    g_free (uri);
}

void
e_mail_display_popup_prefer_plain_type_register (GTypeModule *type_module)
{
    e_mail_display_popup_prefer_plain_register_type (type_module);
}

static void
e_mail_display_popup_prefer_plain_dispose (GObject *object)
{
    EMailDisplayPopupPreferPlain *extension;

    extension = E_MAIL_DISPLAY_POPUP_PREFER_PLAIN (object);

    if (extension->action_group != NULL) {
        g_object_unref (extension->action_group);
        extension->action_group = NULL;
    }

    /* Chain up to parent's dispose() method. */
    G_OBJECT_CLASS (e_mail_display_popup_prefer_plain_parent_class)->
        dispose (object);
}

static void
e_mail_display_popup_prefer_plain_finalize (GObject *object)
{
    EMailDisplayPopupPreferPlain *extension;

    extension = E_MAIL_DISPLAY_POPUP_PREFER_PLAIN (object);

    g_free (extension->text_html_id);
    g_free (extension->text_plain_id);

    /* Chain up to parent's finalize() method. */
    G_OBJECT_CLASS (e_mail_display_popup_prefer_plain_parent_class)->
        finalize (object);
}

static void
e_mail_display_popup_prefer_plain_class_init (EMailDisplayPopupPreferPlainClass *class)
{
    EExtensionClass *extension_class;
    GObjectClass *object_class;

    extension_class = E_EXTENSION_CLASS (class);
    extension_class->extensible_type = E_TYPE_MAIL_DISPLAY;

    object_class = G_OBJECT_CLASS (class);
    object_class->dispose = e_mail_display_popup_prefer_plain_dispose;
    object_class->finalize = e_mail_display_popup_prefer_plain_finalize;
}

static void
e_mail_display_popup_extension_interface_init (EMailDisplayPopupExtensionInterface *iface)
{
    iface->update_actions = mail_display_popup_prefer_plain_update_actions;
}

void
e_mail_display_popup_prefer_plain_class_finalize (EMailDisplayPopupPreferPlainClass *class)
{

}

static void
e_mail_display_popup_prefer_plain_init (EMailDisplayPopupPreferPlain *extension)
{
    extension->action_group = NULL;
    extension->text_html_id = NULL;
    extension->text_plain_id = NULL;
    extension->document = NULL;
}