[evolution/webkit: 8/102] Port collapsable To/Cc/Bcc fields and collapsable headers to JavaScript
- From: Dan VrÃtil <dvratil src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/webkit: 8/102] Port collapsable To/Cc/Bcc fields and collapsable headers to JavaScript
- Date: Fri, 6 Jan 2012 09:25:44 +0000 (UTC)
commit 7d9082349e6c73e0619ccc90b037d6a5356d7485
Author: Dan VrÃtil <dvratil redhat com>
Date: Wed Jul 27 17:04:56 2011 +0200
Port collapsable To/Cc/Bcc fields and collapsable headers to JavaScript
Use JavaScript to handle collapsing/expanding of To, Cc and Bcc header
fields and collapsing of the whole headers themselves.
The headers collapsing must notify "headers-state" property of EMFormatHTML
when changed. This is done by extending EWebView API by function for
installing callback functions to JavaScript.
Finally, the simple_headers property was removed from EMFormatHTML as it
was not used anymore.
addressbook/gui/widgets/eab-contact-display.c | 2 +-
data/webview.css | 10 +
mail/e-mail-display.c | 78 ++---
mail/em-format-html.c | 546 ++++++++++++++-----------
mail/em-format-html.h | 2 -
widgets/misc/e-web-view.c | 106 +++++
widgets/misc/e-web-view.h | 12 +
7 files changed, 452 insertions(+), 304 deletions(-)
---
diff --git a/addressbook/gui/widgets/eab-contact-display.c b/addressbook/gui/widgets/eab-contact-display.c
index 395f6fc..b686bd7 100644
--- a/addressbook/gui/widgets/eab-contact-display.c
+++ b/addressbook/gui/widgets/eab-contact-display.c
@@ -519,7 +519,7 @@ render_contact_list_row (GString *buffer,
g_string_append (buffer, "<tr>");
if (e_destination_is_evolution_list (destination)) {
g_string_append_printf (buffer,
- "<td width=" IMAGE_COL_WIDTH " valign=\"top\"><img src=\"%s/minus.png\" onClick=\"collapse_list(this, %s);\"></td><td width=\"100%%\">%s",
+ "<td width=" IMAGE_COL_WIDTH " valign=\"top\"><img src=\"%s/minus.png\" onClick=\"collapse_list(this, %s);\" class=\"navigable\"></td><td width=\"100%%\">%s",
evolution_imagesdir,
e_destination_get_contact_uid (destination),
name ? name : email_addr);
diff --git a/data/webview.css b/data/webview.css
index 1f87964..704c745 100644
--- a/data/webview.css
+++ b/data/webview.css
@@ -21,3 +21,13 @@ th {
font-family: monospace;
font-size: 0.8em;
}
+
+span.navigable, div.navigable, p.navigable {
+ cursor: hand;
+ text-decoration: underline;
+ color: #003399;
+}
+
+img.navigable {
+ cursor: hand;
+}
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index 3e33bac..7aae7bf 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -260,69 +260,44 @@ mail_display_process_mailto (EWebView *web_view,
return FALSE;
}
-static void
-mail_display_link_clicked (GtkHTML *html,
- const gchar *uri)
+static gboolean
+mail_display_link_clicked (WebKitWebView *web_view,
+ WebKitWebFrame *frame,
+ WebKitNetworkRequest *request,
+ WebKitWebNavigationAction *navigation_action,
+ WebKitWebPolicyDecision *policy_decision,
+ gpointer user_data)
{
+ EMailDisplay *display = user_data;
EMailDisplayPrivate *priv;
+ const gchar *uri = webkit_network_request_get_uri (request);
priv = E_MAIL_DISPLAY_GET_PRIVATE (html);
- g_return_if_fail (priv->formatter != NULL);
-
- if (g_str_has_prefix (uri, "##")) {
- guint32 flags;
-
- flags = priv->formatter->header_wrap_flags;
-
- if (strcmp (uri, "##TO##") == 0) {
- if (!(flags & EM_FORMAT_HTML_HEADER_TO))
- flags |= EM_FORMAT_HTML_HEADER_TO;
- else
- flags &= ~EM_FORMAT_HTML_HEADER_TO;
- } else if (strcmp (uri, "##CC##") == 0) {
- if (!(flags & EM_FORMAT_HTML_HEADER_CC))
- flags |= EM_FORMAT_HTML_HEADER_CC;
- else
- flags &= ~EM_FORMAT_HTML_HEADER_CC;
- } else if (strcmp (uri, "##BCC##") == 0) {
- if (!(flags & EM_FORMAT_HTML_HEADER_BCC))
- flags |= EM_FORMAT_HTML_HEADER_BCC;
- else
- flags &= ~EM_FORMAT_HTML_HEADER_BCC;
- } else if (strcmp (uri, "##HEADERS##") == 0) {
- EMFormatHTMLHeadersState state;
-
- state = em_format_html_get_headers_state (
- priv->formatter);
-
- if (state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED)
- state = EM_FORMAT_HTML_HEADERS_STATE_EXPANDED;
- else
- state = EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED;
-
- em_format_html_set_headers_state (
- priv->formatter, state);
- }
-
- priv->formatter->header_wrap_flags = flags;
- em_format_queue_redraw (EM_FORMAT (priv->formatter));
-
- } else if (mail_display_process_mailto (E_WEB_VIEW (html), uri)) {
+ g_return_val_if_fail (priv->formatter != NULL, FALSE);
+
+ if (mail_display_process_mailto (E_WEB_VIEW (display), uri)) {
/* do nothing, function handled the "mailto:" uri already */
- } else if (*uri == '#')
- gtk_html_jump_to_anchor (html, uri + 1);
+ webkit_web_policy_decision_ignore (policy_decision);
+ return TRUE;
- else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0)
+ } else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0) {
/* ignore */ ;
+ webkit_web_policy_decision_ignore (policy_decision);
+ return TRUE;
- else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0)
+ } else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0) {
/* ignore */ ;
+ webkit_web_policy_decision_ignore (policy_decision);
+ return TRUE;
else {
/* Chain up to parent's link_clicked() method. */
GTK_HTML_CLASS (e_mail_display_parent_class)->
link_clicked (html, uri);
}
+
+ /* Let webkit handle it */
+ return FALSE;
}
static void
@@ -331,7 +306,6 @@ e_mail_display_class_init (EMailDisplayClass *class)
GObjectClass *object_class;
GtkWidgetClass *widget_class;
EWebViewClass *web_view_class;
- GtkHTMLClass *html_class;
g_type_class_add_private (class, sizeof (EMailDisplayPrivate));
@@ -347,10 +321,6 @@ e_mail_display_class_init (EMailDisplayClass *class)
web_view_class = E_WEB_VIEW_CLASS (class);
web_view_class->process_mailto = mail_display_process_mailto;
- html_class = GTK_HTML_CLASS (class);
- html_class->url_requested = mail_display_url_requested;
- html_class->link_clicked = mail_display_link_clicked;
-
g_object_class_install_property (
object_class,
PROP_FORMATTER,
@@ -371,6 +341,8 @@ e_mail_display_init (EMailDisplay *display)
GError *error = NULL;
web_view = E_WEB_VIEW (display);
+ g_signal_connect (web_view, "navigation-policy-decision-requested",
+ G_CALLBACK (mail_display_link_clicked), display);
display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 280e044..a12dd8e 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -54,6 +54,8 @@
#include <glib/gi18n.h>
+#include <JavaScriptCore/JavaScript.h>
+
#include "e-mail-enumtypes.h"
#include "em-format-html.h"
#include "em-utils.h"
@@ -139,7 +141,11 @@ static void efh_resource_requested (WebKitWebView *web_view,
WebKitNetworkRequest *request,
WebKitNetworkResponse *reponse,
gpointer user_data);
-
+static void efh_install_js_callbacks (WebKitWebView *web_view,
+ WebKitWebFrame *frame,
+ gpointer context,
+ gpointer window_object,
+ gpointer user_data);
static void efh_format_message (EMFormat *emf,
CamelStream *stream,
CamelMimePart *part,
@@ -1006,6 +1012,9 @@ efh_init (EMFormatHTML *efh,
g_signal_connect (
web_view, "frame-created",
G_CALLBACK (efh_webview_frame_created), efh);
+ g_signal_connect (
+ web_view, "window-object-cleared",
+ G_CALLBACK (efh_install_js_callbacks), efh);
color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_BODY];
gdk_color_parse ("#eeeeee", color);
@@ -1804,10 +1813,10 @@ efh_webview_frame_loaded (GObject *object,
frame_name = webkit_web_frame_get_name (frame);
/* Get total height of the document inside the frame */
- e_web_view_frame_exec_script (E_WEB_VIEW (web_view), frame_name, "document.body.offsetHeight;", &val);
+ e_web_view_frame_exec_script (E_WEB_VIEW (web_view), frame_name, "document.body.scrollHeight;", &val);
/* Change height of the frame so that entire content is visible */
- script = g_strdup_printf ("window.document.getElementById(\"%s\").height=%d;", frame_name, (int)g_value_get_double (&val));
+ script = g_strdup_printf ("window.document.getElementById(\"%s\").height=%d;", frame_name, (int)(g_value_get_double (&val) + 10));
e_web_view_exec_script (E_WEB_VIEW (web_view), script, NULL);
g_free (script);
}
@@ -1826,6 +1835,31 @@ efh_webview_frame_created (WebKitWebView *web_view,
}
}
+static void
+efh_headers_collapsed_state_changed (EWebView *web_view, size_t arg_count, const JSValueRef args[], gpointer user_data)
+{
+ EMFormatHTML *efh = user_data;
+ JSGlobalContextRef ctx = e_web_view_get_global_context (web_view);
+
+ gboolean collapsed = JSValueToBoolean (ctx, args[0]);
+
+ if (collapsed) {
+ em_format_html_set_headers_state (efh, EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED);
+ } else {
+ em_format_html_set_headers_state (efh, EM_FORMAT_HTML_HEADERS_STATE_EXPANDED);
+ }
+}
+
+static void
+efh_install_js_callbacks (WebKitWebView *web_view, WebKitWebFrame *frame, gpointer context, gpointer window_object, gpointer user_data)
+{
+ if (frame != webkit_web_view_get_main_frame (web_view))
+ return;
+
+ e_web_view_install_js_callback (E_WEB_VIEW (web_view), "headers_collapsed",
+ (EWebViewJSFunctionCallback) efh_headers_collapsed_state_changed, user_data);
+}
+
/* ********************************************************************** */
#include "em-format/em-inline-filter.h"
@@ -2646,33 +2680,29 @@ efh_format_text_header (EMFormatHTML *emfh,
html = value;
is_rtl = gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL;
- if (emfh->simple_headers) {
- fmt = "<b>%s</b>: %s<br>";
+
+ if (flags & EM_FORMAT_HTML_HEADER_NOCOLUMNS) {
+ if (flags & EM_FORMAT_HEADER_BOLD) {
+ fmt = "<tr><td><b>%s:</b> %s</td></tr>";
+ } else {
+ fmt = "<tr><td>%s: %s</td></tr>";
+ }
+ } else if (flags & EM_FORMAT_HTML_HEADER_NODEC) {
+ if (is_rtl)
+ fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th valign=top align=\"left\" nowrap>%1$s<b> </b></th></tr>";
+ else
+ fmt = "<tr><th align=\"right\" valign=\"top\" nowrap>%s<b> </b></th><td valign=top>%s</td></tr>";
} else {
- if (flags & EM_FORMAT_HTML_HEADER_NOCOLUMNS) {
- if (flags & EM_FORMAT_HEADER_BOLD) {
- fmt = "<tr><td><b>%s:</b> %s</td></tr>";
- } else {
- fmt = "<tr><td>%s: %s</td></tr>";
- }
- } else if (flags & EM_FORMAT_HTML_HEADER_NODEC) {
+ if (flags & EM_FORMAT_HEADER_BOLD) {
if (is_rtl)
- fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th valign=top align=\"left\" nowrap>%1$s<b> </b></th></tr>";
+ fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th align=\"left\" nowrap>%1$s:<b> </b></th></tr>";
else
- fmt = "<tr><th align=\"right\" valign=\"top\" nowrap>%s<b> </b></th><td valign=top>%s</td></tr>";
+ fmt = "<tr><th align=\"right\" valign=\"top\" nowrap>%s:<b> </b></th><td>%s</td></tr>";
} else {
-
- if (flags & EM_FORMAT_HEADER_BOLD) {
- if (is_rtl)
- fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%%\">%2$s</td><th align=\"left\" nowrap>%1$s:<b> </b></th></tr>";
- else
- fmt = "<tr><th align=\"right\" valign=\"top\" nowrap>%s:<b> </b></th><td>%s</td></tr>";
- } else {
- if (is_rtl)
- fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%\">%2$s</td><td align=\"left\" nowrap>%1$s:<b> </b></td></tr>";
- else
- fmt = "<tr><td align=\"right\" valign=\"top\" nowrap>%s:<b> </b></td><td>%s</td></tr>";
- }
+ if (is_rtl)
+ fmt = "<tr><td align=\"right\" valign=\"top\" width=\"100%\">%2$s</td><td align=\"left\" nowrap>%1$s:<b> </b></td></tr>";
+ else
+ fmt = "<tr><td align=\"right\" valign=\"top\" nowrap>%s:<b> </b></td><td>%s</td></tr>";
}
}
@@ -2696,17 +2726,9 @@ efh_format_address (EMFormatHTML *efh,
guint32 flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES;
gchar *name, *mailto, *addr;
gint i = 0;
- gboolean wrap = FALSE;
gchar *str = NULL;
gint limit = mail_config_get_address_count ();
- if (field ) {
- if ((!strcmp (field, _("To")) && !(efh->header_wrap_flags & EM_FORMAT_HTML_HEADER_TO))
- || (!strcmp (field, _("Cc")) && !(efh->header_wrap_flags & EM_FORMAT_HTML_HEADER_CC))
- || (!strcmp (field, _("Bcc")) && !(efh->header_wrap_flags & EM_FORMAT_HTML_HEADER_BCC)))
- wrap = TRUE;
- }
-
while (a) {
if (a->name)
name = camel_text_to_html (a->name, flags, 0);
@@ -2763,48 +2785,47 @@ efh_format_address (EMFormatHTML *efh,
g_string_append (out, ", ");
/* Let us add a '...' if we have more addresses */
- if (limit > 0 && wrap && a && (i > (limit - 1))) {
+ if (limit > 0 && (i == limit - 1)) {
gchar *evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
-
- if (!strcmp (field, _("To"))) {
- g_string_append (out, "<a href=\"##TO##\">...</a>");
- str = g_strdup_printf ("<a href=\"##TO##\"><img src=\"%s/plus.png\"></a> ", evolution_imagesdir);
+ const gchar *id = NULL;
+
+ if (strcmp (field, _("To")) == 0) {
+ id = "to";
+ } else if (strcmp (field, _("Cc")) == 0) {
+ id = "cc";
+ } else if (strcmp (field, _("Bcc")) == 0) {
+ id = "bcc";
}
- else if (!strcmp (field, _("Cc"))) {
- g_string_append (out, "<a href=\"##CC##\">...</a>");
- str = g_strdup_printf ("<a href=\"##CC##\"><img src=\"%s/plus.png\"></a> ", evolution_imagesdir);
- }
- else if (!strcmp (field, _("Bcc"))) {
- g_string_append (out, "<a href=\"##BCC##\">...</a>");
- str = g_strdup_printf ("<a href=\"##BCC##\"><img src=\"%s/plus.png\"></a> ", evolution_imagesdir);
+
+ if (id) {
+ g_string_append_printf (out, "<span id=\"moreaddr-%s\" style=\"display: none;\">", id);
+ str = g_strdup_printf ("<img src=\"%s/plus.png\" onClick=\"collapse_addresses('%s');\" id=\"moreaddr-img-%s\" class=\"navigable\"> ",
+ evolution_imagesdir, id, id);
}
g_free (evolution_imagesdir);
-
- if (str)
- return str;
}
-
}
- if (limit > 0 && i > (limit)) {
- gchar *evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+ if (str) {
+ const gchar *id = NULL;
- if (!strcmp (field, _("To"))) {
- str = g_strdup_printf ("<a href=\"##TO##\"><img src=\"%s/minus.png\"></a> ", evolution_imagesdir);
- }
- else if (!strcmp (field, _("Cc"))) {
- str = g_strdup_printf ("<a href=\"##CC##\"><img src=\"%s/minus.png\"></a> ", evolution_imagesdir);
- }
- else if (!strcmp (field, _("Bcc"))) {
- str = g_strdup_printf ("<a href=\"##BCC##\"><img src=\"%s/minus.png\"></a> ", evolution_imagesdir);
+ if (strcmp (field, _("To")) == 0) {
+ id = "to";
+ } else if (strcmp (field, _("Cc")) == 0) {
+ id = "cc";
+ } else if (strcmp (field, _("Bcc")) == 0) {
+ id = "bcc";
}
- g_free (evolution_imagesdir);
+ if (id) {
+ g_string_append_printf (out, "</span><span class=\"navigable\" onClick=\"collapse_addresses('%s');\" " \
+ "id=\"moreaddr-ellipsis-%s\" style=\"display: inline;\">...</span>",
+ id, id);
+ }
}
return str;
-
}
static void
@@ -2839,7 +2860,7 @@ efh_format_header (EMFormat *emf,
guint32 flags,
const gchar *charset)
{
- EMFormatHTML *efh = (EMFormatHTML *) emf;
+ EMFormatHTML *efh = EM_FORMAT_HTML (emf);
gchar *name, *buf, *value = NULL;
const gchar *label, *txt;
gboolean addrspec = FALSE;
@@ -2987,100 +3008,111 @@ efh_format_header (EMFormat *emf,
}
static void
-efh_format_headers (EMFormatHTML *efh,
- GString *buffer,
- CamelMedium *part,
- GCancellable *cancellable)
+efh_format_short_headers (EMFormatHTML *efh,
+ GString *buffer,
+ CamelMedium *part,
+ gboolean visible,
+ GCancellable *cancellable)
{
- EMFormat *emf = (EMFormat *) efh;
+ EMFormat *emf = EM_FORMAT (efh);
const gchar *charset;
CamelContentType *ct;
- struct _camel_header_raw *header;
- gboolean have_icon = FALSE;
- const gchar *photo_name = NULL;
- CamelInternetAddress *cia = NULL;
- gboolean face_decoded = FALSE, contact_has_photo = FALSE;
- guchar *face_header_value = NULL;
- gsize face_header_len = 0;
- gchar *header_sender = NULL, *header_from = NULL, *name;
- gboolean mail_from_delegate = FALSE;
const gchar *hdr_charset;
gchar *evolution_imagesdir;
+ gchar *subject = NULL;
+ struct _camel_header_address *addrs = NULL;
+ struct _camel_header_raw *header;
+ GString *from;
- if (!part)
+ if (cancellable && g_cancellable_is_cancelled (cancellable))
return;
ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
charset = camel_content_type_param (ct, "charset");
charset = camel_iconv_charset_name (charset);
-
- if (!efh->simple_headers)
- g_string_append_printf (
- buffer, "<font color=\"#%06x\">\n"
- "<table cellpadding=\"0\" width=\"100%%\">",
- e_color_to_value (
- &efh->priv->colors[
- EM_FORMAT_HTML_COLOR_HEADER]));
-
hdr_charset = emf->charset ? emf->charset : emf->default_charset;
+
evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+ from = g_string_new ("");
- /* If the header is collapsed, display just subject and sender in one row and leave */
- if (efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED && efh->priv->headers_collapsable) {
- gchar *subject = NULL;
- struct _camel_header_address *addrs = NULL;
- GString *from = g_string_new ("");
+ g_string_append_printf (buffer, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" id=\"short-headers\" style=\"display: %s\">",
+ visible ? "block" : "none");
- header = ((CamelMimePart *) part)->headers;
- while (header) {
- if (!g_ascii_strcasecmp (header->name, "From")) {
- GString *tmp;
- if (!(addrs = camel_header_address_decode (header->value, hdr_charset))) {
- header = header->next;
- continue;
- }
- tmp = g_string_new ("");
- efh_format_address (efh, tmp, addrs, header->name);
-
- if (tmp->len)
- g_string_printf (from, _("From: %s"), tmp->str);
- g_string_free (tmp, TRUE);
- } else if (!g_ascii_strcasecmp (header->name, "Subject")) {
- gchar *buf = NULL;
- buf = camel_header_unfold (header->value);
- g_free (subject);
- subject = camel_header_decode_string (buf, hdr_charset);
- g_free (buf);
+ header = ((CamelMimePart *) part)->headers;
+ while (header) {
+ if (!g_ascii_strcasecmp (header->name, "From")) {
+ GString *tmp;
+ if (!(addrs = camel_header_address_decode (header->value, hdr_charset))) {
+ header = header->next;
+ continue;
}
- header = header->next;
+ tmp = g_string_new ("");
+ efh_format_address (efh, tmp, addrs, header->name);
+
+ if (tmp->len)
+ g_string_printf (from, _("From: %s"), tmp->str);
+ g_string_free (tmp, TRUE);
+
+ } else if (!g_ascii_strcasecmp (header->name, "Subject")) {
+ gchar *buf = NULL;
+ buf = camel_header_unfold (header->value);
+ g_free (subject);
+ subject = camel_header_decode_string (buf, hdr_charset);
+ g_free (buf);
}
+ header = header->next;
+ }
- g_string_append_printf (
- buffer,
- "<tr>"
- "<td width=\"20\" valign=\"top\">"
- "<a href=\"##HEADERS##\">"
- "<img src=\"%s/plus.png\">"
- "</a></td>"
- "<td><strong>%s</strong> %s%s%s</td>"
- "</tr>",
- evolution_imagesdir,
- subject ? subject : _("(no subject)"),
- from->len ? "(" : "",
- from->str,
- from->len ? ")" : "");
+ g_string_append_printf (
+ buffer,
+ "<tr><td><strong>%s</strong> %s%s%s</td></tr>",
+ subject ? subject : _("(no subject)"),
+ from->len ? "(" : "", from->str, from->len ? ")" : "");
- g_free (subject);
- if (addrs)
- camel_header_address_list_clear (&addrs);
- g_string_free (from, TRUE);
+ g_string_append (buffer, "</table>");
- g_string_append (buffer, "</table>");
+ g_free (subject);
+ if (addrs)
+ camel_header_address_list_clear (&addrs);
- g_free (evolution_imagesdir);
+ g_string_free (from, TRUE);
+ g_free (evolution_imagesdir);
+}
+static void
+efh_format_full_headers (EMFormatHTML *efh,
+ GString *buffer,
+ CamelMedium *part,
+ gboolean visible,
+ GCancellable *cancellable)
+{
+ EMFormat *emf = EM_FORMAT (efh);
+ const gchar *charset;
+ CamelContentType *ct;
+ struct _camel_header_raw *header;
+ gboolean have_icon = FALSE;
+ const gchar *photo_name = NULL;
+ CamelInternetAddress *cia = NULL;
+ gboolean face_decoded = FALSE, contact_has_photo = FALSE;
+ guchar *face_header_value = NULL;
+ gsize face_header_len = 0;
+ gchar *header_sender = NULL, *header_from = NULL, *name;
+ gboolean mail_from_delegate = FALSE;
+ const gchar *hdr_charset;
+ gchar *evolution_imagesdir;
+
+ if (cancellable && g_cancellable_is_cancelled (cancellable))
return;
- }
+
+ ct = camel_mime_part_get_content_type ((CamelMimePart *) part);
+ charset = camel_content_type_param (ct, "charset");
+ charset = camel_iconv_charset_name (charset);
+ hdr_charset = emf->charset ? emf->charset : emf->default_charset;
+
+ evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
+
+ g_string_append_printf (buffer, "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" id=\"full-headers\" style=\"display: %s\" width=\"100%%\">",
+ visible ? "block" : "none");
header = ((CamelMimePart *) part)->headers;
while (header) {
@@ -3151,42 +3183,7 @@ efh_format_headers (EMFormatHTML *efh,
g_free (header_sender);
g_free (header_from);
- if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL) {
- if (efh->priv->headers_collapsable)
- g_string_append_printf (
- buffer,
- "<tr>"
- "<td valign=\"top\" width=\"20\">"
- "<a href=\"##HEADERS##\">"
- "<img src=\"%s/minus.png\">"
- "</a></td>"
- "<td><table width=\"100%%\" border=0 "
- "cellpadding=\"0\">\n",
- evolution_imagesdir);
- else
- g_string_append (
- buffer,
- "<tr><td>"
- "<table width=\"100%%\" border=0 "
- "cellpadding=\"0\">\n");
-
- } else {
- if (efh->priv->headers_collapsable)
- g_string_append_printf (
- buffer,
- "<tr>"
- "<td valign=\"top\" width=\"20\">"
- "<a href=\"##HEADERS##\">"
- "<img src=\"%s/minus.png\">"
- "</a></td>"
- "<td><table border=0 cellpadding=\"0\">\n",
- evolution_imagesdir);
- else
- g_string_append (
- buffer,
- "<tr><td>"
- "<table border=0 cellpadding=\"0\">\n");
- }
+ g_string_append (buffer, "<tr><td><table border=0 cellpadding=\"0\">\n");
g_free (evolution_imagesdir);
@@ -3272,98 +3269,136 @@ efh_format_headers (EMFormatHTML *efh,
}
}
- if (!efh->simple_headers) {
- g_string_append (buffer, "</table></td>");
-
- if (photo_name) {
- gchar *classid;
- CamelMimePart *photopart;
- gboolean only_local_photo;
-
- cia = camel_internet_address_new ();
- camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
- only_local_photo = em_format_html_get_only_local_photos (efh);
- photopart = em_utils_contact_photo (cia, only_local_photo);
+ g_string_append (buffer, "</table></td>");
- if (photopart) {
- contact_has_photo = TRUE;
- classid = g_strdup_printf (
- "icon:///em-format-html/%s/photo/header",
- emf->part_id->str);
- g_string_append_printf (
- buffer,
- "<td align=\"right\" valign=\"top\">"
- "<img width=64 src=\"%s\"></td>",
- classid);
- em_format_add_puri (emf, sizeof (EMFormatPURI), classid,
- photopart, efh_write_image);
- g_object_unref (photopart);
-
- g_free (classid);
- }
- g_object_unref (cia);
- }
+ if (photo_name) {
+ gchar *classid;
+ CamelMimePart *photopart;
+ gboolean only_local_photo;
- if (!contact_has_photo && face_decoded) {
- gchar *classid;
- CamelMimePart *part;
+ cia = camel_internet_address_new ();
+ camel_address_decode ((CamelAddress *) cia, (const gchar *) photo_name);
+ only_local_photo = em_format_html_get_only_local_photos (efh);
+ photopart = em_utils_contact_photo (cia, only_local_photo);
- part = camel_mime_part_new ();
- camel_mime_part_set_content (
- (CamelMimePart *) part,
- (const gchar *) face_header_value,
- face_header_len, "image/png");
+ if (photopart) {
+ contact_has_photo = TRUE;
classid = g_strdup_printf (
- "icon:///em-format-html/face/photo/header");
+ "icon:///em-format-html/%s/photo/header",
+ emf->part_id->str);
g_string_append_printf (
buffer,
"<td align=\"right\" valign=\"top\">"
- "<img width=48 src=\"%s\"></td>",
+ "<img width=64 src=\"%s\"></td>",
classid);
- em_format_add_puri (
- emf, sizeof (EMFormatPURI),
- classid, part, efh_write_image);
- g_object_unref (part);
+ em_format_add_puri (emf, sizeof (EMFormatPURI), classid,
+ photopart, efh_write_image);
+ g_object_unref (photopart);
+
g_free (classid);
- g_free (face_header_value);
}
+ g_object_unref (cia);
+ }
- if (have_icon && efh->show_icon) {
- GtkIconInfo *icon_info;
- gchar *classid;
- CamelMimePart *iconpart = NULL;
+ if (!contact_has_photo && face_decoded) {
+ gchar *classid;
+ CamelMimePart *part;
- classid = g_strdup_printf (
- "icon:///em-format-html/%s/icon/header",
- emf->part_id->str);
- g_string_append_printf (
- buffer,
- "<td align=\"right\" valign=\"top\">"
- "<img width=16 height=16 src=\"%s\"></td>",
- classid);
+ part = camel_mime_part_new ();
+ camel_mime_part_set_content (
+ (CamelMimePart *) part,
+ (const gchar *) face_header_value,
+ face_header_len, "image/png");
+ classid = g_strdup_printf (
+ "icon:///em-format-html/face/photo/header");
+ g_string_append_printf (
+ buffer,
+ "<td align=\"right\" valign=\"top\">"
+ "<img width=48 src=\"%s\"></td>",
+ classid);
+ em_format_add_puri (
+ emf, sizeof (EMFormatPURI),
+ classid, part, efh_write_image);
+ g_object_unref (part);
+ g_free (classid);
+ g_free (face_header_value);
+ }
- icon_info = gtk_icon_theme_lookup_icon (
- gtk_icon_theme_get_default (),
- "evolution", 16, GTK_ICON_LOOKUP_NO_SVG);
- if (icon_info != NULL) {
- iconpart = em_format_html_file_part (
- (EMFormatHTML *) emf, "image/png",
- gtk_icon_info_get_filename (icon_info),
- cancellable);
- gtk_icon_info_free (icon_info);
- }
+ if (have_icon && efh->show_icon) {
+ GtkIconInfo *icon_info;
+ gchar *classid;
+ CamelMimePart *iconpart = NULL;
- if (iconpart) {
- em_format_add_puri (
- emf, sizeof (EMFormatPURI),
- classid, iconpart, efh_write_image);
- g_object_unref (iconpart);
- }
- g_free (classid);
+ classid = g_strdup_printf (
+ "icon:///em-format-html/%s/icon/header",
+ emf->part_id->str);
+ g_string_append_printf (
+ buffer,
+ "<td align=\"right\" valign=\"top\">"
+ "<img width=16 height=16 src=\"%s\"></td>",
+ classid);
+ icon_info = gtk_icon_theme_lookup_icon (
+ gtk_icon_theme_get_default (),
+ "evolution", 16, GTK_ICON_LOOKUP_NO_SVG);
+ if (icon_info != NULL) {
+ iconpart = em_format_html_file_part (
+ (EMFormatHTML *) emf, "image/png",
+ gtk_icon_info_get_filename (icon_info),
+ cancellable);
+ gtk_icon_info_free (icon_info);
}
+ if (iconpart) {
+ em_format_add_puri (
+ emf, sizeof (EMFormatPURI),
+ classid, iconpart, efh_write_image);
+ g_object_unref (iconpart);
+ }
+ g_free (classid);
+ }
+
+ g_string_append (buffer, "</tr></table>");
+}
+
+static void
+efh_format_headers (EMFormatHTML *efh,
+ GString *buffer,
+ CamelMedium *part,
+ GCancellable *cancellable)
+{
+ gchar *evolution_imagesdir;
+
+ if (!part)
+ return;
+
+
+ evolution_imagesdir = g_filename_to_uri (EVOLUTION_IMAGESDIR, NULL, NULL);
- g_string_append (buffer, "</tr></table>\n</font>\n");
+ g_string_append_printf (
+ buffer, "<font color=\"#%06x\">\n"
+ "<table border=\"0\" width=\"100%%\">"
+ "<tr><td valign=\"top\" width=\"20\">",
+ e_color_to_value (
+ &efh->priv->colors[
+ EM_FORMAT_HTML_COLOR_HEADER]));
+
+ if (efh->priv->headers_collapsable) {
+ g_string_append_printf (buffer,
+ "<img src=\"%s/%s\" onClick=\"collapse_headers();\" class=\"navigable\" id=\"collapse-headers-img\" /></td><td>",
+ evolution_imagesdir,
+ (efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED) ? "plus.png" : "minus.png");
+
+ efh_format_short_headers (efh, buffer, part,
+ (efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_COLLAPSED),
+ cancellable);
}
+
+ efh_format_full_headers (efh, buffer, part,
+ (efh->priv->headers_state == EM_FORMAT_HTML_HEADERS_STATE_EXPANDED),
+ cancellable);
+
+ g_string_append (buffer, "</td></tr></table></font>");
+
+ g_free (evolution_imagesdir);
}
static void
@@ -3385,7 +3420,6 @@ efh_format_message (EMFormat *emf,
emf->valid_parent = NULL;
buffer = g_string_sized_new (1024);
-
g_string_append_printf (buffer,
"<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" \
"<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\">\n" \
@@ -3394,9 +3428,25 @@ efh_format_message (EMFormat *emf,
" table th { color: #000; font-weight: bold; }\n" \
"</style>\n" \
"<script type=\"text/javascript\">\n" \
- "function body_loaded() { window.location.hash=\"" EFM_MESSAGE_START_ANAME "\"; }" \
+ "function body_loaded() { window.location.hash='" EFM_MESSAGE_START_ANAME "'; }\n" \
+ "function collapse_addresses(field) {\n" \
+ " var e=window.document.getElementById(\"moreaddr-\"+field).style;\n" \
+ " var f=window.document.getElementById(\"moreaddr-ellipsis-\"+field).style;\n" \
+ " var g=window.document.getElementById(\"moreaddr-img-\"+field);\n" \
+ " if (e.display==\"inline\") { e.display=\"none\"; f.display=\"inline\"; g.src=g.src.substr(0,g.src.lastIndexOf(\"/\"))+\"/plus.png\"; }\n" \
+ " else { e.display=\"inline\"; f.display=\"none\"; g.src=g.src.substr(0,g.src.lastIndexOf(\"/\"))+\"/minus.png\"; }\n" \
+ "}\n" \
+ "function collapse_headers() {\n" \
+ " var f=window.document.getElementById(\"full-headers\").style;\n" \
+ " var s=window.document.getElementById(\"short-headers\").style;\n" \
+ " var i=window.document.getElementById(\"collapse-headers-img\");\n" \
+ " if (f.display==\"block\") { f.display=\"none\"; s.display=\"block\";" \
+ " i.src=i.src.substr(0,i.src.lastIndexOf(\"/\"))+\"/plus.png\"; window.headers_collapsed(true, window.em_format_html); }\n" \
+ " else { f.display=\"block\"; s.display=\"none\";" \
+ " i.src=i.src.substr(0,i.src.lastIndexOf(\"/\"))+\"/minus.png\"; window.headers_collapsed(false, window.em_format_html); }\n" \
+ "}\n" \
"</script>\n" \
- "</body>\n" \
+ "</head>\n" \
"<body bgcolor =\"#%06x\" text=\"#%06x\" marginwidth=6 marginheight=6 onLoad=\"body_loaded();\">",
e_color_to_value (
&efh->priv->colors[
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
index a531de6..66895aa 100644
--- a/mail/em-format-html.h
+++ b/mail/em-format-html.h
@@ -195,7 +195,6 @@ struct _EMFormatHTMLPObject {
* @load_http:2:
* @load_http_now:1:
* @mark_citations:1:
- * @simple_headers:1:
* @hide_headers:1:
* @show_icon:1:
*
@@ -214,7 +213,6 @@ struct _EMFormatHTML {
GSList *headers;
guint32 text_html_flags; /* default flags for text to html conversion */
- guint simple_headers:1; /* simple header format, no box/table */
guint hide_headers:1; /* no headers at all */
guint show_icon:1; /* show an icon when the sender used Evo */
guint32 header_wrap_flags;
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index 077cffe..640066f 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -51,6 +51,8 @@ struct _EWebViewPrivate {
GdkPixbufAnimation *cursor_image;
gchar *cursor_image_src;
+ GHashTable *js_callbacks;
+
GtkAction *open_proxy;
GtkAction *print_proxy;
GtkAction *save_as_proxy;
@@ -806,6 +808,11 @@ web_view_dispose (GObject *object)
priv->cursor_image_src = NULL;
}
+ if (priv->js_callbacks != NULL) {
+ g_hash_table_destroy (priv->js_callbacks);
+ priv->js_callbacks = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@@ -1662,6 +1669,9 @@ e_web_view_init (EWebView *web_view)
ui_manager = gtk_ui_manager_new ();
web_view->priv->ui_manager = ui_manager;
+ web_view->priv->js_callbacks = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
+
g_signal_connect_swapped (
ui_manager, "connect-proxy",
G_CALLBACK (web_view_connect_proxy_cb), web_view);
@@ -1900,6 +1910,17 @@ e_web_view_get_html (EWebView *web_view)
return NULL;
}
+JSGlobalContextRef
+e_web_view_get_global_context (EWebView *web_view)
+{
+ WebKitWebFrame *main_frame;
+
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), 0);
+
+ main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
+ return webkit_web_frame_get_global_context (main_frame);
+}
+
GType
e_web_view_exec_script (EWebView *web_view, const gchar *script, GValue *value)
{
@@ -1992,6 +2013,91 @@ e_web_view_frame_exec_script (EWebView *web_view, const gchar *frame_name, const
return G_VALUE_TYPE (value);
}
+static JSValueRef
+web_view_handle_js_callback (JSContextRef ctx, JSObjectRef function, JSObjectRef this_object,
+ size_t argument_count, const JSValueRef arguments[], JSValueRef *exception)
+{
+ gpointer web_view;
+ gpointer user_data;
+ gchar *fnc_name;
+ size_t fnc_name_len;
+
+ EWebViewJSFunctionCallback callback;
+
+ JSStringRef js_webview_prop = JSStringCreateWithUTF8CString ("webview");
+ JSStringRef js_userdata_prop = JSStringCreateWithUTF8CString ("user-data");
+ JSStringRef js_fncname_prop = JSStringCreateWithUTF8CString ("fnc-name");
+ JSStringRef js_fncname_str;
+
+ JSValueRef js_webview = JSObjectGetProperty (ctx, function, js_webview_prop, NULL);
+ JSValueRef js_userdata = JSObjectGetProperty (ctx, function, js_userdata_prop, NULL);
+ JSValueRef js_fncname = JSObjectGetProperty (ctx, function, js_fncname_prop, NULL);
+
+ web_view = GINT_TO_POINTER ((int) JSValueToNumber (ctx, js_webview, NULL));
+ user_data = GINT_TO_POINTER ((int) JSValueToNumber (ctx, js_userdata, NULL));
+ js_fncname_str = JSValueToStringCopy (ctx, js_fncname, NULL);
+ fnc_name_len = JSStringGetLength (js_fncname_str);
+
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), 0);
+
+ /* Convert fncname to gchar* and lookup the callback in hashtable */
+ fnc_name = g_malloc (fnc_name_len + 1);
+ JSStringGetUTF8CString (js_fncname_str, fnc_name, fnc_name_len+1);
+ callback = g_hash_table_lookup (E_WEB_VIEW (web_view)->priv->js_callbacks, fnc_name);
+
+ g_return_val_if_fail (callback != NULL, 0);
+
+ /* Call the callback function */
+ callback (E_WEB_VIEW (web_view), argument_count, arguments, user_data);
+
+ JSStringRelease (js_fncname_str);
+ JSStringRelease (js_fncname_prop);
+ JSStringRelease (js_webview_prop);
+ JSStringRelease (js_userdata_prop);
+
+ g_free (fnc_name);
+
+ return 0;
+}
+
+void
+e_web_view_install_js_callback (EWebView *web_view, const gchar *fnc_name, EWebViewJSFunctionCallback callback, gpointer user_data)
+{
+ WebKitWebFrame *frame;
+ JSGlobalContextRef ctx;
+ JSObjectRef global_obj, js_func;
+ JSStringRef js_fnc_name, js_webview_prop, js_userdata_prop, js_fncname_prop;
+
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+ g_return_if_fail (fnc_name != NULL);
+ g_return_if_fail (callback != NULL);
+
+ frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
+ ctx = webkit_web_frame_get_global_context (frame);
+ global_obj = JSContextGetGlobalObject (ctx);
+ js_fnc_name = JSStringCreateWithUTF8CString (fnc_name);
+ js_func = JSObjectMakeFunctionWithCallback (ctx, NULL,
+ (JSObjectCallAsFunctionCallback) web_view_handle_js_callback);
+ js_webview_prop = JSStringCreateWithUTF8CString ("webview");
+ js_userdata_prop = JSStringCreateWithUTF8CString ("user-data");
+ js_fncname_prop = JSStringCreateWithUTF8CString ("fnc-name");
+
+ /* Set some properties to the function */
+ JSObjectSetProperty (ctx, js_func, js_webview_prop, JSValueMakeNumber (ctx, GPOINTER_TO_INT (web_view)), 0, NULL);
+ JSObjectSetProperty (ctx, js_func, js_userdata_prop, JSValueMakeNumber (ctx, GPOINTER_TO_INT (user_data)), 0, NULL);
+ JSObjectSetProperty (ctx, js_func, js_fncname_prop, JSValueMakeString (ctx, js_fnc_name), 0, NULL);
+
+ /* Set the function as a property of global object */
+ JSObjectSetProperty (ctx, global_obj, js_fnc_name, js_func, 0, NULL);
+
+ JSStringRelease (js_fncname_prop);
+ JSStringRelease (js_userdata_prop);
+ JSStringRelease (js_webview_prop);
+ JSStringRelease (js_fnc_name);
+
+ g_hash_table_insert (web_view->priv->js_callbacks, g_strdup (fnc_name), callback);
+}
+
gboolean
e_web_view_get_animate (EWebView *web_view)
{
diff --git a/widgets/misc/e-web-view.h b/widgets/misc/e-web-view.h
index 48a7cc2..d43b3eb 100644
--- a/widgets/misc/e-web-view.h
+++ b/widgets/misc/e-web-view.h
@@ -28,6 +28,7 @@
#define E_WEB_VIEW_H
#include <webkit/webkit.h>
+#include <JavaScriptCore/JavaScript.h>
/* Standard GObject macros */
#define E_TYPE_WEB_VIEW \
@@ -59,6 +60,11 @@ struct _EWebView {
EWebViewPrivate *priv;
};
+typedef void (*EWebViewJSFunctionCallback) (EWebView *web_view,
+ size_t arg_count,
+ const JSValueRef args[],
+ gpointer user_data);
+
struct _EWebViewClass {
WebKitWebViewClass parent_class;
@@ -112,6 +118,8 @@ void e_web_view_frame_load_uri (EWebView *web_view,
const gchar *uri);
const gchar* e_web_view_frame_get_uri (EWebView *web_view,
const gchar *frame_name);
+JSGlobalContextRef
+ e_web_view_get_global_context (EWebView *web_view);
GType e_web_view_exec_script (EWebView *web_view,
const gchar *script,
GValue *value);
@@ -119,6 +127,10 @@ GType e_web_view_frame_exec_script (EWebView *web_view,
const gchar *frame_name,
const gchar *script,
GValue *value);
+void e_web_view_install_js_callback (EWebView *web_view,
+ const gchar *fnc_name,
+ EWebViewJSFunctionCallback callback,
+ gpointer user_data);
gchar * e_web_view_get_html (EWebView *web_view);
gboolean e_web_view_get_animate (EWebView *web_view);
void e_web_view_set_animate (EWebView *web_view,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]