* src/widgets/modest-gtkhtml-msg-view.c:
authorJose Dapena Paz <jdapena@igalia.com>
Wed, 25 Jun 2008 10:53:39 +0000 (10:53 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Wed, 25 Jun 2008 10:53:39 +0000 (10:53 +0000)
        * Add implementation of external images fetching. We show a
          button for letting user accept external images when they're
          available.
        * Rework all the external images fetching code to use the
          new tinymail stream cache.
* src/widgets/modest-gtkhtml-mime-part-view.c:
        * Fix some issues in the way we created the streams to avoid
          some crashes.
        * Now images retrieval should happen in msg view window layer,
          not on msg or mime part view.
        * Implement new ModestMimePartView methods to know if we
          can view images. Also use the TnyMsg information to show if
          we can fetch external images.
* src/widgets/modest-msg-view.c:
        * New signal fetch-image to let upper layers handle retrieving
          images from external sources.
        * New methods set view images and get view images to set if
          the user can view external images.
* src/widgets/modest-mime-part-view.c:
        * New methods to get/set view images state, and to know if a
          message has external images.
* src/widgets/modest-tny-stream-gtkthml.[ch]:
        * Keep a reference to the GtkHTML to keep it alive while stream
          is alive.
* src/maemo/modest-msg-view-window.c:
        * Handle new ModestMsgView signal "fetch-image", using the new
          stream cache. Now all the image retrieval happens here, using
          that cache as backstore.
* src/maemo/modest-account-settings-dialog.c:
        * Fix leaks in sizegroups.
* src/modest-utils.[ch]:
        * Added a new method to get the cache id we'll use to store the
          images in image cache.
* src/modest-runtime.[ch]:
        * Added method to retrieve the images cache singleton.
* src/modest-singletons.[ch]:
        * Provide a image cache using the TnyFsStreamCache.

pmo-trunk-r4773

18 files changed:
src/maemo/modest-account-settings-dialog.c
src/maemo/modest-msg-view-window.c
src/modest-init.c
src/modest-runtime.c
src/modest-runtime.h
src/modest-singletons.c
src/modest-singletons.h
src/modest-utils.c
src/modest-utils.h
src/widgets/modest-gtkhtml-mime-part-view.c
src/widgets/modest-gtkhtml-mime-part-view.h
src/widgets/modest-gtkhtml-msg-view.c
src/widgets/modest-mime-part-view.c
src/widgets/modest-mime-part-view.h
src/widgets/modest-msg-view.c
src/widgets/modest-msg-view.h
src/widgets/modest-tny-stream-gtkhtml.c
src/widgets/modest-tny-stream-gtkhtml.h

index 67bec94..0fdc76b 100644 (file)
@@ -388,6 +388,8 @@ create_page_account_details (ModestAccountSettingsDialog *self)
        connect_for_modified (self, self->checkbox_leave_messages);
        gtk_box_pack_start (GTK_BOX (box), self->caption_leave_messages, FALSE, FALSE, MODEST_MARGIN_HALF);
        gtk_widget_show (self->caption_leave_messages);
+
+       g_object_unref (sizegroup);
        
        gtk_widget_show (GTK_WIDGET (box));
        
@@ -572,6 +574,8 @@ create_page_user_details (ModestAccountSettingsDialog *self)
        gtk_widget_show (self->button_signature);
        gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
        gtk_widget_show (caption);
+
+       g_object_unref (sizegroup);
                
        g_signal_connect (G_OBJECT (self->button_signature), "clicked",
                G_CALLBACK (on_button_signature), self);
@@ -683,6 +687,8 @@ static GtkWidget* create_page_incoming (ModestAccountSettingsDialog *self)
        gtk_widget_show (self->checkbox_incoming_auth);
        connect_for_modified (self, self->checkbox_incoming_auth);
        gtk_box_pack_start (GTK_BOX (box), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
+
+       g_object_unref (sizegroup);
        gtk_widget_show (caption);
        
        gtk_widget_show (GTK_WIDGET (box));
@@ -915,6 +921,8 @@ static GtkWidget* create_page_outgoing (ModestAccountSettingsDialog *self)
        /* Only enable the button when the checkbox is checked: */
        enable_widget_for_togglebutton (self->button_outgoing_smtp_servers, 
                GTK_TOGGLE_BUTTON (self->checkbox_outgoing_smtp_specific));
+
+       g_object_unref (sizegroup);
                
        g_signal_connect (G_OBJECT (self->button_outgoing_smtp_servers), "clicked",
                G_CALLBACK (on_button_outgoing_smtp_servers), self);
index 05ae61e..4cc78e0 100644 (file)
@@ -155,6 +155,11 @@ static gboolean msg_is_visible (TnyHeader *header, gboolean check_outbox);
 
 static void check_dimming_rules_after_change (ModestMsgViewWindow *window);
 
+static gboolean on_fetch_image (ModestMsgView *msgview,
+                               const gchar *uri,
+                               TnyStream *stream,
+                               ModestMsgViewWindow *window);
+
 /* list my signals */
 enum {
        MSG_CHANGED_SIGNAL,
@@ -823,6 +828,8 @@ modest_msg_view_window_construct (ModestMsgViewWindow *self,
                          G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
        g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
                          G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
+       g_signal_connect (G_OBJECT (priv->msg_view), "fetch_image",
+                         G_CALLBACK (on_fetch_image), obj);
 
        g_signal_connect (G_OBJECT (obj), "key-release-event",
                          G_CALLBACK (modest_msg_view_window_key_event),
@@ -2979,3 +2986,116 @@ static void on_move_focus (GtkWidget *widget,
        g_signal_stop_emission_by_name (G_OBJECT (widget), "move-focus");
 }
 
+static TnyStream *
+fetch_image_open_stream (TnyStreamCache *self, gint64 *expected_size, gchar *uri)
+{
+       GnomeVFSResult result;
+       GnomeVFSHandle *handle = NULL;
+       GnomeVFSFileInfo *info = NULL;
+       TnyStream *stream;
+
+       result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
+       if (result != GNOME_VFS_OK) {
+               *expected_size = 0;
+               return NULL;
+       }
+       
+       info = gnome_vfs_file_info_new ();
+       result = gnome_vfs_get_file_info_from_handle (handle, info, GNOME_VFS_FILE_INFO_DEFAULT);
+       if (result != GNOME_VFS_OK || ! (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
+               /* We put a "safe" default size for going to cache */
+               *expected_size = (300*1024);
+       } else {
+               *expected_size = info->size;
+       }
+       gnome_vfs_file_info_unref (info);
+
+       stream = tny_vfs_stream_new (handle);
+
+       return stream;
+
+}
+
+typedef struct {
+       gchar *uri;
+       gchar *cache_id;
+       TnyStream *output_stream;
+       GtkWidget *msg_view;
+} FetchImageData;
+
+gboolean
+on_fetch_image_idle_refresh_view (gpointer userdata)
+{
+
+       FetchImageData *fidata = (FetchImageData *) userdata;
+       g_message ("REFRESH VIEW");
+       if (GTK_WIDGET_DRAWABLE (fidata->msg_view)) {
+               g_message ("QUEUING DRAW");
+               gtk_widget_queue_draw (fidata->msg_view);
+       }
+       g_object_unref (fidata->msg_view);
+       g_slice_free (FetchImageData, fidata);
+       return FALSE;
+}
+
+static gpointer
+on_fetch_image_thread (gpointer userdata)
+{
+       FetchImageData *fidata = (FetchImageData *) userdata;
+       TnyStreamCache *cache;
+       TnyStream *cache_stream;
+
+       cache = modest_runtime_get_images_cache ();
+       cache_stream = tny_stream_cache_get_stream (cache, fidata->cache_id, (TnyStreamCacheOpenStreamFetcher) fetch_image_open_stream, (gpointer) fidata->uri);
+       g_free (fidata->cache_id);
+       g_free (fidata->uri);
+
+       if (cache_stream != NULL) {
+               tny_stream_write_to_stream (cache_stream, fidata->output_stream);
+               tny_stream_close (cache_stream);
+               g_object_unref (cache_stream);
+       }
+
+       tny_stream_close (fidata->output_stream);
+       g_object_unref (fidata->output_stream);
+
+
+       gdk_threads_enter ();
+       g_idle_add (on_fetch_image_idle_refresh_view, fidata);
+       gdk_threads_leave ();
+
+       return NULL;
+}
+
+static gboolean
+on_fetch_image (ModestMsgView *msgview,
+               const gchar *uri,
+               TnyStream *stream,
+               ModestMsgViewWindow *window)
+{
+       const gchar *current_account;
+       ModestMsgViewWindowPrivate *priv;
+       FetchImageData *fidata;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
+
+       current_account = modest_window_get_active_account (MODEST_WINDOW (window));
+
+       fidata = g_slice_new0 (FetchImageData);
+       fidata->msg_view = g_object_ref (msgview);
+       fidata->uri = g_strdup (uri);
+       fidata->cache_id = modest_images_cache_get_id (current_account, uri);
+       fidata->output_stream = g_object_ref (stream);
+
+       if (g_thread_create (on_fetch_image_thread, fidata, FALSE, NULL) == NULL) {
+               g_object_unref (fidata->output_stream);
+               g_free (fidata->cache_id);
+               g_free (fidata->uri);
+               g_object_unref (fidata->msg_view);
+               g_slice_free (FetchImageData, fidata);
+               tny_stream_close (stream);
+               return FALSE;
+       }
+
+       return TRUE;;
+}
index 8a3b868..7839b57 100644 (file)
@@ -306,7 +306,7 @@ modest_init_uninit (void)
        
        if (gnome_vfs_initialized()) /* apparently, this returns TRUE, even after a shutdown */
                gnome_vfs_shutdown ();
-               
+
        _is_initialized = FALSE;
        return TRUE;
 }
index 487f9a7..568fb46 100644 (file)
@@ -126,6 +126,13 @@ modest_runtime_get_account_mgr   (void)
        return modest_singletons_get_account_mgr (_singletons);
 }
 
+TnyStreamCache*
+modest_runtime_get_images_cache   (void)
+{
+       g_return_val_if_fail (_singletons, NULL);
+       return modest_singletons_get_images_cache (_singletons);
+}
+
 ModestEmailClipboard*
 modest_runtime_get_email_clipboard   (void)
 {
index 5726a3d..abd4cbf 100644 (file)
@@ -42,6 +42,7 @@
 #include <modest-signal-mgr.h>
 #include <tny-platform-factory.h>
 #include "widgets/modest-window-mgr.h"
+#include <tny-stream-cache.h>
 
 G_BEGIN_DECLS
 
@@ -122,6 +123,15 @@ ModestConf*         modest_runtime_get_conf   (void);
 ModestAccountMgr*         modest_runtime_get_account_mgr   (void);
 
 /**
+ * modest_runtime_get_images_cache:
+ * 
+ * get the images #TnyStreamCache singleton instance
+ * 
+ * Returns: the images #TnyStreamCache singleton. This should NOT be unref'd.
+ **/
+TnyStreamCache*         modest_runtime_get_images_cache   (void);
+
+/**
  * modest_runtime_get_email_clipboard:
  * 
  * get the #ModestEmailClipboard singleton instance
index 3084cbd..32ada6b 100644 (file)
@@ -30,6 +30,7 @@
 #include "modest-singletons.h"
 #include "modest-runtime.h"
 #include "modest-debug.h"
+#include <tny-fs-stream-cache.h>
 
 /* 'private'/'protected' functions */
 static void modest_singletons_class_init (ModestSingletonsClass *klass);
@@ -46,6 +47,7 @@ struct _ModestSingletonsPrivate {
        TnyPlatformFactory        *platform_fact;
        TnyDevice                 *device;
        ModestWindowMgr           *window_mgr;
+       TnyStreamCache            *images_cache;
 };
 #define MODEST_SINGLETONS_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                MODEST_TYPE_SINGLETONS, \
@@ -93,6 +95,7 @@ static void
 modest_singletons_init (ModestSingletons *obj)
 {
        ModestSingletonsPrivate *priv;
+       gchar *images_cache_path;
        priv = MODEST_SINGLETONS_GET_PRIVATE(obj);
 
        priv->conf            = NULL;
@@ -103,6 +106,7 @@ modest_singletons_init (ModestSingletons *obj)
        priv->platform_fact   = NULL;
        priv->device          = NULL;
        priv->window_mgr      = NULL;
+       priv->images_cache    = NULL;
        
        priv->conf           = modest_conf_new ();
        if (!priv->conf) {
@@ -151,6 +155,14 @@ modest_singletons_init (ModestSingletons *obj)
                g_printerr ("modest: cannot create modest window manager instance\n");
                return;
        }
+
+       images_cache_path = g_build_filename (g_get_home_dir (), MODEST_DIR, MODEST_IMAGES_CACHE_DIR, NULL);
+       priv->images_cache = tny_fs_stream_cache_new (images_cache_path, MODEST_IMAGES_CACHE_SIZE);
+       g_free (images_cache_path);
+       if (!priv->images_cache) {
+               g_printerr ("modest: cannot create images cache instance\n");
+               return;
+       }
 }
 
 static void
@@ -159,6 +171,12 @@ modest_singletons_finalize (GObject *obj)
        ModestSingletonsPrivate *priv;
                
        priv = MODEST_SINGLETONS_GET_PRIVATE(obj);
+
+       if (priv->images_cache) {
+               MODEST_DEBUG_VERIFY_OBJECT_LAST_REF (priv->images_cache, "");
+               g_object_unref (G_OBJECT (priv->images_cache));
+               priv->images_cache = NULL;
+       }
        
        if (priv->window_mgr) {
                MODEST_DEBUG_VERIFY_OBJECT_LAST_REF(priv->window_mgr,"");
@@ -301,3 +319,10 @@ modest_singletons_get_window_mgr (ModestSingletons *self)
        g_return_val_if_fail (self, NULL);
        return MODEST_SINGLETONS_GET_PRIVATE(self)->window_mgr;
 }
+
+TnyStreamCache* 
+modest_singletons_get_images_cache (ModestSingletons *self)
+{
+       g_return_val_if_fail (self, NULL);
+       return MODEST_SINGLETONS_GET_PRIVATE(self)->images_cache;
+}
index bc3c8a9..cfa6ca3 100644 (file)
@@ -40,6 +40,7 @@
 #include <modest-cache-mgr.h>
 #include <modest-tny-platform-factory.h>
 #include "widgets/modest-window-mgr.h"
+#include <tny-stream-cache.h>
 
 G_BEGIN_DECLS
 
@@ -187,6 +188,14 @@ ModestMailOperationQueue* modest_singletons_get_mail_operation_queue (ModestSing
  **/
 ModestWindowMgr*          modest_singletons_get_window_mgr           (ModestSingletons *self);
 
+/**
+ * modest_singletons_get_images_cache:
+ * @self: a #ModestSingletons
+ *
+ * Gets the #TnyStreamCache used to store the external images cache.
+ */
+TnyStreamCache*           modest_singletons_get_images_cache         (ModestSingletons *self);
+
 G_END_DECLS
 
 #endif /* __MODEST_SINGLETONS_H__ */
index c2a1e6e..d598b05 100644 (file)
@@ -719,3 +719,19 @@ modest_utils_run_sort_dialog (GtkWindow *parent_window,
        on_destroy_dialog (GTK_DIALOG(dialog));
 }
 
+
+gchar *
+modest_images_cache_get_id (const gchar *account, const gchar *uri)
+{
+       GnomeVFSURI *vfs_uri;
+       gchar *result;
+       vfs_uri = gnome_vfs_uri_new (uri);
+       if (vfs_uri == NULL)
+               return NULL;
+       result = g_strdup_printf ("%s__%x", account, gnome_vfs_uri_hash (vfs_uri));
+       gnome_vfs_uri_unref (vfs_uri);
+       return result;
+}
index 05f42a9..9934396 100644 (file)
@@ -160,4 +160,16 @@ gint modest_list_index (TnyList *list, GObject *object);
  */
 guint64 modest_folder_available_space (const gchar *maildir_path);
 
+/**
+ * modest_images_cache_get_id:
+ * @account: a #TnyAccount
+ * @uri: an uri string
+ *
+ * obtains the hash corresponding to an image external resource to be
+ * stored in image cache.
+ *
+ * Returns: a newly allocated string containing the hash key
+ */
+gchar *modest_images_cache_get_id (const gchar *account, const gchar *uri);
+
 #endif /*__MODEST_MAEMO_UTILS_H__*/
index 28031b9..22c60cd 100644 (file)
@@ -67,6 +67,12 @@ static TnyMimePart* modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartV
 /* ModestMimePartView implementation */
 static gboolean modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self);
 static gboolean modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self);
+static gboolean modest_gtkhtml_mime_part_view_get_view_images (ModestMimePartView *self);
+static gboolean modest_gtkhtml_mime_part_view_get_view_images_default (ModestMimePartView *self);
+static void     modest_gtkhtml_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images);
+static void     modest_gtkhtml_mime_part_view_set_view_images_default (ModestMimePartView *self, gboolean view_images);
+static gboolean modest_gtkhtml_mime_part_view_has_external_images (ModestMimePartView *self);
+static gboolean modest_gtkhtml_mime_part_view_has_external_images_default (ModestMimePartView *self);
 /* ModestZoomable implementation */
 static gdouble modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self);
 static void modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value);
@@ -94,6 +100,9 @@ static void          set_text_part   (ModestGtkhtmlMimePartView *self, TnyMimePa
 static void          set_empty_part  (ModestGtkhtmlMimePartView *self);
 static void          set_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
 static gboolean      is_empty   (ModestGtkhtmlMimePartView *self);
+static gboolean      get_view_images   (ModestGtkhtmlMimePartView *self);
+static void          set_view_images   (ModestGtkhtmlMimePartView *self, gboolean view_images);
+static gboolean      has_external_images   (ModestGtkhtmlMimePartView *self);
 static void          set_zoom   (ModestGtkhtmlMimePartView *self, gdouble zoom);
 static gdouble       get_zoom   (ModestGtkhtmlMimePartView *self);
 static gboolean      has_contents_receiver (gpointer engine, const gchar *data,
@@ -107,6 +116,8 @@ typedef struct _ModestGtkhtmlMimePartViewPrivate ModestGtkhtmlMimePartViewPrivat
 struct _ModestGtkhtmlMimePartViewPrivate {
        TnyMimePart *part;
        gdouble current_zoom;
+       gboolean view_images;
+       gboolean has_external_images;
 };
 
 #define MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
@@ -199,6 +210,9 @@ modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass)
        klass->set_part_func = modest_gtkhtml_mime_part_view_set_part_default;
        klass->clear_func = modest_gtkhtml_mime_part_view_clear_default;
        klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty_default;
+       klass->get_view_images_func = modest_gtkhtml_mime_part_view_get_view_images_default;
+       klass->set_view_images_func = modest_gtkhtml_mime_part_view_set_view_images_default;
+       klass->has_external_images_func = modest_gtkhtml_mime_part_view_has_external_images_default;
        klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom_default;
        klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom_default;
        klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus_default;
@@ -219,8 +233,8 @@ modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self)
        gtk_html_set_editable        (GTK_HTML(self), FALSE);
        gtk_html_allow_selection     (GTK_HTML(self), TRUE);
        gtk_html_set_caret_mode      (GTK_HTML(self), FALSE);
-       gtk_html_set_blocking        (GTK_HTML(self), FALSE);
-       gtk_html_set_images_blocking (GTK_HTML(self), FALSE);
+       gtk_html_set_blocking        (GTK_HTML(self), TRUE);
+       gtk_html_set_images_blocking (GTK_HTML(self), TRUE);
 
        g_signal_connect (G_OBJECT(self), "link_clicked",
                          G_CALLBACK(on_link_clicked), self);
@@ -231,6 +245,8 @@ modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self)
 
        priv->part = NULL;
        priv->current_zoom = 1.0;
