* src/maemo/modest-msg-view-window.c:
[modest] / src / maemo / modest-msg-view-window.c
index 5159c34..3018a45 100644 (file)
@@ -39,7 +39,6 @@
 #include <modest-maemo-utils.h>
 #include <modest-tny-msg.h>
 #include <modest-msg-view-window.h>
-#include <modest-attachments-view.h>
 #include <modest-main-window-ui.h>
 #include "modest-msg-view-window-ui-dimming.h"
 #include <modest-widget-memory.h>
@@ -48,7 +47,7 @@
 #include <modest-tny-folder.h>
 #include <modest-text-utils.h>
 #include <modest-account-mgr-helpers.h>
-#include "modest-progress-bar-widget.h"
+#include "modest-progress-bar.h"
 #include "modest-defs.h"
 #include "modest-hildon-includes.h"
 #include "modest-ui-dimming-manager.h"
 #include <modest-tny-account.h>
 #include <modest-mime-part-view.h>
 #include <modest-isearch-view.h>
+#include <modest-tny-mime-part.h>
 #include <math.h>
 #include <errno.h>
 #include <glib/gstdio.h>
+#include <modest-debug.h>
 
 #define DEFAULT_FOLDER "MyDocs/.documents"
 
@@ -94,34 +95,30 @@ static void modest_msg_view_window_show_toolbar   (ModestWindow *window,
 static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
                                                           GdkEvent *event,
                                                           ModestMsgViewWindow *window);
