* Changed the signature of the refresh folder callback. This will allow us to know...
[modest] / src / modest-ui-actions.c
index 834beeb..ea02866 100644 (file)
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif /*HAVE_CONFIG_H*/
 
 #include <glib/gi18n.h>
+#include <glib/gprintf.h>
 #include <string.h>
 #include <modest-runtime.h>
 #include <modest-tny-folder.h>
 #include <modest-tny-msg.h>
 #include <modest-tny-account.h>
 #include <modest-address-book.h>
-
+#include "modest-error.h"
 #include "modest-ui-actions.h"
 
 #include "modest-tny-platform-factory.h"
 #include "modest-platform.h"
+#include <tny-mime-part.h>
+
+#ifdef MODEST_PLATFORM_MAEMO
+#include "maemo/modest-osso-state-saving.h"
+#endif /* MODEST_PLATFORM_MAEMO */
 
+#include "widgets/modest-ui-constants.h"
 #include <widgets/modest-main-window.h>
 #include <widgets/modest-msg-view-window.h>
 #include <widgets/modest-account-view-window.h>
 #include <widgets/modest-details-dialog.h>
-
+#include <widgets/modest-attachments-view.h>
+#include "widgets/modest-folder-view.h"
+#include "widgets/modest-global-settings-dialog.h"
+#include "modest-connection-specific-smtp-window.h"
 #include "modest-account-mgr-helpers.h"
 #include "modest-mail-operation.h"
 #include "modest-text-utils.h"
 
 #ifdef MODEST_HAVE_EASYSETUP
 #include "easysetup/modest-easysetup-wizard.h"
-#endif /*MODEST_HAVE_EASYSETUP*/
+#endif /* MODEST_HAVE_EASYSETUP */
 
 #include <modest-widget-memory.h>
 #include <tny-error.h>
 #include <tny-simple-list.h>
 #include <tny-msg-view.h>
 #include <tny-device.h>
+#include <tny-merge-folder.h>
+
+#include <gtkhtml/gtkhtml.h>
 
-typedef struct _GetMsgAsyncHelper {
+typedef struct _GetMsgAsyncHelper {    
        ModestWindow *window;
+       ModestMailOperation *mail_op;
        TnyIterator *iter;
-       GFunc func;
+       guint num_ops;
+       GFunc func;     
        gpointer user_data;
 } GetMsgAsyncHelper;
 
@@ -77,19 +92,54 @@ typedef enum _ReplyForwardAction {
 } ReplyForwardAction;
 
 typedef struct _ReplyForwardHelper {
-guint reply_forward_type;
+       guint reply_forward_type;
        ReplyForwardAction action;
        gchar *account_name;
+       GtkWidget *parent_window;
 } ReplyForwardHelper;
 
 
-static void     reply_forward_func     (gpointer data, gpointer user_data);
-static void     read_msg_func          (gpointer data, gpointer user_data);
-static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg,        GError **err, 
+/*
+ * The do_headers_action uses this kind of functions to perform some
+ * action to each member of a list of headers
+ */
+typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
+
+static void     do_headers_action     (ModestWindow *win, 
+                                      HeadersFunc func,
+                                      gpointer user_data);
+
+static void     open_msg_cb            (ModestMailOperation *mail_op, 
+                                       TnyHeader *header, 
+                                       TnyMsg *msg,
                                        gpointer user_data);
+
+static void     reply_forward_cb       (ModestMailOperation *mail_op, 
+                                       TnyHeader *header, 
+                                       TnyMsg *msg,
+                                       gpointer user_data);
+
 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
 
-static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
+
+static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
+                                                  ModestMailOperationState *state,
+                                                  gpointer user_data);
+
+
+
+static void
+run_account_setup_wizard (ModestWindow *win)
+{
+       ModestEasysetupWizardDialog *wizard;
+
+       g_return_if_fail (MODEST_IS_WINDOW(win));
+       
+       wizard = modest_easysetup_wizard_dialog_new ();
+       gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
+       gtk_dialog_run (GTK_DIALOG (wizard));
+       gtk_widget_destroy (GTK_WIDGET (wizard));
+}
 
 
 void   
@@ -118,7 +168,14 @@ modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
        gtk_widget_destroy(about);
 }
 
-
+/*
+ * Gets the list of currently selected messages. If the win is the
+ * main window, then it returns a newly allocated list of the headers
+ * selected in the header view. If win is the msg view window, then
+ * the value returned is a list with just a single header.
+ *
+ * The caller of this funcion must free the list.
+ */
 static TnyList *
 get_selected_headers (ModestWindow *win)
 {
@@ -131,84 +188,222 @@ get_selected_headers (ModestWindow *win)
                
        } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
                /* for MsgViewWindows, we simply return a list with one element */
-               TnyMsg *msg;
                TnyHeader *header;
                TnyList *list = NULL;
                
-               msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
-               if (msg) {
-                       header = tny_msg_get_header (msg);
+               header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
+               if (header != NULL) {
                        list = tny_simple_list_new ();
                        tny_list_prepend (list, G_OBJECT(header));
                        g_object_unref (G_OBJECT(header));
                }
+
                return list;
 
        } else
                return NULL;
 }
 
+static void
+headers_action_mark_as_read (TnyHeader *header,
+                            ModestWindow *win,
+                            gpointer user_data)
+{
+       TnyHeaderFlags flags;
+
+       g_return_if_fail (TNY_IS_HEADER(header));
+
+       flags = tny_header_get_flags (header);
+       if (flags & TNY_HEADER_FLAG_SEEN) return;
+       tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
+}
+
+static void
+headers_action_mark_as_unread (TnyHeader *header,
+                              ModestWindow *win,
+                              gpointer user_data)
+{
+       TnyHeaderFlags flags;
+
+       g_return_if_fail (TNY_IS_HEADER(header));
+
+       flags = tny_header_get_flags (header);
+       if (flags & TNY_HEADER_FLAG_SEEN)  {
+               tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
+       }
+}
+
+
+static void
+headers_action_delete (TnyHeader *header,
+                      ModestWindow *win,
+                      gpointer user_data)
+{
+       ModestMailOperation *mail_op = NULL;
+
+       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
+                                        mail_op);
+       
+       /* Always delete. TODO: Move to trash still not supported */
+       modest_mail_operation_remove_msg (mail_op, header, FALSE);
+       g_object_unref (G_OBJECT (mail_op));
+
+       /* refilter treemodel to hide marked-as-deleted rows */
+       if (MODEST_IS_HEADER_VIEW (user_data))
+               modest_header_view_refilter (MODEST_HEADER_VIEW (user_data));
+}
+
 void
 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
 {
-       TnyList *header_list;
-       TnyIterator *iter;
+       TnyList *header_list = NULL;
+       TnyIterator *iter = NULL;
+       TnyHeader *header = NULL;
+       gchar *message = NULL;
+       gchar *desc = NULL;
+       gint response;
+       ModestWindowMgr *mgr;
+       GtkWidget *header_view = NULL;
 
        g_return_if_fail (MODEST_IS_WINDOW(win));
-               
-       header_list = get_selected_headers (win);
        
-       if (header_list) {
-               iter = tny_list_create_iterator (header_list);
-               do {
-                       TnyHeader *header;
-                       ModestMailOperation *mail_op;
+       /* Check first if the header view has the focus */
+       if (MODEST_IS_MAIN_WINDOW (win)) {
+               header_view = 
+                       modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
+                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
+               if (!gtk_widget_is_focus (header_view))
+                       return;
+       }
+       
+       header_list = get_selected_headers (win);
+       if (!header_list) return;
 
+       /* Check if any of the headers is already opened, or in the process of being opened */
+       if (MODEST_IS_MAIN_WINDOW (win)) {
+               gboolean found;
+               iter = tny_list_create_iterator (header_list);
+               found = FALSE;
+               mgr = modest_runtime_get_window_mgr ();
+               while (!tny_iterator_is_done (iter) && !found) {
                        header = TNY_HEADER (tny_iterator_get_current (iter));
-                       /* TODO: thick grain mail operation involving
-                          a list of objects. Composite pattern ??? */
-                       /* TODO: add confirmation dialog */
-                       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE);
-                       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
-                                                        mail_op);
+                       found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
+                       g_object_unref (header);
+                       tny_iterator_next (iter);
+               }
+               g_object_unref (iter);
 
-                       /* Always delete. TODO: Move to trash still not supported */
-                       modest_mail_operation_remove_msg (mail_op, header, FALSE);
+               if (found) {
+                       gchar *num, *msg;
 
-                       /* Frees */
-                       g_object_unref (G_OBJECT (mail_op));
-                       g_object_unref (G_OBJECT (header));
+                       num = g_strdup_printf ("%d", tny_list_get_length (header_list));
+                       msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
 
-                       tny_iterator_next (iter);
+                       modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
+                       
+                       g_free (msg);
+                       g_free (num);
+                       g_object_unref (header_list);
+                       return;
+               }
+       }
+
+       /* Select message */
+       if (tny_list_get_length(header_list) == 1) {
+               iter = tny_list_create_iterator (header_list);
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
+               g_object_unref (header);
+               g_object_unref (iter);
+       }
+       message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
+                                          tny_list_get_length(header_list)), desc);
+
+       /* Confirmation dialog */               
+       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
+                                                           message);
+       
+
+       if (response == GTK_RESPONSE_OK) {      
+               ModestMainWindow *main_window;
+               ModestWindowMgr *mgr;
+
+               /* Remove each header. If it's a view window header_view == NULL */
+               do_headers_action (win, headers_action_delete, header_view);
+
+               if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
+                       /* Close msg view window or select next */
+                       if (modest_msg_view_window_last_message_selected (MODEST_MSG_VIEW_WINDOW (win)) &&
+                           modest_msg_view_window_first_message_selected (MODEST_MSG_VIEW_WINDOW (win))) {
+                               modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
+                       } else {
+                               modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (win));
+                       }
+               }
+
+               /* Refilter header view model, if main window still exists */
+               mgr = modest_runtime_get_window_mgr ();
+               main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
+               if (main_window) {
+                       GtkWidget *widget;
 
-               } while (!tny_iterator_is_done (iter));
+                       widget = modest_main_window_get_child_widget (main_window,
+                                                                     MODEST_WIDGET_TYPE_HEADER_VIEW);
+                       modest_header_view_refilter (MODEST_HEADER_VIEW (widget));
 
-               /* Free iter */
-               g_object_unref (G_OBJECT (iter));
+                       /* Update toolbar dimming state */
+                       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
+               }
        }
 
-       if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
-               gtk_widget_destroy (GTK_WIDGET(win));
-       } 
+       /* free */
+       g_free(message);
+       g_free(desc);
+       g_object_unref (header_list);
 }
 
 
 void
 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
 {
+#ifdef MODEST_PLATFORM_MAEMO
+       modest_osso_save_state();
+#endif /* MODEST_PLATFORM_MAEMO */
+
+       g_debug ("closing down, clearing %d item(s) from operation queue",
+                modest_mail_operation_queue_num_elements
+                (modest_runtime_get_mail_operation_queue()));
+
+       /* cancel all outstanding operations */
+       modest_mail_operation_queue_cancel_all 
+               (modest_runtime_get_mail_operation_queue());
+       
+       g_debug ("queue has been cleared");
+
+       /* note: when modest-tny-account-store is finalized,
+          it will automatically set all network connections
+          to offline */
+
        gtk_main_quit ();
 }
 
 void
 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
 {
-       if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
-               gtk_widget_destroy (GTK_WIDGET (win));
-       } else if (MODEST_IS_WINDOW (win)) {
-               gtk_widget_destroy (GTK_WIDGET (win));
-       } else {
-               g_return_if_reached ();
-       }
+       gboolean ret_value;
+       g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
+
+/*     if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
+/*             gtk_widget_destroy (GTK_WIDGET (win)); */
+/*     } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
+/*             gboolean ret_value; */
+/*             g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
+/*     } else if (MODEST_IS_WINDOW (win)) { */
+/*             gtk_widget_destroy (GTK_WIDGET (win)); */
+/*     } else { */
+/*             g_return_if_reached (); */
+/*     } */
 }
 
 void
@@ -220,29 +415,24 @@ modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
        clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
        selection = gtk_clipboard_wait_for_text (clipboard);
 
-       modest_address_book_add_address (selection);
-       g_free (selection);
+       /* Question: why is the clipboard being used here? 
+        * It doesn't really make a lot of sense. */
+
+       if (selection)
+       {
+               modest_address_book_add_address (selection);
+               g_free (selection);
+       }
 }
 
 void
 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
 {
-       
-       /* This is currently only implemented for Maemo,
-        * because it requires a providers preset file which is not publically available.
-        */
+       /* This is currently only implemented for Maemo */
 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
-       GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
-       gboolean accounts_exist = account_names != NULL;
-       g_slist_free (account_names);
-       
-/* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
-       if (!accounts_exist) {
-               /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
-               ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
-               gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
-               gtk_dialog_run (GTK_DIALOG (wizard));
-               gtk_widget_destroy (GTK_WIDGET (wizard));
+       if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
+               run_account_setup_wizard (win);
+               return;
        } else  {
                /* Show the list of accounts: */
                GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
@@ -277,27 +467,86 @@ modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
 #endif /* MODEST_PLATFORM_MAEMO */
 }
 