+       priv->view_images = FALSE;
+       priv->has_external_images = FALSE;
 }
 
 static void
@@ -265,66 +281,8 @@ typedef struct {
        gpointer buffer;
        GtkHTML *html;
        GtkHTMLStream *stream;
-       gboolean html_finalized;
 } ImageFetcherInfo;
 
-static void
-html_finalized_notify (ImageFetcherInfo *ifinfo,
-                      GObject *destroyed)
-{
-       ifinfo->html_finalized = TRUE;
-}
-
-static void
-image_fetcher_close (GnomeVFSAsyncHandle *handle,
-                    GnomeVFSResult result,
-                    gpointer data)
-{
-}
-
-static void
-image_fetcher_read (GnomeVFSAsyncHandle *handle,
-                   GnomeVFSResult result,
-                   gpointer buffer,
-                   GnomeVFSFileSize bytes_requested,
-                   GnomeVFSFileSize bytes_read,
-                   ImageFetcherInfo *ifinfo)
-{
-
-       if (ifinfo->html_finalized || result != GNOME_VFS_OK) {
-               gnome_vfs_async_close (handle, (GnomeVFSAsyncCloseCallback) image_fetcher_close, (gpointer) NULL);
-               if (!ifinfo->html_finalized) {
-                       gtk_html_stream_close (ifinfo->stream, GTK_HTML_STREAM_OK);
-                       g_object_weak_unref ((GObject *) ifinfo->html, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
-               }
-               g_slice_free1 (128, ifinfo->buffer);
-               g_slice_free (ImageFetcherInfo, ifinfo);
-               return;
-       }
-       gtk_html_stream_write (ifinfo->stream, buffer, bytes_read);
-       gnome_vfs_async_read (handle, ifinfo->buffer, 128, 
-                             (GnomeVFSAsyncReadCallback)image_fetcher_read, ifinfo);
-       return;
-}
-
-static void
-image_fetcher_open (GnomeVFSAsyncHandle *handle,
-                   GnomeVFSResult result,
-                   ImageFetcherInfo *ifinfo)
-{
-       if (!ifinfo->html_finalized && result == GNOME_VFS_OK) {
-               ifinfo->buffer = g_slice_alloc (128);
-               gnome_vfs_async_read (handle, ifinfo->buffer, 128, 
-                                     (GnomeVFSAsyncReadCallback) image_fetcher_read, ifinfo);
-       } else {
-               if (!ifinfo->html_finalized) {
-                       gtk_html_stream_close (ifinfo->stream, GTK_HTML_STREAM_OK);
-                       g_object_weak_unref ((GObject *) ifinfo->html, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
-               }
-               g_slice_free (ImageFetcherInfo, ifinfo);
-       }
-}
-
 static gboolean
 on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, 
                  ModestGtkhtmlMimePartView *self)
@@ -333,26 +291,15 @@ on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
        TnyStream *tny_stream;
        g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
 
-       if (g_str_has_prefix (uri, "http:") &&
-           modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_FETCH_HTML_EXTERNAL_IMAGES, NULL)) {
-               GnomeVFSAsyncHandle *handle;
-               ImageFetcherInfo *ifinfo;
-
-               ifinfo = g_slice_new (ImageFetcherInfo);
-               ifinfo->html_finalized = FALSE;
-               ifinfo->html = (GtkHTML *) self;
-               ifinfo->buffer = NULL;
-               ifinfo->stream = stream;
-               g_object_weak_ref ((GObject *) self, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
-               gnome_vfs_async_open (&handle, uri, GNOME_VFS_OPEN_READ,
-                                     GNOME_VFS_PRIORITY_DEFAULT, 
-                                     (GnomeVFSAsyncOpenCallback) image_fetcher_open, ifinfo);
-               return FALSE;
+       if (g_str_has_prefix (uri, "http:")) {
+               ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+
+               if (!priv->view_images)
+                       priv->has_external_images = TRUE;
        }
-       
-       tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream));
+                       
+       tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream, GTK_HTML (widget)));
        g_signal_emit_by_name (MODEST_MIME_PART_VIEW (self), "fetch-url", uri, tny_stream, &result);
