[evolution] Add zooming and drag-and-drop to the plugin.



commit e13eb8a5b52c0b95f5b235c61245277230d565dc
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sun Nov 8 01:49:48 2009 -0500

    Add zooming and drag-and-drop to the plugin.
    
    A bunch of crusty old code in em-format-html-display.c falls out.

 mail/Makefile.am                    |    2 -
 mail/em-format-html-display.c       |  277 +---------------------------
 mail/em-format-html-display.h       |    4 +
 mail/em-format-html.c               |    4 -
 mail/em-icon-stream.c               |  347 -----------------------------------
 mail/em-icon-stream.h               |   61 ------
 plugins/image-inline/Makefile.am    |    1 +
 plugins/image-inline/image-inline.c |  165 ++++++++++++++---
 8 files changed, 151 insertions(+), 710 deletions(-)
---
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 7f284e9..01d41aa 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -70,7 +70,6 @@ mailinclude_HEADERS =					\
 	em-format-html-display.h			\
 	em-format-html-print.h				\
 	em-html-stream.h				\
-	em-icon-stream.h				\
 	em-inline-filter.h				\
 	em-junk.h					\
 	em-search-context.h				\
@@ -127,7 +126,6 @@ libevolution_mail_la_SOURCES =				\
 	em-format-html-display.c			\
 	em-format-html-print.c				\
 	em-html-stream.c				\
-	em-icon-stream.c				\
 	em-inline-filter.c				\
 	em-junk.c					\
 	em-search-context.c				\
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index de64e2b..34c146e 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -76,7 +76,6 @@
 #include "e-mail-display.h"
 #include "e-mail-attachment-bar.h"
 #include "em-format-html-display.h"
-#include "em-icon-stream.h"
 #include "em-utils.h"
 #include "widgets/misc/e-attachment-button.h"
 #include "widgets/misc/e-attachment-view.h"
@@ -126,7 +125,6 @@ static const gchar *smime_sign_colour[5] = {
 };
 
 static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri);
-static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
 static void efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
 static gboolean efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
 static gboolean efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *object);
@@ -672,58 +670,7 @@ em_format_html_display_new (void)
 
 /* ********************************************************************** */
 
