aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2012-06-26 19:39:47 +0800
committerDan Vrátil <dvratil@redhat.com>2012-06-26 19:40:59 +0800
commit99a875edae6c57fd6540818d3f0da994b135a068 (patch)
tree53acc10d4dd0d44b569a0a2052e8a4300d2ef4a2
parent137eec97eb4f3d25f662e651c168d67e7e9e85e4 (diff)
downloadgsoc2013-evolution-99a875edae6c57fd6540818d3f0da994b135a068.tar.gz
gsoc2013-evolution-99a875edae6c57fd6540818d3f0da994b135a068.tar.zst
gsoc2013-evolution-99a875edae6c57fd6540818d3f0da994b135a068.zip
Bug #515004 - Allow toggling between text and HTML view of mail
-rw-r--r--data/webview.css4
-rw-r--r--em-format/e-mail-formatter-text-html.c3
-rw-r--r--em-format/e-mail-formatter-text-plain.c26
-rw-r--r--mail/Makefile.am2
-rw-r--r--mail/e-mail-display-popup-extension.c55
-rw-r--r--mail/e-mail-display-popup-extension.h64
-rw-r--r--mail/e-mail-display.c78
-rw-r--r--modules/prefer-plain/Makefile.am2
-rw-r--r--modules/prefer-plain/e-mail-display-popup-prefer-plain.c380
-rw-r--r--modules/prefer-plain/e-mail-display-popup-prefer-plain.h30
-rw-r--r--modules/prefer-plain/e-mail-parser-prefer-plain.c270
-rw-r--r--modules/prefer-plain/evolution-module-prefer-plain.c2
-rw-r--r--widgets/misc/e-web-view.c5
13 files changed, 732 insertions, 189 deletions
diff --git a/data/webview.css b/data/webview.css
index 09f94043fb..a8a936d0a2 100644
--- a/data/webview.css
+++ b/data/webview.css
@@ -1,6 +1,6 @@
html, body {
- padding: 0;
- margin: 0;
+ padding: 0;
+ margin: 0;
}
img {
diff --git a/em-format/e-mail-formatter-text-html.c b/em-format/e-mail-formatter-text-html.c
index 8834994496..e5d25a39b7 100644
--- a/em-format/e-mail-formatter-text-html.c
+++ b/em-format/e-mail-formatter-text-html.c
@@ -309,12 +309,13 @@ emfe_text_html_format (EMailFormatterExtension *extension,
"<div class=\"part-container-nostyle\">"
"<iframe width=\"100%%\" height=\"10\" "
" frameborder=\"0\" src=\"%s\" "
- " id=\"%s.iframe\" "
+ " id=\"%s.iframe\" name=\"%s\" "
" style=\"border: 1px solid #%06x; background-color: #%06x;\">"
"</iframe>"
"</div>",
uri,
part->id,
+ part->id,
e_color_to_value ((GdkColor *)
e_mail_formatter_get_color (
formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
diff --git a/em-format/e-mail-formatter-text-plain.c b/em-format/e-mail-formatter-text-plain.c
index a8cb7f2943..7859a41ab8 100644
--- a/em-format/e-mail-formatter-text-plain.c
+++ b/em-format/e-mail-formatter-text-plain.c
@@ -114,12 +114,8 @@ emfe_text_plain_format (EMailFormatterExtension *extension,
content = g_strdup_printf (
"<div class=\"part-container\" style=\""
- "border-color: #%06x;"
- "background-color: #%06x; color: #%06x;\">"
- "<div class=\"part-container-inner-margin pre\">\n",
- e_color_to_value ((GdkColor *)
- e_mail_formatter_get_color (
- formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ "border: none; padding: 10px; margin: 0; "
+ "background-color: #%06x; color: #%06x;\">\n",
e_color_to_value ((GdkColor *)
e_mail_formatter_get_color (
formatter, E_MAIL_FORMATTER_COLOR_CONTENT)),
@@ -134,7 +130,7 @@ emfe_text_plain_format (EMailFormatterExtension *extension,
g_object_unref (filtered_stream);
g_free (content);
- camel_stream_write_string (stream, "</div></div>\n", cancellable, NULL);
+ camel_stream_write_string (stream, "</div>\n", cancellable, NULL);
if (context->mode == E_MAIL_FORMATTER_MODE_RAW) {
camel_stream_write_string (stream, "</body></html>",
@@ -153,10 +149,20 @@ emfe_text_plain_format (EMailFormatterExtension *extension,
NULL);
str = g_strdup_printf (
+ "<div class=\"part-container-nostyle\" >"
"<iframe width=\"100%%\" height=\"10\""
- " id=\"%s.iframe\" "
- " frameborder=\"0\" src=\"%s\"></iframe>",
- part->id, uri);
+ " id=\"%s.iframe\" name=\"%s\" "
+ " frameborder=\"0\" src=\"%s\" "
+ " style=\"border: 1px solid #%06x; background-color: #%06x;\">"
+ "</iframe>"
+ "</div>",
+ part->id, part->id, uri,
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_FRAME)),
+ e_color_to_value ((GdkColor *)
+ e_mail_formatter_get_color (
+ formatter, E_MAIL_FORMATTER_COLOR_CONTENT)));
camel_stream_write_string (stream, str, cancellable, NULL);
diff --git a/mail/Makefile.am b/mail/Makefile.am
index cd02ad6fdf..9dda24f16d 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -67,6 +67,7 @@ mailinclude_HEADERS = \
e-mail-config-welcome-page.h \
e-mail-config-window.h \
e-mail-display.h \
+ e-mail-display-popup-extension.h \
e-mail-folder-pane.h \
e-mail-junk-options.h \
e-mail-label-action.h \
@@ -146,6 +147,7 @@ libevolution_mail_la_SOURCES = \
e-mail-config-welcome-page.c \
e-mail-config-window.c \
e-mail-display.c \
+ e-mail-display-popup-extension.c \
e-mail-folder-pane.c \
e-mail-junk-options.c \
e-mail-label-action.c \
diff --git a/mail/e-mail-display-popup-extension.c b/mail/e-mail-display-popup-extension.c
new file mode 100644
index 0000000000..a4441797c3
--- /dev/null
+++ b/mail/e-mail-display-popup-extension.c
@@ -0,0 +1,55 @@
+/*
+ * e-mail-display-popup-extension.c
+ *
+ * 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/>
+ *
+ */
+
+#include "e-mail-display-popup-extension.h"
+#include "e-mail-display.h"
+
+G_DEFINE_INTERFACE (
+ EMailDisplayPopupExtension,
+ e_mail_display_popup_extension,
+ G_TYPE_OBJECT)
+
+
+static void
+e_mail_display_popup_extension_default_init (EMailDisplayPopupExtensionInterface *iface)
+{
+
+}
+
+/**
+ * e_mail_display_popup_extension_update_actions:
+ *
+ * @extension: An object derived from #EMailDisplayPopupExtension
+ * @context: A #WebKitHitTestResult describing context of the popup menu
+ *
+ * When #EMailDisplay is about to display a popup menu, it calls this function
+ * on every extension so that they can add their items to the menu.
+ */
+void
+e_mail_display_popup_extension_update_actions (EMailDisplayPopupExtension *extension,
+ WebKitHitTestResult *context)
+{
+ EMailDisplayPopupExtensionInterface *iface;
+
+ g_return_if_fail (E_IS_MAIL_DISPLAY_POPUP_EXTENSION (extension));
+
+ iface = E_MAIL_DISPLAY_POPUP_EXTENSION_GET_INTERFACE (extension);
+ g_return_if_fail (iface->update_actions != NULL);
+
+ iface->update_actions (extension, context);
+}
diff --git a/mail/e-mail-display-popup-extension.h b/mail/e-mail-display-popup-extension.h
new file mode 100644
index 0000000000..307071e56e
--- /dev/null
+++ b/mail/e-mail-display-popup-extension.h
@@ -0,0 +1,64 @@
+/*
+ * e-mail-dispaly-popup-extension.h
+ *
+ * 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/>
+ *
+ */
+
+#ifndef E_MAIL_DISPLAY_POPUP_EXTENSION_H
+#define E_MAIL_DISPLAY_POPUP_EXTENSION_H
+
+#include <glib-object.h>
+#include <webkit/webkit.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION \
+ (e_mail_display_popup_extension_get_type ())
+#define E_MAIL_DISPLAY_POPUP_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION, EMailDisplayPopupExtension))
+#define E_MAIL_DISPLAY_POPUP_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION, EMailDisplayPopupExtensionInterface))
+#define E_IS_MAIL_DISPLAY_POPUP_EXTENSION(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION))
+#define E_IS_MAIL_DISPLAY_POPUP_EXTENSION_INTERFACE(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION))
+#define E_MAIL_DISPLAY_POPUP_EXTENSION_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE \
+ ((obj), E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION, EMailDisplayPopupExtensionInterface))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailDisplayPopupExtension EMailDisplayPopupExtension;
+typedef struct _EMailDisplayPopupExtensionInterface EMailDisplayPopupExtensionInterface;
+
+struct _EMailDisplayPopupExtensionInterface {
+ GTypeInterface parent_interface;
+
+ void (*update_actions) (EMailDisplayPopupExtension *extension,
+ WebKitHitTestResult *context);
+};
+
+GType e_mail_display_popup_extension_get_type (void);
+
+void e_mail_display_popup_extension_update_actions
+ (EMailDisplayPopupExtension *extension,
+ WebKitHitTestResult *context);
+
+G_END_DECLS
+
+#endif /* E_MAIL_DISPLAY_POPUP_EXTENSION_H */
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index dab8c3be1c..6e0f0a32e5 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -24,6 +24,7 @@
#endif
#include "e-mail-display.h"
+#include "e-mail-display-popup-extension.h"
#include <glib/gi18n.h>
#include <gdk/gdk.h>
@@ -52,7 +53,10 @@
#define d(x)
-G_DEFINE_TYPE (EMailDisplay, e_mail_display, E_TYPE_WEB_VIEW)
+G_DEFINE_TYPE (
+ EMailDisplay,
+ e_mail_display,
+ E_TYPE_WEB_VIEW);
#define E_MAIL_DISPLAY_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -161,49 +165,67 @@ static GtkActionEntry image_entries[] = {
};
-static void
-mail_display_update_actions (EWebView *web_view,
- GdkEventButton *event)
+static gboolean
+mail_display_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
{
WebKitHitTestResult *hit_test;
WebKitHitTestResultContext context;
gchar *image_src;
gboolean visible;
GtkAction *action;
-
- /* Chain up first! */
- E_WEB_VIEW_CLASS (e_mail_display_parent_class)->
- update_actions (web_view, event);
+ GList *extensions, *iter;
+ EWebView *web_view = E_WEB_VIEW (widget);
hit_test = webkit_web_view_get_hit_test_result (
WEBKIT_WEB_VIEW (web_view), event);
+
g_object_get (
G_OBJECT (hit_test),
"context", &context,
"image-uri", &image_src,
NULL);
- if (!(context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE))
- return;
+ if ((context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE)) {
+ visible = image_src && g_str_has_prefix (image_src, "cid:");
+ if (!visible && image_src) {
+ CamelStream *image_stream;
- visible = image_src && g_str_has_prefix (image_src, "cid:");
- if (!visible && image_src) {
- CamelStream *image_stream;
+ image_stream = camel_data_cache_get (
+ emd_global_http_cache, "http",
+ image_src, NULL);
- image_stream = camel_data_cache_get (emd_global_http_cache, "http", image_src, NULL);
+ visible = image_stream != NULL;
- visible = image_stream != NULL;
+ if (image_stream)
+ g_object_unref (image_stream);
+ }
+
+ if (image_src)
+ g_free (image_src);
- if (image_stream)
- g_object_unref (image_stream);
+ action = e_web_view_get_action (web_view, "image-save");
+ if (action)
+ gtk_action_set_visible (action, visible);
}
- if (image_src)
- g_free (image_src);
+ extensions = e_extensible_list_extensions (
+ E_EXTENSIBLE (web_view), E_TYPE_EXTENSION);
+ for (iter = extensions; iter; iter = g_list_next (iter)) {
+ EExtension *extension = iter->data;
+
+ if (!E_IS_MAIL_DISPLAY_POPUP_EXTENSION (extension))
+ continue;
- action = e_web_view_get_action (web_view, "image-save");
- if (action)
- gtk_action_set_visible (action, visible);
+ e_mail_display_popup_extension_update_actions (
+ E_MAIL_DISPLAY_POPUP_EXTENSION (extension), hit_test);
+ }
+ g_list_free (extensions);
+
+ g_object_unref (hit_test);
+
+ /* Chain up to parent's button_press_event() method. */
+ return GTK_WIDGET_CLASS (e_mail_display_parent_class)->button_press_event (widget, event);
}
static void
@@ -231,6 +253,15 @@ mail_display_update_formatter_colors (EMailDisplay *display)
}
static void
+mail_display_constructed (GObject *object)
+{
+ e_extensible_load_extensions (E_EXTENSIBLE (object));
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_mail_display_parent_class)->constructed (object);
+}
+
+static void
mail_display_set_property (GObject *object,
guint property_id,
const GValue *value,
@@ -1358,17 +1389,18 @@ e_mail_display_class_init (EMailDisplayClass *class)
g_type_class_add_private (class, sizeof (EMailDisplayPrivate));
object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = mail_display_constructed;
object_class->set_property = mail_display_set_property;
object_class->get_property = mail_display_get_property;
object_class->dispose = mail_display_dispose;
web_view_class = E_WEB_VIEW_CLASS (class);
web_view_class->set_fonts = mail_display_set_fonts;
- web_view_class->update_actions = mail_display_update_actions;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = mail_display_realize;
widget_class->style_set = mail_display_style_set;
+ widget_class->button_press_event = mail_display_button_press_event;
g_object_class_install_property (
object_class,
diff --git a/modules/prefer-plain/Makefile.am b/modules/prefer-plain/Makefile.am
index e4e6b56d02..18cb7438e7 100644
--- a/modules/prefer-plain/Makefile.am
+++ b/modules/prefer-plain/Makefile.am
@@ -14,6 +14,8 @@ module_prefer_plain_la_CPPFLAGS = \
module_prefer_plain_la_SOURCES = \
e-mail-parser-prefer-plain.c \
e-mail-parser-prefer-plain.h \
+ e-mail-display-popup-prefer-plain.c \
+ e-mail-display-popup-prefer-plain.h \
evolution-module-prefer-plain.c
module_prefer_plain_la_LIBADD = \
diff --git a/modules/prefer-plain/e-mail-display-popup-prefer-plain.c b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
new file mode 100644
index 0000000000..75c74db71e
--- /dev/null
+++ b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
@@ -0,0 +1,380 @@
+/*
+ * 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 {
+ EExtension parent;
+
+ WebKitDOMDocument *document;
+ gchar *text_plain_id;
+ gchar *text_html_id;
+
+ GtkActionGroup *action_group;
+
+} EMailDisplayPopupPreferPlain;
+
+typedef struct _EMailDisplayPopupPreferPlainClass {
+ EExtensionClass parent_class;
+} EMailDisplayPopupPreferPlainClass;
+
+#define E_MAIL_DISPLAY_POPUP_PREFER_PLAIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), e_mail_display_popup_prefer_plain_get_type(), 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);
+
+ 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_class_init (EMailDisplayPopupPreferPlainClass *klass)
+{
+ EExtensionClass *extension_class;
+
+ e_mail_display_popup_prefer_plain_parent_class = g_type_class_peek_parent (klass);
+
+ extension_class = E_EXTENSION_CLASS (klass);
+ extension_class->extensible_type = E_TYPE_MAIL_DISPLAY;
+}
+
+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 *klass)
+{
+
+}
+
+
+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;
+}
diff --git a/modules/prefer-plain/e-mail-display-popup-prefer-plain.h b/modules/prefer-plain/e-mail-display-popup-prefer-plain.h
new file mode 100644
index 0000000000..432ed4a634
--- /dev/null
+++ b/modules/prefer-plain/e-mail-display-popup-prefer-plain.h
@@ -0,0 +1,30 @@
+/*
+ * e-mail-display-popup-prefer-plain.h
+ *
+ * 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/>
+ *
+ */
+
+#ifndef E_MAIL_DISPLAY_POPUP_PREFER_PLAIN_H
+#define E_MAIL_DISPLAY_POPUP_PREFER_PLAIN_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_display_popup_prefer_plain_type_register (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_DISPLAY_POPUP_PREFER_PLAIN_H */
diff --git a/modules/prefer-plain/e-mail-parser-prefer-plain.c b/modules/prefer-plain/e-mail-parser-prefer-plain.c
index 1906563caf..a6f0f4c6b6 100644
--- a/modules/prefer-plain/e-mail-parser-prefer-plain.c
+++ b/modules/prefer-plain/e-mail-parser-prefer-plain.c
@@ -49,9 +49,9 @@ static void e_mail_parser_mail_extension_interface_init (EMailExtensionInterface
static void e_mail_parser_parser_extension_interface_init (EMailParserExtensionInterface *iface);
enum {
- EPP_NORMAL,
- EPP_PREFER,
- EPP_TEXT
+ PREFER_HTML,
+ PREFER_PLAIN,
+ ONLY_PLAIN
};
G_DEFINE_DYNAMIC_TYPE_EXTENDED (
@@ -151,48 +151,19 @@ make_part_attachment (EMailParser *parser,
return parts;
}
-static GSList *
-export_as_attachments (CamelMultipart *mp,
- EMailParser *parser,
- CamelMimePart *except,
- GString *part_id,
- GCancellable *cancellable)
+static void
+hide_parts (GSList *parts)
{
- gint i, nparts;
- CamelMimePart *part;
- gint len;
- GSList *parts;
+ GSList *iter;
- if (!mp || !CAMEL_IS_MULTIPART (mp))
- return NULL;
+ for (iter = parts; iter; iter = g_slist_next (iter)) {
+ EMailPart *p = iter->data;
- len = part_id->len;
- nparts = camel_multipart_get_number (mp);
- parts = NULL;
- for (i = 0; i < nparts; i++) {
- part = camel_multipart_get_part (mp, i);
-
- if (part != except) {
- CamelMultipart *multipart = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
-
- g_string_append_printf (part_id, ".aleternative-prefer-plain.%d", i);
- if (CAMEL_IS_MULTIPART (multipart)) {
- parts = g_slist_concat (parts,
- export_as_attachments (
- multipart, parser,
- except, part_id,
- cancellable));
- } else {
- parts = g_slist_concat (parts,
- make_part_attachment (
- parser, part, part_id,
- FALSE, cancellable));
- }
- g_string_truncate (part_id, len);
- }
- }
+ if (!p)
+ continue;
- return parts;
+ p->is_hidden = TRUE;
+ }
}
static GSList *
@@ -204,150 +175,149 @@ empe_prefer_plain_parse (EMailParserExtension *extension,
{
EMailParserPreferPlain *emp_pp;
CamelMultipart *mp;
- CamelMimePart *display_part = NULL, *calendar_part = NULL;
- gint i, nparts, partidlen, displayid = 0, calendarid = 0;
+ gint i, nparts, partidlen;
GSList *parts;
+ CamelContentType *ct;
emp_pp = (EMailParserPreferPlain *) extension;
- /* We 'can' parse HTML as well!
- * The reason simply is to convert the HTML part to attachment in some
- * cases, otherwise we will return NULL and fallback to "normal" parser. */
- if (camel_content_type_is (camel_mime_part_get_content_type (part), "text", "html")) {
- GQueue *extensions;
- EMailExtensionRegistry *reg;
+ ct = camel_mime_part_get_content_type (part);
- reg = e_mail_parser_get_extension_registry (parser);
- extensions = e_mail_extension_registry_get_for_mime_type (
- reg, "text/html");
+ /* We can actually parse HTML, but just to discard it when
+ * "Only ever show plain text" mode is set */
+ if (camel_content_type_is (ct, "text", "html")) {
- if (emp_pp->mode != EPP_TEXT
- || strstr (part_id->str, ".alternative-prefer-plain.") != NULL
- || e_mail_part_is_inline (part, extensions)) {
+ /* Prevent recursion, fall back to next (real text/html) parser */
+ if (strstr (part_id->str, ".alternative-prefer-plain.") != NULL)
+ return NULL;
+ /* Not enforcing text/plain, so use real parser */
+ if (emp_pp->mode != ONLY_PLAIN)
return NULL;
- } else if (emp_pp->show_suppressed) {
- return make_part_attachment (
- parser, part, part_id,
- TRUE, cancellable);
+ /* Enforcing text/plain, but wants HTML as attachment */
+ if (emp_pp->show_suppressed) {
+ return make_part_attachment (parser, part, part_id,
+ FALSE, cancellable);
}
- /* Return an empty item. We MUST return something, otherwise
- * the parser would think we have failed to parse the part
- * and would let a fallback extension to parse it and we don't
- * want that... */
- /* FIXME: In theory we could parse it anyway and just set
- * is_hidden to TRUE....? */
+ /* Enforcing text/plain, does not want HTML part as attachment
+ * so return nothing (can't return NULL as parser would fall
+ * back to next extension) */
return g_slist_alloc ();
}
- mp = (CamelMultipart *) camel_medium_get_content ((CamelMedium *) part);
- partidlen = part_id->len;
-
parts = NULL;
- if (emp_pp->mode == EPP_NORMAL) {
- gboolean have_plain = FALSE;
-
- /* Try to find text/html part even when not as last and force
- * to show it. Old handler will show the last part of
- * multipart/alternate, but if we can offer HTML, then
- * offer it, regardless of position in multipart. But do
- * this when have only text/plain and text/html parts,
- * not more. */
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- CamelContentType *content_type;
+ partidlen = part_id->len;
- part = camel_multipart_get_part (mp, i);
+ mp = (CamelMultipart *) camel_medium_get_content (CAMEL_MEDIUM (part));
- if (!part)
- continue;
+ if (!CAMEL_IS_MULTIPART (mp)) {
+ return e_mail_parser_parse_part_as (
+ parser, part, part_id,
+ "application/vnd.evolution.source", cancellable);
+ }
- content_type = camel_mime_part_get_content_type (part);
+ nparts = camel_multipart_get_number (mp);
+ for (i = 0; i < nparts; i++) {
- if (camel_content_type_is (content_type, "text", "html")) {
- displayid = i;
- display_part = part;
+ CamelMimePart *sp;
+ GSList *sparts = NULL;
- if (have_plain)
- break;
- } else if (camel_content_type_is (content_type, "text", "plain")) {
- have_plain = TRUE;
+ sp = camel_multipart_get_part (mp, i);
+ ct = camel_mime_part_get_content_type (sp);
- if (display_part)
- break;
+ g_string_truncate (part_id, partidlen);
+ g_string_append_printf (part_id, ".alternative-prefer-plain.%d", i);
+
+ if (camel_content_type_is (ct, "text", "html")) {
+
+ if (emp_pp->mode != PREFER_HTML) {
+ if (emp_pp->show_suppressed) {
+ sparts = make_part_attachment (
+ parser, sp, part_id,
+ FALSE, cancellable);
+ } else {
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
+ hide_parts (sparts);
+ }
+ } else {
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
}
+
+ parts = g_slist_concat (parts, sparts);
+ continue;
}
- if (display_part && have_plain && nparts == 2) {
- g_string_append_printf (part_id, ".alternative-prefer-plain.%d", displayid);
- /* FIXME Not passing a GCancellable here. */
- parts = e_mail_parser_parse_part_as (
- parser, display_part, part_id,
- "text/html", cancellable);
+ if (camel_content_type_is (ct, "text", "plain")) {
- g_string_truncate (part_id, partidlen);
- } else {
- /* Parser will automatically fallback to next extension */
- return NULL;
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
+ if (emp_pp->mode == PREFER_HTML) {
+ hide_parts (sparts);
+ }
+
+ parts = g_slist_concat (parts, sparts);
+ continue;
}
- return parts;
+ /* Always show calendar part! */
+ if (camel_content_type_is (ct, "text", "calendar") ||
+ camel_content_type_is (ct, "text", "x-calendar")) {
- } else if (!CAMEL_IS_MULTIPART (mp)) {
- return e_mail_parser_parse_part_as (
- parser, part, part_id,
- "application/vnd.evolution.source", cancellable);
- }
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
- nparts = camel_multipart_get_number (mp);
- for (i = 0; i < nparts; i++) {
- CamelContentType *ct;
-
- part = camel_multipart_get_part (mp, i);
-
- if (!part)
+ parts = g_slist_concat (parts, sparts);
continue;
-
- ct = camel_mime_part_get_content_type (part);
- if (!display_part && camel_content_type_is (ct, "text", "plain")) {
- displayid = i;
- display_part = part;
- } else if (!calendar_part && (camel_content_type_is (ct, "text", "calendar") || camel_content_type_is (ct, "text", "x-calendar"))) {
- calendarid = i;
- calendar_part = part;
}
- }
- /* if we found a text part, show it */
- if (display_part) {
- g_string_append_printf(part_id, ".alternative-prefer-plain.%d", displayid);
- parts = g_slist_concat (parts,
- e_mail_parser_parse_part_as (
- parser, display_part, part_id,
- "text/plain", cancellable));
+ /* Multiparts can represent a text/html with inline images or so */
+ if (camel_content_type_is (ct, "multipart", "*")) {
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
- g_string_truncate (part_id, partidlen);
- }
+ if (emp_pp->mode != PREFER_HTML) {
+ hide_parts (sparts);
+ } else {
+ GSList *iter;
+ gboolean has_html = FALSE;
+
+ /* Check whether the multipart contains a
+ * text/html part and hide the whole multipart if
+ * it does not. Otherwise assume that it's what
+ * we wan't to display */
+ for (iter = sparts; iter; iter = g_slist_next (iter)) {
+ EMailPart *p = iter->data;
+ if (!p)
+ continue;
+
+ if (strstr (p->id, ".text_html") != NULL) {
+ has_html = TRUE;
+ break;
+ }
+ }
+ if (!has_html)
+ hide_parts (sparts);
+ }
+
+ parts = g_slist_concat (parts, sparts);
+ continue;
+ }
- /* all other parts are attachments */
- if (emp_pp->show_suppressed) {
- parts = g_slist_concat (parts,
- export_as_attachments (
- mp, parser, display_part, part_id,
+ /* Parse everything else as an attachment */
+ sparts = e_mail_parser_parse_part (
+ parser, sp, part_id, cancellable);
+ parts = g_slist_concat (
+ parts,
+ e_mail_parser_wrap_as_attachment (
+ parser, sp, sparts, part_id,
cancellable));
- } else if (calendar_part) {
- g_string_append_printf(part_id, ".alternative-prefer-plain.%d", calendarid);
- parts = g_slist_concat (parts,
- make_part_attachment (
- parser, calendar_part, part_id,
- FALSE, NULL));
}
- g_string_truncate (part_id, partidlen);
-
return parts;
}
@@ -465,9 +435,9 @@ e_mail_parser_prefer_plain_class_init (EMailParserPreferPlainClass *class)
"mode",
"Mode",
NULL,
- EPP_NORMAL,
- EPP_TEXT,
- EPP_NORMAL,
+ PREFER_HTML,
+ ONLY_PLAIN,
+ PREFER_HTML,
G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (
diff --git a/modules/prefer-plain/evolution-module-prefer-plain.c b/modules/prefer-plain/evolution-module-prefer-plain.c
index cb81932594..9bb6450e80 100644
--- a/modules/prefer-plain/evolution-module-prefer-plain.c
+++ b/modules/prefer-plain/evolution-module-prefer-plain.c
@@ -17,6 +17,7 @@
*/
#include "e-mail-parser-prefer-plain.h"
+#include "e-mail-display-popup-prefer-plain.h"
#include <gmodule.h>
#include <gio/gio.h>
@@ -49,6 +50,7 @@ e_module_load (GTypeModule *type_module)
}
e_mail_parser_prefer_plain_type_register (type_module);
+ e_mail_display_popup_prefer_plain_type_register (type_module);
g_strfreev (disabled_plugins);
g_object_unref (settings);
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index 20b5569a85..8d5d614bce 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -851,6 +851,8 @@ web_view_constructed (GObject *object)
g_object_unref (settings);
#endif
+ e_extensible_load_extensions (E_EXTENSIBLE (object));
+
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_web_view_parent_class)->constructed (object);
}
@@ -1861,9 +1863,6 @@ e_web_view_init (EWebView *web_view)
id = "org.gnome.evolution.webview";
e_plugin_ui_register_manager (ui_manager, id, web_view);
e_plugin_ui_enable_manager (ui_manager, id);
-
- e_extensible_load_extensions (E_EXTENSIBLE (web_view));
-
}
GtkWidget *