-void modest_msg_view_window_on_row_changed(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               GtkTreeIter *arg2,
-               ModestMsgViewWindow *window);
-
-void modest_msg_view_window_on_row_deleted(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               ModestMsgViewWindow *window);
-
-void modest_msg_view_window_on_row_inserted(
-               GtkTreeModel *header_model,
-               GtkTreePath *tree_path,
-               GtkTreeIter *tree_iter,
-               ModestMsgViewWindow *window);
-
-void modest_msg_view_window_on_row_reordered(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               GtkTreeIter *arg2,
-               gpointer arg3,
-               ModestMsgViewWindow *window);
-
-void modest_msg_view_window_update_model_replaced(
-               ModestHeaderViewObserver *window,
-               GtkTreeModel *model,
-               const gchar *tny_folder_id);
+
+static void modest_msg_view_window_on_row_changed (GtkTreeModel *header_model,
+                                                  GtkTreePath *arg1,
+                                                  GtkTreeIter *arg2,
+                                                  ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_deleted (GtkTreeModel *header_model,
+                                                  GtkTreePath *arg1,
+                                                  ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_inserted (GtkTreeModel *header_model,
+                                                   GtkTreePath *tree_path,
+                                                   GtkTreeIter *tree_iter,
+                                                   ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_on_row_reordered (GtkTreeModel *header_model,
+                                                    GtkTreePath *arg1,
+                                                    GtkTreeIter *arg2,
+                                                    gpointer arg3,
+                                                    ModestMsgViewWindow *window);
+
+static void modest_msg_view_window_update_model_replaced (ModestHeaderViewObserver *window,
+                                                         GtkTreeModel *model,
+                                                         const gchar *tny_folder_id);
 
 static void cancel_progressbar  (GtkToolButton *toolbutton,
                                 ModestMsgViewWindow *self);
@@ -156,6 +153,7 @@ static void init_window (ModestMsgViewWindow *obj);
 
 static gboolean msg_is_visible (TnyHeader *header, gboolean check_outbox);
 
+static void check_dimming_rules_after_change (ModestMsgViewWindow *window);
 
 /* list my signals */
 enum {
@@ -424,19 +422,9 @@ modest_msg_view_window_init (ModestMsgViewWindow *obj)
        init_window (MODEST_MSG_VIEW_WINDOW(obj));
        
        /* Set window icon */
-       window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON); 
+       window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON, MODEST_ICON_SIZE_BIG); 
        if (window_icon) {
-               /* scale the icon, because it won't be shown unless it's
-                * 64 x 54 -- hildon quirk. this looks a bit ugly now,
-                * so waiting for correctly sized icons, then this scaling
-                * code can disappear -- djcb
-                */
-               GdkPixbuf *scaled =
-                       gdk_pixbuf_scale_simple (window_icon, 64, 54, GDK_INTERP_BILINEAR);
-               if (scaled) {
-                       gtk_window_set_icon (GTK_WINDOW (obj), scaled);
-                       g_object_unref (scaled);
-               }
+               gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
                g_object_unref (window_icon);
        }       
        
@@ -544,26 +532,13 @@ set_toolbar_mode (ModestMsgViewWindow *self,
 }
 
 
-static GtkWidget *
-menubar_to_menu (GtkUIManager *ui_manager)
-{
-       GtkWidget *main_menu;
-
-       /* Get the menubar from the UI manager */
-       main_menu = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
-
-       return main_menu;
-}
-
 static void
 init_window (ModestMsgViewWindow *obj)
 {
        GtkWidget *main_vbox;
        ModestMsgViewWindowPrivate *priv;
-       ModestWindowPrivate *parent_priv;
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
-       parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
 
        priv->msg_view = GTK_WIDGET (tny_platform_factory_new_msg_view (modest_tny_platform_factory_get_instance ()));
        modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
@@ -712,7 +687,8 @@ select_next_valid_row (GtkTreeModel *model,
                       gboolean cycle)
 {
        GtkTreeIter tmp_iter;
-       GtkTreePath *path, *next;
+       GtkTreePath *path;
+       GtkTreePath *next = NULL;
        gboolean retval = FALSE;
 
        g_return_val_if_fail (gtk_tree_row_reference_valid (*row_reference), FALSE);
@@ -738,6 +714,8 @@ select_next_valid_row (GtkTreeModel *model,
 
        /* Free */
        gtk_tree_path_free (path);
+       if (next)
+               gtk_tree_path_free (next);
 
        return retval;
 }
@@ -745,8 +723,8 @@ select_next_valid_row (GtkTreeModel *model,
 /* TODO: This should be in _init(), with the parameters as properties. */
 static void
 modest_msg_view_window_construct (ModestMsgViewWindow *self, 
-                           const gchar *modest_account_name,
-                           const gchar *msg_uid)
+                                 const gchar *modest_account_name,
+                                 const gchar *msg_uid)
 {
        GObject *obj = NULL;
        ModestMsgViewWindowPrivate *priv = NULL;
@@ -762,14 +740,14 @@ modest_msg_view_window_construct (ModestMsgViewWindow *self,
        priv->msg_uid = g_strdup (msg_uid);
 
        /* Menubar */
-       parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
+       parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
        hildon_window_set_menu    (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
        gtk_widget_show (parent_priv->menubar);
        parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
 
-       menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
-       toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
-       clipboard_rules_group = modest_dimming_rules_group_new ("ModestClipboardDimmingRules", FALSE);
+       menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
+       toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
+       clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
 
        /* Add common dimming rules */
        modest_dimming_rules_group_add_rules (menu_rules_group, 
@@ -847,9 +825,6 @@ modest_msg_view_window_construct (ModestMsgViewWindow *self,
 
        update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
 
-       /* Check toolbar dimming rules */
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
-       modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), "ModestClipboardDimmingRules");
 
 }
 
@@ -868,6 +843,10 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg,
        ModestWindow *main_window = NULL;
        ModestWindowMgr *mgr = NULL;
 
+       MODEST_DEBUG_BLOCK (
+              modest_tny_mime_part_to_string (TNY_MIME_PART (msg), 0);
+       );
+
        mgr = modest_runtime_get_window_mgr ();
        window = MODEST_MSG_VIEW_WINDOW (modest_window_mgr_get_msg_view_window (mgr));
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
@@ -880,44 +859,55 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg,
         * and change the list selection when necessary: */
 
        main_window = modest_window_mgr_get_main_window(mgr, FALSE); /* don't create */
-       if (!main_window) {
-               g_warning ("%s: BUG: no main window", __FUNCTION__);
-               return NULL;
+       if (main_window) {
+               header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget(
+                                                        MODEST_MAIN_WINDOW(main_window),
+                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
        }
        
-       header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget(
-                                                MODEST_MAIN_WINDOW(main_window),
-                                                MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
        if (header_view != NULL){
                header_folder = modest_header_view_get_folder(header_view);
-               priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == TNY_FOLDER_TYPE_OUTBOX);
-               g_assert(header_folder != NULL);
-               priv->header_folder_id = tny_folder_get_id(header_folder);
-               g_assert(priv->header_folder_id != NULL);
-               g_object_unref(header_folder);
-       }
-
-       priv->header_model = g_object_ref(model);
-       priv->row_reference = gtk_tree_row_reference_copy (row_reference);
-       priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
-       select_next_valid_row (model, &(priv->next_row_reference), TRUE);
-
-       priv->row_changed_handler = g_signal_connect(
-                       GTK_TREE_MODEL(model), "row-changed",
-                       G_CALLBACK(modest_msg_view_window_on_row_changed),
-                       window);
-       priv->row_deleted_handler = g_signal_connect(
-                       GTK_TREE_MODEL(model), "row-deleted",
-                       G_CALLBACK(modest_msg_view_window_on_row_deleted),
-                       window);
-       priv->row_inserted_handler = g_signal_connect (
-                       GTK_TREE_MODEL(model), "row-inserted",
-                       G_CALLBACK(modest_msg_view_window_on_row_inserted),
-                       window);
-       priv->rows_reordered_handler = g_signal_connect(
-                       GTK_TREE_MODEL(model), "rows-reordered",
-                       G_CALLBACK(modest_msg_view_window_on_row_reordered),
-                       window);
+               /* This could happen if the header folder was
+                  unseleted before opening this msg window (for
+                  example if the user selects an account in the
+                  folder view of the main window */
+               if (header_folder) {
+                       priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == TNY_FOLDER_TYPE_OUTBOX);
+                       priv->header_folder_id = tny_folder_get_id(header_folder);
+                       g_assert(priv->header_folder_id != NULL);
+                       g_object_unref(header_folder);
+               }
+       }
+
+       /* Setup row references and connect signals */
+       priv->header_model = g_object_ref (model);
+
+       if (row_reference) {
+               priv->row_reference = gtk_tree_row_reference_copy (row_reference);
+               priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
+               select_next_valid_row (model, &(priv->next_row_reference), TRUE);
+       } else {
+               priv->row_reference = NULL;
+               priv->next_row_reference = NULL;
+       }
+
+       /* Connect signals */
+       priv->row_changed_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-changed",
+                                 G_CALLBACK(modest_msg_view_window_on_row_changed),
+                                 window);
+       priv->row_deleted_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-deleted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_deleted),
+                                 window);
+       priv->row_inserted_handler = 
+               g_signal_connect (GTK_TREE_MODEL(model), "row-inserted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_inserted),
+                                 window);
+       priv->rows_reordered_handler = 
+               g_signal_connect(GTK_TREE_MODEL(model), "rows-reordered",
+                                G_CALLBACK(modest_msg_view_window_on_row_reordered),
+                                window);
 
        if (header_view != NULL){
                modest_header_view_add_observer(header_view,
@@ -927,11 +917,12 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg,
        tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
        update_window_title (MODEST_MSG_VIEW_WINDOW (window));
        gtk_widget_show_all (GTK_WIDGET (window));
-
        modest_msg_view_window_update_priority (window);
 
-       /* Check toolbar dimming rules */
+       /* Check dimming rules */
        modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
 
        return MODEST_WINDOW(window);
 }
@@ -957,7 +948,15 @@ modest_msg_view_window_new_for_search_result (TnyMsg *msg,
        priv->is_search_result = TRUE;
 
        tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       
        update_window_title (window);
+       gtk_widget_show_all (GTK_WIDGET (window));
+       modest_msg_view_window_update_priority (window);
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
 
        return MODEST_WINDOW(window);
 }
@@ -981,24 +980,63 @@ modest_msg_view_window_new_for_attachment (TnyMsg *msg,
        tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
        update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
 
+       gtk_widget_show_all (GTK_WIDGET (obj));
+
+       /* Check dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
+
        return MODEST_WINDOW(obj);
 }
 
-void modest_msg_view_window_on_row_changed(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               GtkTreeIter *arg2,
-               ModestMsgViewWindow *window){
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+static void
+modest_msg_view_window_on_row_changed (GtkTreeModel *header_model,
+                                      GtkTreePath *arg1,
+                                      GtkTreeIter *arg2,
+                                      ModestMsgViewWindow *window)
+{
+       check_dimming_rules_after_change (window);
 }
 
-void modest_msg_view_window_on_row_deleted(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               ModestMsgViewWindow *window){
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+static void 
+modest_msg_view_window_on_row_deleted(GtkTreeModel *header_model,
+                                     GtkTreePath *arg1,
+                                     ModestMsgViewWindow *window)
+{
+       check_dimming_rules_after_change (window);
+}
+
+static gboolean
+check_dimming_rules_after_change_in_idle (gpointer data)
+{
+       /* The window could have dissapeared */
+       if (MODEST_IS_WINDOW (data)) {
+               ModestWindow *win = MODEST_WINDOW (data);
+               gdk_threads_enter ();
+               modest_ui_actions_check_menu_dimming_rules (win);
+               modest_ui_actions_check_toolbar_dimming_rules (win);
+               gdk_threads_leave ();
+       }
+
+       return FALSE;
+}
+
+static void
+check_dimming_rules_after_change (ModestMsgViewWindow *window)
+{
+       static guint dimming_delayer = 0;
+
+       if (dimming_delayer > 0)
+               g_source_remove (dimming_delayer);
+
+       /* We're expecting a lot of changes at the same time so don't
+          need to check dimming rules for every change that
+          happens */
+       dimming_delayer = g_timeout_add (100, check_dimming_rules_after_change_in_idle, window);
 }
 
+
 /* On insertions we check if the folder still has the message we are
  * showing or do not. If do not, we do nothing. Which means we are still
  * not attached to any header folder and thus next/prev buttons are
@@ -1010,84 +1048,122 @@ void modest_msg_view_window_on_row_deleted(
  * inserted into the model again for example if it is removed by the
  * imap server and the header view is refreshed.)
  */
-void modest_msg_view_window_on_row_inserted(
-               GtkTreeModel *new_model,
-               GtkTreePath *tree_path,
-               GtkTreeIter *tree_iter,
-               ModestMsgViewWindow *window){
+static void 
+modest_msg_view_window_on_row_inserted (GtkTreeModel *model,
+                                       GtkTreePath *tree_path,
+                                       GtkTreeIter *tree_iter,
+                                       ModestMsgViewWindow *window)
+{
        ModestMsgViewWindowPrivate *priv = NULL; 
        TnyHeader *header = NULL;
-       gchar *uid = NULL;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
-
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
-       
-       /* If we already has a model attached then the message shown by
-        * msg-view is in it, and thus we do not need any actions but
-        * to check the dimming rules.*/
-       if(priv->header_model != NULL){
-               gtk_tree_row_reference_free(priv->next_row_reference);
-               priv->next_row_reference = gtk_tree_row_reference_copy(
-                               priv->row_reference);
-               select_next_valid_row (priv->header_model,
-                               &(priv->next_row_reference), FALSE);
-               modest_ui_actions_check_toolbar_dimming_rules (
-                               MODEST_WINDOW (window));
-               return;
-       }
 
+       g_assert (model == priv->header_model);
+       
        /* Check if the newly inserted message is the same we are actually
         * showing. IF not, we should remain detached from the header model
-        * and thus prev and next toolbarbuttons should remain dimmed. */
-       gtk_tree_model_get (new_model, tree_iter, 
-                       TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, &header, -1);
-       uid = modest_tny_folder_get_header_unique_id(header);
-       g_object_unref(G_OBJECT(header));
-       header = NULL;
-       if(!g_str_equal(priv->msg_uid, uid)){
+        * and thus prev and next toolbar buttons should remain dimmed. */
+       gtk_tree_model_get (model, tree_iter, 
+                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, 
+                           &header, -1);
+
+       if (TNY_IS_HEADER (header)) {
+               gchar *uid = NULL;
+
+               uid = modest_tny_folder_get_header_unique_id (header);
+               if (!g_str_equal(priv->msg_uid, uid)) {
+                       check_dimming_rules_after_change (window);
+                       g_free(uid);
+                       g_object_unref (G_OBJECT(header));
+                       return;
+               }
                g_free(uid);
-               return;
+               g_object_unref(G_OBJECT(header));
+       }
+
+       if (priv->row_reference) {
+               gtk_tree_row_reference_free (priv->row_reference); 
        }
-       g_free(uid);
 
        /* Setup row_reference for the actual msg. */
-       priv->row_reference = gtk_tree_row_reference_new(
-                       new_model, tree_path);
-       if(priv->row_reference == NULL){
+       priv->row_reference = gtk_tree_row_reference_new (priv->header_model, tree_path);
+       if (priv->row_reference == NULL) {
                g_warning("No reference for msg header item.");
                return;
        }
 
-       /* Attach new_model and connect some callback to it to become able
-        * to detect changes in header-view. */
-       priv->header_model = g_object_ref(new_model);
-       g_signal_connect (new_model, "row-changed",
-                       G_CALLBACK (modest_msg_view_window_on_row_changed),
-                       window);
-       g_signal_connect (new_model, "row-deleted",
-                       G_CALLBACK (modest_msg_view_window_on_row_deleted),
-                       window);
-       g_signal_connect (new_model, "rows-reordered",
-                       G_CALLBACK (modest_msg_view_window_on_row_reordered),
-                       window);
-
        /* Now set up next_row_reference. */
-       priv->next_row_reference = gtk_tree_row_reference_copy(
-                       priv->row_reference);
-       select_next_valid_row (priv->header_model,
-                       &(priv->next_row_reference), FALSE);
+       if (priv->next_row_reference) {
+               gtk_tree_row_reference_free (priv->next_row_reference); 
+       }
 
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+       select_next_valid_row (priv->header_model,
+                              &(priv->next_row_reference), FALSE);
+
+       /* Connect the remaining callbacks to become able to detect
+        * changes in header-view. */
+       priv->row_changed_handler = 
+               g_signal_connect (priv->header_model, "row-changed",
+                                 G_CALLBACK (modest_msg_view_window_on_row_changed),
+                                 window);
+       priv->row_deleted_handler = 
+               g_signal_connect (priv->header_model, "row-deleted",
+                                 G_CALLBACK (modest_msg_view_window_on_row_deleted),
+                                 window);
+       priv->rows_reordered_handler = 
+               g_signal_connect (priv->header_model, "rows-reordered",
+                                 G_CALLBACK (modest_msg_view_window_on_row_reordered),
+                                 window);
+
+       check_dimming_rules_after_change (window);      
 }
 
-void modest_msg_view_window_on_row_reordered(
-               GtkTreeModel *header_model,
-               GtkTreePath *arg1,
-               GtkTreeIter *arg2,
-               gpointer arg3,
-               ModestMsgViewWindow *window){
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+static void 
+modest_msg_view_window_on_row_reordered (GtkTreeModel *header_model,
+                                        GtkTreePath *arg1,
+                                        GtkTreeIter *arg2,
+                                        gpointer arg3,
+                                        ModestMsgViewWindow *window)
+{
+       ModestMsgViewWindowPrivate *priv = NULL; 
+       gboolean already_changed = FALSE;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(window);
+
+       /* If the current row was reordered select the proper next
+          valid row. The same if the next row reference changes */
+       if (priv->row_reference && 
+           gtk_tree_row_reference_valid (priv->row_reference)) {
+               GtkTreePath *path;
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
+               if (gtk_tree_path_compare (path, arg1) == 0) {
+                       if (priv->next_row_reference) {
+                               gtk_tree_row_reference_free (priv->next_row_reference);
+                       }
+                       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+                       select_next_valid_row (header_model, &(priv->next_row_reference), FALSE);
+                       already_changed = TRUE;
+               }
+               gtk_tree_path_free (path);
+       }
+       if (!already_changed &&
+           priv->next_row_reference &&
+           gtk_tree_row_reference_valid (priv->next_row_reference)) {
+               GtkTreePath *path;
+               path = gtk_tree_row_reference_get_path (priv->next_row_reference);
+               if (gtk_tree_path_compare (path, arg1) == 0) {
+                       if (priv->next_row_reference) {
+                               gtk_tree_row_reference_free (priv->next_row_reference);
+                       }
+                       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+                       select_next_valid_row (header_model, &(priv->next_row_reference), FALSE);
+               }
+               gtk_tree_path_free (path);
+       }
+       check_dimming_rules_after_change (window);
 }
 
 /* The modest_msg_view_window_update_model_replaced implements update
@@ -1099,10 +1175,11 @@ void modest_msg_view_window_on_row_reordered(
  * the new model. In this case the view will be detached from it's
  * header folder. From this point the next/prev buttons are dimmed.
  */
-void modest_msg_view_window_update_model_replaced(
-               ModestHeaderViewObserver *observer,
-               GtkTreeModel *model,
-               const gchar *tny_folder_id){
+static void 
+modest_msg_view_window_update_model_replaced (ModestHeaderViewObserver *observer,
+                                             GtkTreeModel *model,
+                                             const gchar *tny_folder_id)
+{
        ModestMsgViewWindowPrivate *priv = NULL; 
        ModestMsgViewWindow *window = NULL;
 
@@ -1116,51 +1193,61 @@ void modest_msg_view_window_update_model_replaced(
         * not care about it's model (msg list). Else if the
         * header-view shows the folder the msg shown by us is in, we
         * shall replace our model reference and make some check. */
-       if(tny_folder_id == NULL || !g_str_equal(tny_folder_id, priv->header_folder_id))
+       if(model == NULL || tny_folder_id == NULL || 
+          (priv->header_folder_id && !g_str_equal(tny_folder_id, priv->header_folder_id)))
                return;
-       
+
        /* Model is changed(replaced), so we should forget the old
         * one. Because there might be other references and there
         * might be some change on the model even if we unreferenced
         * it, we need to disconnect our signals here. */
-       if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
-                                          priv->row_changed_handler))
-               g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
-                                            priv->row_changed_handler);
-       priv->row_changed_handler = 0;
-       if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
-                                          priv->row_deleted_handler))
-               g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
-                                            priv->row_deleted_handler);
-       priv->row_deleted_handler = 0;
-       if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
-                                          priv->row_inserted_handler))
-               g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
-                                            priv->row_inserted_handler);
-       priv->row_inserted_handler = 0;
-       if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
-                                          priv->rows_reordered_handler))
-               g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
-                                            priv->rows_reordered_handler);
-       priv->rows_reordered_handler = 0;
-       g_object_unref(priv->header_model);
-       priv->header_model = NULL;
-       g_object_unref(priv->row_reference);
-       priv->row_reference = NULL;
-       g_object_unref(priv->next_row_reference);
-       priv->next_row_reference = NULL;
+       if (priv->header_model) {
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_changed_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_changed_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_deleted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_deleted_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->row_inserted_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->row_inserted_handler);
+               if (g_signal_handler_is_connected(G_OBJECT (priv->header_model), 
+                                                 priv->rows_reordered_handler))
+                       g_signal_handler_disconnect(G_OBJECT (priv->header_model), 
+                                                   priv->rows_reordered_handler);
 