-       tny_stream_close (tny_stream);
        g_object_unref (tny_stream);
        return result;
 }
@@ -370,7 +317,7 @@ set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
        
        gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
 
-       tny_stream     = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
+       tny_stream     = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
        tny_stream_reset (tny_stream);
 
        tny_mime_part_decode_to_stream ((TnyMimePart*)part, tny_stream, NULL);
@@ -388,7 +335,7 @@ set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
        g_return_if_fail (part);
 
        gtkhtml_stream = gtk_html_begin(GTK_HTML(self)); 
-       tny_stream =  TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
+       tny_stream =  TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
        text_to_html_stream = TNY_STREAM (modest_stream_text_to_html_new (tny_stream));
        modest_stream_text_to_html_set_linkify_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 64*1024);
        modest_stream_text_to_html_set_full_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 640*1024);
@@ -421,6 +368,7 @@ set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
        g_return_if_fail (self);
        
        priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self);
+       priv->has_external_images = FALSE;
 
        if (part != priv->part) {
                if (priv->part)
@@ -482,6 +430,39 @@ is_empty   (ModestGtkhtmlMimePartView *self)
        return !has_contents;
 }
 
+static gboolean      
+get_view_images   (ModestGtkhtmlMimePartView *self)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
+
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+       return priv->view_images;
+}
+
+static void
+set_view_images   (ModestGtkhtmlMimePartView *self, gboolean view_images)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self));
+
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+       priv->view_images = view_images;
+}
+
+static gboolean      
+has_external_images   (ModestGtkhtmlMimePartView *self)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
+
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+       return priv->has_external_images;
+}
+
 static void
 set_zoom (ModestGtkhtmlMimePartView *self, gdouble zoom)
 {
@@ -602,6 +583,9 @@ modest_mime_part_view_init (gpointer g, gpointer iface_data)
        ModestMimePartViewIface *klass = (ModestMimePartViewIface *)g;
 
        klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty;
+       klass->get_view_images_func = modest_gtkhtml_mime_part_view_get_view_images;
+       klass->set_view_images_func = modest_gtkhtml_mime_part_view_set_view_images;
+       klass->has_external_images_func = modest_gtkhtml_mime_part_view_has_external_images;
 
        return;
 }
