aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-11-08 11:09:32 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-11-10 08:57:09 +0800
commit6db0e254190a80cf1cccb3629442b78e76c55b36 (patch)
tree7d3199173472fb0d4efc70f1ca6ecb56f75fccb4
parent214f3a8038667a7bf75c379b91a8a687095d4d05 (diff)
downloadgsoc2013-evolution-6db0e254190a80cf1cccb3629442b78e76c55b36.tar.gz
gsoc2013-evolution-6db0e254190a80cf1cccb3629442b78e76c55b36.tar.zst
gsoc2013-evolution-6db0e254190a80cf1cccb3629442b78e76c55b36.zip
Prototype an inline image plugin.
Uses GtkImageView to display the image.
-rw-r--r--configure.ac22
-rw-r--r--mail/em-format-html-display.c2
-rw-r--r--mail/em-format-html.c4
-rw-r--r--plugins/image-inline/Makefile.am29
-rw-r--r--plugins/image-inline/image-inline.c219
-rw-r--r--plugins/image-inline/org-gnome-image-inline.eplug.xml125
6 files changed, 401 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 731928106c..7115f98983 100644
--- a/configure.ac
+++ b/configure.ac
@@ -62,6 +62,7 @@ m4_define([hal_minimum_version], [0.5.4])
m4_define([libnotify_minimum_version], [0.3.0])
m4_define([gnome_pilot_minimum_version], [2.0.15])
m4_define([gweather_minimum_version], [2.25.3])
+m4_define([gtkimageview_minimum_version], [1.6])
dnl ******************************
dnl Compiler Warning Flags
@@ -1542,6 +1543,26 @@ if test "x$enable_weather" = "xyes"; then
fi
fi
+dnl *****************************************
+dnl image-inline plugin requires gtkimageview
+dnl *****************************************
+AC_ARG_ENABLE([image-inline],
+ [AS_HELP_STRING([--enable-image-inline],
+ [Enable image-inline plugin @<:@default=yes@:>@])],
+ [enable_image_inline="$enableval"], [enable_image_inline=yes])
+
+if test "x$enable_image_inline" = "xyes"; then
+ PKG_CHECK_MODULES(GTKIMAGEVIEW, gtkimageview >= gtkimageview_minimum_version, have_imageview=yes, have_imageview=no)
+ AC_SUBST(GTKIMAGEVIEW_CFLAGS)
+ AC_SUBST(GTKIMAGEVIEW_LIBS)
+
+ if test "x$have_imageview" = "xyes"; then
+ plugins_standard="$plugins_standard image-inline"
+ else
+ AC_MSG_ERROR([gtkimageview is required for the image-inline plugin. Use --disable-image-inline to exclude the plugin.])
+ fi
+fi
+
dnl *********************************
dnl pst-import plugin requires libpst
dnl *********************************
@@ -1762,6 +1783,7 @@ plugins/face/Makefile
plugins/google-account-setup/Makefile
plugins/groupwise-features/Makefile
plugins/hula-account-setup/Makefile
+plugins/image-inline/Makefile
plugins/imap-features/Makefile
plugins/itip-formatter/Makefile
plugins/mail-notification/Makefile
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 6a2f56525c..de64e2b15c 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -699,6 +699,7 @@ efhd_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormat
/* ********************************************************************** */
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 },
@@ -721,6 +722,7 @@ static EMFormatHandler type_builtin_table[] = {
{ (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 }
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 47213dc5d5..29bb47653f 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -2105,6 +2105,7 @@ 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 },
@@ -2120,6 +2121,7 @@ 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 },
@@ -2133,8 +2135,10 @@ 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
new file mode 100644
index 0000000000..5ff7c260eb
--- /dev/null
+++ b/plugins/image-inline/Makefile.am
@@ -0,0 +1,29 @@
+@EVO_PLUGIN_RULE@
+
+plugin_DATA = org-gnome-image-inline.eplug
+
+plugin_LTLIBRARIES = liborg-gnome-image-inline.la
+
+liborg_gnome_image_inline_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ $(GNOME_PLATFORM_CFLAGS) \
+ $(EVOLUTION_MAIL_CFLAGS) \
+ $(GTKIMAGEVIEW_CFLAGS)
+
+liborg_gnome_image_inline_la_SOURCES = image-inline.c
+
+liborg_gnome_image_inline_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
+
+liborg_gnome_image_inline_la_LIBADD = \
+ $(top_builddir)/mail/libevolution-mail.la \
+ $(GTKIMAGEVIEW_LIBS) \
+ $(EVOLUTION_MAIL_LIBS) \
+ $(GNOME_PLATFORM_LIBS)
+
+EXTRA_DIST = org-gnome-image-inline.eplug.xml
+
+BUILT_SOURCES = $(plugin_DATA)
+CLEANFILES = $(BUILT_SOURCES)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/image-inline/image-inline.c b/plugins/image-inline/image-inline.c
new file mode 100644
index 0000000000..81e5d92c5e
--- /dev/null
+++ b/plugins/image-inline/image-inline.c
@@ -0,0 +1,219 @@
+/*
+ * image-inline.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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <camel/camel-medium.h>
+#include <camel/camel-mime-part.h>
+#include <camel/camel-stream-mem.h>
+#include <gtkhtml/gtkhtml-embedded.h>
+#include <gtkimageview/gtkimagescrollwin.h>
+
+#include "mail/em-format-hook.h"
+#include "mail/em-format-html.h"
+
+static gint org_gnome_image_inline_classid;
+
+/* Forward Declarations */
+void org_gnome_image_inline_format (gpointer ep, EMFormatHookTarget *target);
+
+typedef struct _ImageInlinePObject ImageInlinePObject;
+
+struct _ImageInlinePObject {
+ EMFormatHTMLPObject object;
+
+ GdkPixbuf *pixbuf;
+ GtkWidget *widget;
+};
+
+static void
+size_allocate_cb (GtkHTMLEmbedded *embedded,
+ GtkAllocation *event,
+ ImageInlinePObject *image_object)
+{
+ GtkWidget *widget;
+ gint pixbuf_width;
+ gint pixbuf_height;
+ gint widget_width;
+ gint widget_height;
+ gdouble zoom;
+
+ widget = GTK_WIDGET (image_object->object.format->html);
+ widget_width = widget->allocation.width - 12;
+
+ 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
+ zoom = (gdouble) widget_width / pixbuf_width;
+
+ widget_width = MIN (widget_width, pixbuf_width);
+ widget_height = (gint) (zoom * pixbuf_height);
+
+ gtk_widget_set_size_request (
+ image_object->widget, widget_width, widget_height);
+}
+
+static void
+org_gnome_image_inline_pobject_free (EMFormatHTMLPObject *object)
+{
+ ImageInlinePObject *image_object;
+
+ image_object = (ImageInlinePObject *) object;
+
+ if (image_object->pixbuf != NULL) {
+ g_object_unref (image_object->pixbuf);
+ image_object->pixbuf = NULL;
+ }
+
+ if (image_object->widget != NULL) {
+ g_object_unref (image_object->widget);
+ image_object->widget = NULL;
+ }
+}
+
+static void
+org_gnome_image_inline_decode (ImageInlinePObject *image_object,
+ CamelMimePart *mime_part)
+{
+ GdkPixbuf *pixbuf;
+ GdkPixbufLoader *loader;
+ CamelContentType *content_type;
+ CamelDataWrapper *data_wrapper;
+ CamelMedium *medium;
+ CamelStream *stream;
+ GByteArray *array;
+ gchar *mime_type;
+ GError *error = NULL;
+
+ array = g_byte_array_new ();
+ medium = CAMEL_MEDIUM (mime_part);
+
+ /* Stream takes ownership of the byte array. */
+ stream = camel_stream_mem_new_with_byte_array (array);
+ 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;
+ }
+
+ gdk_pixbuf_loader_write (loader, array->data, array->len, &error);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ goto exit;
+ }
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ if (pixbuf != NULL)
+ image_object->pixbuf = g_object_ref (pixbuf);
+
+ gdk_pixbuf_loader_close (loader, &error);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ goto exit;
+ }
+
+exit:
+ camel_object_unref (mime_part);
+ camel_object_unref (stream);
+}
+
+static gboolean
+org_gnome_image_inline_embed (EMFormatHTML *format,
+ GtkHTMLEmbedded *embedded,
+ EMFormatHTMLPObject *object)
+{
+ ImageInlinePObject *image_object;
+ GtkImageView *image_view;
+ GtkWidget *container;
+ GtkWidget *widget;
+
+ image_object = (ImageInlinePObject *) object;
+
+ if (image_object->pixbuf == NULL)
+ return FALSE;
+
+ 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);
+
+ gtk_image_view_set_pixbuf (
+ image_view, image_object->pixbuf, TRUE);
+
+ g_signal_connect (
+ embedded, "size-allocate",
+ G_CALLBACK (size_allocate_cb), image_object);
+
+ return TRUE;
+}
+
+void
+org_gnome_image_inline_format (gpointer ep, EMFormatHookTarget *target)
+{
+ ImageInlinePObject *image_object;
+ gchar *classid;
+
+ classid = g_strdup_printf (
+ "org-gnome-image-inline-display-%d",
+ org_gnome_image_inline_classid++);
+
+ image_object = (ImageInlinePObject *)
+ em_format_html_add_pobject (
+ EM_FORMAT_HTML (target->format),
+ sizeof (ImageInlinePObject),
+ classid, target->part,
+ org_gnome_image_inline_embed);
+
+ camel_object_ref (target->part);
+
+ image_object->object.free = org_gnome_image_inline_pobject_free;
+ org_gnome_image_inline_decode (image_object, target->part);
+
+ camel_stream_printf (
+ target->stream, "<object classid=%s></object>", classid);
+
+ g_free (classid);
+}
diff --git a/plugins/image-inline/org-gnome-image-inline.eplug.xml b/plugins/image-inline/org-gnome-image-inline.eplug.xml
new file mode 100644
index 0000000000..581d43b46c
--- /dev/null
+++ b/plugins/image-inline/org-gnome-image-inline.eplug.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+ <e-plugin
+ type="shlib"
+ id="org.gnome.evolution.plugin.imageInline"
+ location="@PLUGINDIR@/liborg-gnome-image-inline@SOEXT@"
+ _name="Inline Image">
+
+ <author name="Matthew Barnes" email="mbarnes@redhat.com"/>
+ <_description>
+ View image attachments directly in mail messages.
+ </_description>
+
+ <!-- Everything GdkPixbuf can handle, we can handle. -->
+
+ <hook class="org.gnome.evolution.mail.format:1.0">
+ <group id="EMFormatHTMLDisplay">
+
+ <!-- Standard Types -->
+
+ <item
+ mime_type="image/bmp"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/gif"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/jp2"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/jpeg"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/jpeg2000"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/jpx"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/png"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/svg"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/tiff"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/vnd.wap.wbmp"
+ format="org_gnome_image_inline_format"/>
+
+ <!-- Experimental Types -->
+
+ <item
+ mime_type="image/x-bmp"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-cmu-raster"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-emf"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-ico"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-icon"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-icns"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-MS-bmp"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-mgx-emf"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-pcx"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-portable-anymap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-portable-bitmap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-portable-graymap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-portable-pixmap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-sun-raster"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-tga"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-win-bitmap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-wmf"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-xbitmap"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/x-xpixmap"
+ format="org_gnome_image_inline_format"/>
+
+ <!-- Bogus Types (seen in the wild) -->
+
+ <item
+ mime_type="image/jpg"
+ format="org_gnome_image_inline_format"/>
+ <item
+ mime_type="image/pjpeg"
+ format="org_gnome_image_inline_format"/>
+
+ </group>
+ </hook>
+
+ </e-plugin>
+</e-plugin-list>