Avoid redrawing many times on downloading images in message view
[modest] / src / widgets / modest-msg-view-window.c
index 38456ee..b6366cd 100644 (file)
@@ -78,6 +78,8 @@
 #ifdef MODEST_TOOLKIT_HILDON2
 #include <hildon/hildon.h>
 #endif
+#include <tny-camel-bs-mime-part.h>
+#include <tny-camel-bs-msg.h>
 
 #define MYDOCS_ENV "MYDOCSDIR"
 #define DOCS_FOLDER ".documents"
@@ -124,6 +126,7 @@ struct _ModestMsgViewWindowPrivate {
        gulong row_deleted_handler;
        gulong row_inserted_handler;
        gulong rows_reordered_handler;
+       gulong fetch_image_redraw_handler;
 
        guint purge_timeout;
        GtkWidget *remove_attachment_banner;
@@ -490,6 +493,7 @@ modest_msg_view_window_init (ModestMsgViewWindow *obj)
        priv->row_deleted_handler = 0;
        priv->row_inserted_handler = 0;
        priv->rows_reordered_handler = 0;
+       priv->fetch_image_redraw_handler = 0;
        priv->progress_hint = FALSE;
        priv->fetching_images = 0;
 
@@ -637,6 +641,11 @@ modest_msg_view_window_finalize (GObject *obj)
           call this function before */
        modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj));
 