@@ -613,11 +597,47 @@ modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self)
 }
 
 static gboolean
+modest_gtkhtml_mime_part_view_get_view_images (ModestMimePartView *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_view_images_func (self);
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images)
+{
+       MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_view_images_func (self, view_images);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_has_external_images (ModestMimePartView *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->has_external_images_func (self);
+}
+
+static gboolean
 modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self)
 {
        return is_empty (MODEST_GTKHTML_MIME_PART_VIEW (self));
 }
 
+static gboolean
+modest_gtkhtml_mime_part_view_get_view_images_default (ModestMimePartView *self)
+{
+       return get_view_images (MODEST_GTKHTML_MIME_PART_VIEW (self));
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_view_images_default (ModestMimePartView *self, gboolean view_images)
+{
+       set_view_images (MODEST_GTKHTML_MIME_PART_VIEW (self), view_images);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_has_external_images_default (ModestMimePartView *self)
+{
+       return has_external_images (MODEST_GTKHTML_MIME_PART_VIEW (self));
+}
+
 
 /* MODEST ZOOMABLE IMPLEMENTATION */
 static void
index 510f071..8a134cf 100644 (file)
@@ -65,6 +65,9 @@ struct _ModestGtkhtmlMimePartViewClass {
        void (*clear_func) (TnyMimePartView *self);
        /* ModestMimePartView interface methods */
        gboolean (*is_empty_func) (ModestMimePartView *self);
+       gboolean (*get_view_images_func) (ModestMimePartView *self);
+       void (*set_view_images_func) (ModestMimePartView *self, gboolean view_images);
+       gboolean (*has_external_images_func) (ModestMimePartView *self);
        /* ModestZoomable interface methods */
        gdouble (*get_zoom_func) (ModestZoomable *self);
        void (*set_zoom_func) (ModestZoomable *self, gdouble value);
index 4532119..b752eb5 100644 (file)
@@ -36,6 +36,7 @@
 #include <glib/gi18n.h>
 #include <tny-list.h>
 #include <tny-simple-list.h>
+#include <tny-vfs-stream.h>
 
 #include <modest-tny-msg.h>
 #include <modest-text-utils.h>
@@ -70,6 +71,7 @@ static void     get_property (GObject *object, guint prop_id, GValue *value, GPa
 /* headers signals */
 static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestGtkhtmlMsgView *msg_view);
 static void on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer userdata);
+static void on_view_images_clicked (GtkButton * button, gpointer self);
 
 /* body view signals */
 static gboolean on_activate_link (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMsgView *msg_view);
@@ -213,6 +215,7 @@ struct _ModestGtkhtmlMsgViewPrivate {
        GtkWidget   *headers_box;
        GtkWidget   *html_scroll;
        GtkWidget   *attachments_box;
+       GtkWidget   *view_images_button;
 
        /* internal adjustments for set_scroll_adjustments */
        GtkAdjustment *hadj;
@@ -1040,8 +1043,9 @@ modest_gtkhtml_msg_view_init (ModestGtkhtmlMsgView *obj)
 
        priv->body_view                 = GTK_WIDGET (g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL));
        priv->mail_header_view        = GTK_WIDGET(modest_mail_header_view_new (TRUE));
+       priv->view_images_button = gtk_button_new_with_label (_("TODO: view images"));
        gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
-
+       gtk_widget_set_no_show_all (priv->view_images_button, TRUE);
        priv->attachments_view        = GTK_WIDGET(modest_attachments_view_new (NULL));
 
        g_signal_connect (G_OBJECT(priv->body_view), "activate_link",
@@ -1061,6 +1065,9 @@ modest_gtkhtml_msg_view_init (ModestGtkhtmlMsgView *obj)
        g_signal_connect (G_OBJECT (priv->attachments_view), "activate",
                          G_CALLBACK (on_attachment_activated), obj);
 
+       g_signal_connect (G_OBJECT (priv->view_images_button), "clicked",
+                         G_CALLBACK (on_view_images_clicked), obj);
+
        html_vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW(priv->html_scroll));
 
        g_signal_connect (G_OBJECT (html_vadj), "changed",
@@ -1073,6 +1080,10 @@ modest_gtkhtml_msg_view_init (ModestGtkhtmlMsgView *obj)
 
        if (priv->mail_header_view)
                gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0);
+       if (priv->view_images_button) {
+               gtk_box_pack_start (GTK_BOX (priv->headers_box), priv->view_images_button, FALSE, FALSE, 0);
+               gtk_widget_hide (priv->view_images_button);
+       }
        
        if (priv->attachments_view) {
                gchar *att_label = g_strconcat (_("mcen_me_viewer_attachments"), ":", NULL);
@@ -1318,6 +1329,22 @@ on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_par
        g_signal_emit_by_name (G_OBJECT(self), "attachment_clicked", mime_part);
 }
 
+static void
+on_view_images_clicked (GtkButton * button, gpointer self)
+{
+       ModestGtkhtmlMsgViewPrivate *priv = MODEST_GTKHTML_MSG_VIEW_GET_PRIVATE (self);
+       TnyMimePart *part;
+
+       modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), TRUE);
+       gtk_widget_hide (priv->view_images_button);
+       part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (priv->body_view));
+       tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (priv->body_view), part);
+       tny_msg_set_allow_external_images (TNY_MSG (priv->msg), TRUE);
+       g_object_unref (part);
+       
+
+}
+
 static gboolean
 on_activate_link (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMsgView *self)
 {
@@ -1426,8 +1453,12 @@ on_fetch_url (GtkWidget *widget, const gchar *uri,
        const gchar* my_uri;
        TnyMimePart *part = NULL;
        
+
+
        priv = MODEST_GTKHTML_MSG_VIEW_GET_PRIVATE (self);
 
+       if (modest_mime_part_view_has_external_images (MODEST_MIME_PART_VIEW (priv->body_view)))
+               gtk_widget_show (priv->view_images_button);
        /*
         * we search for either something starting with cid:, or something
         * with no prefix at all; this latter case occurs when sending mails
@@ -1440,12 +1471,42 @@ on_fetch_url (GtkWidget *widget, const gchar *uri,
        
        /* now try to find the embedded image */
        part = find_cid_image (priv->msg, my_uri);
+
        if (!part) {
-               g_printerr ("modest: %s: '%s' not found\n", __FUNCTION__, my_uri);
-               return FALSE;   
+               GtkIconTheme *current_theme;
+               GtkIconInfo *icon_info;
+
+               if (g_str_has_prefix (uri, "http:")) {
+                       if (modest_mime_part_view_get_view_images (MODEST_MIME_PART_VIEW (priv->body_view))) {
+                               gboolean result = FALSE;
+                               g_signal_emit_by_name (self, "fetch-image", uri, stream, &result);
+                               return result;
+                       } else {
+                               current_theme = gtk_icon_theme_get_default ();
+                               icon_info = gtk_icon_theme_lookup_icon (current_theme, "qgn_indi_messagin_nullcmas", 26,
+                                                                       GTK_ICON_LOOKUP_NO_SVG);
+                               if (icon_info != NULL) {
+                                       const gchar *filename;
+                                       TnyStream *vfs_stream;
+                                       GnomeVFSHandle *handle;
+                                       filename = gtk_icon_info_get_filename (icon_info);
+                                       gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ);
+                                       vfs_stream = tny_vfs_stream_new (handle);
+                                       while (tny_stream_write_to_stream (vfs_stream, stream) > 0);
+                                       tny_stream_close (vfs_stream);
+                                       g_object_unref (vfs_stream);
+                                       gtk_icon_info_free (icon_info);
+                               }
+                               tny_stream_close (stream);
+                               return TRUE;
+                       }
+               } else {
+                       return FALSE;
+               }
        }
 
        tny_mime_part_decode_to_stream ((TnyMimePart*)part, stream, NULL);
+       tny_stream_close (stream);
        g_object_unref (G_OBJECT(part));
        return TRUE;
 }