-       modest_ui_actions_check_toolbar_dimming_rules(MODEST_WINDOW(window));
+               /* Frees */
+               if (priv->row_reference)
+                       gtk_tree_row_reference_free (priv->row_reference);
+               if (priv->next_row_reference)
+                       gtk_tree_row_reference_free (priv->next_row_reference);
+               g_object_unref(priv->header_model);
+
+               /* Initialize */
+               priv->row_changed_handler = 0;
+               priv->row_deleted_handler = 0;
+               priv->row_inserted_handler = 0;
+               priv->rows_reordered_handler = 0;
+               priv->next_row_reference = NULL;
+               priv->row_reference = NULL;
+               priv->header_model = NULL;
+       }
 
-       g_assert(model != NULL);
+       priv->header_model = g_object_ref (model);
 
        /* Also we must connect to the new model for row insertions.
         * Only for insertions now. We will need other ones only after
         * the msg is show by msg-view is added to the new model. */
-       priv->row_inserted_handler = g_signal_connect (
-                       model, "row-inserted",
-                       G_CALLBACK(modest_msg_view_window_on_row_inserted),
-                       window);
+       priv->row_inserted_handler =
+               g_signal_connect (priv->header_model, "row-inserted",
+                                 G_CALLBACK(modest_msg_view_window_on_row_inserted),
+                                 window);
+
+       modest_ui_actions_check_menu_dimming_rules(MODEST_WINDOW(window));
+       modest_ui_actions_check_toolbar_dimming_rules(MODEST_WINDOW(window));
 }
 
 gboolean 
