diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2009-11-08 11:09:32 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2009-11-10 08:57:09 +0800 |
commit | 6db0e254190a80cf1cccb3629442b78e76c55b36 (patch) | |
tree | 7d3199173472fb0d4efc70f1ca6ecb56f75fccb4 | |
parent | 214f3a8038667a7bf75c379b91a8a687095d4d05 (diff) | |
download | gsoc2013-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.ac | 22 | ||||
-rw-r--r-- | mail/em-format-html-display.c | 2 | ||||
-rw-r--r-- | mail/em-format-html.c | 4 | ||||
-rw-r--r-- | plugins/image-inline/Makefile.am | 29 | ||||
-rw-r--r-- | plugins/image-inline/image-inline.c | 219 | ||||
-rw-r--r-- | plugins/image-inline/org-gnome-image-inline.eplug.xml | 125 |
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> |