+static void
+on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
+{
+       ModestWindow *main_window = MODEST_WINDOW (user_data);
+       
+       /* Save any changes. */
+       modest_connection_specific_smtp_window_save_server_accounts (
+                       MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
+                       modest_window_get_active_account (main_window));
+       gtk_widget_destroy (GTK_WIDGET (window));
+}
+
+
+
+void
+modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
+{
+       /* This is currently only implemented for Maemo,
+        * because it requires an API (libconic) to detect different connection 
+        * possiblities.
+        */
+#ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
+       
+       /* Create the window if necessary: */
+       const gchar *active_account_name = modest_window_get_active_account (win);
+       
+       /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
+        * or show the default account?
+        * If we show the default account then the account name should be shown in 
+        * the window when we show it. */
+       if (!active_account_name) {
+               g_warning ("%s: No account is active.", __FUNCTION__);
+               return;
+       }
+               
+       GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
+       modest_connection_specific_smtp_window_fill_with_connections (
+               MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
+               modest_runtime_get_account_mgr(), 
+               active_account_name);
+
+       /* Show the window: */  
+       gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
+       gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
+       gtk_widget_show (specific_window);
+    
+       /* Save changes when the window is hidden: */
+       g_signal_connect (specific_window, "hide", 
+               G_CALLBACK (on_smtp_servers_window_hide), win);
+#endif /* MODEST_PLATFORM_MAEMO */
+}
+
 void
 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
 {
-       ModestWindow *msg_win;
+       ModestWindow *msg_win = NULL;
        TnyMsg *msg = NULL;
        TnyFolder *folder = NULL;
        gchar *account_name = NULL;
        gchar *from_str = NULL;
-       GError *err = NULL;
+/*     GError *err = NULL; */
        TnyAccount *account = NULL;
        ModestWindowMgr *mgr;
+       gchar *signature = NULL, *blank_and_signature = NULL;
+
+       /* if there are no accounts yet, just show the wizard */
+       if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
+                       run_account_setup_wizard (win);
+                       return;
+       }
        
-       account_name = g_strdup(modest_window_get_active_account (win));
+       account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
        if (!account_name)
-               account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
+               account_name = g_strdup (modest_window_get_active_account (win));
        if (!account_name) {
                g_printerr ("modest: no account found\n");
                goto cleanup;
        }
        
-       account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
+       account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
                                                                       account_name,
                                                                       TNY_ACCOUNT_TYPE_STORE);
        if (!account) {
@@ -311,7 +560,17 @@ modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
                goto cleanup;
        }
 
-       msg = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
+       if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
+                                        MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
+               signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
+                                                          MODEST_ACCOUNT_SIGNATURE, FALSE);
+               blank_and_signature = g_strconcat ("\n", signature, NULL);
+               g_free (signature);
+       } else {
+               blank_and_signature = g_strdup ("");
+       }
+
+       msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
        if (!msg) {
                g_printerr ("modest: failed to create new msg\n");
                goto cleanup;
@@ -323,15 +582,9 @@ modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
                goto cleanup;
        }
        
-       tny_folder_add_msg (folder, msg, &err);
-       if (err) {
-               g_printerr ("modest: error adding msg to Drafts folder: %s",
-                           err->message);
-               g_error_free (err);
-               goto cleanup;
-       }
 
        /* Create and register edit window */
+       /* This is destroyed by TOOD. */
        msg_win = modest_msg_edit_window_new (msg, account_name);
        mgr = modest_runtime_get_window_mgr ();
        modest_window_mgr_register_window (mgr, msg_win);
@@ -344,6 +597,9 @@ modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
 cleanup:
        g_free (account_name);
        g_free (from_str);
+       g_free (blank_and_signature);
+       if (msg_win)
+               g_object_unref (msg_win);
        if (account)
                g_object_unref (G_OBJECT(account));
        if (msg)
@@ -352,128 +608,523 @@ cleanup:
                g_object_unref (G_OBJECT(folder));
 }
 
-
-void
-modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
+gboolean 
+modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
+                                      TnyHeader *header,
+                                      TnyMsg *msg)
 {
-       modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
-}
+       ModestMailOperationStatus status;
+
+       /* If there is no message or the operation was not successful */
+       status = modest_mail_operation_get_status (mail_op);
+       if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
 
+               /* Remove the header from the preregistered uids */
+               modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
+                                                    header);
 
+               return FALSE;
+       }
+
+       return TRUE;
+}
 
 static void
-reply_forward_func (gpointer data, gpointer user_data)
+open_msg_cb (ModestMailOperation *mail_op, 
+            TnyHeader *header, 
+            TnyMsg *msg, 
+            gpointer user_data)
 {
-       TnyMsg *msg, *new_msg;
-       GetMsgAsyncHelper *helper;
-       ReplyForwardHelper *rf_helper;
-       ModestWindow *msg_win;
-       ModestEditType edit_type;
-       gchar *from;
-       GError *err = NULL;
-       TnyFolder *folder = NULL;
-       TnyAccount *account = NULL;
-       ModestWindowMgr *mgr;
+       ModestWindowMgr *mgr = NULL;
+       ModestWindow *parent_win = NULL;
+       ModestWindow *win = NULL;
+       TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
+       gchar *account = NULL;
+       TnyFolder *folder;
        
-       msg = TNY_MSG (data);
-       helper = (GetMsgAsyncHelper *) user_data;
-       rf_helper = (ReplyForwardHelper *) helper->user_data;
-
-       from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
-                                                  rf_helper->account_name);
-       /* Create reply mail */
-       switch (rf_helper->action) {
-       case ACTION_REPLY:
-               new_msg = 
-                       modest_tny_msg_create_reply_msg (msg,  from, 
-                                                        rf_helper->reply_forward_type,
-                                                        MODEST_TNY_MSG_REPLY_MODE_SENDER);
-               break;
-       case ACTION_REPLY_TO_ALL:
-               new_msg = 
-                       modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
-                                                        MODEST_TNY_MSG_REPLY_MODE_ALL);
-               edit_type = MODEST_EDIT_TYPE_REPLY;
-               break;
-       case ACTION_FORWARD:
-               new_msg = 
-                       modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
-               edit_type = MODEST_EDIT_TYPE_FORWARD;
-               break;
-       default:
-               g_return_if_reached ();
+       /* Do nothing if there was any problem with the mail
+          operation. The error will be shown by the error_handler of
+          the mail operation */
+       if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
+               printf ("DEBUG: %s: modest_ui_actions_msg_retrieval_check() failed.\n", 
+                       __FUNCTION__);
                return;
        }
 
-       if (!new_msg) {
-               g_printerr ("modest: failed to create message\n");
-               goto cleanup;
-       }
+       parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
+       folder = tny_header_get_folder (header);
 
-       account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
-                                                                      rf_helper->account_name,
-                                                                      TNY_ACCOUNT_TYPE_STORE);
-       if (!account) {
-               g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
-               goto cleanup;
-       }
+       /* Mark header as read */
+       headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
 
-       folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
-       if (!folder) {
-               g_printerr ("modest: failed to find Drafts folder\n");
-               goto cleanup;
-       }
+       /* Get account */
+       account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
+       if (!account)
+               account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
        
-       tny_folder_add_msg (folder, msg, &err);
-       if (err) {
-               g_printerr ("modest: error adding msg to Drafts folder: %s",
-                           err->message);
-               g_error_free (err);
-               goto cleanup;
-       }       
+       /* Gets folder type (OUTBOX headers will be opened in edit window */
+       if (modest_tny_folder_is_local_folder (folder))
+               folder_type = modest_tny_folder_get_local_folder_type (folder);
+
+       /* If the header is in the drafts folder then open the editor,
+          else the message view window */
+       if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
+               /* we cannot edit without a valid account... */
+               if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
+                       run_account_setup_wizard(parent_win);
+                       goto cleanup;
+               }
+               win = modest_msg_edit_window_new (msg, account);
+       } else {
+               gchar *uid = modest_tny_folder_get_header_unique_id (header);
+               
+               if (MODEST_IS_MAIN_WINDOW (parent_win)) {
+                       GtkWidget *header_view;
+                       GtkTreeSelection *sel;
+                       GList *sel_list = NULL;
+                       GtkTreeModel *model;
+                       
+                       header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
+                                                                          MODEST_WIDGET_TYPE_HEADER_VIEW);
 
-       /* Create and register the windows */                   
-       msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
-       mgr = modest_runtime_get_window_mgr ();
-       modest_window_mgr_register_window (mgr, msg_win);
+                       sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
+                       sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
 
-       /* Show edit window */
-       gtk_widget_show_all (GTK_WIDGET (msg_win));
+                       if (sel_list != NULL) {
+                               GtkTreeRowReference *row_reference;
 
-cleanup:
-       if (new_msg)
-               g_object_unref (G_OBJECT (new_msg));
-       if (folder)
-               g_object_unref (G_OBJECT (folder));
-       if (account)
-               g_object_unref (G_OBJECT (account));
+                               row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
+                               g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
+                               g_list_free (sel_list);
+                               
+                               win = modest_msg_view_window_new_with_header_model (msg, 
+                                                                                   account,
+                                                                                   (const gchar*) uid,
+                                                                                   model, 
+                                                                                   row_reference);
+                               gtk_tree_row_reference_free (row_reference);
+                       } else {
+                               win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
+                       }
+               } else {
+                       win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
+               }
+               g_free (uid);
+       }
        
-       g_free (rf_helper->account_name);
-       g_slice_free (ReplyForwardHelper, rf_helper);
+       /* Register and show new window */
+       if (win != NULL) {
+               mgr = modest_runtime_get_window_mgr ();
+               modest_window_mgr_register_window (mgr, win);
+               g_object_unref (win);
+               gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
+               gtk_widget_show_all (GTK_WIDGET(win));
+       }
+
+       /* Update toolbar dimming state */
+       if (MODEST_IS_MAIN_WINDOW (parent_win)) {
+               modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
+       }
+
+cleanup:
+       /* Free */
+       g_free(account);
+       g_object_unref (parent_win);
+/*     g_object_unref (msg); */
+       g_object_unref (folder);
+}
+
+void
+modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
+                                              gpointer user_data)
+{
+       const GError *error;
+       GObject *win = modest_mail_operation_get_source (mail_op);
+
+       error = modest_mail_operation_get_error (mail_op);
+       printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
+       if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
+
+               modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
+                                                       error->message);
+       } else {
+               modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
+                                                       _("mail_ni_ui_folder_get_msg_folder_error"));
+       }
+
+       if (win)
+               g_object_unref (win);
 }
+
 /*
- * Common code for the reply and forward actions
+ * This function is used by both modest_ui_actions_on_open and
+ * modest_ui_actions_on_header_activated. This way we always do the
+ * same when trying to open messages.
  */
 static void