@@ -1189,7 +1276,9 @@ modest_msg_view_window_get_header (ModestMsgViewWindow *self)
        /* If the message was not obtained from a treemodel,
         * for instance if it was opened directly by the search UI:
         */
-       if (priv->header_model == NULL) {
+       if (priv->header_model == NULL || 
+           priv->row_reference == NULL ||
+           !gtk_tree_row_reference_valid (priv->row_reference)) {
                msg = modest_msg_view_window_get_message (self);
                if (msg) {
                        header = tny_msg_get_header (msg);
@@ -1199,12 +1288,6 @@ modest_msg_view_window_get_header (ModestMsgViewWindow *self)
        }
 
        /* Get iter of the currently selected message in the header view: */
-       /* TODO: Why not just give this window a ref of the TnyHeader or TnyMessage,
-        * instead of sometimes retrieving it from the header view?
-        * Then we wouldn't be dependent on the message actually still being selected 
-        * in the header view. murrayc. */
-       if (!gtk_tree_row_reference_valid (priv->row_reference))
-               return NULL;
        path = gtk_tree_row_reference_get_path (priv->row_reference);
        g_return_val_if_fail (path != NULL, NULL);
        gtk_tree_model_get_iter (priv->header_model, 
@@ -1277,10 +1360,14 @@ modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
 {
        GtkToggleAction *toggle;
        ModestWindowPrivate *parent_priv;
+       ModestMsgViewWindowPrivate *priv;
+
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
        parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
        
        toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
        gtk_toggle_action_set_active (toggle, FALSE);
+       modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
 }
 
 static void
@@ -1315,6 +1402,7 @@ modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
                        priv->last_search = NULL;
                } else {
                        modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+                       hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
                }
        } else {
                if (!modest_isearch_view_search_next (MODEST_ISEARCH_VIEW (priv->msg_view))) {
@@ -1323,6 +1411,7 @@ modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
                        priv->last_search = NULL;
                } else {
                        modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+                       hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
                }
        }
        
@@ -1422,7 +1511,21 @@ modest_msg_view_window_key_event (GtkWidget *window,
                                  GdkEventKey *event,
                                  gpointer userdata)
 {
-       
+       GtkWidget *focus;
+
+       focus = gtk_window_get_focus (GTK_WINDOW (window));
+
+       /* for the find toolbar case */
+       if (focus && GTK_IS_ENTRY (focus)) {
+               if (event->keyval == GDK_BackSpace) {
+                       GdkEvent *copy;
+                       copy = gdk_event_copy ((GdkEvent *) event);
+                       gtk_widget_event (focus, copy);
+                       gdk_event_free (copy);
+                       return TRUE;
+               } else 
+                       return FALSE;
+       }
        if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
            event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
            event->keyval == GDK_Page_Up || event->keyval == GDK_KP_Page_Up ||
@@ -1480,7 +1583,7 @@ modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        /*if no model (so no rows at all), then virtually we are the last*/
-       if (!priv->header_model)
+       if (!priv->header_model || !priv->row_reference)
                return TRUE;
 
        path = gtk_tree_row_reference_get_path (priv->row_reference);
@@ -1532,7 +1635,9 @@ static gboolean
 msg_is_visible (TnyHeader *header, gboolean check_outbox)
 {
        return (!(tny_header_get_flags(header) & TNY_HEADER_FLAG_DELETED)) &&
-               ( (!check_outbox) || (modest_tny_all_send_queues_get_msg_status (header) != MODEST_TNY_SEND_QUEUE_FAILED)) ;
+               ( (!check_outbox) || 
+                 ((modest_tny_all_send_queues_get_msg_status (header) != MODEST_TNY_SEND_QUEUE_FAILED) &&
+                  (modest_tny_all_send_queues_get_msg_status (header) != MODEST_TNY_SEND_QUEUE_SENDING))) ;
        
 }
 
@@ -1549,7 +1654,7 @@ modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        /*if no model (so no rows at all), then virtually we are the first*/
-       if (!priv->header_model)
+       if (!priv->header_model || !priv->row_reference)
                return TRUE;
 
        path = gtk_tree_row_reference_get_path (priv->row_reference);
@@ -1586,6 +1691,49 @@ modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
        return is_first_selected;
 }
 
+typedef struct {
+       TnyHeader *header;
+       GtkTreeRowReference *row_reference;
+} MsgReaderInfo;
+
+static void
+message_reader_performer (gboolean canceled, 
+                         GError *err,
+                         GtkWindow *parent_window, 
+                         TnyAccount *account, 
+                         gpointer user_data)
+{
+       ModestMailOperation *mail_op = NULL;
+       MsgReaderInfo *info;
+
+       info = (MsgReaderInfo *) user_data;
+       if (canceled || err) {
+               goto frees;
+       }
+
+       /* Register the header - it'll be unregistered in the callback */
+       modest_window_mgr_register_header (modest_runtime_get_window_mgr (), info->header, NULL);
+
+       /* New mail operation */
+       mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
+                                                                modest_ui_actions_disk_operations_error_handler, 
+                                                                NULL, NULL);
+                               
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
+       modest_mail_operation_get_msg (mail_op, info->header, TRUE, view_msg_cb, info->row_reference);
+       g_object_unref (mail_op);
+
+       /* Update dimming rules */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_window));
+       modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (parent_window));
+
+ frees:
+       /* Frees. The row_reference will be freed by the view_msg_cb callback */
+       g_object_unref (info->header);
+       g_slice_free (MsgReaderInfo, info);
+}
+
+
 /**
  * Reads the message whose summary item is @header. It takes care of
  * several things, among others:
@@ -1604,10 +1752,12 @@ message_reader (ModestMsgViewWindow *window,
                TnyHeader *header,
                GtkTreeRowReference *row_reference)
 {
-       ModestMailOperation *mail_op = NULL;
        gboolean already_showing = FALSE;
        ModestWindow *msg_window = NULL;
        ModestWindowMgr *mgr;
+       TnyAccount *account;
+       TnyFolder *folder;
+       MsgReaderInfo *info;
 
        g_return_val_if_fail (row_reference != NULL, FALSE);
 
@@ -1626,7 +1776,6 @@ message_reader (ModestMsgViewWindow *window,
                /* Ask the user if he wants to download the message if
                   we're not online */
                if (!tny_device_is_online (modest_runtime_get_device())) {
-                       TnyFolder *folder = NULL;
                        GtkResponseType response;
 
                        response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
@@ -1634,30 +1783,31 @@ message_reader (ModestMsgViewWindow *window,
                        if (response == GTK_RESPONSE_CANCEL)
                                return FALSE;
                
-                       /* Offer the connection dialog if necessary */
                        folder = tny_header_get_folder (header);
-                       if (folder) {
-                               if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, 
-                                                                                             TNY_FOLDER_STORE (folder))) {
-                                       g_object_unref (folder);
-                                       return FALSE;
-                               }
-                               g_object_unref (folder);
-                       }
+                       info = g_slice_new (MsgReaderInfo);
+                       info->header = g_object_ref (header);
+                       info->row_reference = gtk_tree_row_reference_copy (row_reference);
+
+                       /* Offer the connection dialog if necessary */
+                       modest_platform_connect_if_remote_and_perform ((GtkWindow *) window, 
+                                                                      TRUE,
+                                                                      TNY_FOLDER_STORE (folder),
+                                                                      message_reader_performer, 
+                                                                      info);
+                       g_object_unref (folder);
+                       return TRUE;
                }
        }