@@ -1462,6 +1523,7 @@ set_message (ModestGtkhtmlMsgView *self, TnyMsg *msg)
        
        priv = MODEST_GTKHTML_MSG_VIEW_GET_PRIVATE(self);
        gtk_widget_set_no_show_all (priv->mail_header_view, FALSE);
+       modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), FALSE);
 
        html_vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->html_scroll));
        html_vadj->upper = 0;
@@ -1495,6 +1557,8 @@ set_message (ModestGtkhtmlMsgView *self, TnyMsg *msg)
 
        modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW(priv->attachments_view),
                                             msg);
+
+       modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), tny_msg_get_allow_external_images (msg));
        
        body = modest_tny_msg_find_body_part (msg, TRUE);
        if (body) {
@@ -1509,6 +1573,13 @@ set_message (ModestGtkhtmlMsgView *self, TnyMsg *msg)
        } else 
                tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
 
+       if (modest_mime_part_view_has_external_images (MODEST_MIME_PART_VIEW (priv->body_view)) &&
+           !modest_mime_part_view_get_view_images (MODEST_MIME_PART_VIEW (priv->body_view))) {
+               gtk_widget_show (priv->view_images_button);
+       } else {
+               gtk_widget_hide (priv->view_images_button);
+       }
+
        gtk_widget_show (priv->body_view);
        gtk_widget_set_no_show_all (priv->attachments_box, TRUE);
        gtk_widget_show_all (priv->mail_header_view);