-reply_forward (ReplyForwardAction action, ModestWindow *win)
-{
-       TnyList *header_list;
-       guint reply_forward_type;
-       TnyHeader *header;
-       TnyFolder *folder;
-       GetMsgAsyncHelper *helper;
-       ReplyForwardHelper *rf_helper;
-       
-       g_return_if_fail (MODEST_IS_WINDOW(win));
+_modest_ui_actions_open (TnyList *headers, ModestWindow *win)
+{
+       ModestWindowMgr *mgr = NULL;
+       TnyIterator *iter = NULL;
+       ModestMailOperation *mail_op1 = NULL;
+       ModestMailOperation *mail_op2 = NULL;
+       TnyList *not_opened_headers = NULL;
+       TnyList *not_opened_cached_headers = NULL;
+       TnyHeaderFlags flags;
+               
+       /* Look if we already have a message view for each header. If
+          true, then remove the header from the list of headers to
+          open */
+       mgr = modest_runtime_get_window_mgr ();
+       iter = tny_list_create_iterator (headers);
+       not_opened_headers = tny_simple_list_new ();
+       not_opened_cached_headers = tny_simple_list_new ();
+       while (!tny_iterator_is_done (iter)) {
 
-       header_list = get_selected_headers (win);
-       if (!header_list)
-               return;
-       
-       reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
-                                                 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
-                                                 NULL);
-       /* We assume that we can only select messages of the
+               ModestWindow *window;
+               TnyHeader *header;
+               gboolean found;
+               
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               flags = tny_header_get_flags (header);
+
+               window = NULL;
+               found = modest_window_mgr_find_registered_header (mgr, header, &window);
+               
+               /* Do not open again the message and present the
+                  window to the user */
+               if (found) {
+                       if (window)
+                               gtk_window_present (GTK_WINDOW (window));
+                       else
+                               /* the header has been registered already, we don't do
+                                * anything but wait for the window to come up*/
+                               g_warning ("debug: header %p already registered, waiting for window",
+                                          header);
+               } else {
+                       if (!(flags & TNY_HEADER_FLAG_CACHED))
+                               tny_list_append (not_opened_headers, G_OBJECT (header));
+                       /* Check if msg has already been retreived */
+                       else
+                               tny_list_append (not_opened_cached_headers, G_OBJECT (header));
+               }
+               g_object_unref (header);
+               tny_iterator_next (iter);
+       }
+       g_object_unref (iter);
+       iter = NULL;
+       
+       /* If some messages would have to be downloaded, ask the user to 
+        * make a connection. It's generally easier to do this here (in the mainloop) 
+        * than later in a thread:
+        */
+       if (tny_list_get_length (not_opened_cached_headers) > 0) {
+               gboolean connected = modest_platform_connect_and_wait (GTK_WINDOW (win));
+               
+               /* Don't go further if a connection would be necessary but none is available: */
+               if (!connected) {
+                       g_object_unref (not_opened_headers);
+                       g_object_unref (not_opened_cached_headers);
+                       return;
+               }
+       }
+       
+       /* Register the headers before actually creating the windows: */
+       TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
+       while (!tny_iterator_is_done (iter_not_opened)) {
+               TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
+               modest_window_mgr_register_header (mgr, header);
+               g_object_unref (header);
+               
+               tny_iterator_next (iter_not_opened);
+       }
+       g_object_unref (iter_not_opened);
+       iter_not_opened = NULL;
+       
+       TnyIterator *iter_cached = tny_list_create_iterator (not_opened_cached_headers);
+       while (!tny_iterator_is_done (iter_cached)) {
+               TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_cached));
+               modest_window_mgr_register_header (mgr, header);
+               g_object_unref (header);
+               
+               tny_iterator_next (iter_cached);
+       }
+       g_object_unref (iter_cached);
+       iter_cached = NULL;
+       
+       
+       /* Open each uncached message */
+       if (tny_list_get_length (not_opened_headers) > 0) {
+               mail_op1 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                        G_OBJECT (win), 
+                                                                        modest_ui_actions_get_msgs_full_error_handler, 
+                                                                        NULL);
+               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op1);
+               if (tny_list_get_length (not_opened_headers) > 1) {
+                       modest_mail_operation_get_msgs_full (mail_op1, 
+                                                            not_opened_headers, 
+                                                            open_msg_cb, 
+                                                            NULL, 
+                                                            NULL);
+               } else {
+                       TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
+                       TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
+                       modest_mail_operation_get_msg (mail_op1, header, open_msg_cb, NULL);
+                       g_object_unref (header);
+                       g_object_unref (iter);
+               }
+       }
+
+       /* Open each cached message */
+       if (tny_list_get_length (not_opened_cached_headers) > 0) {
+               mail_op2 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                        G_OBJECT (win), 
+                                                                        modest_ui_actions_get_msgs_full_error_handler, 
+                                                                        NULL);
+               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op2);
+               if (tny_list_get_length (not_opened_cached_headers) > 1) {
+                       modest_mail_operation_get_msgs_full (mail_op2, 
+                                                            not_opened_headers, 
+                                                            open_msg_cb, 
+                                                            NULL, 
+                                                            NULL);
+               } else {
+                       TnyIterator *iter = tny_list_create_iterator (not_opened_cached_headers);
+                       TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
+                       modest_mail_operation_get_msg (mail_op2, header, open_msg_cb, NULL);
+                       g_object_unref (header);
+                       g_object_unref (iter);
+               }
+       }
+
+       /* Clean */
+       if (not_opened_headers != NULL)
+               g_object_unref (not_opened_headers);
+       if (not_opened_cached_headers != NULL)
+               g_object_unref (not_opened_cached_headers);
+       if (iter != NULL) 
+               g_object_unref (iter);
+       if (mail_op1 != NULL)
+               g_object_unref (mail_op1);
+       if (mail_op2 != NULL) 
+               g_object_unref (mail_op2);
+}
+
+void
+modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
+{
+       TnyList *headers;
+
+       /* Get headers */
+       headers = get_selected_headers (win);
+       if (!headers)
+               return;
+
+       /* Open them */
+       _modest_ui_actions_open (headers, win);
+
+       g_object_unref(headers);
+}
+
+
+static void
+free_reply_forward_helper (gpointer data)
+{
+       ReplyForwardHelper *helper;
+
+       helper = (ReplyForwardHelper *) data;
+       g_free (helper->account_name);
+       g_slice_free (ReplyForwardHelper, helper);
+}
+
+static void
+reply_forward_cb (ModestMailOperation *mail_op, 
+                 TnyHeader *header, 
+                 TnyMsg *msg,
+                 gpointer user_data)
+{
+       TnyMsg *new_msg;
+       ReplyForwardHelper *rf_helper;
+       ModestWindow *msg_win = NULL;
+       ModestEditType edit_type;
+       gchar *from = NULL;
+       TnyAccount *account = NULL;
+       ModestWindowMgr *mgr = NULL;
+       gchar *signature = NULL;
+
+       /* If there was any error */
+       if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
+               return;
+                       
+       g_return_if_fail (user_data != NULL);
+       rf_helper = (ReplyForwardHelper *) user_data;
+
+       from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
+                                                  rf_helper->account_name);
+       if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
+                                        rf_helper->account_name,
+                                        MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
+               signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
+                                                          rf_helper->account_name,
+                                                          MODEST_ACCOUNT_SIGNATURE, FALSE);
+       }
+
+       /* Create reply mail */
+       switch (rf_helper->action) {
+       case ACTION_REPLY:
+               new_msg = 
+                       modest_tny_msg_create_reply_msg (msg,  from, signature,
+                                                        rf_helper->reply_forward_type,
+                                                        MODEST_TNY_MSG_REPLY_MODE_SENDER);
+               break;
+       case ACTION_REPLY_TO_ALL:
+               new_msg = 
+                       modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
+                                                        MODEST_TNY_MSG_REPLY_MODE_ALL);
+               edit_type = MODEST_EDIT_TYPE_REPLY;
+               break;
+       case ACTION_FORWARD:
+               new_msg = 
+                       modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
+               edit_type = MODEST_EDIT_TYPE_FORWARD;
+               break;
+       default:
+               g_return_if_reached ();
+               return;
+       }
+
+       g_free (signature);
+
+       if (!new_msg) {
+               g_printerr ("modest: failed to create message\n");
+               goto cleanup;
+       }
+
+       account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
+                                                                      rf_helper->account_name,
+                                                                      TNY_ACCOUNT_TYPE_STORE);
+       if (!account) {
+               g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
+               goto cleanup;
+       }
+
+       /* Create and register the windows */
+       msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
+       mgr = modest_runtime_get_window_mgr ();
+       modest_window_mgr_register_window (mgr, msg_win);
+
+       if (rf_helper->parent_window != NULL) {
+               gdouble parent_zoom;
+
+               parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
+               modest_window_set_zoom (msg_win, parent_zoom);
+       }
+
+       /* Show edit window */
+       gtk_widget_show_all (GTK_WIDGET (msg_win));
+
+cleanup:
+       if (msg_win)
+               g_object_unref (msg_win);
+       if (new_msg)
+               g_object_unref (G_OBJECT (new_msg));
+       if (account)
+               g_object_unref (G_OBJECT (account));
+/*     g_object_unref (msg); */
+       g_object_unref (header);
+       free_reply_forward_helper (rf_helper);
+}
+
+/*
+ * Checks a list of headers. If any of them are not currently
+ * downloaded (CACHED) then it asks the user for permission to
+ * download them.
+ *
+ * Returns FALSE if the user does not want to download the
+ * messages. Returns TRUE if the user allowed the download or if all
+ * of them are currently downloaded
+ */
+static gboolean
+download_uncached_messages (TnyList *header_list, GtkWindow *win)
+{
+       TnyIterator *iter;
+       gboolean retval;
+       gint uncached_messages = 0;
+
+       iter = tny_list_create_iterator (header_list);
+       while (!tny_iterator_is_done (iter)) {
+               TnyHeader *header;
+               TnyHeaderFlags flags;
+
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               flags = tny_header_get_flags (header);
+               /* TODO: is this the right flag?, it seems that some
+                  headers that have been previously downloaded do not
+                  come with it */
+               if (! (flags & TNY_HEADER_FLAG_CACHED))
+                       uncached_messages ++;
+               g_object_unref (header);
+               tny_iterator_next (iter);
+       }
+       g_object_unref (iter);
+
+       /* Ask for user permission to download the messages */
+       retval = TRUE;
+       if (uncached_messages > 0) {
+               GtkResponseType response;
+               response = 
+                       modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
+                                                                ngettext("mcen_nc_get_msg",
+                                                                         "mcen_nc_get_msgs",
+                                                                        uncached_messages));
+               if (response == GTK_RESPONSE_CANCEL)
+                       retval = FALSE;
+               else {
+                       /* If a download will be necessary, make sure that we have a connection: */
+                       retval = modest_platform_connect_and_wait(win); 
+               }
+       }
+       return retval;
+}
+
+
+/*
+ * Common code for the reply and forward actions
+ */
+static void
+reply_forward (ReplyForwardAction action, ModestWindow *win)
+{
+       ModestMailOperation *mail_op = NULL;
+       TnyList *header_list = NULL;
+       ReplyForwardHelper *rf_helper = NULL;
+       guint reply_forward_type;
+       gboolean continue_download;
+       
+       g_return_if_fail (MODEST_IS_WINDOW(win));
+
+       /* we need an account when editing */
+       if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
+               run_account_setup_wizard (win);
+               return;
+       }
+       
+       header_list = get_selected_headers (win);
+       if (!header_list)
+               return;
+
+       /* Check that the messages have been previously downloaded */
+       continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
+       if (!continue_download) {
+               g_object_unref (header_list);
+               return;
+       }
+       
+       reply_forward_type = 
+               modest_conf_get_int (modest_runtime_get_conf (),
+                                    (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
+                                    NULL);
+       /* We assume that we can only select messages of the
           same folder and that we reply all of them from the
           same account. In fact the interface currently only
           allows single selection */
@@ -482,41 +1133,64 @@ reply_forward (ReplyForwardAction action, ModestWindow *win)
        rf_helper = g_slice_new0 (ReplyForwardHelper);
        rf_helper->reply_forward_type = reply_forward_type;
        rf_helper->action = action;
-
        rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
+       if ((win != NULL) && (MODEST_IS_WINDOW (win)))
+               rf_helper->parent_window = GTK_WIDGET (win);
        if (!rf_helper->account_name)
                rf_helper->account_name =
                        modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
 
-       helper = g_slice_new0 (GetMsgAsyncHelper);
-       helper->window = win;
-       helper->func = reply_forward_func;
-       helper->iter = tny_list_create_iterator (header_list);
-       helper->user_data = rf_helper;
-
        if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
                TnyMsg *msg;
-               msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
-               if (!msg) {
+               TnyHeader *header;
+               /* Get header and message. Do not free them here, the
+                  reply_forward_cb must do it */
+               msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
+               header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
+               if (!msg || !header) {
+                       if (msg)
+                               g_object_unref (msg);
+                       if (header)
+                               g_object_unref (header);
                        g_printerr ("modest: no message found\n");
                        return;
-               } else
-                       reply_forward_func (msg, helper);
+               } else {
+                       reply_forward_cb (NULL, header, msg, rf_helper);
+               }
        } else {
-               header = TNY_HEADER (tny_iterator_get_current (helper->iter));
-               folder = tny_header_get_folder (header);
-               if (folder) {
-                       /* The callback will call it per each header */
-                       tny_folder_get_msg_async (folder, header, get_msg_cb, NULL, helper);
-                       g_object_unref (G_OBJECT (folder));
-               } else 
-                       g_printerr ("modest: no folder for header\n");
-               
+               TnyHeader *header;
+               TnyIterator *iter;
+
+               /* Retrieve messages */
+               mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                        G_OBJECT(win),
+                                                                        modest_ui_actions_get_msgs_full_error_handler, 
+                                                                        NULL);
+               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
+
+               /* Only reply/forward to one message */
+               iter = tny_list_create_iterator (header_list);
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               g_object_unref (iter);
+
+               modest_mail_operation_get_msg (mail_op,
+                                              header,
+                                              reply_forward_cb,
+                                              rf_helper);
+
+/*             modest_mail_operation_get_msgs_full (mail_op,  */
+/*                                                  header_list,  */
+/*                                                  reply_forward_cb,  */
+/*                                                  rf_helper,  */
+/*                                                  free_reply_forward_helper); */
+
                /* Clean */
-               g_object_unref (G_OBJECT (header));
+               g_object_unref(mail_op);
        }
-}
 
+       /* Free */
+       g_object_unref (header_list);
+}
 
 void
 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
@@ -601,132 +1275,111 @@ modest_ui_actions_on_sort (GtkAction *action,
        }
 }
 
