[evolution/webkit] Fix 'Copy Image' and 'Save Image' in mail display



commit d2103dca9f86042fd62bbdd0786820e14aa52819
Author: Dan VrÃtil <dvratil redhat com>
Date:   Fri Jan 6 13:02:21 2012 +0100

    Fix 'Copy Image' and 'Save Image' in mail display

 mail/e-mail-display.c         |   87 +++++++++++++++++--
 mail/e-mail-reader.c          |  123 +++++++++++++++++++++++++-
 mail/em-format-html-display.c |  194 -----------------------------------------
 widgets/misc/e-web-view.c     |   60 +++++++++++++
 4 files changed, 260 insertions(+), 204 deletions(-)
---
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
index bd469b5..93c5525 100644
--- a/mail/e-mail-display.c
+++ b/mail/e-mail-display.c
@@ -65,7 +65,8 @@ struct _EMailDisplayPrivate {
 
         GtkWidget *current_webview;
 
-	GtkActionGroup *actions;
+	GtkActionGroup *mailto_actions;
+        GtkActionGroup *images_actions;
 };
 
 enum {
@@ -106,6 +107,15 @@ static const gchar *ui =
 "  </popup>"
 "</ui>";
 
+static const gchar *image_ui =
+"<ui>"
+"  <popup name='context'>"
+"    <placeholder name='custom-actions-2'>"
+"      <menuitem action='image-save'/>"
+"    </placeholder>"
+"  </popup>"
+"</ui>";
+
 static GtkActionEntry mailto_entries[] = {
 
 	{ "add-to-address-book",
@@ -146,6 +156,19 @@ static GtkActionEntry mailto_entries[] = {
 	  NULL }
 };
 
+
+static GtkActionEntry image_entries[] = {
+
+        { "image-save",
+        GTK_STOCK_SAVE,
+        N_("Save _Image..."),
+        NULL,
+        N_("Save the image to a file"),
+        NULL    /* Handled by EMailReader */ },
+
+};
+
+
 static gboolean
 mail_display_webview_enter_notify_event (GtkWidget *widget,
                                          GdkEvent *event,
@@ -164,6 +187,38 @@ mail_display_webview_enter_notify_event (GtkWidget *widget,
 }
 
 static void
+mail_display_webview_update_actions (EWebView *web_view,
+                                     gpointer user_data)
+{
+        EMailDisplay *display = user_data;
+
+        const gchar *image_src;
+        gboolean visible;
+        GtkAction *action;
+
+        g_return_if_fail (web_view != NULL);
+
+        image_src = e_web_view_get_cursor_image_src (web_view);
+        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);
+
+                visible = image_stream != NULL;
+
+                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);
+}
+
+
+
+static void
 formatter_image_loading_policy_changed_cb (GObject *object,
                                            GParamSpec *pspec,
                                            gpointer user_data)
@@ -630,7 +685,8 @@ mail_display_setup_webview (EMailDisplay *display,
 		G_CALLBACK (mail_display_emit_popup_event), display);
         g_signal_connect (web_view, "enter-notify-event",
                 G_CALLBACK (mail_display_webview_enter_notify_event), display);
-
+        g_signal_connect (web_view, "update-actions",
+                G_CALLBACK (mail_display_webview_update_actions), display);
 
         settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
         /* When webviews holds headers or attached image then the can_load_images option
@@ -645,9 +701,18 @@ mail_display_setup_webview (EMailDisplay *display,
 	 * no chance of I/O errors.  Failure here implies a malformed
 	 * UI definition.  Full stop. */
 	ui_manager = e_web_view_get_ui_manager (web_view);
-	gtk_ui_manager_insert_action_group (ui_manager, display->priv->actions, 0);
+	gtk_ui_manager_insert_action_group (ui_manager, display->priv->mailto_actions, 0);
 	gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
 
+        if (error != NULL) {
+                g_error ("%s", error->message);
+                g_error_free (error);
+        }
+
+        error = NULL;
+        gtk_ui_manager_insert_action_group (ui_manager, display->priv->images_actions, 0);
+        gtk_ui_manager_add_ui_from_string (ui_manager, image_ui, -1, &error);
+
 	if (error != NULL) {
 		g_error ("%s", error->message);
                 g_error_free (error);
@@ -1004,10 +1069,14 @@ mail_display_init (EMailDisplay *display)
 
 	display->priv->webviews = NULL;
 
-	display->priv->actions = gtk_action_group_new ("mailto");
-	gtk_action_group_add_actions (display->priv->actions, mailto_entries, 
+	display->priv->mailto_actions = gtk_action_group_new ("mailto");
+	gtk_action_group_add_actions (display->priv->mailto_actions, mailto_entries, 
 		G_N_ELEMENTS (mailto_entries), NULL);
 
+        display->priv->images_actions = gtk_action_group_new ("image");
+        gtk_action_group_add_actions (display->priv->images_actions, image_entries,
+                G_N_ELEMENTS (image_entries), NULL);
+
 
 	/* WEBKIT TODO: ESearchBar */
 
@@ -1242,10 +1311,16 @@ GtkAction*
 e_mail_display_get_action (EMailDisplay *display,
 			   const gchar *action_name)
 {
+        GtkAction *action;
+
 	g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
 	g_return_val_if_fail (action_name != NULL, NULL);
 
-	return gtk_action_group_get_action (display->priv->actions, action_name);
+	action = gtk_action_group_get_action (display->priv->mailto_actions, action_name);
+        if (!action)
+                action = gtk_action_group_get_action (display->priv->images_actions, action_name);
+
+        return action;
 }
 
 void
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 1f58347..2679b23 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -247,6 +247,118 @@ exit:
 }
 
 static void
+attachment_load_finish (EAttachment *attachment,
+                        GAsyncResult *result,
+                        GFile *file)
+{
+        EShell *shell;
+        GtkWindow *parent;
+
+        e_attachment_load_finish (attachment, result, NULL);
+
+        shell = e_shell_get_default ();
+        parent = e_shell_get_active_window (shell);
+
+        e_attachment_save_async (
+                attachment, file, (GAsyncReadyCallback)
+                e_attachment_save_handle_error, parent);
+
+        g_object_unref (file);
+}
+
+static void
+action_mail_image_save_cb (GtkAction *action,
+                           EMailReader *reader)
+{
+        EMailDisplay *display;
+        EWebView *web_view;
+        EMFormat *emf;
+        const gchar *image_src;
+        CamelMimePart *part;
+        EAttachment *attachment;
+        GFile *file;
+
+        display = e_mail_reader_get_mail_display (reader);
+        web_view = e_mail_display_get_current_web_view (display);
+
+        if (!E_IS_WEB_VIEW (web_view))
+                return;
+
+        image_src = e_web_view_get_cursor_image_src (web_view);
+        if (!image_src)
+                return;
+
+        emf = EM_FORMAT (e_mail_display_get_formatter (display));
+        g_return_if_fail (emf != NULL);
+        g_return_if_fail (emf->message != NULL);
+
+        if (g_str_has_prefix (image_src, "cid:")) {
+                part = camel_mime_message_get_part_by_content_id (
+                        emf->message, image_src + 4);
+                g_return_if_fail (part != NULL);
+
+                g_object_ref (part);
+        } else {
+                CamelStream *image_stream;
+                CamelDataWrapper *dw;
+                CamelDataCache *cache;
+                const gchar *filename;
+                const gchar *user_cache_dir;
+
+                /* Open cache and find the file there */
+                user_cache_dir = e_get_user_cache_dir ();
+                cache = camel_data_cache_new (user_cache_dir, NULL);
+                image_stream = camel_data_cache_get (cache, "http", image_src, NULL);
+                if (!image_stream) {
+                        g_object_unref (cache);
+                        return;
+                }
+
+                filename = strrchr (image_src, '/');
+                if (filename && strchr (filename, '?'))
+                        filename = NULL;
+                else if (filename)
+                        filename = filename + 1;
+
+                part = camel_mime_part_new ();
+                if (filename)
+                        camel_mime_part_set_filename (part, filename);
+
+                dw = camel_data_wrapper_new ();
+                camel_data_wrapper_set_mime_type (
+                        dw, "application/octet-stream");
+                camel_data_wrapper_construct_from_stream_sync (
+                        dw, image_stream, NULL, NULL);
+                camel_medium_set_content (CAMEL_MEDIUM (part), dw);
+                g_object_unref (dw);
+
+                camel_mime_part_set_encoding (
+                        part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+                g_object_unref (image_stream);
+                g_object_unref (cache);
+        }
+
+        file = e_shell_run_save_dialog (
+                e_shell_get_default (),
+                _("Save Image"), camel_mime_part_get_filename (part),
+                NULL, NULL, NULL);
+        if (file == NULL) {
+                g_object_unref (part);
+                return;
+        }
+
+        attachment = e_attachment_new ();
+        e_attachment_set_mime_part (attachment, part);
+
+        e_attachment_load_async (
+                attachment, (GAsyncReadyCallback)
+                attachment_load_finish, file);
+
+        g_object_unref (part);
+}
+
+static void
 action_mail_charset_cb (GtkRadioAction *action,
                         GtkRadioAction *current,
                         EMailReader *reader)
@@ -2957,11 +3069,8 @@ mail_reader_message_loaded (EMailReader *reader,
 			NULL, format_parser_async_done_cb, reader);
 
 		g_hash_table_insert (formatters, mail_uri, formatter);
+		e_mail_display_set_formatter (display, EM_FORMAT_HTML (formatter));
 	} else {
-		EMailDisplay *display;
-
-		display = e_mail_reader_get_mail_display (reader);
-
 		e_mail_display_set_formatter (display, EM_FORMAT_HTML (formatter));
 		e_mail_display_load (display, formatter->uri_base);
 	}
@@ -3757,6 +3866,12 @@ e_mail_reader_init (EMailReader *reader,
 		action, "activate",
 		G_CALLBACK (action_search_folder_sender_cb), reader);
 
+        action_name = "image-save";
+        action = e_mail_display_get_action (display, action_name);
+        g_signal_connect (
+                action, "activate",
+                G_CALLBACK (action_mail_image_save_cb), reader);
+
 #ifndef G_OS_WIN32
 	/* Lockdown integration. */
 
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 5cdd3ef..47ed14e 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -675,173 +675,6 @@ efhd_parse_secure (EMFormat *emf,
 }
 
 static void
-attachment_load_finish (EAttachment *attachment,
-                        GAsyncResult *result,
-                        GFile *file)
-{
-	EShell *shell;
-	GtkWindow *parent;
-
-	e_attachment_load_finish (attachment, result, NULL);
-
-	shell = e_shell_get_default ();
-	parent = e_shell_get_active_window (shell);
-
-	e_attachment_save_async (
-		attachment, file, (GAsyncReadyCallback)
-		e_attachment_save_handle_error, parent);
-
-	g_object_unref (file);
-}
-
-
-static void
-action_image_save_cb (GtkAction *action,
-                      EMFormatHTMLDisplay *efhd)
-{
-#if 0 /* FIXME WEBKIT */
-	EWebView *web_view;
-	EMFormat *emf;
-	const gchar *image_src;
-	CamelMimePart *part;
-	EAttachment *attachment;
-	GFile *file;
-
-	/* FIXME WEBKIT At this moment there's no way how to get EMailDisplay from
-	   EMFormat(HTML)
-	web_view = em_format_html_get_web_view (EM_FORMAT_HTML (efhd));
-	g_return_if_fail (web_view != NULL);
-	*/
-	return;
-
-	image_src = e_web_view_get_cursor_image_src (web_view);
-	if (!image_src)
-		return;
-
-	emf = EM_FORMAT (efhd);
-	g_return_if_fail (emf != NULL);
-	g_return_if_fail (emf->message != NULL);
-
-	if (g_str_has_prefix (image_src, "cid:")) {
-		part = camel_mime_message_get_part_by_content_id (
-			emf->message, image_src + 4);
-		g_return_if_fail (part != NULL);
-
-		g_object_ref (part);
-	} else {
-		CamelStream *image_stream;
-		CamelDataWrapper *dw;
-		CamelDataCache *cache;
-		const gchar *filename;
-		const gchar *user_cache_dir;
-
-		/* Open cache and find the file there */
-		user_cache_dir = e_get_user_cache_dir ();
-		cache = camel_data_cache_new (user_cache_dir, NULL);
-		image_stream = camel_data_cache_get (cache, "http", image_src, NULL);
-		if (!image_stream) {
-			g_object_unref (cache);
-			return;
-		}
-
-		filename = strrchr (image_src, '/');
-		if (filename && strchr (filename, '?'))
-			filename = NULL;
-		else if (filename)
-			filename = filename + 1;
-
-		part = camel_mime_part_new ();
-		if (filename)
-			camel_mime_part_set_filename (part, filename);
-
-		dw = camel_data_wrapper_new ();
-		camel_data_wrapper_set_mime_type (
-			dw, "application/octet-stream");
-		camel_data_wrapper_construct_from_stream_sync (
-			dw, image_stream, NULL, NULL);
-		camel_medium_set_content (CAMEL_MEDIUM (part), dw);
-		g_object_unref (dw);
-
-		camel_mime_part_set_encoding (
-			part, CAMEL_TRANSFER_ENCODING_BASE64);
-
-		g_object_unref (image_stream);
-		g_object_unref (cache);
-	}
-
-	file = e_shell_run_save_dialog (
-		e_shell_get_default (),
-		_("Save Image"), camel_mime_part_get_filename (part),
-		NULL, NULL, NULL);
-	if (file == NULL) {
-		g_object_unref (part);
-		return;
-	}
-
-	attachment = e_attachment_new ();
-	e_attachment_set_mime_part (attachment, part);
-
-	e_attachment_load_async (
-		attachment, (GAsyncReadyCallback)
-		attachment_load_finish, file);
-
-	g_object_unref (part);
-#endif
-}
-
-static void
-efhd_web_view_update_actions_cb (EWebView *web_view,
-                                 EMFormatHTMLDisplay *efhd)
-{
-	const gchar *image_src;
-	gboolean visible;
-	GtkAction *action;
-
-	g_return_if_fail (web_view != NULL);
-
-	image_src = e_web_view_get_cursor_image_src (web_view);
-	visible = image_src && g_str_has_prefix (image_src, "cid:");
-	if (!visible && image_src) {
-		CamelDataCache *cache;
-		CamelStream *image_stream;
-		const gchar *user_cache_dir;
-
-		user_cache_dir = e_get_user_cache_dir ();
-		cache = camel_data_cache_new (user_cache_dir, NULL);
-		image_stream = camel_data_cache_get (cache, "http", image_src, NULL);
-
-		visible = image_stream != NULL;
-
-		if (image_stream)
-			g_object_unref (image_stream);
-
-		g_object_unref (cache);
-	}
-
-	action = e_web_view_get_action (web_view, "efhd-image-save");
-	if (action)
-		gtk_action_set_visible (action, visible);
-}
-
-static GtkActionEntry image_entries[] = {
-	{ "efhd-image-save",
-	  GTK_STOCK_SAVE,
-	  N_("Save _Image..."),
-	  NULL,
-	  N_("Save the image to a file"),
-	  G_CALLBACK (action_image_save_cb) }
-};
-
-static const gchar *image_ui =
-	"<ui>"
-	"  <popup name='context'>"
-	"    <placeholder name='custom-actions-2'>"
-	"      <menuitem action='efhd-image-save'/>"
-	"    </placeholder>"
-	"  </popup>"
-	"</ui>";
-
-static void
 efhd_finalize (GObject *object)
 {
 	EMFormatHTMLDisplay *efhd;
@@ -874,12 +707,6 @@ efhd_class_init (EMFormatHTMLDisplayClass *class)
 static void
 efhd_init (EMFormatHTMLDisplay *efhd)
 {
-	EWebView *web_view;
-	GtkActionGroup *image_actions;
-	GtkUIManager *ui_manager;
-	GError *error = NULL;
-
-
 	efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efhd);
 
         /* we want to convert url's etc */
@@ -887,27 +714,6 @@ efhd_init (EMFormatHTMLDisplay *efhd)
 		CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
 		CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
 
-/* FIXME WEBKIT There's no way how to get web_view from EFHD for now...
-	image_actions = e_web_view_get_action_group (web_view, "image");
-	g_return_if_fail (image_actions != NULL);
-
-	gtk_action_group_add_actions (
-		image_actions, image_entries,
-		G_N_ELEMENTS (image_entries), efhd);
-*/
-	/* Because we are loading from a hard-coded string, there is
-	 * no chance of I/O errors.  Failure here implies a malformed
-	 * UI definition.  Full stop. */
-/* FIXME WEBKIT There 's no way how to get web_view from EFHD for now...
-	ui_manager = e_web_view_get_ui_manager (web_view);
-	gtk_ui_manager_add_ui_from_string (ui_manager, image_ui, -1, &error);
-	if (error != NULL)
-		g_error ("%s", error->message);
-
-	g_signal_connect (
-		web_view, "update-actions",
-		G_CALLBACK (efhd_web_view_update_actions_cb), efhd);
-*/
 }
 
 GType
diff --git a/widgets/misc/e-web-view.c b/widgets/misc/e-web-view.c
index 0bdd4ac..b7af87f 100644
--- a/widgets/misc/e-web-view.c
+++ b/widgets/misc/e-web-view.c
@@ -719,6 +719,66 @@ web_view_button_press_event (GtkWidget *widget,
 
 	web_view = E_WEB_VIEW (widget);
 
+        if (event) {
+                WebKitHitTestResult *test;
+                WebKitHitTestResultContext context;
+
+                test = webkit_web_view_get_hit_test_result (WEBKIT_WEB_VIEW (web_view), event);
+
+                if (!test)
+                        goto chainup;
+
+                g_object_get (G_OBJECT (test), "context", &context, NULL);
+                if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) {
+                        WebKitWebDataSource *data_source;
+                        WebKitWebFrame *frame;
+                        GList *subresources, *res;
+
+                        g_object_get (G_OBJECT (test), "image-uri", &uri, NULL);
+
+                        if (!uri)
+                                goto chainup;
+
+                        if (web_view->priv->cursor_image_src)
+                                g_free (web_view->priv->cursor_image_src);
+                        web_view->priv->cursor_image_src = uri;
+
+                        /* Iterate through all resources of the loaded webpage and
+                           try to find resource with URI matching cursor_image_src */
+                        frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
+                        data_source = webkit_web_frame_get_data_source (frame);
+                        subresources = webkit_web_data_source_get_subresources (data_source);
+                        for (res = subresources; res; res = res->next) {
+                                WebKitWebResource *src = res->data;
+                                GdkPixbufLoader *loader;
+                                GString *data;
+
+                                if (g_strcmp0 (webkit_web_resource_get_uri (src),
+                                        web_view->priv->cursor_image_src) != 0)
+                                        continue;
+
+                                data = webkit_web_resource_get_data (src);
+
+                                loader = gdk_pixbuf_loader_new ();
+                                if (!gdk_pixbuf_loader_write (loader,
+                                        (guchar *) data->str, data->len, NULL)) {
+                                        g_object_unref (loader);
+                                        break;
+                                }
+                                gdk_pixbuf_loader_close (loader, NULL);
+
+                                if (web_view->priv->cursor_image)
+                                        g_object_unref (web_view->priv->cursor_image);
+
+                                web_view->priv->cursor_image =
+                                        g_object_ref (gdk_pixbuf_loader_get_animation (loader));
+
+                                g_object_unref (loader);
+                                break;
+                        }
+                }
+        }
+
 	if (event != NULL && event->button != 3)
 		goto chainup;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]