diff options
author | Dan Vrátil <dvratil@redhat.com> | 2012-06-26 19:39:47 +0800 |
---|---|---|
committer | Dan Vrátil <dvratil@redhat.com> | 2012-06-26 19:40:59 +0800 |
commit | 99a875edae6c57fd6540818d3f0da994b135a068 (patch) | |
tree | 53acc10d4dd0d44b569a0a2052e8a4300d2ef4a2 | |
parent | 137eec97eb4f3d25f662e651c168d67e7e9e85e4 (diff) | |
download | gsoc2013-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.css | 4 | ||||
-rw-r--r-- | em-format/e-mail-formatter-text-html.c | 3 | ||||
-rw-r--r-- | em-format/e-mail-formatter-text-plain.c | 26 | ||||
-rw-r--r-- | mail/Makefile.am | 2 | ||||
-rw-r--r-- | mail/e-mail-display-popup-extension.c | 55 | ||||
-rw-r--r-- | mail/e-mail-display-popup-extension.h | 64 | ||||
-rw-r--r-- | mail/e-mail-display.c | 78 | ||||
-rw-r--r-- | modules/prefer-plain/Makefile.am | 2 | ||||
-rw-r--r-- | modules/prefer-plain/e-mail-display-popup-prefer-plain.c | 380 | ||||
-rw-r--r-- | modules/prefer-plain/e-mail-display-popup-prefer-plain.h | 30 | ||||
-rw-r--r-- | modules/prefer-plain/e-mail-parser-prefer-plain.c | 270 | ||||
-rw-r--r-- | modules/prefer-plain/evolution-module-prefer-plain.c | 2 | ||||
-rw-r--r-- | widgets/misc/e-web-view.c | 5 |
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 * |