-
-static gboolean
-action_send (const gchar* account_name)
+static void
+new_messages_arrived (ModestMailOperation *self, 
+                     gint new_messages,
+                     gpointer user_data)
 {
-       TnyAccount *tny_account;
-       ModestTnySendQueue *send_queue;
-
-       g_return_val_if_fail (account_name, FALSE);
-
-       /* Get the transport account according to the open connection, 
-        * because the account might specify connection-specific SMTP servers.
-        */
-       tny_account = 
-               modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
-                                                                    account_name);
-       if (!tny_account) {
-               g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
-               return FALSE;
-       }
-       
-       send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
-       if (!send_queue) {
-               g_object_unref (G_OBJECT(tny_account));
-               g_printerr ("modest: cannot get send queue for %s\n", account_name);
-               return FALSE;
-       }
-       
-       //modest_tny_send_queue_flush (send_queue);
-
-       g_object_unref (G_OBJECT(send_queue));
-       g_object_unref (G_OBJECT(tny_account));
+       if (new_messages == 0)
+               return;
 
-       return TRUE;
+       modest_platform_on_new_msg ();
 }
 
-
-static gboolean
-action_receive (const gchar* account_name)
+/*
+ * This function performs the send & receive required actions. The
+ * window is used to create the mail operation. Typically it should
+ * always be the main window, but we pass it as argument in order to
+ * be more flexible.
+ */
+void
+modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
 {
-       TnyAccount *tny_account;
+       gchar *acc_name = NULL;
        ModestMailOperation *mail_op;
 
-       g_return_val_if_fail (account_name, FALSE);
-
-       tny_account = 
-               modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
-                                                                    account_name,
-                                                                    TNY_ACCOUNT_TYPE_STORE);
-       if (!tny_account) {
-               g_printerr ("modest: cannot get tny store account for %s\n", account_name);
-               return FALSE;
+       /* If no account name was provided then get the current account, and if
+          there is no current account then pick the default one: */
+       if (!account_name) {
+               acc_name = g_strdup (modest_window_get_active_account(win));
+               if (!acc_name)
+                       acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
+               if (!acc_name) {
+                       g_printerr ("modest: cannot get default account\n");
+                       return;
+               }
+       } else {
+               acc_name = g_strdup (account_name);
        }
 
-       /* Create the mail operation */
+       /* Set send/receive operation in progress */    
+       modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
+
+       mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
+                                                                G_OBJECT (win),
+                                                                modest_ui_actions_send_receive_error_handler,
+                                                                NULL);
+
+       g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
+                         G_CALLBACK (_on_send_receive_progress_changed), 
+                         win);
+
+       /* Send & receive. */
        /* TODO: The spec wants us to first do any pending deletions, before receiving. */
-       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
+       /* Receive and then send. The operation is tagged initially as
+          a receive operation because the account update performs a
+          receive and then a send. The operation changes its type
+          internally, so the progress objects will receive the proper
+          progress information */
        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-       modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
-
-       g_object_unref (G_OBJECT(tny_account));
+       modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
        g_object_unref (G_OBJECT (mail_op));
-               
-       return TRUE;
+       
+       /* Free */
+       g_free (acc_name);
 }
 
-/** Check that an appropriate connection is open.
+/*
+ * Refreshes all accounts. This function will be used by automatic
+ * updates
  */
-gboolean check_for_connection (const gchar *account_name)
+void
+modest_ui_actions_do_send_receive_all (ModestWindow *win)
 {
-       TnyDevice *device = modest_runtime_get_device ();
+       GSList *account_names, *iter;
 
-/*
-       g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
-       
-       TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
-*/
-       
-       if (tny_device_is_online (device))
-               return TRUE;
-       else {
-               modest_platform_connect_and_wait (NULL);
-               
-               /* TODO: Wait until a result. */
-               return TRUE;
+       account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
+                                                         TRUE);
+
+       iter = account_names;
+       while (iter) {                  
+               modest_ui_actions_do_send_receive ((const char*) iter->data, win);
+               iter = g_slist_next (iter);
        }
+
+       modest_account_mgr_free_account_names (account_names);
+       account_names = NULL;
 }
 
+/*
+ * Handler of the click on Send&Receive button in the main toolbar
+ */
 void
 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
 {
-       gchar *account_name;
-
-       
-       g_message ("%s: online? %s", __FUNCTION__,  
-               tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
-                               
-       /* As per the UI spec, only the active account should be affected, 
-        * else the default folder if there is no active account: */                            
-       account_name =
-               g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
-       if (!account_name)
-               account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
-       if (!account_name) {
-               g_printerr ("modest: cannot get default account\n");
-               return;
-       }
+       /* Check if accounts exist */
+       gboolean accounts_exist = 
+               modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
        
-       /* Do not continue if no suitable connection is open: */
-       if (!check_for_connection (account_name))
-               return;
-
-       /* As per the UI spec,
-        * for POP accounts, we should receive,
-        * for IMAP we should synchronize everything, including receiving,
-        * for SMTP we should send,
-        * first receiving, then sending:
-        */
-       if (!action_receive(account_name))
-               g_printerr ("modest: failed to receive\n");
-       if (!action_send(account_name))
-               g_printerr ("modest: failed to send\n");
+       /* If not, allow the user to create an account before trying to send/receive. */
+       if (!accounts_exist)
+               modest_ui_actions_on_accounts (NULL, win);
        
+       /* Refresh the active account */
+       modest_ui_actions_do_send_receive (NULL, win);
 }
 
 
-
 void
 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
 {
@@ -745,7 +1398,7 @@ modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *
        /* what is saved/restored is depending on the style; thus; we save with
         * old style, then update the style, and restore for this new style
         */
-       modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
+       modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
        
        if (modest_header_view_get_style
            (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
@@ -756,191 +1409,102 @@ modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *
                                              MODEST_HEADER_VIEW_STYLE_DETAILS);
 
        modest_widget_memory_restore (conf, G_OBJECT(header_view),
-                                     "header-view");
+                                     MODEST_CONF_HEADER_VIEW_KEY);
 }
 
 
-
-/*
- * Marks a message as read and passes it to the msg preview widget
- */
-static void
-read_msg_func (gpointer data, gpointer user_data)
+void 
+modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
+                                     TnyHeader *header,
+                                     ModestMainWindow *main_window)
 {
-       TnyMsg *msg;
-       TnyHeader *header;
-       GetMsgAsyncHelper *helper;
-       TnyHeaderFlags header_flags;
-       GtkWidget *msg_preview;
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
+       g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
        
-       msg = TNY_MSG (data);
-       helper = (GetMsgAsyncHelper *) user_data;
-
-       msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
-                                                          MODEST_WIDGET_TYPE_MSG_PREVIEW);
-       if (!msg_preview)
+       /* If no header has been selected then exit */
+       if (!header)
                return;
-       
-       header = TNY_HEADER (tny_iterator_get_current (helper->iter));
-       header_flags = tny_header_get_flags (header);
-       tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
-       g_object_unref (G_OBJECT (header));
-
-       /* Set message on msg view */
-       modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
-}
-
-/*
- * This function is a generic handler for the tny_folder_get_msg_async
- * call. It expects as user_data a #GetMsgAsyncHelper. This helper
- * contains a user provided function that is called inside this
- * method. This will allow us to use this callback in many different
- * places. This callback performs the common actions for the
- * get_msg_async call, more specific actions will be done by the user
- * function
- */
-static void
-get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
-{
-       GetMsgAsyncHelper *helper;
-
-       helper = (GetMsgAsyncHelper *) user_data;
-
-       if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
-               modest_ui_actions_on_item_not_found (NULL,
-                                                    MODEST_ITEM_TYPE_MESSAGE,
-                                                    helper->window);
-               return;
-       }
-
-       /* Call user function */
-       helper->func (msg, user_data);
-
-       /* Process next element (if exists) */
-       tny_iterator_next (helper->iter);
-       if (tny_iterator_is_done (helper->iter)) {
-               TnyList *headers;
-               headers = tny_iterator_get_list (helper->iter);
-               /* Free resources */
-               g_object_unref (G_OBJECT (headers));
-               g_object_unref (G_OBJECT (helper->iter));
-               g_slice_free (GetMsgAsyncHelper, helper);
-       } else {
-               TnyHeader *header;
-               header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
-               tny_folder_get_msg_async (folder, header,                         
-                                         get_msg_cb, NULL, helper);
-               g_object_unref (G_OBJECT(header));
-       }
-}
-
-void 
-modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
-                                     TnyHeader *header,
-                                     ModestMainWindow *main_window)
-{
-       TnyFolder *folder;
-       GetMsgAsyncHelper *helper;
-       TnyList *list;
-
-       g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
-
-       /* when there's no header, clear the msgview */
-       if (!header) {
-               GtkWidget *msg_preview;
 
-               /* Clear msg preview if exists */
-               msg_preview = modest_main_window_get_child_widget(main_window,
-                                                                 MODEST_WIDGET_TYPE_MSG_PREVIEW);
-       
-               if (msg_preview)
-                       modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
-               return;
-       }
+       /* Update focus */
+       if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
+           gtk_widget_grab_focus (GTK_WIDGET(header_view));
 
        /* Update Main window title */
-       if (GTK_WIDGET_HAS_FOCUS (header_view)) {
+       if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
                const gchar *subject = tny_header_get_subject (header);
-               if (subject && strcmp (subject, ""))
+               if (subject && strlen(subject) > 0)
                        gtk_window_set_title (GTK_WINDOW (main_window), subject);
                else
                        gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
        }
 
-       /* Create list */
-       list = tny_simple_list_new ();
-       tny_list_prepend (list, G_OBJECT (header));
-
-       /* Fill helper data */
-       helper = g_slice_new0 (GetMsgAsyncHelper);
-       helper->window = MODEST_WINDOW (main_window);
-       helper->iter = tny_list_create_iterator (list);
-       helper->func = read_msg_func;
-
-       folder = tny_header_get_folder (TNY_HEADER(header));
-
-       tny_folder_get_msg_async (TNY_FOLDER(folder),
-                                 header, get_msg_cb,
-                                 NULL, helper);
-
-       /* Frees */
-       g_object_unref (G_OBJECT (folder));
+       /* Update toolbar dimming state */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
 }
 
-
-
-void 
-modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
+void
+modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
+                                      TnyHeader *header,
                                       ModestMainWindow *main_window)
 {
-       ModestWindow *win = NULL;
-       TnyFolder *folder = NULL;
-       TnyMsg    *msg    = NULL;
-       ModestWindowMgr *mgr;
-       
+       TnyList *headers;
+
        g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
        
        if (!header)
                return;
 
-       folder = tny_header_get_folder (header);
-       if (!folder) {
-               g_printerr ("modest: cannot get folder for header\n");
-               return;
-       }
+       headers = tny_simple_list_new ();
+       tny_list_prepend (headers, G_OBJECT (header));
 
-       /* FIXME: make async?; check error  */
-       msg = tny_folder_get_msg (folder, header, NULL);
-       if (!msg) {
-               g_printerr ("modest: cannot get msg for header\n");
-               goto cleanup;
-       }
+       _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
 
-       /* Look if we already have a message view for that header */    
-       mgr = modest_runtime_get_window_mgr ();
-       win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
+       g_object_unref (headers);
+}
 
-       /* If not, create a new window */
-       if (!win) {
-               gchar *account;
+static void
+set_active_account_from_tny_account (TnyAccount *account,
+                                    ModestWindow *window)
+{
+       const gchar *server_acc_name = tny_account_get_id (account);
+       
+       /* We need the TnyAccount provided by the
+          account store because that is the one that
+          knows the name of the Modest account */
+       TnyAccount *modest_server_account = modest_server_account = 
+               modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
+                                                            MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
+                                                            server_acc_name);
+       
+       const gchar *modest_acc_name = 
+               modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
+       modest_window_set_active_account (window, modest_acc_name);
+       g_object_unref (modest_server_account);
+}
 
-               account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
-               if (!account)
-                       account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
 
-               win = modest_msg_view_window_new (msg, account);
-               modest_window_mgr_register_window (mgr, win);
+static void
+folder_refreshed_cb (ModestMailOperation *mail_op, 
+                    TnyFolder *folder, 
+                    gpointer user_data)
+{
+       ModestMainWindow *win = NULL;
+       GtkWidget *header_view;
 
-               gtk_window_set_transient_for (GTK_WINDOW (win),
-                                             GTK_WINDOW (main_window));
-       }
+       g_return_if_fail (TNY_IS_FOLDER (folder));
 
-       gtk_widget_show_all (GTK_WIDGET(win));
+       win = MODEST_MAIN_WINDOW (user_data);
+       header_view = 
+               modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
 
-       g_object_unref (G_OBJECT (msg));
-       
-cleanup:
-       g_object_unref (G_OBJECT (folder));
+       /* Check if folder is empty and set headers view contents style */
+       if (tny_folder_get_all_count (folder) == 0) {
+       printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
+               modest_main_window_set_contents_style (win,
+                                                      MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
+       } else {
+               printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
+       }
 }
 
 void 