index a276c6a..692428a 100644 (file)
@@ -55,6 +55,47 @@ modest_mime_part_view_is_empty (ModestMimePartView *self)
        return MODEST_MIME_PART_VIEW_GET_IFACE (self)->is_empty_func (self);
 }
 
+/**
+ * modest_mime_part_view_get_view_images:
+ * @self: a #ModestMimePartView
+ *
+ * checks if we have enabled capability to view contained images.
+ *
+ * Returns: %TRUE if we show images, %FALSE otherwise.
+ */
+gboolean
+modest_mime_part_view_get_view_images (ModestMimePartView *self)
+{
+       return MODEST_MIME_PART_VIEW_GET_IFACE (self)->get_view_images_func (self);
+}
+
+/**
+ * modest_mime_part_view_set_view_images:
+ * @self: a #ModestMimePartView
+ * @view_images: a #gboolean
+ *
+ * set if we want to show images or not.
+ */
+void
+modest_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images)
+{
+       MODEST_MIME_PART_VIEW_GET_IFACE (self)->set_view_images_func (self, view_images);
+}
+
+/**
+ * modest_mime_part_view_has_external_images: 
+ * @self: a #ModestMimePartView
+ *
+ * checks if there are external images in the mime part.
+ *
+ * Returns: %TRUE if there are external images, %FALSE otherwise.
+ */
+gboolean
+modest_mime_part_view_has_external_images (ModestMimePartView *self)
+{
+       return MODEST_MIME_PART_VIEW_GET_IFACE (self)->has_external_images_func (self);
+}
+
 static void
 modest_mime_part_view_base_init (gpointer g_class)
 {
index b559861..95d7ea8 100644 (file)
@@ -55,11 +55,17 @@ struct _ModestMimePartViewIface
        
        /* virtuals */
        gboolean (*is_empty_func) (ModestMimePartView *self);
+       gboolean (*get_view_images_func) (ModestMimePartView *self);
+       void (*set_view_images_func) (ModestMimePartView *self, gboolean view_images);
+       gboolean (*has_external_images_func) (ModestMimePartView *self);
 };
 
 GType modest_mime_part_view_get_type (void);
 
 gboolean modest_mime_part_view_is_empty (ModestMimePartView *self);