-
-       /* New mail operation */
-       mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(window),
-                                                                modest_ui_actions_get_msgs_full_error_handler, 
-                                                                NULL, NULL);
-                               
-       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-       modest_mail_operation_get_msg (mail_op, header, view_msg_cb, row_reference);
-       g_object_unref (mail_op);
-
-       /* Update toolbar dimming rules */
-       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+       
+       folder = tny_header_get_folder (header);
+       account = tny_folder_get_account (folder);
+       info = g_slice_new (MsgReaderInfo);
+       info->header = g_object_ref (header);
+       info->row_reference = gtk_tree_row_reference_copy (row_reference);
+       
+       message_reader_performer (FALSE, NULL, (GtkWindow *) window, account, info);
+       g_object_unref (account);
+       g_object_unref (folder);
 
        return TRUE;
 }
@@ -1675,6 +1825,9 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
+       if (!priv->row_reference)
+               return FALSE;
+
        /* Update the next row reference if it's not valid. This could
           happen if for example the header which it was pointing to,
           was deleted. The best place to do it is in the row-deleted
@@ -1706,71 +1859,32 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
        /* Read the message & show it */
        if (!message_reader (window, priv, header, row_reference)) {
                retval = FALSE;
-               gtk_tree_row_reference_free (row_reference);
        }
+       gtk_tree_row_reference_free (row_reference);
 
        /* Free */
        g_object_unref (header);
 
-       return retval;          
+       return retval;
 }
 
-gboolean 
-modest_msg_view_window_select_first_message (ModestMsgViewWindow *self)
-{
-       ModestMsgViewWindowPrivate *priv = NULL;
-       TnyHeader *header = NULL;
-       GtkTreeIter iter;
-       GtkTreePath *path = NULL;
-       GtkTreeRowReference *row_reference = NULL;
-
-       g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
-       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
-
-       /* Check that the model is not empty */
-       if (!gtk_tree_model_get_iter_first (priv->header_model, &iter))
-               return FALSE;
-
-       /* Get the header */
-       gtk_tree_model_get (priv->header_model, 
-                           &iter, 
-                           TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
-                           &header, -1);
-       g_return_val_if_fail (TNY_IS_HEADER (header), FALSE);
-       if (!msg_is_visible (header, priv->is_outbox)) {
-               g_object_unref (header);
-               return modest_msg_view_window_select_next_message (self);
-       }
-       
-       path = gtk_tree_model_get_path (priv->header_model, &iter);
-       row_reference = gtk_tree_row_reference_new (priv->header_model, path);
-       gtk_tree_path_free (path);
-
-       /* Read the message & show it */
-       message_reader (self, priv, header, row_reference);
-       
-       /* Free */
-       g_object_unref (header);
-
-       return TRUE;
-}
 gboolean        
 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
 {
        ModestMsgViewWindowPrivate *priv = NULL;
        GtkTreePath *path;
-       GtkTreeRowReference *row_reference = NULL;
+       gboolean finished = FALSE;
+       gboolean retval = FALSE;
 
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        /* Return inmediatly if there is no header model */
-       if (!priv->header_model)
+       if (!priv->header_model || !priv->row_reference)
                return FALSE;
 
        path = gtk_tree_row_reference_get_path (priv->row_reference);
-       while (gtk_tree_path_prev (path)) {
+       while (!finished && gtk_tree_path_prev (path)) {
                TnyHeader *header;
                GtkTreeIter iter;
 
@@ -1778,29 +1892,23 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
                gtk_tree_model_get (priv->header_model, &iter, 
                                    TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
                                    &header, -1);
-               if (!header)
-                       break;
-               if (!msg_is_visible (header, priv->is_outbox)) {
-                       g_object_unref (header);
-                       continue;
-               }
-
-               row_reference = gtk_tree_row_reference_new (priv->header_model, path);
-               /* Read the message & show it */
-               if (!message_reader (window, priv, header, row_reference)) {
-                       gtk_tree_row_reference_free (row_reference);
+               finished = TRUE;
+               if (header) {
+                       if (msg_is_visible (header, priv->is_outbox)) {
+                               GtkTreeRowReference *row_reference;
+                               row_reference = gtk_tree_row_reference_new (priv->header_model, path);
+                               /* Read the message & show it */
+                               retval = message_reader (window, priv, header, row_reference);
+                               gtk_tree_row_reference_free (row_reference);
+                       } else {
+                               finished = FALSE;
+                       }
                        g_object_unref (header);
-                       break;
                }
-
-               gtk_tree_path_free (path);
-               g_object_unref (header);
-
-               return TRUE;
        }
 
        gtk_tree_path_free (path);
-       return FALSE;
+       return retval;
 }
 
 static void
@@ -1815,8 +1923,16 @@ view_msg_cb (ModestMailOperation *mail_op,
        ModestMsgViewWindowPrivate *priv = NULL;
        GtkTreeRowReference *row_reference = NULL;
 
-       /* If there was any error */
+       /* Unregister the header (it was registered before creating the mail operation) */
+       modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), header);
+
        row_reference = (GtkTreeRowReference *) user_data;
+       if (canceled) {
+               gtk_tree_row_reference_free (row_reference);
+               return;
+       }
+       
+       /* If there was any error */
        if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
                gtk_tree_row_reference_free (row_reference);                    
                return;
@@ -1828,21 +1944,27 @@ view_msg_cb (ModestMailOperation *mail_op,
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
 
        /* Update the row reference */
-       gtk_tree_row_reference_free (priv->row_reference);
-       priv->row_reference = gtk_tree_row_reference_copy (row_reference);
-       priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
-       select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
-       gtk_tree_row_reference_free (row_reference);
+       if (priv->row_reference != NULL) {
+               gtk_tree_row_reference_free (priv->row_reference);
+               priv->row_reference = gtk_tree_row_reference_copy (row_reference);
+               if (priv->next_row_reference != NULL) {
+                       gtk_tree_row_reference_free (priv->next_row_reference);
+               }
+               priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
+               select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
+       }
 
        /* Mark header as read */
        if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
                tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
 
        /* Set new message */
-       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
-       modest_msg_view_window_update_priority (self);
-       update_window_title (MODEST_MSG_VIEW_WINDOW (self));
-       modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+       if (priv->msg_view != NULL && TNY_IS_MSG_VIEW (priv->msg_view)) {
+               tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+               modest_msg_view_window_update_priority (self);
+               update_window_title (MODEST_MSG_VIEW_WINDOW (self));
+               modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
+       }
 
        /* Set the new message uid of the window  */
        if (priv->msg_uid) {
@@ -1854,8 +1976,9 @@ view_msg_cb (ModestMailOperation *mail_op,
        g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL], 
                       0, priv->header_model, priv->row_reference);
 
-       /* Free new references */
+       /* Frees */
        g_object_unref (self);
+       gtk_tree_row_reference_free (row_reference);            
 }
 
 TnyFolderType
@@ -1875,7 +1998,7 @@ modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
 
                folder = tny_msg_get_folder (msg);
                if (folder) {
-                       folder_type = tny_folder_get_folder_type (folder);
+                       folder_type = modest_tny_folder_guess_folder_type (folder);
                        g_object_unref (folder);
                }
                g_object_unref (msg);
@@ -1889,12 +2012,12 @@ static void
 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
 {
        ModestMsgViewWindowPrivate *priv;
+       TnyHeader *header = NULL;
        TnyHeaderFlags flags = 0;
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
-       if (priv->header_model) {
-               TnyHeader *header;
+       if (priv->header_model && priv->row_reference) {
                GtkTreeIter iter;
                GtkTreePath *path = NULL;
 
@@ -1906,17 +2029,72 @@ modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
 
                gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
                                    &header, -1);
-               if (header) {
-                       flags = tny_header_get_flags (header);
-                       g_object_unref(G_OBJECT(header));
-               }
                gtk_tree_path_free (path);
+       } else {
+               TnyMsg *msg;
+               msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+               if (msg) {
+                       header = tny_msg_get_header (msg);
+                       g_object_unref (msg);
+               }
+       }
+
+       if (header) {
+               flags = tny_header_get_flags (header);
+               g_object_unref(G_OBJECT(header));
        }
 
        modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
 
 }
 
+static void
+toolbar_resize (ModestMsgViewWindow *self)
+{
+       ModestMsgViewWindowPrivate *priv = NULL;
+       ModestWindowPrivate *parent_priv = NULL;
+       GtkWidget *widget;
+       gint static_button_size;
+       ModestWindowMgr *mgr;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
+       priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
+       parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
+
+       mgr = modest_runtime_get_window_mgr ();
+       static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?118:108;
+
+       if (parent_priv->toolbar) {
+               /* left size buttons */
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FindInMessage");
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE);
+               gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1);
+               
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->next_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->next_toolitem), TRUE);
+               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->prev_toolitem), TRUE);
+               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->prev_toolitem), TRUE);
+       }
+               
+}
+
 static gboolean
 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
 {
@@ -1937,6 +2115,7 @@ modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowStat
                if (is_fullscreen != active) {
                        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
                }
+               toolbar_resize (MODEST_MSG_VIEW_WINDOW (widget));
        }
 
        return FALSE;