@@ -951,7 +1515,7 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
 {
        ModestConf *conf;
        GtkWidget *header_view;
-       
+
        g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
 
        header_view = modest_main_window_get_child_widget(main_window,
@@ -961,23 +1525,61 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
        
        conf = modest_runtime_get_conf ();
 
-       if (TNY_IS_FOLDER (folder_store)) {
-
-               modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
-
+       if (TNY_IS_ACCOUNT (folder_store)) {
                if (selected) {
+                       /* Update active account */
+                       set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
+                       /* Show account details */
+                       modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
+               }
+       } else {
+               if (TNY_IS_FOLDER (folder_store) && selected) {
+                       
+                       /* Update the active account */
+                       TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
+                       if (account) {
+                               set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
+                               g_object_unref (account);
+                               account = NULL;
+                       }
+
+                       /* Set the header style by default, it could
+                          be changed later by the refresh callback to
+                          empty */
+                       modest_main_window_set_contents_style (main_window, 
+                                                              MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
+
+                       /* Set folder on header view. This function
+                          will call tny_folder_refresh_async so we
+                          pass a callback that will be called when
+                          finished. We use that callback to set the
+                          empty view if there are no messages */
                        modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
-                                                      TNY_FOLDER (folder_store));
-                       modest_widget_memory_restore (conf, G_OBJECT(header_view),
-                                                     "header-view");
+                                                      TNY_FOLDER (folder_store),
+                                                      folder_refreshed_cb,
+                                                      main_window);
+                       
+                       /* Restore configuration. We need to do this
+                          *after* the set_folder because the widget
+                          memory asks the header view about its
+                          folder  */
+                       modest_widget_memory_restore (modest_runtime_get_conf (), 
+                                                     G_OBJECT(header_view),
+                                                     MODEST_CONF_HEADER_VIEW_KEY);
                } else {
-                       modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
-                       modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
+                       /* Update the active account */
+                       modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
+                       /* Save only if we're seeing headers */
+                       if (modest_main_window_get_contents_style (main_window) ==
+                           MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
+                               modest_widget_memory_save (conf, G_OBJECT (header_view), 
+                                                          MODEST_CONF_HEADER_VIEW_KEY);
+                       modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
                }
-       } else if (TNY_IS_ACCOUNT (folder_store)) {
-
-               modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
        }
+
+       /* Update toolbar dimming state */
+       modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
 }
 
 void 
@@ -990,8 +1592,6 @@ modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemTyp
 
        item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
        
-       if (g_main_depth > 0)   
-               gdk_threads_enter ();
        online = tny_device_is_online (modest_runtime_get_device());
 
        if (online) {
@@ -1021,19 +1621,17 @@ modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemTyp
 
                gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
                if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
-//                     modest_platform_connect_and_wait ();;
+//                     modest_platform_connect_and_wait ();
                }
        }
        gtk_widget_destroy (dialog);
-       if (g_main_depth > 0)   
-               gdk_threads_leave ();
 }
 
 void
 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
                                     ModestWindow *win)
 {
-       g_message ("%s %s", __FUNCTION__, link);
+       /* g_message ("%s %s", __FUNCTION__, link); */
 }      
 
 
@@ -1055,8 +1653,7 @@ void
 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
                                             ModestWindow *win)
 {
-       g_message (__FUNCTION__);
-       
+       modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
 }
 
 void
@@ -1064,25 +1661,23 @@ modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
                                          const gchar *address,
                                          ModestWindow *win)
 {
-       g_message ("%s %s", __FUNCTION__, address);
+       /* g_message ("%s %s", __FUNCTION__, address); */
 }
 
 void
-modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
+modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
 {
        TnyTransportAccount *transport_account;
        ModestMailOperation *mail_operation;
        MsgData *data;
        gchar *account_name, *from;
        ModestAccountMgr *account_mgr;
+       gchar *info_text = NULL;
 
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
        
        data = modest_msg_edit_window_get_msg_data (edit_window);
 
-       /* FIXME: Code added just for testing. The final version will
-          use the send queue provided by tinymail and some
-          classifier */
        account_mgr = modest_runtime_get_account_mgr();
        account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
        if (!account_name) 
@@ -1092,10 +1687,16 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
                modest_msg_edit_window_free_msg_data (edit_window, data);
                return;
        }
+
+       if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+               account_name = g_strdup (data->account_name);
+       }
+
        transport_account =
-               TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
+               TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
                                      (modest_runtime_get_account_store(),
-                                      account_name));
+                                      account_name,
+                                      TNY_ACCOUNT_TYPE_TRANSPORT));
        if (!transport_account) {
                g_printerr ("modest: no transport account found for '%s'\n", account_name);
                g_free (account_name);
@@ -1105,11 +1706,116 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
        from = modest_account_mgr_get_from_string (account_mgr, account_name);
 
        /* Create the mail operation */         
-       mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND);
+       mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
+
+       modest_mail_operation_save_to_drafts (mail_operation,
+                                             transport_account,
+                                             data->draft_msg,
+                                             from,
+                                             data->to, 
+                                             data->cc, 
+                                             data->bcc,
+                                             data->subject, 
+                                             data->plain_body, 
+                                             data->html_body,
+                                             data->attachments,
+                                             data->priority_flags);
+       /* Frees */
+       g_free (from);
+       g_free (account_name);
+       g_object_unref (G_OBJECT (transport_account));
+       g_object_unref (G_OBJECT (mail_operation));
+
+       modest_msg_edit_window_free_msg_data (edit_window, data);
+
+       info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
+       modest_platform_information_banner (NULL, NULL, info_text);
+       g_free (info_text);
+}
+
+/* For instance, when clicking the Send toolbar button when editing a message: */
+void
+modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
+
+       if (!modest_msg_edit_window_check_names (edit_window))
+               return;
+       
+       /* Offer the connection dialog, if necessary: */        
+       if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
+               return;
+       
+       /* FIXME: Code added just for testing. The final version will
+          use the send queue provided by tinymail and some
+          classifier */
+       ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
+       gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
+       if (!account_name) 
+               account_name = modest_account_mgr_get_default_account (account_mgr);
+               
+       if (!account_name) {
+               g_printerr ("modest: no account found\n");
+               return;
+       }
+       
+       MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
+
+       if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+               account_name = g_strdup (data->account_name);
+       }
+       
+       /* Get the currently-active transport account for this modest account: */
+       TnyTransportAccount *transport_account =
+               TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
+                                     (modest_runtime_get_account_store(),
+                                      account_name));
+       if (!transport_account) {
+               g_printerr ("modest: no transport account found for '%s'\n", account_name);
+               g_free (account_name);
+               modest_msg_edit_window_free_msg_data (edit_window, data);
+               return;
+       }
+       
+       gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
+
+       /* mail content checks and dialogs */
+       if (data->subject == NULL || data->subject[0] == '\0') {
+               GtkResponseType response;
+               response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
+                                                                   _("mcen_nc_subject_is_empty_send"));
+               if (response == GTK_RESPONSE_CANCEL) {
+                       g_free (account_name);
+                       return;
+               }
+       }
+
+       if (data->plain_body == NULL || data->plain_body[0] == '\0') {
+               GtkResponseType response;
+               gchar *note_message;
+               gchar *note_subject = data->subject;
+               if (note_subject == NULL || note_subject[0] == '\0')
+                       note_subject = _("mail_va_no_subject");
+               note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
+               response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
+                                                                   note_message);
+               g_free (note_message);
+               if (response == GTK_RESPONSE_CANCEL) {
+                       g_free (account_name);
+                       return;
+               }
+       }
+
+       modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
+
+       /* Create the mail operation */
+       ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
 
        modest_mail_operation_send_new_mail (mail_operation,
                                             transport_account,
+                                            data->draft_msg,
                                             from,
                                             data->to, 
                                             data->cc, 
@@ -1119,16 +1825,18 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
                                             data->html_body,
                                             data->attachments,
                                             data->priority_flags);
-       /* Frees */
+                                            
+       /* Free data: */
        g_free (from);
        g_free (account_name);
        g_object_unref (G_OBJECT (transport_account));
        g_object_unref (G_OBJECT (mail_operation));
 
        modest_msg_edit_window_free_msg_data (edit_window, data);
+       modest_msg_edit_window_set_sent (edit_window, TRUE);
 
-       /* Save settings and close the window */
-       gtk_widget_destroy (GTK_WIDGET (edit_window));
+       /* Save settings and close the window: */
+       modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
 }
 
 void 
@@ -1256,44 +1964,24 @@ modest_ui_actions_on_insert_image (GtkAction *action,
        modest_msg_edit_window_insert_image (window);
 }
 
-/*
- * Shows a dialog with an entry that asks for some text. The returned
- * value must be freed by the caller. The dialog window title will be
- * set to @title.
- */
-static gchar *
-ask_for_folder_name (GtkWindow *parent_window,
-                    const gchar *title)
+void 
+modest_ui_actions_on_attach_file (GtkAction *action,
+                                 ModestMsgEditWindow *window)
 {
-       GtkWidget *dialog, *entry;
-       gchar *folder_name = NULL;
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       g_return_if_fail (GTK_IS_ACTION (action));
 
-       /* Ask for folder name */
-       dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
-                                             parent_window,
-                                             GTK_DIALOG_MODAL,
-                                             GTK_STOCK_CANCEL,
-                                             GTK_RESPONSE_REJECT,
-                                             GTK_STOCK_OK,
-                                             GTK_RESPONSE_ACCEPT,
-                                             NULL);
-       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
-                           gtk_label_new(title),
-                           FALSE, FALSE, 0);
-               
-       entry = gtk_entry_new_with_max_length (40);
-       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
-                           entry,
-                           TRUE, FALSE, 0);    
-       
-       gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
-       
-       if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
-               folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
+       modest_msg_edit_window_attach_file (window);
+}
 
-       gtk_widget_destroy (dialog);
+void 
+modest_ui_actions_on_remove_attachments (GtkAction *action,
+                                        ModestMsgEditWindow *window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       g_return_if_fail (GTK_IS_ACTION (action));
 
-       return folder_name;
+       modest_msg_edit_window_remove_attachments (window, NULL);
 }
 
 void 
@@ -1326,26 +2014,20 @@ modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_windo
                        if (result == GTK_RESPONSE_REJECT) {
                                finished = TRUE;
                        } else {
-                               ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
+                               ModestMailOperation *mail_op;
                                TnyFolder *new_folder = NULL;
 
+                               mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
+                                                                     G_OBJECT(main_window));
                                modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
                                                                 mail_op);
-               
                                new_folder = modest_mail_operation_create_folder (mail_op,
                                                                                  parent_folder,
                                                                                  (const gchar *) folder_name);
                                if (new_folder) {
                                        g_object_unref (new_folder);
                                        finished = TRUE;
-                               } 
-/*                             else { */
-/*                                     /\* TODO: check error and follow proper actions *\/ */
-/* /\*                                         suggested_name = X; *\/ */
-/*                                     /\* Show error to the user *\/ */
-/*                                     modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
-/*                                                                             MODEST_INFORMATION_CREATE_FOLDER); */
-/*                             } */
+                               }
                                g_object_unref (mail_op);
                        }
                        g_free (folder_name);
@@ -1356,34 +2038,81 @@ modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_windo
        }
 }
 
+static void
+modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
+                                              gpointer user_data)
+{
+       GObject *win = modest_mail_operation_get_source (mail_op);
+       const GError *error = NULL;
+       const gchar *message = NULL;
+       
+       /* Get error message */
+       error = modest_mail_operation_get_error (mail_op);
+       if (error != NULL && error->message != NULL) {
+               message = error->message;
+       } else {
+               message = _("!!! FIXME: Unable to rename");
+       }
+       
+       /* Show notification dialog */
+       modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
+       g_object_unref (win);
+}
+
 void 
 modest_ui_actions_on_rename_folder (GtkAction *action,
                                     ModestMainWindow *main_window)
 {
        TnyFolderStore *folder;
        GtkWidget *folder_view;
-       
+       GtkWidget *header_view; 
+
        g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
 
        folder_view = modest_main_window_get_child_widget (main_window,
                                                           MODEST_WIDGET_TYPE_FOLDER_VIEW);
        if (!folder_view)
                return;
+
+       header_view = modest_main_window_get_child_widget (main_window,
+                                                          MODEST_WIDGET_TYPE_HEADER_VIEW);
        
+       if (!header_view)
+               return;
+
        folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
+
+       /* Offer the connection dialog if necessary: */
+       if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
+               g_object_unref (G_OBJECT (folder));
+               return;
+       }
+
        
        if (folder && TNY_IS_FOLDER (folder)) {
                gchar *folder_name;
-               folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
-                                                  _("Please enter a new name for the folder"));
+               gint response;
+               const gchar *current_name;
 
-               if (folder_name != NULL && strlen (folder_name) > 0) {
+               current_name = tny_folder_get_name (TNY_FOLDER (folder));
+               response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
+                                                                    current_name, &folder_name);
+
+               if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
                        ModestMailOperation *mail_op;
 
-                       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
+                       mail_op = 
+                               modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
+                                                                              G_OBJECT(main_window),
+                                                                              modest_ui_actions_rename_folder_error_handler,
+                                                                              NULL);
+
+
                        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
                                                         mail_op);
 