+gboolean modest_mime_part_view_get_view_images (ModestMimePartView *self);
+void modest_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images);
+gboolean modest_mime_part_view_has_external_images (ModestMimePartView *self);
 
 G_END_DECLS
 
index cfb5b6d..d79ad62 100644 (file)
 
 #include <widgets/modest-msg-view.h>
 #include <widgets/modest-isearch-view.h>
+#include <modest-marshal.h>
 
 enum {
        ATTACHMENT_CLICKED_SIGNAL,
        RECPT_ACTIVATED_SIGNAL,
        LINK_CONTEXTUAL_SIGNAL,
+       FETCH_IMAGE_SIGNAL,
        LAST_SIGNAL
 };
 static guint signals[LAST_SIGNAL] = {0};
@@ -88,6 +90,12 @@ modest_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags)
        MODEST_MSG_VIEW_GET_IFACE (self)->set_priority_func (self, flags);
 }
 
+void
+modest_msg_view_set_view_images (ModestMsgView *self, gboolean view_images)
+{
+       MODEST_MSG_VIEW_GET_IFACE (self)->set_view_images_func (self, view_images);
+}
+
 TnyList*
 modest_msg_view_get_selected_attachments (ModestMsgView *self)
 {
@@ -146,6 +154,15 @@ modest_msg_view_base_init (gpointer g_class)
                                      g_cclosure_marshal_VOID__STRING,
                                      G_TYPE_NONE, 1, G_TYPE_STRING);
                