+       if (priv->fetch_image_redraw_handler > 0) {
+               g_source_remove (priv->fetch_image_redraw_handler);
+               priv->fetch_image_redraw_handler = 0;
+       }
+
        if (priv->other_body != NULL) {
                g_object_unref (priv->other_body);
                priv->other_body = NULL;
@@ -1737,7 +1746,7 @@ modest_msg_view_window_key_event (GtkWidget *window,
 {
        GtkWidget *focus;
 
-       focus = gtk_window_get_focus (GTK_WINDOW (window));
+       focus = gtk_container_get_focus_child ((GtkContainer *) window);
 
        /* for the isearch toolbar case */
        if (focus && GTK_IS_ENTRY (focus)) {
@@ -2247,6 +2256,30 @@ view_msg_cb (ModestMailOperation *mail_op,
                return;
        }
 
+       if (msg && TNY_IS_CAMEL_BS_MSG (msg)) {
+               TnyMimePart *body;
+               body = modest_tny_msg_find_body_part (msg, TRUE);
+               
+               if (body && !tny_camel_bs_mime_part_is_fetched (TNY_CAMEL_BS_MIME_PART (body))) {
+                       /* We have body structure but not the body mime part. What we do
+                        * is restarting load of message */
+                       self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
+                       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+
+                       tny_header_unset_flag (TNY_HEADER (header), TNY_HEADER_FLAG_CACHED);
+
+                       modest_msg_view_window_reload (self);
+
+                       if (row_reference)
+                               gtk_tree_row_reference_free (row_reference);
+                       g_object_unref (body);
+                       return;
+               }
+
+               if (body)
+                       g_object_unref  (body);
+       }
+
        /* Get the window */ 
        self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
@@ -2737,6 +2770,24 @@ on_decode_to_stream_async_handler (TnyMimePart *mime_part,
        g_slice_free (DecodeAsyncHelper, helper);
 }
 
+static void
+view_attachment_connect_handler (gboolean canceled,
+                                GError *err,
+                                GtkWindow *parent_window,
+                                TnyAccount *account,
+                                TnyMimePart *part)
+{
+
+       if (canceled || err) {
+               g_object_unref (part);
+               return;
+       }
+
+       modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (parent_window),
+                                               part);
+       g_object_unref (part);
+}
+
 void
 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, 
                                        TnyMimePart *mime_part)
@@ -2786,6 +2837,28 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window,
        if (tny_mime_part_is_purged (mime_part))
                goto frees;
 
+       if (TNY_IS_CAMEL_BS_MIME_PART (mime_part) &&
+           !tny_camel_bs_mime_part_is_fetched (TNY_CAMEL_BS_MIME_PART (mime_part))) {
+               gboolean is_merge;
+               TnyAccount *account;
+
+               is_merge = g_str_has_prefix (priv->msg_uid, "merge:");
+               account = NULL;
+               /* Get the account */
+               if (!is_merge)
+                       account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
+                                                                 priv->msg_uid);
+
+               if (!tny_device_is_online (modest_runtime_get_device())) {
+                       modest_platform_connect_and_perform (GTK_WINDOW (window),
+                                                            TRUE,
+                                                            TNY_ACCOUNT (account),
+                                                            (ModestConnectedPerformer) view_attachment_connect_handler,
+                                                            g_object_ref (mime_part));
+                       goto frees;
+               }
+       }
+
        if (!modest_tny_mime_part_is_msg (mime_part) && tny_mime_part_get_filename (mime_part)) {
                gchar *filepath = NULL;
                const gchar *att_filename = tny_mime_part_get_filename (mime_part);
@@ -2976,7 +3049,9 @@ idle_save_mime_part_show_result (SaveMimePartInfo *info)
         * modest_platform_system_banner is or does Gtk+ code */
 
        gdk_threads_enter (); /* CHECKED */
-       if (info->result == GNOME_VFS_OK) {
+       if (info->result == GNOME_VFS_ERROR_CANCELLED) {
+               /* nothing */
+       } else if (info->result == GNOME_VFS_OK) {
                modest_platform_system_banner (NULL, NULL, _CS_SAVED);
        } else if (info->result == GNOME_VFS_ERROR_NO_SPACE) {
                gchar *msg = NULL;
@@ -2997,6 +3072,48 @@ idle_save_mime_part_show_result (SaveMimePartInfo *info)
        return FALSE;
 }
 
+static void
+save_mime_part_to_file_connect_handler (gboolean canceled,
+                                       GError *err,
+                                       GtkWindow *parent_window,
+                                       TnyAccount *account,
+                                       SaveMimePartInfo *info)
+{
+       if (canceled || err) {
+               if (canceled && !err) {
+                       info->result = GNOME_VFS_ERROR_CANCELLED;
+               }
+               g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
+       } else {
+               g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
+       }
+}
+
+static gboolean
+save_mime_part_to_file_connect_idle (SaveMimePartInfo *info)
+{
+       gboolean is_merge;
+       TnyAccount *account;
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (info->window);
+
+       is_merge = g_str_has_prefix (priv->msg_uid, "merge:");
+       account = NULL;
+
+       /* Get the account */
+       if (!is_merge)
+               account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
+                                                         priv->msg_uid);
+
+       modest_platform_connect_and_perform (GTK_WINDOW (info->window),
+                                            TRUE,
+                                            TNY_ACCOUNT (account),
+                                            (ModestConnectedPerformer) save_mime_part_to_file_connect_handler,
+                                            info);
+       return FALSE;
+}
+
 static gpointer
 save_mime_part_to_file (SaveMimePartInfo *info)
 {
@@ -3004,6 +3121,12 @@ save_mime_part_to_file (SaveMimePartInfo *info)
        TnyStream *stream;
        SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
 
+       if (TNY_IS_CAMEL_BS_MIME_PART (pair->part) &&
+           !tny_camel_bs_mime_part_is_fetched (TNY_CAMEL_BS_MIME_PART (pair->part))) {
+               g_idle_add ((GSourceFunc) save_mime_part_to_file_connect_idle, info);
+               return NULL;
+       }
+
        info->result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0644);
        if (info->result == GNOME_VFS_OK) {
                GError *error = NULL;
@@ -3091,14 +3214,14 @@ save_mime_parts_to_file_with_checks (GtkWindow *parent,
 
                        escaped_basename = g_uri_unescape_string (basename, NULL);
                        message = g_strdup_printf ("%s\n%s",
-                                                  _FM("docm_nc_replace_file"),
+                                                  _FM_REPLACE_FILE,
                                                   (escaped_basename) ? escaped_basename : "");
                        response = modest_platform_run_confirmation_dialog (parent, message);
                        g_free (message);
                        g_free (escaped_basename);
                } else {
                        response = modest_platform_run_confirmation_dialog (parent,
-                                                                           _FM("docm_nc_replace_multiple"));
+                                                                           _FM_REPLACE_MULTIPLE);
                }
                if (response != GTK_RESPONSE_OK)
                        is_ok = FALSE;
@@ -3153,10 +3276,10 @@ save_attachments_response (GtkDialog *dialog,
                if (modest_maemo_utils_in_usb_mode ()) {
                        err_msg = dgettext ("hildon-status-bar-usb", "usbh_ib_mmc_usb_connected");
                } else {
-                       err_msg = _FM("sfil_ib_readonly_location");
+                       err_msg = _FM_READ_ONLY_LOCATION;
                }
 #else
-               err_msg = _FM("sfil_ib_readonly_location");
+               err_msg = _FM_READ_ONLY_LOCATION;
 #endif
                modest_platform_system_banner (NULL, NULL, err_msg);
        } else {
@@ -3222,10 +3345,11 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window,
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        if (mime_parts == NULL) {
+               GtkWindow *toplevel = (GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *) window);
                /* In Hildon 2.2 save and delete operate over all the attachments as there's no
                 * selection available */
                mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
-               if (mime_parts && !modest_toolkit_utils_select_attachments (GTK_WINDOW (window), mime_parts, FALSE)) {
+               if (mime_parts && !modest_toolkit_utils_select_attachments (toplevel, mime_parts, FALSE)) {
                        g_object_unref (mime_parts);
                        return;
                }
@@ -3307,7 +3431,7 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window,
        /* if multiple, set multiple string */
        if (save_multiple_str) {
                g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
-               gtk_window_set_title (GTK_WINDOW (save_dialog), _FM("sfil_ti_save_objects_files"));
+               gtk_window_set_title (GTK_WINDOW (save_dialog), _FM_SAVE_OBJECT_FILES);
                g_free (save_multiple_str);
        }
 
@@ -3544,6 +3668,21 @@ typedef struct {
 } FetchImageData;
 
 gboolean
+on_fetch_image_timeout_refresh_view (gpointer userdata)
+{
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (userdata);
+       update_progress_hint (MODEST_MSG_VIEW_WINDOW (userdata));
+       if (GTK_WIDGET_DRAWABLE (priv->msg_view)) {
+               gtk_widget_queue_draw (GTK_WIDGET (priv->msg_view));
+       }
+       priv->fetch_image_redraw_handler = 0;
+       g_object_unref (userdata);
+       return FALSE;
+}
+
+gboolean
 on_fetch_image_idle_refresh_view (gpointer userdata)
 {
 
@@ -3555,8 +3694,10 @@ on_fetch_image_idle_refresh_view (gpointer userdata)
 
                priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (fidata->window);
                priv->fetching_images--;
-               gtk_widget_queue_draw (fidata->msg_view);
-               update_progress_hint (MODEST_MSG_VIEW_WINDOW (fidata->window));
+               if (priv->fetch_image_redraw_handler == 0) {
+                       priv->fetch_image_redraw_handler = g_timeout_add (500, on_fetch_image_timeout_refresh_view, g_object_ref (fidata->window));
+               }
+
        }
        gdk_threads_leave ();