+                       modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
+
                        modest_mail_operation_rename_folder (mail_op,
                                                             TNY_FOLDER (folder),
                                                             (const gchar *) folder_name);
@@ -1396,6 +2125,17 @@ modest_ui_actions_on_rename_folder (GtkAction *action,
 }
 
 static void
+modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
+                                              gpointer user_data)
+{
+       GObject *win = modest_mail_operation_get_source (mail_op);
+
+       modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
+                                               _("mail_in_ui_folder_delete_error"));
+       g_object_unref (win);
+}
+
+static void
 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
 {
        TnyFolderStore *folder;
@@ -1412,25 +2152,37 @@ delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
 
        folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
 
+       /* Show an error if it's an account */
+       if (!TNY_IS_FOLDER (folder)) {
+               modest_platform_run_information_dialog (GTK_WINDOW (main_window),
+                                                       _("mail_in_ui_folder_delete_error"));
+               g_object_unref (G_OBJECT (folder));
+               return ;
+       }
+
+       /* Offer the connection dialog if necessary: */
+       if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
+               g_object_unref (G_OBJECT (folder));
+               return;
+       }
+
        /* Ask the user */      
        message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
                                    tny_folder_get_name (TNY_FOLDER (folder)));
-       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
+       response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
                                                            (const gchar *) message);
        g_free (message);
 
        if (response == GTK_RESPONSE_OK) {
-               ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE);
+               ModestMailOperation *mail_op = 
+                       modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
+                                                                      G_OBJECT(main_window),
+                                                                      modest_ui_actions_delete_folder_error_handler,
+                                                                      NULL);
 
                modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
                                                 mail_op);
                modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
-
-               /* Show error if happened */
-               if (modest_mail_operation_get_error (mail_op))
-                       modest_platform_run_information_dialog (GTK_WINDOW (main_window),
-                                                               MODEST_INFORMATION_DELETE_FOLDER);
-
                g_object_unref (G_OBJECT (mail_op));
        }
 
@@ -1456,16 +2208,37 @@ modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainW
 
 void
 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
-                                        const gchar* account_name,
+                                        const gchar* server_account_name,
+                                        gchar **username,
                                         gchar **password, 
                                         gboolean *cancel, 
                                         gboolean *remember,
                                         ModestMainWindow *main_window)
 {
-       gchar *txt;
-       GtkWidget *dialog, *entry, *remember_pass_check;
-
-       dialog = gtk_dialog_new_with_buttons (_("Password requested"),
+       g_return_if_fail(server_account_name);
+       /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
+       
+       /* Initalize output parameters: */
+       if (cancel)
+               *cancel = FALSE;
+               
+       if (remember)
+               *remember = TRUE;
+               
+#ifdef MODEST_PLATFORM_MAEMO
+       /* Maemo uses a different (awkward) button order,
+        * It should probably just use gtk_alternative_dialog_button_order ().
+        */
+       GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
+                                             NULL,
+                                             GTK_DIALOG_MODAL,
+                                             GTK_STOCK_OK,
+                                             GTK_RESPONSE_ACCEPT,
+                                             GTK_STOCK_CANCEL,
+                                             GTK_RESPONSE_REJECT,
+                                             NULL);
+#else
+       GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
                                              NULL,
                                              GTK_DIALOG_MODAL,
                                              GTK_STOCK_CANCEL,
@@ -1473,40 +2246,143 @@ modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
                                              GTK_STOCK_OK,
                                              GTK_RESPONSE_ACCEPT,
                                              NULL);
+#endif /* MODEST_PLATFORM_MAEMO */
+
        gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
        
-       txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
+       gchar *server_name = modest_server_account_get_hostname (
+               modest_runtime_get_account_mgr(), server_account_name);
+       if (!server_name) {/* This happened once, though I don't know why. murrayc. */
+               g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
+               *cancel = TRUE;
+               return;
+       }
+       
+       /* This causes a warning because the logical ID has no %s in it, 
+        * though the translation does, but there is not much we can do about that: */
+       gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
        gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
                            FALSE, FALSE, 0);
        g_free (txt);
+       g_free (server_name);
+       server_name = NULL;
 
-       entry = gtk_entry_new_with_max_length (40);
-       gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
-       gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
+       /* username: */
+       gchar *initial_username = modest_server_account_get_username (
+               modest_runtime_get_account_mgr(), server_account_name);
        
-       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
-                           TRUE, FALSE, 0);    
-
+       GtkWidget *entry_username = gtk_entry_new ();
+       if (initial_username)
+               gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
+       /* Dim this if a connection has ever succeeded with this username,
+        * as per the UI spec: */
+       const gboolean username_known = 
+               modest_server_account_get_username_has_succeeded(
+                       modest_runtime_get_account_mgr(), server_account_name);
+       gtk_widget_set_sensitive (entry_username, !username_known);
+       
+#ifdef MODEST_PLATFORM_MAEMO
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
+       
+       /* Create a size group to be used by all captions.
+        * Note that HildonCaption does not create a default size group if we do not specify one.
+        * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
+       GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+       
+       GtkWidget *caption = hildon_caption_new (sizegroup, 
+               _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (entry_username);
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
+               FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+#else 
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
+                           TRUE, FALSE, 0);
+#endif /* MODEST_PLATFORM_MAEMO */     
+                           
+       /* password: */
+       GtkWidget *entry_password = gtk_entry_new ();
+       gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
+       /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
+       
+#ifdef MODEST_PLATFORM_MAEMO
+       /* Auto-capitalization is the default, so let's turn it off: */
+       hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
+               HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
+       
+       caption = hildon_caption_new (sizegroup, 
+               _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
+       gtk_widget_show (entry_password);
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
+               FALSE, FALSE, MODEST_MARGIN_HALF);
+       gtk_widget_show (caption);
+       g_object_unref (sizegroup);
+#else 
+       gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
+                           TRUE, FALSE, 0);
+#endif /* MODEST_PLATFORM_MAEMO */     
+                               
+/* This is not in the Maemo UI spec:
        remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
        gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
                            TRUE, FALSE, 0);
+*/
 
        gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
        
        if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
-               *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
-               *cancel   = FALSE;
+               if (username) {
+                       *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
+                       
+                       modest_server_account_set_username (
+                                modest_runtime_get_account_mgr(), server_account_name, 
+                                *username);
+                                
+                       const gboolean username_was_changed = 
+                               (strcmp (*username, initial_username) != 0);
+                       if (username_was_changed) {
+                               g_warning ("%s: tinymail does not yet support changing the "
+                                       "username in the get_password() callback.\n", __FUNCTION__);
+                       }
+               }
+                       
+               if (password) {
+                       *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
+                       
+                       /* We do not save the password in the configuration, 
+                        * because this function is only called for passwords that should 
+                        * not be remembered:
+                       modest_server_account_set_password (
+                                modest_runtime_get_account_mgr(), server_account_name, 
+                                *password);
+                       */
+               }
+               
+               if (cancel)
+                       *cancel   = FALSE;
+                       
        } else {
-               *password = NULL;
-               *cancel   = TRUE;
+               if (username)
+                       *username = NULL;
+                       
+               if (password)
+                       *password = NULL;
+                       
+               if (cancel)
+                       *cancel   = TRUE;
        }
 
+/* This is not in the Maemo UI spec:
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
                *remember = TRUE;
        else
                *remember = FALSE;
+*/
 
        gtk_widget_destroy (dialog);
+       
+       /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
 }
 
 void
@@ -1522,9 +2398,13 @@ modest_ui_actions_on_cut (GtkAction *action,
                GtkTextBuffer *buffer;
                GtkClipboard *clipboard;
 
-               clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+               clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
                buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
                gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
+       } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
+               modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
+       } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
+               modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
        }
 }
 
@@ -1535,36 +2415,97 @@ modest_ui_actions_on_copy (GtkAction *action,
        GtkClipboard *clipboard;
        GtkWidget *focused_widget;
 
-       clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+       clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
        focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
+
        if (GTK_IS_LABEL (focused_widget)) {
                gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
        } else if (GTK_IS_EDITABLE (focused_widget)) {
                gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
        } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
                GtkTextBuffer *buffer;
-
                buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
                gtk_text_buffer_copy_clipboard (buffer, clipboard);
-       }
+               modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
+       } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
+               TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
+               TnyIterator *iter = tny_list_create_iterator (header_list);
+               TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
+               TnyFolder *folder = tny_header_get_folder (header);
+               TnyAccount *account = tny_folder_get_account (folder);
+               const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
+               /* If it's POP then ask */
+               gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
+                      MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
+               g_object_unref (account);
+               g_object_unref (folder);
+               g_object_unref (header);
+               g_object_unref (iter);
+               
+               /* Check that the messages have been previously downloaded */
+               gboolean continue_download = TRUE;
+               if (ask)
+                       continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
+               if (continue_download)
+                       modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
+               g_object_unref (header_list);
+       } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
+               modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
+       }    
+
+       /* Show information banner */
+       modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
+       
 }
 
 void
 modest_ui_actions_on_undo (GtkAction *action,
                           ModestWindow *window)
 {
+       ModestEmailClipboard *clipboard = NULL;
+
        if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
                modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
-       } else {
+       } else if (MODEST_IS_MAIN_WINDOW (window)) {
+               /* Clear clipboard source */
+               clipboard = modest_runtime_get_email_clipboard ();
+               modest_email_clipboard_clear (clipboard);               
+       }
+       else {
                g_return_if_reached ();
        }
 }
 
 void
+modest_ui_actions_on_redo (GtkAction *action,
+                          ModestWindow *window)
+{
+       if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
+               modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
+       }
+       else {
+               g_return_if_reached ();
+       }
+}
+
+
+static void
+paste_msgs_cb (const GObject *object, gpointer user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
+       g_return_if_fail (GTK_IS_WIDGET (user_data));
+       
+       /* destroy information note */
+       gtk_widget_destroy (GTK_WIDGET(user_data));
+}
+
+void
 modest_ui_actions_on_paste (GtkAction *action,
                            ModestWindow *window)
 {
-       GtkWidget *focused_widget;
+       GtkWidget *focused_widget = NULL;
+       GtkWidget *inf_note = NULL;
+       ModestMailOperation *mail_op = NULL;
 
        focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
        if (GTK_IS_EDITABLE (focused_widget)) {
@@ -1573,12 +2514,69 @@ modest_ui_actions_on_paste (GtkAction *action,
                GtkTextBuffer *buffer;
                GtkClipboard *clipboard;
 
-               clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+               clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
                buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
                gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
+       } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
+               ModestEmailClipboard *clipboard = NULL;
+               TnyFolder *src_folder = NULL;
+               TnyFolderStore *folder_store = NULL;
+               TnyList *data = NULL;           
+               gboolean delete = FALSE;
+               
+               /* Check clipboard source */
+               clipboard = modest_runtime_get_email_clipboard ();
+               if (modest_email_clipboard_cleared (clipboard)) 
+                       return;
+               
+               /* Get elements to paste */
+               modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
+
+               /* Create a new mail operation */
+               mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
+               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
+                                                mail_op);
+               
+               /* Get destination folder */
+               folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
+
+               /* Launch notification */
+               inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
+                                                            _CS("ckct_nw_pasting"));
+               if (inf_note != NULL)  {
+                       gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
+                       gtk_widget_show (GTK_WIDGET(inf_note));
+               }
+
+               /* transfer messages  */
+               if (data != NULL) {
+                       modest_mail_operation_xfer_msgs (mail_op, 
+                                                        data,
+                                                        TNY_FOLDER (folder_store),
+                                                        delete,
+                                                        paste_msgs_cb,
+                                                        inf_note);
+                       
+               } else if (src_folder != NULL) {                        
+                       modest_mail_operation_xfer_folder (mail_op, 
+                                                          src_folder,
+                                                          folder_store,
+                                                          delete,
+                                                          paste_msgs_cb,
+                                                          inf_note);
+               }
+
+               /* Free */
+               if (data != NULL) 
+                       g_object_unref (data);
+               if (src_folder != NULL) 
+                       g_object_unref (src_folder);
+               if (folder_store != NULL) 
+                       g_object_unref (folder_store);
        }
 }
 
+
 void
 modest_ui_actions_on_select_all (GtkAction *action,
                                 ModestWindow *window)
