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));
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);
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));
/* 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);
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,
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),
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;;
+}
if (gnome_vfs_initialized()) /* apparently, this returns TRUE, even after a shutdown */
gnome_vfs_shutdown ();
-
+
_is_initialized = FALSE;
return TRUE;
}
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)
{
#include <modest-signal-mgr.h>
#include <tny-platform-factory.h>
#include "widgets/modest-window-mgr.h"
+#include <tny-stream-cache.h>
G_BEGIN_DECLS
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
#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);
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, \
modest_singletons_init (ModestSingletons *obj)
{
ModestSingletonsPrivate *priv;
+ gchar *images_cache_path;
priv = MODEST_SINGLETONS_GET_PRIVATE(obj);
priv->conf = NULL;
priv->platform_fact = NULL;
priv->device = NULL;
priv->window_mgr = NULL;
+ priv->images_cache = NULL;
priv->conf = modest_conf_new ();
if (!priv->conf) {
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
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,"");
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;
+}
#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
**/
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__ */
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;
+}
*/
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__*/
/* 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);
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,
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), \
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;
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);
priv->part = NULL;
priv->current_zoom = 1.0;
+ priv->view_images = FALSE;
+ priv->has_external_images = FALSE;
}
static void
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)
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;
}
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);
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);
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)
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)
{
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;
}
}
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
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);
#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>
/* 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);
GtkWidget *headers_box;
GtkWidget *html_scroll;
GtkWidget *attachments_box;
+ GtkWidget *view_images_button;
/* internal adjustments for set_scroll_adjustments */
GtkAdjustment *hadj;
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",
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",
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);
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)
{
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
/* 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;
}
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;
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) {
} 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);
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)
{
/* 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
#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};
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)
{
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;
}
}
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);
gpointer user_data);
void (*recpt_activated) (ModestMsgView *msgview, const gchar *address,
gpointer user_data);
+ gboolean (*fetch_image) (ModestMsgView *msgview, const gchar *uri,
+ TnyStream *stream);
};
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
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, \
priv = MODEST_TNY_STREAM_GTKHTML_GET_PRIVATE(obj);
priv->stream = NULL;
+ priv->html = NULL;
}
static void
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;
g_return_val_if_fail (stream, NULL);
priv->stream = stream;
+ priv->html = g_object_ref (html);
return obj;
}
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 */
}
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;
}
*
* 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