@@ -1944,16 +2123,6 @@ modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowStat
 }
 
 static void
-set_homogeneous (GtkWidget *widget,
-                gpointer data)
-{
-       if (GTK_IS_TOOL_ITEM (widget)) {
-               gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
-               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
-       }
-}
-
-static void
 modest_msg_view_window_show_toolbar (ModestWindow *self,
                                     gboolean show_toolbar)
 {
@@ -1976,21 +2145,14 @@ modest_msg_view_window_show_toolbar (ModestWindow *self,
                                                                  "/ToolBar");
                gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
 
-               /* Set homogeneous toolbar */
-               gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar), 
-                                      set_homogeneous, NULL);
-
                priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
                priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
                priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
                priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
-               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
-               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
-               gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
-               gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
+               toolbar_resize (MODEST_MSG_VIEW_WINDOW (self));
 
                /* Add ProgressBar (Transfer toolbar) */ 
-               priv->progress_bar = modest_progress_bar_widget_new ();
+               priv->progress_bar = modest_progress_bar_new ();
                gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
                placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
                insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
@@ -2056,7 +2218,7 @@ modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
        if (!GTK_WIDGET_VISIBLE (window))
                return;
 
-       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), "ModestClipboardDimmingRules");
+       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
 }
 
 gboolean 
@@ -2136,21 +2298,25 @@ on_mail_operation_started (ModestMailOperation *mail_op,
        ModestMailOperationTypeOperation op_type;
        GSList *tmp;
        ModestMsgViewWindowPrivate *priv;
+       GObject *source = NULL;
 
        self = MODEST_MSG_VIEW_WINDOW (user_data);
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
        op_type = modest_mail_operation_get_type_operation (mail_op);
        tmp = priv->progress_widgets;
-       
-       if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || op_type == MODEST_MAIL_OPERATION_TYPE_OPEN ) {
-               set_toolbar_transfer_mode(self);
-               while (tmp) {
-                       modest_progress_object_add_operation (
-                                       MODEST_PROGRESS_OBJECT (tmp->data),
-                                       mail_op);
-                       tmp = g_slist_next (tmp);
+       source = modest_mail_operation_get_source(mail_op);
+       if (G_OBJECT (self) == source) {
+               if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || op_type == MODEST_MAIL_OPERATION_TYPE_OPEN ) {
+                       set_toolbar_transfer_mode(self);
+                       while (tmp) {
+                               modest_progress_object_add_operation (
+                                               MODEST_PROGRESS_OBJECT (tmp->data),
+                                               mail_op);
+                               tmp = g_slist_next (tmp);
+                       }
                }
        }
+       g_object_unref (source);
 }
 
 static void 
@@ -2169,9 +2335,8 @@ on_mail_operation_finished (ModestMailOperation *mail_op,
        
        if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || op_type == MODEST_MAIL_OPERATION_TYPE_OPEN ) {
                while (tmp) {
-                       modest_progress_object_remove_operation (
-                                       MODEST_PROGRESS_OBJECT (tmp->data),
-                                       mail_op);
+                       modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
+                                                                mail_op);
                        tmp = g_slist_next (tmp);
                }
 
@@ -2179,6 +2344,14 @@ on_mail_operation_finished (ModestMailOperation *mail_op,
                if (observers_empty (self)) {
                        set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
                }
+
+               /* Update dimming rules. We have to do this right here
+                  and not in view_msg_cb because at that point the
+                  transfer mode is still enabled so the dimming rule
+                  won't let the user delete the message that has been
+                  readed for example */
+               modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
+               modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
        }
 }
 
@@ -2217,11 +2390,11 @@ on_queue_changed (ModestMailOperationQueue *queue,
        }
 }
 
-GList *
+TnyList *
 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win) 
 {
        ModestMsgViewWindowPrivate *priv;
-       GList *selected_attachments = NULL;
+       TnyList *selected_attachments = NULL;
        
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
@@ -2238,7 +2411,7 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart
        const gchar *msg_uid;
        gchar *attachment_uid = NULL;
        gint attachment_index = 0;
-       GList *attachments;
+       TnyList *attachments;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
        g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
@@ -2246,8 +2419,8 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart
 
        msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window));
        attachments = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