-static void
-efhd_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *handle)
-{
-	gchar *classid;
-	struct _attach_puri *info;
-
-	classid = g_strdup_printf("image%s", ((EMFormat *)efh)->part_id->str);
-	info = (struct _attach_puri *)em_format_add_puri((EMFormat *)efh, sizeof(*info), classid, part, efhd_attachment_frame);
-	em_format_html_add_pobject(efh, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_image);
-
-	info->handle = handle;
-	info->shown = TRUE;
-	info->snoop_mime_type = ((EMFormat *) efh)->snoop_mime_type;
-	if (camel_operation_cancel_check (NULL) || !info->puri.format || !((EMFormatHTML *)info->puri.format)->html) {
-		/* some fake value, we are cancelled anyway, thus doesn't matter */
-		info->fit_width = 256;
-	} else {
-		info->fit_width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
-	}
-
-	camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
-	g_free(classid);
-}
-
-/* ********************************************************************** */
-
 static EMFormatHandler type_builtin_table[] = {
-#if 0
-	{ (gchar *) "image/gif", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/jpeg", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/png", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-png", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/tiff", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-bmp", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/bmp", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/svg", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-cmu-raster", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-ico", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-portable-anymap", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-portable-bitmap", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-portable-graymap", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-portable-pixmap", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/x-xpixmap", (EMFormatFunc)efhd_image },
-
-	/* This is where one adds those busted, non-registered types,
-	   that some idiot mailer writers out there decide to pull out
-	   of their proverbials at random. */
-
-	{ (gchar *) "image/jpg", (EMFormatFunc)efhd_image },
-	{ (gchar *) "image/pjpeg", (EMFormatFunc)efhd_image },
-#endif
-
 	{ (gchar *) "x-evolution/message/prefix", (EMFormatFunc)efhd_message_prefix },
 	{ (gchar *) "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar }
 };
@@ -839,219 +786,6 @@ efhd_attachment_button_expanded (GtkWidget *widget,
 
 /* ********************************************************************** */
 
-static void
-efhd_drag_data_get(GtkWidget *w, GdkDragContext *drag, GtkSelectionData *data, guint info, guint time, EMFormatHTMLPObject *pobject)
-{
-	CamelMimePart *part = pobject->part;
-	gchar *uri, *uri_crlf, *path;
-	CamelStream *stream;
-
-	switch (info) {
-	case 0: /* mime/type request */
-		stream = camel_stream_mem_new();
-		/* TODO: shoudl format_format_text run on the content-object? */
-		/* TODO: should we just do format_content? */
-		if (camel_content_type_is (((CamelDataWrapper *)part)->mime_type, "text", "*")) {
-			/* FIXME: this should be an em_utils method, it only needs a default charset param */
-			em_format_format_text((EMFormat *)pobject->format, stream, (CamelDataWrapper *)part);
-		} else {
-			CamelDataWrapper *dw = camel_medium_get_content_object((CamelMedium *)part);
-
-			camel_data_wrapper_decode_to_stream(dw, stream);
-		}
-
-		gtk_selection_data_set(data, data->target, 8,
-				       ((CamelStreamMem *)stream)->buffer->data,
-				       ((CamelStreamMem *)stream)->buffer->len);
-		camel_object_unref(stream);
-		break;
-	case 1: /* text-uri-list request */
-		/* Kludge around Nautilus requesting the same data many times */
-		uri = g_object_get_data((GObject *)w, "e-drag-uri");
-		if (uri) {
-			gtk_selection_data_set(data, data->target, 8, (guchar *)uri, strlen(uri));
-			return;
-		}
-
-		path = em_utils_temp_save_part(w, part, FALSE);
-		if (path == NULL)
-			return;
-
-		uri = g_filename_to_uri(path, NULL, NULL);
-		g_free(path);
-		uri_crlf = g_strconcat(uri, "\r\n", NULL);
-		g_free(uri);
-		gtk_selection_data_set(data, data->target, 8, (guchar *)uri_crlf, strlen(uri_crlf));
-		g_object_set_data_full((GObject *)w, "e-drag-uri", uri_crlf, g_free);
-		break;
-	default:
-		abort();
-	}
-}
-
-static void
-efhd_drag_data_delete(GtkWidget *w, GdkDragContext *drag, EMFormatHTMLPObject *pobject)
-{
-	gchar *uri;
-
-	uri = g_object_get_data((GObject *)w, "e-drag-uri");
-	if (uri) {
-		/* NB: this doesn't kill the dnd directory */
-		/* NB: is this ever called? */
-		/* NB even more: doesn't the e-drag-uri have \r\n
-		 * appended? (see efhd_drag_data_get())
-		 */
-		gchar *filename = g_filename_from_uri (uri, NULL, NULL);
-		g_unlink(filename);
-		g_free(filename);
-		g_object_set_data((GObject *)w, "e-drag-uri", NULL);
-	}
-}
-
-static void
-efhd_write_icon_job(struct _EMFormatHTMLJob *job, gint cancelled)
-{
-	EMFormatHTMLPObject *pobject;
-	CamelDataWrapper *dw;
-
-	if (cancelled)
-		return;
-
-	pobject = job->u.data;
-	dw = camel_medium_get_content_object((CamelMedium *)pobject->part);
-	camel_data_wrapper_decode_to_stream(dw, job->stream);
-	camel_stream_close(job->stream);
-}
-
-static void
-efhd_image_resized(GtkWidget *w, GtkAllocation *event, struct _attach_puri *info)
-{
-	GdkPixbuf *pb;
-	gint width;
-
-	if (info->fit_width == 0)
-		return;
-
-	width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
-	if (info->fit_width == width)
-		return;
-	info->fit_width = width;
-
-	pb = em_icon_stream_get_image(info->puri.cid, info->fit_width, info->fit_height);
-	if (pb) {
-		gtk_image_set_from_pixbuf(info->image, pb);
-		g_object_unref(pb);
-	}
-}
-
-static void
-efhd_change_cursor(GtkWidget *w, GdkEventCrossing *event, struct _attach_puri *info)
-{
-	if (info->shown && info->image) {
-		if (info->fit_width != 0) {
-			if (em_icon_stream_is_resized(info->puri.cid, info->fit_width, info->fit_height))
-				e_cursor_set(w->window, E_CURSOR_ZOOM_IN);
-
-		}
-	}
-}
-
-static void
-efhd_image_fit_width(GtkWidget *widget, GdkEventButton *event, struct _attach_puri *info)
-{
-	gint width;
-
-	width = ((GtkWidget *)((EMFormatHTML *)info->puri.format)->html)->allocation.width - 12;
-
-	if (info->shown && info->image) {
-		if (info->fit_width != 0) {
-			if (em_icon_stream_is_resized(info->puri.cid, info->fit_width, info->fit_height)) {
-				if (info->fit_width != width) {
-					info->fit_width = width;
-					e_cursor_set (widget->window, E_CURSOR_ZOOM_IN);
-				} else {
-					info->fit_width = 0;
-					e_cursor_set(widget->window, E_CURSOR_ZOOM_OUT);
-				}
-			}
-		} else {
-			info->fit_width = width;
-			e_cursor_set (widget->window, E_CURSOR_ZOOM_IN);
-		}
-	}
-
-	gtk_image_set_from_pixbuf(info->image, em_icon_stream_get_image(info->puri.cid, info->fit_width, info->fit_height));
-}
-
-/* When the puri gets freed in the formatter thread and if the image is resized, crash will happen
-   See bug #333864 So while freeing the puri, we disconnect the image attach resize attached with
-   the puri */
-
-static void
-efhd_image_unallocate (struct _EMFormatPURI * puri)
-{
-	struct _attach_puri *info = (struct _attach_puri *) puri;
-	g_signal_handlers_disconnect_by_func(info->html, efhd_image_resized, info);
-
-	g_signal_handlers_disconnect_by_func(info->event_box, efhd_change_cursor, info);
-	g_signal_handlers_disconnect_by_func(info->event_box, efhd_image_fit_width, info);
-}
-
-static gboolean
-efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
-{
-	GtkWidget *box;
-	EMFormatHTMLJob *job;
-	struct _attach_puri *info;
-	GdkPixbuf *pixbuf;
-	GtkTargetEntry drag_types[] = {
-		{ NULL, 0, 0 },
-		{ (gchar *) "text/uri-list", 0, 1 },
-	};
-	gchar *simple_type;
-
-	info = (struct _attach_puri *)em_format_find_puri((EMFormat *)efh, pobject->classid);
-
-	info->image = (GtkImage *)gtk_image_new();
-	info->html = eb;
-	info->puri.free = efhd_image_unallocate;
-
-	pixbuf = em_icon_stream_get_image(pobject->classid, info->fit_width, info->fit_height);
-	if (pixbuf) {
-		gtk_image_set_from_pixbuf(info->image, pixbuf);
-		g_object_unref(pixbuf);
-	} else {
-		job = em_format_html_job_new(efh, efhd_write_icon_job, pobject);
-		job->stream = (CamelStream *)em_icon_stream_new((GtkImage *)info->image, pobject->classid, info->fit_width, info->fit_height, TRUE);
-		em_format_html_job_queue(efh, job);
-	}
-
-	box = gtk_event_box_new();
-	info->event_box = box;
-	gtk_container_add((GtkContainer *)box, (GtkWidget *)info->image);
-	gtk_widget_show_all(box);
-	gtk_container_add((GtkContainer *)eb, box);
-
-	g_signal_connect(eb, "size_allocate", G_CALLBACK(efhd_image_resized), info);
-
-	simple_type = camel_content_type_simple(((CamelDataWrapper *)pobject->part)->mime_type);
-	camel_strdown(simple_type);
-
-	drag_types[0].target = simple_type;
-	gtk_drag_source_set(box, GDK_BUTTON1_MASK, drag_types, G_N_ELEMENTS (drag_types), GDK_ACTION_COPY);
-	g_free(simple_type);
-
-	g_signal_connect(box, "drag-data-get", G_CALLBACK(efhd_drag_data_get), pobject);
-	g_signal_connect (box, "drag-data-delete", G_CALLBACK(efhd_drag_data_delete), pobject);
-
-	g_signal_connect(box, "enter-notify-event", G_CALLBACK(efhd_change_cursor), info);
-	g_signal_connect(box, "button-press-event", G_CALLBACK(efhd_image_fit_width), info);
-
-	g_object_set_data (G_OBJECT (box), "efh", efh);
-
-	return TRUE;
-}
-
 /* attachment button callback */
 static gboolean
 efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
@@ -1083,8 +817,8 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
 	parent = gtk_widget_get_toplevel (GTK_WIDGET (efh->html));
 	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
 
-	view = E_ATTACHMENT_VIEW (efhd->priv->attachment_view);
-	gtk_widget_show (efhd->priv->attachment_view);
+	view = em_format_html_display_get_attachment_view (efhd);
+	gtk_widget_show (GTK_WIDGET (view));
 
 	store = e_attachment_view_get_store (view);
 	e_attachment_store_add_attachment (store, info->attachment);
@@ -1298,3 +1032,10 @@ efhd_attachment_optional(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPOb
 	return TRUE;
 }
 
+EAttachmentView *
+em_format_html_display_get_attachment_view (EMFormatHTMLDisplay *html_display)
+{
+	g_return_val_if_fail (EM_IS_FORMAT_HTML_DISPLAY (html_display), NULL);
+
+	return E_ATTACHMENT_VIEW (html_display->priv->attachment_view);
+}
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index 4626598..089b361 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -26,6 +26,7 @@
 #define EM_FORMAT_HTML_DISPLAY_H
 
 #include <mail/em-format-html.h>
+#include <misc/e-attachment-view.h>
 
 /* Standard GObject macros */
 #define EM_TYPE_FORMAT_HTML_DISPLAY \
@@ -66,6 +67,9 @@ struct _EMFormatHTMLDisplayClass {
 GType		em_format_html_display_get_type	(void);
 EMFormatHTMLDisplay *
 		em_format_html_display_new	(void);
+EAttachmentView *
+		em_format_html_display_get_attachment_view
+						(EMFormatHTMLDisplay *html_display);
 
 G_END_DECLS
 
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 29bb476..47213dc 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -2105,7 +2105,6 @@ efh_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatH
 }
 
 static EMFormatHandler type_builtin_table[] = {
-#if 0
 	{ (gchar *) "image/gif", (EMFormatFunc)efh_image },
 	{ (gchar *) "image/jpeg", (EMFormatFunc)efh_image },
 	{ (gchar *) "image/png", (EMFormatFunc)efh_image },
@@ -2121,7 +2120,6 @@ static EMFormatHandler type_builtin_table[] = {
 	{ (gchar *) "image/x-portable-graymap", (EMFormatFunc)efh_image },
 	{ (gchar *) "image/x-portable-pixmap", (EMFormatFunc)efh_image },
 	{ (gchar *) "image/x-xpixmap", (EMFormatFunc)efh_image },
-#endif
 	{ (gchar *) "text/enriched", (EMFormatFunc)efh_text_enriched },
 	{ (gchar *) "text/plain", (EMFormatFunc)efh_text_plain },
 	{ (gchar *) "text/html", (EMFormatFunc)efh_text_html },
@@ -2135,10 +2133,8 @@ static EMFormatHandler type_builtin_table[] = {
 	   that some idiot mailer writers out there decide to pull out
 	   of their proverbials at random. */
 
-#if 0
 	{ (gchar *) "image/jpg", (EMFormatFunc)efh_image },
 	{ (gchar *) "image/pjpeg", (EMFormatFunc)efh_image },
-#endif
 
 	/* special internal types */
 
diff --git a/plugins/image-inline/Makefile.am b/plugins/image-inline/Makefile.am
index 5ff7c26..d59203a 100644
--- a/plugins/image-inline/Makefile.am
+++ b/plugins/image-inline/Makefile.am
@@ -7,6 +7,7 @@ plugin_LTLIBRARIES = liborg-gnome-image-inline.la
 liborg_gnome_image_inline_la_CPPFLAGS =			\
 	$(AM_CPPFLAGS)					\
 	-I$(top_srcdir)					\
+	-I$(top_srcdir)/widgets				\
 	$(GNOME_PLATFORM_CFLAGS)			\
 	$(EVOLUTION_MAIL_CFLAGS)			\
 	$(GTKIMAGEVIEW_CFLAGS)
diff --git a/plugins/image-inline/image-inline.c b/plugins/image-inline/image-inline.c
index 81e5d92..688a7d7 100644
--- a/plugins/image-inline/image-inline.c
+++ b/plugins/image-inline/image-inline.c
@@ -31,8 +31,8 @@
 #include <gtkhtml/gtkhtml-embedded.h>
 #include <gtkimageview/gtkimagescrollwin.h>
 
-#include "mail/em-format-hook.h"
-#include "mail/em-format-html.h"
+#include <mail/em-format-hook.h>
+#include <mail/em-format-html-display.h>
 
 static gint org_gnome_image_inline_classid;
 
@@ -44,13 +44,118 @@ typedef struct _ImageInlinePObject ImageInlinePObject;
 struct _ImageInlinePObject {
 	EMFormatHTMLPObject object;
 
+	CamelMimePart *mime_part;
 	GdkPixbuf *pixbuf;
 	GtkWidget *widget;
 };
 
 static void
+set_drag_source (GtkImageView *image_view)
+{
+	GtkTargetEntry *targets;
+	GtkTargetList *list;
+	gint n_targets;
+
+	list = gtk_target_list_new (NULL, 0);
+	gtk_target_list_add_uri_targets (list, 0);
+	targets = gtk_target_table_new_from_list (list, &n_targets);
+
+	gtk_drag_source_set (
+		GTK_WIDGET (image_view), GDK_BUTTON1_MASK,
+		targets, n_targets, GDK_ACTION_COPY);
+
+	gtk_target_table_free (targets, n_targets);
+	gtk_target_list_unref (list);
+}
+
+static gboolean
+button_press_press_cb (GtkImageView *image_view,
+                       GdkEventButton *event,
+                       ImageInlinePObject *image_object)
+{
+	if (event->type != GDK_2BUTTON_PRESS)
+		return FALSE;
+
+	if (gtk_image_view_get_zoom (image_view) < 1.0) {
+		gtk_image_view_set_zoom (image_view, 1.0);
+		gtk_drag_source_unset (GTK_WIDGET (image_view));
+	} else {
+		gtk_image_view_set_fitting (image_view, TRUE);
+		set_drag_source (image_view);
+	}
+
+	return TRUE;
+}
+
+static void
+drag_data_get_cb (GtkImageView *image_view,
+                  GdkDragContext *context,
+                  GtkSelectionData *selection,
+                  guint info,
+                  guint time,
+                  ImageInlinePObject *image_object)
+{
+	EMFormatHTMLDisplay *html_display;
+	EAttachmentStore *store;
+	EAttachmentView *view;
+	EAttachment *attachment = NULL;
+	GtkTreeRowReference *reference;
+	GtkTreePath *path;
+	GList *list, *iter;
+
+	/* XXX This illustrates the lack of integration between EMFormat
+	 *     and EAttachment, in that we now have to search through the
+	 *     attachment store to find an attachment whose CamelMimePart
+	 *     matches ours.  This allows us to defer to EAttachmentView
+	 *     for the drag-data-get implementation. */
+
+	html_display = EM_FORMAT_HTML_DISPLAY (image_object->object.format);
+	view = em_format_html_display_get_attachment_view (html_display);
+
+	store = e_attachment_view_get_store (view);
+	list = e_attachment_store_get_attachments (store);
+
+	for (iter = list; iter != NULL; iter = iter->next) {
+		CamelMimePart *mime_part;
+
+		attachment = E_ATTACHMENT (iter->data);
+		mime_part = e_attachment_get_mime_part (attachment);
+
+		if (mime_part == image_object->mime_part) {
+			g_object_ref (attachment);
+			break;
+		}
+
+		attachment = NULL;
+	}
+
+	g_list_foreach (list, (GFunc) g_object_unref, NULL);
+	g_list_free (list);
+
+	/* Make sure we found an EAttachment to select. */
+	g_return_if_fail (E_IS_ATTACHMENT (attachment));
+
+	/* Now select its path in the attachment store. */
+
+	reference = e_attachment_get_reference (attachment);
+	g_return_if_fail (gtk_tree_row_reference_valid (reference));
+
+	path = gtk_tree_row_reference_get_path (reference);
+
+	e_attachment_view_unselect_all (view);
+	e_attachment_view_select_path (view, path);
+
+	gtk_tree_path_free (path);
+
+	/* Let EAttachmentView handle the rest. */
+
+	e_attachment_view_drag_data_get (
+		view, context, selection, info, time);
+}
+
+static void
 size_allocate_cb (GtkHTMLEmbedded *embedded,
-                  GtkAllocation *event,
+                  GtkAllocation *allocation,
                   ImageInlinePObject *image_object)
 {
 	GtkWidget *widget;
@@ -58,7 +163,7 @@ size_allocate_cb (GtkHTMLEmbedded *embedded,
 	gint pixbuf_height;
 	gint widget_width;
 	gint widget_height;
-	gdouble zoom;
+	gdouble zoom = 1.0;
 
 	widget = GTK_WIDGET (image_object->object.format->html);
 	widget_width = widget->allocation.width - 12;
@@ -66,9 +171,7 @@ size_allocate_cb (GtkHTMLEmbedded *embedded,
 	pixbuf_width = gdk_pixbuf_get_width (image_object->pixbuf);
 	pixbuf_height = gdk_pixbuf_get_height (image_object->pixbuf);
 
-	if (pixbuf_width <= widget_width)
-		zoom = 1.0;
-	else
+	if (pixbuf_width > widget_width)
 		zoom = (gdouble) widget_width / pixbuf_width;
 
 	widget_width = MIN (widget_width, pixbuf_width);
@@ -85,6 +188,11 @@ org_gnome_image_inline_pobject_free (EMFormatHTMLPObject *object)
 
 	image_object = (ImageInlinePObject *) object;
 
+	if (image_object->mime_part != NULL) {
+		camel_object_unref (image_object->mime_part);
+		image_object->mime_part = NULL;
+	}
+
 	if (image_object->pixbuf != NULL) {
 		g_object_unref (image_object->pixbuf);
 		image_object->pixbuf = NULL;
@@ -97,20 +205,19 @@ org_gnome_image_inline_pobject_free (EMFormatHTMLPObject *object)
 }
 
 static void
-org_gnome_image_inline_decode (ImageInlinePObject *image_object,
-                               CamelMimePart *mime_part)
+org_gnome_image_inline_decode (ImageInlinePObject *image_object)
 {
 	GdkPixbuf *pixbuf;
 	GdkPixbufLoader *loader;
-	CamelContentType *content_type;
 	CamelDataWrapper *data_wrapper;
+	CamelMimePart *mime_part;
 	CamelMedium *medium;
 	CamelStream *stream;
 	GByteArray *array;
-	gchar *mime_type;
 	GError *error = NULL;
 
 	array = g_byte_array_new ();
+	mime_part = image_object->mime_part;
 	medium = CAMEL_MEDIUM (mime_part);
 
 	/* Stream takes ownership of the byte array. */
@@ -118,17 +225,10 @@ org_gnome_image_inline_decode (ImageInlinePObject *image_object,
 	data_wrapper = camel_medium_get_content_object (medium);
 	camel_data_wrapper_decode_to_stream (data_wrapper, stream);
 
-	content_type = camel_mime_part_get_content_type (mime_part);
-	mime_type = camel_content_type_simple (content_type);
-	loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, &error);
-	g_free (mime_type);
-
-	if (error != NULL) {
-		g_warning ("%s", error->message);
-		g_error_free (error);
-		goto exit;
-	}
-
+	/* Don't trust the content type in the MIME part.  It could
+	 * be lying or it could be "application/octet-stream".  Let
+	 * the GtkPixbufLoader figure it out. */
+	loader = gdk_pixbuf_loader_new ();
 	gdk_pixbuf_loader_write (loader, array->data, array->len, &error);
 
 	if (error != NULL) {
@@ -150,8 +250,8 @@ org_gnome_image_inline_decode (ImageInlinePObject *image_object,
 	}
 
 exit:
-	camel_object_unref (mime_part);
 	camel_object_unref (stream);
+	g_object_unref (loader);
 }
 
 static gboolean
@@ -172,17 +272,25 @@ org_gnome_image_inline_embed (EMFormatHTML *format,
 	container = GTK_WIDGET (embedded);
 
 	widget = gtk_image_view_new ();
-	image_view = GTK_IMAGE_VIEW (widget);
-	gtk_widget_show (widget);
-
-	widget = gtk_image_scroll_win_new (image_view);
 	gtk_container_add (GTK_CONTAINER (container), widget);
 	image_object->widget = g_object_ref (widget);
 	gtk_widget_show (widget);
 
+	image_view = GTK_IMAGE_VIEW (widget);
+
 	gtk_image_view_set_pixbuf (
 		image_view, image_object->pixbuf, TRUE);
 
+	set_drag_source (image_view);
+
+	g_signal_connect (
+		image_view, "button-press-event",
+		G_CALLBACK (button_press_press_cb), image_object);
+
+	g_signal_connect (
+		image_view, "drag-data-get",
+		G_CALLBACK (drag_data_get_cb), image_object);
+
 	g_signal_connect (
 		embedded, "size-allocate",
 		G_CALLBACK (size_allocate_cb), image_object);
@@ -208,9 +316,10 @@ org_gnome_image_inline_format (gpointer ep, EMFormatHookTarget *target)
 			org_gnome_image_inline_embed);
 
 	camel_object_ref (target->part);
+	image_object->mime_part = target->part;
 
 	image_object->object.free = org_gnome_image_inline_pobject_free;
-	org_gnome_image_inline_decode (image_object, target->part);
+	org_gnome_image_inline_decode (image_object);
 
 	camel_stream_printf (
 		target->stream, "<object classid=%s></object>", classid);



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