Commit 99a875ed authored by Dan Vrátil's avatar Dan Vrátil
Browse files

Bug #515004 - Allow toggling between text and HTML view of mail

parent 137eec97
html, body {
padding: 0;
margin: 0;
padding: 0;
margin: 0;
}
img {
......
......@@ -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)),
......
......@@ -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);
......
......@@ -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 \
......
/*
* 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);
}
/*
* 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 */
......@@ -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
......@@ -230,6 +252,15 @@ mail_display_update_formatter_colors (EMailDisplay *display)
e_mail_formatter_set_style (display->priv->formatter, style, state);
}
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,
......@@ -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,
......
......@@ -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 = \
......
/*
* 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;
}