@@ -1586,7 +2584,9 @@ modest_ui_actions_on_select_all (GtkAction *action,
        GtkWidget *focused_widget;
 
        focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
-       if (GTK_IS_LABEL (focused_widget)) {
+       if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
+               modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
+       } else if (GTK_IS_LABEL (focused_widget)) {
                gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
        } else if (GTK_IS_EDITABLE (focused_widget)) {
                gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
@@ -1598,7 +2598,44 @@ modest_ui_actions_on_select_all (GtkAction *action,
                gtk_text_buffer_get_start_iter (buffer, &start);
                gtk_text_buffer_get_end_iter (buffer, &end);
                gtk_text_buffer_select_range (buffer, &start, &end);
+       } else if (GTK_IS_HTML (focused_widget)) {
+               gtk_html_select_all (GTK_HTML (focused_widget));
+       } else if (MODEST_IS_MAIN_WINDOW (window)) {
+               GtkWidget *header_view = focused_widget;
+               GtkTreeSelection *selection = NULL;
+               
+               if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
+                       header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
+                                                                          MODEST_WIDGET_TYPE_HEADER_VIEW);
+                               
+               /* Select all messages */
+               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
+               gtk_tree_selection_select_all (selection);
+
+               /* Set focuse on header view */
+               gtk_widget_grab_focus (header_view);
        }
+
+}
+
+void
+modest_ui_actions_on_mark_as_read (GtkAction *action,
+                                  ModestWindow *window)
+{      
+       g_return_if_fail (MODEST_IS_WINDOW(window));
+               
+       /* Mark each header as read */
+       do_headers_action (window, headers_action_mark_as_read, NULL);
+}
+
+void
+modest_ui_actions_on_mark_as_unread (GtkAction *action,
+                                    ModestWindow *window)
+{      
+       g_return_if_fail (MODEST_IS_WINDOW(window));
+               
+       /* Mark each header as read */
+       do_headers_action (window, headers_action_mark_as_unread, NULL);
 }
 
 void
@@ -1691,17 +2728,19 @@ modest_ui_actions_on_change_fullscreen (GtkAction *action,
        gtk_window_present (GTK_WINDOW (window));
 }
 
-/*
- * Show the header details in a ModestDetailsDialog widget
+/* 
+ * Used by modest_ui_actions_on_details to call do_headers_action 
  */
 static void
-show_header_details (TnyHeader *header, 
-                    GtkWindow *window)
+headers_action_show_details (TnyHeader *header, 
+                            ModestWindow *window,
+                            gpointer user_data)
+
 {
        GtkWidget *dialog;
        
        /* Create dialog */
-       dialog = modest_details_dialog_new_with_header (window, header);
+       dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
 
        /* Run dialog */
        gtk_widget_show_all (dialog);
@@ -1729,7 +2768,9 @@ show_folder_details (TnyFolder *folder,
        gtk_widget_destroy (dialog);
 }
 
-
+/*
+ * Show the header details in a ModestDetailsDialog widget
+ */
 void     
 modest_ui_actions_on_details (GtkAction *action, 
                              ModestWindow *win)
@@ -1742,21 +2783,23 @@ modest_ui_actions_on_details (GtkAction *action,
                TnyMsg *msg;
 
                msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
-               if (!msg) {
+               if (!msg)
                        return;
-               } else {
-                       headers_list = get_selected_headers (win);
-                       if (!headers_list)
-                               return;
+               g_object_unref (msg);           
 
-                       iter = tny_list_create_iterator (headers_list);
+               headers_list = get_selected_headers (win);
+               if (!headers_list)
+                       return;
 
-                       header = TNY_HEADER (tny_iterator_get_current (iter));
-                       show_header_details (header, GTK_WINDOW (win));
-                       g_object_unref (header);
+               iter = tny_list_create_iterator (headers_list);
+
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               headers_action_show_details (header, win, NULL);
+               g_object_unref (header);
+
+               g_object_unref (iter);
+               g_object_unref (headers_list);
 
-                       g_object_unref (iter);
-               }
        } else if (MODEST_IS_MAIN_WINDOW (win)) {
                GtkWidget *folder_view, *header_view;
 
@@ -1764,36 +2807,26 @@ modest_ui_actions_on_details (GtkAction *action,
                folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
                if (gtk_widget_is_focus (folder_view)) {
-                       TnyFolder *folder;
-
-                       folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
-
+                       TnyFolderStore *folder_store
+                               = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
+                       if (!folder_store) {
+                               g_warning ("%s: No item was selected.\n", __FUNCTION__);
+                               return; 
+                       }
                        /* Show only when it's a folder */
-                       if (!folder || !TNY_IS_FOLDER (folder))
-                               return;
+                       /* This function should not be called for account items, 
+                        * because we dim the menu item for them. */
+                       if (TNY_IS_FOLDER (folder_store)) {
+                               show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
+                       }
 
-                       show_folder_details (folder, GTK_WINDOW (win));
+                       g_object_unref (folder_store);
 
                } else {
                        header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
                                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
-                       if (!gtk_widget_is_focus (header_view))
-                               return;
-
-                       headers_list = get_selected_headers (win);
-                       if (!headers_list)
-                               return;
-
-                       iter = tny_list_create_iterator (headers_list);
-                       while (!tny_iterator_is_done (iter)) {
-
-                               header = TNY_HEADER (tny_iterator_get_current (iter));
-                               show_header_details (header, GTK_WINDOW (win));
-                               g_object_unref (header);
-
-                               tny_iterator_next (iter);
-                       }
-                       g_object_unref (iter);
+                       /* Show details of each header */
+                       do_headers_action (win, headers_action_show_details, header_view);
                }
        }
 }
@@ -1884,6 +2917,13 @@ modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *wi
        modest_msg_edit_window_select_contacts (window);
 }
 
+void
+modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+       modest_msg_edit_window_check_names (window);
+}
+
 
 static GtkWidget*
 create_move_to_dialog (ModestWindow *win,
@@ -1908,9 +2948,19 @@ create_move_to_dialog (ModestWindow *win,
                                         GTK_POLICY_AUTOMATIC);
 
        /* Create folder view */
-       *tree_view = modest_folder_view_new (NULL);
-       gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
-                                gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
+       *tree_view = modest_platform_create_folder_view (NULL);
+
+       /* It could happen that we're trying to move a message from a
+          window (msg window for example) after the main window was
+          closed, so we can not just get the model of the folder
+          view */
+       if (MODEST_IS_FOLDER_VIEW (folder_view))
+               gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
+                                        gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
+       else
+               modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
+                                                TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
+
        gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
 
        /* Add scroll to dialog */
@@ -1919,6 +2969,9 @@ create_move_to_dialog (ModestWindow *win,
 
        gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
 
+       /* Select INBOX or local account */
+       modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
+
        return dialog;
 }
 
@@ -1976,28 +3029,225 @@ msgs_move_to_confirmation (GtkWindow *win,
                g_object_unref (header);
                g_object_unref (iter);
 
+               /* if no src_folder, message may be an attahcment */
+               if (src_folder == NULL) 
+                       return GTK_RESPONSE_CANCEL;
+
                /* If the source is a remote folder */
                if (!modest_tny_folder_is_local_folder (src_folder)) {
                        const gchar *message;
                        
-                       if (tny_list_get_length (headers) == 1)
-                               if (has_retrieved_msgs (headers))
-                                       message = _("mcen_nc_move_retrieve");
-                               else
-                                       message = _("mcen_nc_move_header");
-                       else
-                               if (has_retrieved_msgs (headers))
-                                       message = _("mcen_nc_move_retrieves");
-                               else
-                                       message = _("mcen_nc_move_headers");
-                       
+                       if (has_retrieved_msgs (headers))
+                               message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
+                                                   tny_list_get_length (headers));
+                       else 
+                               message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
+                                                   tny_list_get_length (headers));
+
                        response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
                                                                            (const gchar *) message);
                }
+               g_object_unref (src_folder);
        }
        return response;
 }
 
+
+
+static void
+transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
+{
+       ModestMsgViewWindow *self = NULL;
+       gboolean last, first;
+
+       g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
+       self = MODEST_MSG_VIEW_WINDOW (object);
+       
+       last = modest_msg_view_window_last_message_selected (self);
+       first = modest_msg_view_window_first_message_selected (self);   
+       if (last & first) {
+               /* No more messages to view, so close this window */
+/*             gboolean ret_value; */
+/*             g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
+               modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
+       } else if (last)
+               modest_msg_view_window_select_previous_message (self);
+       else 
+               modest_msg_view_window_select_next_message (self);
+}
+
+void
+modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
+                                            gpointer user_data)
+{
+       GObject *win = modest_mail_operation_get_source (mail_op);
+       const GError *error = NULL;
+       const gchar *message = NULL;
+       
+       /* Get error message */
+       error = modest_mail_operation_get_error (mail_op);
+       if (error != NULL && error->message != NULL) {
+               message = error->message;
+       } else {
+               message = _("mail_in_ui_folder_move_target_error");
+       }
+       
+       /* Show notification dialog */
+       modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
+       g_object_unref (win);
+}
+
+void
+modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
+                                             gpointer user_data)
+{
+       GObject *win = modest_mail_operation_get_source (mail_op);
+       const GError *error = modest_mail_operation_get_error (mail_op);
+
+       g_return_if_fail (error != NULL);
+       if (error->message != NULL)             
+               g_printerr ("modest: %s\n", error->message);
+       else
+               g_printerr ("modest: unkonw error on send&receive operation");
+
+       /* Show error message */
+/*     if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
+/*             modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
+/*                                                     _CS("sfil_ib_unable_to_receive")); */
+/*     else  */
+/*             modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
+/*                                                     _CS("sfil_ib_unable_to_send")); */
+       g_object_unref (win);
+}
+
+static void
+open_msg_for_purge_cb (ModestMailOperation *mail_op, 
+                      TnyHeader *header, 
+                      TnyMsg *msg, 
+                      gpointer user_data)
+{
+       TnyList *parts;
+       TnyIterator *iter;
+       gint pending_purges = 0;
+       gboolean some_purged = FALSE;
+       ModestWindow *win = MODEST_WINDOW (user_data);
+
+       /* If there was any error */
+       if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
+               return;
+
+       /* Once the message has been retrieved for purging, we check if
+        * it's all ok for purging */
+
+       parts = tny_simple_list_new ();
+       tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
+       iter = tny_list_create_iterator (parts);
+
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part;
+               part = TNY_MIME_PART (tny_iterator_get_current (iter));
+               if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
+                       if (tny_mime_part_is_purged (part))
+                               some_purged = TRUE;
+                       else
+                               pending_purges++;
+               }
+               tny_iterator_next (iter);
+       }
+
+       if (pending_purges>0) {
+               gint response;
+               response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
+
+               if (response == GTK_RESPONSE_OK) {
+                       modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
+                       tny_iterator_first (iter);
+                       while (!tny_iterator_is_done (iter)) {
+                               TnyMimePart *part;
+                               
+                               part = TNY_MIME_PART (tny_iterator_get_current (iter));
+                               if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
+                                       tny_mime_part_set_purged (part);
+                               tny_iterator_next (iter);
+                       }
+                       
+                       tny_msg_rewrite_cache (msg);
+               }
+       } else {
+               modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
+       }
+
+       /* remove attachments */
+       tny_iterator_first (iter);
+       while (!tny_iterator_is_done (iter)) {
+               TnyMimePart *part;
+                       
+               part = TNY_MIME_PART (tny_iterator_get_current (iter));
+               g_object_unref (part);
+               tny_iterator_next (iter);
+       }
+
+       g_object_unref (iter);
+       g_object_unref (parts);
+}
+
+static void
+modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
+                                                    ModestMainWindow *win)
+{
+       GtkWidget *header_view;
+       TnyList *header_list;
+       TnyIterator *iter;
+       TnyHeader *header;
+       TnyHeaderFlags flags;
+       ModestWindow *msg_view_window =  NULL;
+       gboolean found;
+
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
+
+       header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
+                                                          MODEST_WIDGET_TYPE_HEADER_VIEW);
+
+       header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
+
+       if (tny_list_get_length (header_list) == 1) {
+               iter = tny_list_create_iterator (header_list);
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               g_object_unref (iter);
+       } else {
+               return;
+       }
+
+       found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
+                                                         header, &msg_view_window);
+       flags = tny_header_get_flags (header);
+       if (!(flags & TNY_HEADER_FLAG_CACHED))
+               return;
+       if (found) {
+               if (msg_view_window != NULL) 
+                       modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
+               else {
+                       /* do nothing; uid was registered before, so window is probably on it's way */
+                       g_warning ("debug: header %p has already been registered", header);
+               }
+       } else {
+               ModestMailOperation *mail_op = NULL;
+               modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
+               mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
+                                                                        G_OBJECT (win),
+                                                                        modest_ui_actions_get_msgs_full_error_handler,
+                                                                        NULL);
+               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
+               modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
+               
+               g_object_unref (mail_op);
+       }
+       if (header)
+               g_object_unref (header);
+       if (header_list)
+               g_object_unref (header_list);
+}
+
 /*
  * UI handler for the "Move to" action when invoked from the
  * ModestMainWindow
@@ -2006,9 +3256,10 @@ static void
 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
                                          ModestMainWindow *win)
 {
-       GtkWidget *dialog, *folder_view, *tree_view = NULL;
-       gint result;
-       TnyFolderStore *folder_store;
+       GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
+       GtkWidget *header_view = NULL;
+       gint result = 0;
+       TnyFolderStore *folder_store = NULL;
        ModestMailOperation *mail_op = NULL;
 
        g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
@@ -2016,10 +3267,27 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action,
        /* Get the folder view */
        folder_view = modest_main_window_get_child_widget (win,
                                                           MODEST_WIDGET_TYPE_FOLDER_VIEW);