+               signals[FETCH_IMAGE_SIGNAL] =
+                       g_signal_new ("fetch_image",
+                                     MODEST_TYPE_MSG_VIEW,
+                                     G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST,
+                                     G_STRUCT_OFFSET(ModestMsgViewIface, fetch_image),
+                                     NULL, NULL,
+                                     modest_marshal_BOOLEAN__STRING_OBJECT,
+                                     G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_OBJECT);
+               
                initialized = TRUE;
        }
 }
index 241ac51..02d819a 100644 (file)
@@ -61,6 +61,7 @@ struct _ModestMsgViewIface {
        GtkShadowType (*get_shadow_type_func) (ModestMsgView *self);
        TnyHeaderFlags (*get_priority_func) (ModestMsgView *self);
        void (*set_priority_func) (ModestMsgView *self, TnyHeaderFlags flags);
+       void (*set_view_images_func) (ModestMsgView *self, gboolean view_images);
        TnyList * (*get_selected_attachments_func) (ModestMsgView *self);
        TnyList * (*get_attachments_func) (ModestMsgView *self);
        void (*grab_focus_func) (ModestMsgView *self);
@@ -77,6 +78,8 @@ struct _ModestMsgViewIface {
                                    gpointer user_data);
        void (*recpt_activated)    (ModestMsgView *msgview, const gchar *address,
                                    gpointer user_data);
+       gboolean (*fetch_image)    (ModestMsgView *msgview, const gchar *uri,
+                                   TnyStream *stream);
 };
 
 
@@ -104,6 +107,7 @@ TnyList *modest_msg_view_get_selected_attachments (ModestMsgView *self);
 TnyList *modest_msg_view_get_attachments (ModestMsgView *self);
 void modest_msg_view_grab_focus (ModestMsgView *self);
 void modest_msg_view_remove_attachment (ModestMsgView *view, TnyMimePart *attachment);
+void modest_msg_view_set_view_images (ModestMsgView *view, gboolean view_images);
 
 
 G_END_DECLS
index af05333..943a9e1 100644 (file)
@@ -52,6 +52,7 @@ enum {
 typedef struct _ModestTnyStreamGtkhtmlPrivate ModestTnyStreamGtkhtmlPrivate;
 struct _ModestTnyStreamGtkhtmlPrivate {
        GtkHTMLStream *stream;
+       GtkHTML *html;
 };
 #define MODEST_TNY_STREAM_GTKHTML_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                        MODEST_TYPE_TNY_STREAM_GTKHTML, \
@@ -116,6 +117,7 @@ modest_tny_stream_gtkhtml_init (ModestTnyStreamGtkhtml *obj)
        priv = MODEST_TNY_STREAM_GTKHTML_GET_PRIVATE(obj);
 
        priv->stream  = NULL;
+       priv->html = NULL;
 }
 
 static void
@@ -125,10 +127,14 @@ modest_tny_stream_gtkhtml_finalize (GObject *obj)
 
        priv = MODEST_TNY_STREAM_GTKHTML_GET_PRIVATE(obj);
        priv->stream = NULL;
+       if (priv->html) {
+               g_object_unref (priv->html);
+               priv->html = NULL;
+       }
 }
 
 GObject*
-modest_tny_stream_gtkhtml_new (GtkHTMLStream *stream)
+modest_tny_stream_gtkhtml_new (GtkHTMLStream *stream, GtkHTML *html)
 {
        GObject *obj;
        ModestTnyStreamGtkhtmlPrivate *priv;
@@ -139,6 +145,7 @@ modest_tny_stream_gtkhtml_new (GtkHTMLStream *stream)
        g_return_val_if_fail (stream, NULL);
        
        priv->stream = stream;
+       priv->html = g_object_ref (html);
 
        return obj;
 }
@@ -168,7 +175,10 @@ gtkhtml_write (TnyStream *self, const char *buffer, size_t n)
 
        if (n == 0 || !buffer)
                return 0;
-               
+
+       if (!GTK_WIDGET_VISIBLE (priv->html))
+               return -1;
+
        gtk_html_stream_write (priv->stream, buffer, n);
        return n; /* hmmm */
 }
@@ -188,8 +198,14 @@ gtkhtml_close (TnyStream *self)
        g_return_val_if_fail (self, 0);
        priv = MODEST_TNY_STREAM_GTKHTML_GET_PRIVATE(self);
        
-       gtk_html_stream_close   (priv->stream, GTK_HTML_STREAM_OK);
+       if (GTK_WIDGET_VISIBLE (priv->html)) {
+               gtk_html_stream_close   (priv->stream, GTK_HTML_STREAM_OK);
+       }
        priv->stream = NULL;
+       if (priv->html) {
+               g_object_unref (priv->html);
+               priv->html = NULL;
+       }
 
        return 0;
 }
index 42fd05a..7bc15a5 100644 (file)
@@ -69,7 +69,7 @@ GType       modest_tny_stream_gtkhtml_get_type    (void) G_GNUC_CONST;
  * 
  * Returns: a new #ModestTnyStreamGtkhtml
  **/
-GObject*    modest_tny_stream_gtkhtml_new         (GtkHTMLStream* stream);
+GObject*    modest_tny_stream_gtkhtml_new         (GtkHTMLStream* stream, GtkHTML *html);
 
 
 G_END_DECLS