-       attachment_index = g_list_index (attachments, mime_part);
-       g_list_free (attachments);
+       attachment_index = modest_list_index (attachments, (GObject *) mime_part);
+       g_object_unref (attachments);
        
        if (msg_uid && attachment_index >= 0) {
                attachment_uid = g_strdup_printf ("%s/%d", msg_uid, attachment_index);
@@ -2255,18 +2428,19 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart
 
        if (mime_part == NULL) {
                gboolean error = FALSE;
-               GList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
-               if (selected_attachments == NULL) {
+               TnyList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
+               if (selected_attachments == NULL || tny_list_get_length (selected_attachments) == 0) {
                        error = TRUE;
-               } else if (g_list_length (selected_attachments) > 1) {
+               } else if (tny_list_get_length (selected_attachments) > 1) {
                        hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
                        error = TRUE;
                } else {
-                       mime_part = (TnyMimePart *) selected_attachments->data;
-                       g_object_ref (mime_part);
+                       TnyIterator *iter;
+                       iter = tny_list_create_iterator (selected_attachments);
+                       mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+                       g_object_unref (iter);
                }
-               g_list_foreach (selected_attachments, (GFunc) g_object_unref, NULL);
-               g_list_free (selected_attachments);
+               g_object_unref (selected_attachments);
 
                if (error)
                        return;
@@ -2279,35 +2453,51 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart
                return;
        }
 
-       if (!TNY_IS_MSG (mime_part)) {
+       if (!modest_tny_mime_part_is_msg (mime_part)) {
                gchar *filepath = NULL;
                const gchar *att_filename = tny_mime_part_get_filename (mime_part);
                const gchar *content_type;
+               gboolean show_error_banner = FALSE;
+               GError *err;
                TnyFsStream *temp_stream = NULL;
                temp_stream = modest_utils_create_temp_stream (att_filename, attachment_uid,
                                                               &filepath);
                
                if (temp_stream != NULL) {
                        content_type = tny_mime_part_get_content_type (mime_part);
-                       tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream));
+                       if (tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream), &err) >= 0) {
+                               /* make the file read-only */
+                               if (g_chmod(filepath, 0444) != 0)
+                                       g_warning ("%s: failed to set file '%s' to read-only: %s",
+                                                       __FUNCTION__, filepath, strerror(errno));
 
-                       /* make the file read-only */
-                       if (g_chmod(filepath, 0444) != 0)
-                               g_warning ("%s: failed to set file '%s' to read-only: %s",
-                                          __FUNCTION__, filepath, strerror(errno));
-                       
-                       modest_platform_activate_file (filepath, content_type);
+                               modest_platform_activate_file (filepath, content_type);
+                       } else {
+                               /* error while saving attachment, maybe cerm_device_memory_full */
+                               show_error_banner = TRUE;
+                               if (err != NULL) {
+                                       g_warning ("%s: tny_mime_part_decode_to_stream failed (%s)", __FUNCTION__, err->message);
+                                       g_error_free (err);
+                               }
+                       }
                        g_object_unref (temp_stream);
                        g_free (filepath);
                        /* NOTE: files in the temporary area will be automatically
                         * cleaned after some time if they are no longer in use */
-               } else if (filepath != NULL) {
-                       /* the file may already exist but it isn't writable,
-                        * let's try to open it anyway */
-                       content_type = tny_mime_part_get_content_type (mime_part);
-                       modest_platform_activate_file (filepath, content_type);
-                       g_free (filepath);
+               } else {
+                       if (filepath != NULL) {
+                               /* the file may already exist but it isn't writable,
+                                * let's try to open it anyway */
+                               content_type = tny_mime_part_get_content_type (mime_part);
+                               modest_platform_activate_file (filepath, content_type);
+                               g_free (filepath);
+                       } else {
+                               g_warning ("%s: modest_utils_create_temp_stream failed", __FUNCTION__);
+                               show_error_banner = TRUE;
+                       }
                }
+               if (show_error_banner)
+                       modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed"));
        } else {
                /* message attachment */
                TnyHeader *header = NULL;
@@ -2336,7 +2526,6 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart
                        modest_window_set_zoom (MODEST_WINDOW (msg_win), 
                                                modest_window_get_zoom (MODEST_WINDOW (window)));
                        modest_window_mgr_register_window (mgr, msg_win);
-                       gtk_window_set_transient_for (GTK_WINDOW (msg_win), GTK_WINDOW (window));
                        gtk_widget_show_all (GTK_WIDGET (msg_win));
                }
        }
@@ -2353,7 +2542,7 @@ typedef struct
 {
        GList *pairs;
        GtkWidget *banner;
-       gboolean result;
+       GnomeVFSResult result;
 } SaveMimePartInfo;
 
 static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
@@ -2376,7 +2565,6 @@ save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
        info->pairs = NULL;
        if (with_struct) {
                gtk_widget_destroy (info->banner);
-               g_object_unref (info->banner);
                g_slice_free (SaveMimePartInfo, info);
        }
 }
@@ -2387,16 +2575,16 @@ idle_save_mime_part_show_result (SaveMimePartInfo *info)
        if (info->pairs != NULL) {
                save_mime_part_to_file (info);
        } else {
-               gboolean result;
-               result = info->result;
-
                /* This is a GDK lock because we are an idle callback and
                 * hildon_banner_show_information is or does Gtk+ code */
 
                gdk_threads_enter (); /* CHECKED */
                save_mime_part_info_free (info, TRUE);
-               if (result) {
+               if (info->result == GNOME_VFS_OK) {
                        hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
+               } else if (info->result == GNOME_VFS_ERROR_NO_SPACE) {
+                       hildon_banner_show_information (NULL, NULL, dgettext("ke-recv", 
+                                                                            "cerm_device_memory_full"));
                } else {
                        hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
                }
@@ -2409,23 +2597,22 @@ idle_save_mime_part_show_result (SaveMimePartInfo *info)
 static gpointer
 save_mime_part_to_file (SaveMimePartInfo *info)
 {
-       GnomeVFSResult result;
        GnomeVFSHandle *handle;
        TnyStream *stream;
        SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
 
-       result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0644);
-       if (result == GNOME_VFS_OK) {
+       info->result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0644);
+       if (info->result == GNOME_VFS_OK) {
                stream = tny_vfs_stream_new (handle);
-               tny_mime_part_decode_to_stream (pair->part, stream);
+               if (tny_mime_part_decode_to_stream (pair->part, stream, NULL) < 0) {
+                       info->result = GNOME_VFS_ERROR_IO;
+               }
                g_object_unref (G_OBJECT (stream));
                g_object_unref (pair->part);
                g_slice_free (SaveMimePartPair, pair);
                info->pairs = g_list_delete_link (info->pairs, info->pairs);
-               info->result = TRUE;
        } else {
                save_mime_part_info_free (info, FALSE);
-               info->result = FALSE;
        }
 
        g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
@@ -2462,23 +2649,20 @@ save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
        } else {
                GtkWidget *banner = hildon_banner_show_animation (NULL, NULL, 
                                                                  _CS("sfil_ib_saving"));
-               info->banner = g_object_ref (banner);
+               info->banner = banner;
                g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
-               g_object_unref (banner);
        }
 
 }
 
 
 void
-modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mime_parts)
+modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, TnyList *mime_parts)
 {
-       gboolean clean_list = FALSE;
        ModestMsgViewWindowPrivate *priv;
        GList *files_to_save = NULL;
        GtkWidget *save_dialog = NULL;
        gchar *folder = NULL;
-       gboolean canceled = FALSE;
        const gchar *filename = NULL;
        gchar *save_multiple_str = NULL;
 
@@ -2487,24 +2671,33 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mim
 
        if (mime_parts == NULL) {
                mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
-               if (mime_parts == NULL)
+               if (mime_parts == NULL || tny_list_get_length (mime_parts) == 0)
                        return;
-               clean_list = TRUE;
+       } else {
+               g_object_ref (mime_parts);
        }
 
        /* prepare dialog */
-       if (mime_parts->next == NULL) {
+       if (tny_list_get_length (mime_parts) == 1) {
+               TnyIterator *iter;
                /* only one attachment selected */
-               TnyMimePart *mime_part = (TnyMimePart *) mime_parts->data;
-               if (!TNY_IS_MSG (mime_part) && tny_mime_part_is_attachment (mime_part)) {
+               iter = tny_list_create_iterator (mime_parts);
+               TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
+               g_object_unref (iter);
+               if (!modest_tny_mime_part_is_msg (mime_part) && 
+                   modest_tny_mime_part_is_attachment_for_modest (mime_part) &&
+                   !tny_mime_part_is_purged (mime_part)) {
                        filename = tny_mime_part_get_filename (mime_part);
                } else {
+                       /* TODO: show any error? */
                        g_warning ("Tried to save a non-file attachment");
-                       canceled = TRUE;
+                       g_object_unref (mime_parts);
+                       return;
                }
+               g_object_unref (mime_part);
        } else {
                save_multiple_str = g_strdup_printf (_FM("sfil_va_number_of_objects_attachments"), 
-                                                    g_list_length (mime_parts));
+                                                    tny_list_get_length (mime_parts));
        }
        
        save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), 
@@ -2523,6 +2716,7 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mim
        /* 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"));
        }
                
        /* show dialog */
@@ -2533,40 +2727,39 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mim
                        hildon_banner_show_information 
                                (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
                } else {
-                       GList *node = NULL;
+                       TnyIterator *iter;
 
-                       for (node = mime_parts; node != NULL; node = g_list_next (node)) {
-                               TnyMimePart *mime_part = (TnyMimePart *) node->data;
-                               
-                               if (tny_mime_part_is_attachment (mime_part)) {
-                                       SaveMimePartPair *pair;
+                       iter = tny_list_create_iterator (mime_parts);
+                       while (!tny_iterator_is_done (iter)) {
+                               TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
 
-                                       if ((mime_parts->next != NULL) &&
-                                           (tny_mime_part_get_filename (mime_part) == NULL))
-                                               continue;
+                               if ((modest_tny_mime_part_is_attachment_for_modest (mime_part)) &&
+                                   !tny_mime_part_is_purged (mime_part) &&
+                                   (tny_mime_part_get_filename (mime_part) != NULL)) {
+                                       SaveMimePartPair *pair;
                                        
                                        pair = g_slice_new0 (SaveMimePartPair);
-                                       if (mime_parts->next == NULL) {
-                                               pair->filename = g_strdup (chooser_uri);
+                                       if (save_multiple_str) {
+                                               gchar *escaped = gnome_vfs_escape_slashes (
+                                                       tny_mime_part_get_filename (mime_part));
+                                               pair->filename = g_build_filename (chooser_uri, escaped, NULL);
+                                               g_free (escaped);
                                        } else {
-                                               pair->filename = 
-                                                       g_build_filename (chooser_uri,
-                                                                         tny_mime_part_get_filename (mime_part), NULL);
+                                               pair->filename = g_strdup (chooser_uri);
                                        }
-                                       pair->part = g_object_ref (mime_part);
+                                       pair->part = mime_part;
                                        files_to_save = g_list_prepend (files_to_save, pair);
                                }
+                               tny_iterator_next (iter);
                        }
+                       g_object_unref (iter);
                }
                g_free (chooser_uri);
        }
 
        gtk_widget_destroy (save_dialog);
 
-       if (clean_list) {
-               g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
-               g_list_free (mime_parts);
-       }
+       g_object_unref (mime_parts);
 
        if (files_to_save != NULL) {
                SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
@@ -2602,11 +2795,12 @@ void
 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
 {
        ModestMsgViewWindowPrivate *priv;
-       GList *mime_parts = NULL, *node;
+       TnyList *mime_parts = NULL;
        gchar *confirmation_message;
        gint response;
        gint n_attachments;
        TnyMsg *msg;
+       TnyIterator *iter;
 /*     TnyFolder *folder; */
 
        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
@@ -2618,37 +2812,43 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean
                mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
                
        /* Remove already purged messages from mime parts list */
-       node = mime_parts;
-       while (node != NULL) {
-               TnyMimePart *part = TNY_MIME_PART (node->data);
+       iter = tny_list_create_iterator (mime_parts);
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part = TNY_MIME_PART (tny_iterator_get_current (iter));
+               tny_iterator_next (iter);
                if (tny_mime_part_is_purged (part)) {
-                       GList *deleted_node = node;
-                       node = g_list_next (node);
-                       g_object_unref (part);
-                       mime_parts = g_list_delete_link (mime_parts, deleted_node);
-               } else {
-                       node = g_list_next (node);
+                       tny_list_remove (mime_parts, (GObject *) part);
                }
+               g_object_unref (part);
        }
+       g_object_unref (iter);
 
-       if (mime_parts == NULL)
+       if (tny_list_get_length (mime_parts) == 0) {
+               g_object_unref (mime_parts);
                return;
+       }
 
-       n_attachments = g_list_length (mime_parts);
+       n_attachments = tny_list_get_length (mime_parts);
        if (n_attachments == 1) {
-               const gchar *filename;
+               gchar *filename;
+               TnyMimePart *part;
 
-               if (TNY_IS_MSG (mime_parts->data)) {
+               iter = tny_list_create_iterator (mime_parts);
+               part = (TnyMimePart *) tny_iterator_get_current (iter);
+               g_object_unref (iter);
+               if (modest_tny_mime_part_is_msg (part)) {
                        TnyHeader *header;
-                       header = tny_msg_get_header (TNY_MSG (mime_parts->data));
-                       filename = tny_header_get_subject (header);
+                       header = tny_msg_get_header (TNY_MSG (part));
+                       filename = tny_header_dup_subject (header);
                        g_object_unref (header);
                        if (filename == NULL)
-                               filename = _("mail_va_no_subject");
+                               filename = g_strdup (_("mail_va_no_subject"));
                } else {
-                       filename = tny_mime_part_get_filename (TNY_MIME_PART (mime_parts->data));
+                       filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
                }
                confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
+               g_free (filename);
+               g_object_unref (part);
        } else {
                confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text", 
                                                                 "mcen_nc_purge_files_text", 
@@ -2658,8 +2858,10 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean
                                                            confirmation_message);
        g_free (confirmation_message);
 
-       if (response != GTK_RESPONSE_OK)
+       if (response != GTK_RESPONSE_OK) {
+               g_object_unref (mime_parts);
                return;
+       }
 
        priv->purge_timeout = g_timeout_add (2000, show_remove_attachment_information, window);
 /*     folder = tny_msg_get_folder (msg); */
@@ -2667,18 +2869,25 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean
 /*     tny_folder_refresh (folder, NULL); */
 /*     g_object_unref (folder); */
        
-       for (node = mime_parts; node != NULL; node = g_list_next (node)) {
-               tny_mime_part_set_purged (TNY_MIME_PART (node->data));
+       iter = tny_list_create_iterator (mime_parts);
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part;
+
+               part = (TnyMimePart *) tny_iterator_get_current (iter);
+               tny_mime_part_set_purged (TNY_MIME_PART (part));
 /*             modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
+               g_object_unref (part);
+               tny_iterator_next (iter);
        }
+       g_object_unref (iter);
 
        msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
        tny_msg_view_clear (TNY_MSG_VIEW (priv->msg_view));
        tny_msg_rewrite_cache (msg);
        tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
+       g_object_unref (msg);
 
-       g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
-       g_list_free (mime_parts);
+       g_object_unref (mime_parts);
 
        if (priv->purge_timeout > 0) {
                g_source_remove (priv->purge_timeout);
@@ -2701,18 +2910,21 @@ update_window_title (ModestMsgViewWindow *window)
        ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
        TnyMsg *msg = NULL;
        TnyHeader *header = NULL;
-       const gchar *subject = NULL;
+       gchar *subject = NULL;
        
        msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
 
        if (msg != NULL) {
                header = tny_msg_get_header (msg);
-               subject = tny_header_get_subject (header);
+               subject = tny_header_dup_subject (header);
+               g_object_unref (header);
                g_object_unref (msg);
        }
 
-       if ((subject == NULL)||(subject[0] == '\0'))
-               subject = _("mail_va_no_subject");
+       if ((subject == NULL)||(subject[0] == '\0')) {
+               g_free (subject);
+               subject = g_strdup (_("mail_va_no_subject"));
+       }
 
        gtk_window_set_title (GTK_WINDOW (window), subject);
 }