+                                                          
+       TnyFolderStore *src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
+       
+       /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
+       if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), src_folder)) {
+               if (src_folder) {
+                       g_object_unref (src_folder);
+               }
+               
+               return;
+       }
+
+       /* Get header view */
+       header_view = modest_main_window_get_child_widget (win,
+                                                          MODEST_WIDGET_TYPE_HEADER_VIEW);
 
        /* Create and run the dialog */
        dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
+       modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
        result = gtk_dialog_run (GTK_DIALOG(dialog));
+       g_object_ref (tree_view);
 
        /* We do this to save an indentation level ;-) */
        if (result != GTK_RESPONSE_ACCEPT)
@@ -2027,36 +3295,44 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action,
 
        folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
 
-       if (TNY_IS_ACCOUNT (folder_store))
+       if (TNY_IS_ACCOUNT (folder_store) && 
+           !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
                goto end;
 
+       /* Offer the connection dialog if necessary: */
+       if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), folder_store)) {
+                       goto end;
+       }
+
        /* Get folder or messages to transfer */
        if (gtk_widget_is_focus (folder_view)) {
-               TnyFolderStore *src_folder;
-               src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
+               
+               /* Clean folder on header view before moving it */
+               modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
 
                if (TNY_IS_FOLDER (src_folder)) {
-                       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
-                       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
-                                                        mail_op);
+                       mail_op = 
+                               modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                      G_OBJECT(win),
+                                                                      modest_ui_actions_move_folder_error_handler,
+                                                                      NULL);
+                       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
 
                        modest_mail_operation_xfer_folder (mail_op, 
                                                           TNY_FOLDER (src_folder),
                                                           folder_store,
-                                                          TRUE);
+                                                          TRUE, NULL, NULL);
+                       /* Unref mail operation */
                        g_object_unref (G_OBJECT (mail_op));
+               } else {
+                       g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
                }
-
-               /* Frees */
-               g_object_unref (G_OBJECT (src_folder));
        } else {
-               GtkWidget *header_view;
-               header_view = modest_main_window_get_child_widget (win,
-                                                                  MODEST_WIDGET_TYPE_HEADER_VIEW);
                if (gtk_widget_is_focus (header_view)) {
-                       TnyList *headers;
-                       gint response;
+                       TnyList *headers = NULL;
+                       gint response = 0;
 
+                       /* TODO: Check for connection if the headers are on a network account. */
                        headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
 
                        /* Ask for user confirmation */
@@ -2066,21 +3342,34 @@ modest_ui_actions_on_main_window_move_to (GtkAction *action,
 
                        /* Transfer messages */
                        if (response == GTK_RESPONSE_OK) {
-                               mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
+                               mail_op = 
+                                       modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                                      G_OBJECT(win),
+                                                                                      modest_ui_actions_move_folder_error_handler,
+                                                                                      NULL);
                                modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
                                                                 mail_op);
 
                                modest_mail_operation_xfer_msgs (mail_op, 
                                                                 headers,
                                                                 TNY_FOLDER (folder_store),
-                                                                TRUE);
+                                                                TRUE,
+                                                                NULL,
+                                                                NULL);
+
                                g_object_unref (G_OBJECT (mail_op));
                        }
+                       g_object_unref (headers);
                }
        }
-       g_object_unref (folder_store);
-
+       
  end:
+    if (src_folder)
+       g_object_unref (src_folder);
+                       
+       if (folder_store)
+               g_object_unref (folder_store);
+
        gtk_widget_destroy (dialog);
 }
 
@@ -2094,16 +3383,18 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
                                              ModestMsgViewWindow *win)
 {
        GtkWidget *dialog, *folder_view, *tree_view = NULL;
-       gint result;
-       ModestMainWindow *main_window;
-       TnyMsg *msg;
-       TnyHeader *header;
-       TnyList *headers;
+       gint result = 0;
+       ModestMainWindow *main_window = NULL;
+       TnyHeader *header = NULL;
+       TnyList *headers = NULL;
 
        /* Get the folder view */
        main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
-       folder_view = modest_main_window_get_child_widget (main_window,
-                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
+       if (main_window)
+               folder_view = modest_main_window_get_child_widget (main_window,
+                                                                  MODEST_WIDGET_TYPE_FOLDER_VIEW);
+       else
+               folder_view = NULL;
 
        /* Create and run the dialog */
        dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
@@ -2113,41 +3404,56 @@ modest_ui_actions_on_msg_view_window_move_to (GtkAction *action,
                TnyFolderStore *folder_store;
                gint response;
 
-               folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
-
                /* Create header list */
-               msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
-               header = tny_msg_get_header (msg);
-               headers = tny_simple_list_new ();
-               tny_list_prepend (headers, G_OBJECT (header));
-               g_object_unref (header);
-               g_object_unref (msg);
+               header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
+               g_return_if_fail (header != NULL);
+
+               /* Offer the connection dialog if necessary: */
+               /* TODO: What's the extra g_object_ref() for? Isn't this leaking a ref? */
+               folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (g_object_ref (tree_view)));
+               TnyFolder *header_folder = tny_header_get_folder(header);
+               if (modest_platform_connect_and_wait_if_network_folderstore (NULL, folder_store) &&
+                   modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (header_folder))) {
+                       
+                       headers = tny_simple_list_new ();
+                       tny_list_prepend (headers, G_OBJECT (header));
+                       g_object_unref (header);
 
-               /* Ask user for confirmation. MSG-NOT404 */
-               response = msgs_move_to_confirmation (GTK_WINDOW (win), 
+                       /* Ask user for confirmation. MSG-NOT404 */
+                       response = msgs_move_to_confirmation (GTK_WINDOW (win), 
                                                      TNY_FOLDER (folder_store), 
                                                      headers);
 
-               /* Transfer current msg */
-               if (response == GTK_RESPONSE_OK) {
-                       ModestMailOperation *mail_op;
+                       /* Transfer current msg */
+                       if (response == GTK_RESPONSE_OK) {
+                               ModestMailOperation *mail_op;
 
-                       /* Create mail op */
-                       mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
-                       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
+                               /* Create mail op */
+                               mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
+                               modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
                                                         mail_op);
                        
-                       /* Transfer messages */
-                       modest_mail_operation_xfer_msgs (mail_op, 
+                               /* Transfer messages */
+                               modest_mail_operation_xfer_msgs (mail_op, 
                                                         headers,
                                                         TNY_FOLDER (folder_store),
-                                                        TRUE);
-                       g_object_unref (G_OBJECT (mail_op));
-               } else {
-                       g_object_unref (headers);
+                                                        TRUE,
+                                                        transfer_msgs_from_viewer_cb,
+                                                        NULL);
+                               g_object_unref (G_OBJECT (mail_op));
+                       }
                }
-               g_object_unref (folder_store);
+               
+               if (header_folder)
+                       g_object_unref (header_folder);
+
+               if (headers)
+                       g_object_unref (headers);
+                       
+               if (folder_store)
+                       g_object_unref (folder_store);
        }
+       
        gtk_widget_destroy (dialog);
 }
 
@@ -2165,3 +3471,309 @@ modest_ui_actions_on_move_to (GtkAction *action,
                modest_ui_actions_on_msg_view_window_move_to (action, 
                                                              MODEST_MSG_VIEW_WINDOW (win));
 }
+
+/*
+ * Calls #HeadersFunc for each header already selected in the main
+ * window or the message currently being shown in the msg view window
+ */
+static void
+do_headers_action (ModestWindow *win, 
+                  HeadersFunc func,
+                  gpointer user_data)
+{
+       TnyList *headers_list;
+       TnyIterator *iter;
+       TnyHeader *header;
+       TnyFolder *folder;
+
+       /* Get headers */
+       headers_list = get_selected_headers (win);
+       if (!headers_list)
+               return;
+
+       /* Get the folder */
+       iter = tny_list_create_iterator (headers_list);
+       header = TNY_HEADER (tny_iterator_get_current (iter));
+       folder = tny_header_get_folder (header);
+       g_object_unref (header);
+
+       /* Call the function for each header */
+       while (!tny_iterator_is_done (iter)) {
+               header = TNY_HEADER (tny_iterator_get_current (iter));
+               func (header, win, user_data);
+               g_object_unref (header);
+               tny_iterator_next (iter);
+       }
+
+       /* Trick: do a poke status in order to speed up the signaling
+          of observers */
+       tny_folder_poke_status (folder);
+
+       /* Frees */
+       g_object_unref (folder);
+       g_object_unref (iter);
+       g_object_unref (headers_list);
+}
+
+void 
+modest_ui_actions_view_attachment (GtkAction *action,
+                                  ModestWindow *window)
+{
+       if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
+               modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
+       } else {
+               /* not supported window for this action */
+               g_return_if_reached ();
+       }
+}
+
+void
+modest_ui_actions_save_attachments (GtkAction *action,
+                                   ModestWindow *window)
+{
+       if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
+               modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
+       } else {
+               /* not supported window for this action */
+               g_return_if_reached ();
+       }
+}
+
+void
+modest_ui_actions_remove_attachments (GtkAction *action,
+                                     ModestWindow *window)
+{
+       if (MODEST_IS_MAIN_WINDOW (window)) {
+               modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
+       } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
+               modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
+       } else {
+               /* not supported window for this action */
+               g_return_if_reached ();
+       }
+}
+
+void 
+modest_ui_actions_on_settings (GtkAction *action, 
+                              ModestWindow *win)
+{
+       GtkWidget *dialog;
+
+       dialog = modest_platform_get_global_settings_dialog ();
+       gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
+       gtk_widget_show_all (dialog);
+
+       gtk_dialog_run (GTK_DIALOG (dialog));
+
+       gtk_widget_destroy (dialog);
+}
+
+void 
+modest_ui_actions_on_help (GtkAction *action, 
+                          ModestWindow *win)
+{
+       const gchar *help_id = NULL;
+
+       if (MODEST_IS_MAIN_WINDOW (win)) {
+               const gchar *action_name;
+               action_name = gtk_action_get_name (action);
+
+               if (!strcmp (action_name, "FolderViewCSMHelp") ||
+                   !strcmp (action_name, "HeaderViewCSMHelp")) {
+                       GtkWidget *folder_view;
+                       TnyFolderStore *folder_store;
+                       /* Get selected folder */
+                       folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
+                                                                          MODEST_WIDGET_TYPE_FOLDER_VIEW);
+                       folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
+
+                       /* Switch help_id */
+                       if (TNY_IS_FOLDER (folder_store)) {
+                               switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
+                               case TNY_FOLDER_TYPE_NORMAL:
+                                       help_id = "applications_email_userfolder";
+                                       break;
+                               case TNY_FOLDER_TYPE_INBOX:
+                                       help_id = "applications_email_inbox";
+                                       break;
+                               case TNY_FOLDER_TYPE_OUTBOX:
+                                       help_id = "applications_email_outbox";
+                                       break;
+                               case TNY_FOLDER_TYPE_SENT:
+                                       help_id = "applications_email_sent";
+                                       break;
+                               case TNY_FOLDER_TYPE_DRAFTS:
+                                       help_id = "applications_email_drafts";
+                                       break;
+                               case TNY_FOLDER_TYPE_ARCHIVE:
+                                       help_id = "applications_email_archive";
+                                       break;
+                               default:
+                                       help_id = NULL;
+                               }
+                       }
+                       g_object_unref (folder_store);
+               } else {
+                       help_id = "applications_email_mainview";        
+               }
+       } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
+               help_id = "applications_email_viewer";
+       } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
+               help_id = "applications_email_editor";
+
+       modest_platform_show_help (GTK_WINDOW (win), help_id);
+}
+
+void 
+modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
+                                           ModestWindow *window)
+{
+       ModestMailOperation *mail_op;
+       TnyList *headers;
+
+       /* Get headers */
+       headers = get_selected_headers (window);
+       if (!headers)
+               return;
+
+       /* Create mail operation */
+       mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
+                                                                G_OBJECT (window),
+                                                                modest_ui_actions_get_msgs_full_error_handler, 
+                                                                NULL);
+       modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
+       modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
+
+       /* Frees */
+       g_object_unref (headers);
+       g_object_unref (mail_op);
+}
+
+void
+modest_ui_actions_on_email_menu_activated (GtkAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_edit_menu_activated (GtkAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_view_menu_activated (GtkAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_tools_menu_activated (GtkAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
+                                                ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
+                                                    ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
+                                                    ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
+}
+
+void
+modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       /* Update dimmed */     
+       modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
+}
+
+void
+modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (window));
+
+       modest_platform_show_search_messages (GTK_WINDOW (window));
+}
+
+void     
+modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
+{
+       g_return_if_fail (MODEST_IS_WINDOW (win));
+       modest_platform_show_addressbook (GTK_WINDOW (win));
+}
+
+
+void
+modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
+                                         ModestWindow *window)
+{
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
+
+       modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
+}
+
+static void 
+_on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
+                                  ModestMailOperationState *state,
+                                  gpointer user_data)
+{
+       g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
+
+       /* Set send/receive operation finished */       
+       if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
+               modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
+       
+}
+
+