* add checks that session != NULL
[modest] / src / modest-mail-operation.c
index 0199d9e..4a987c7 100644 (file)
@@ -35,6 +35,8 @@
 #include <tny-folder-store-query.h>
 #include <tny-camel-stream.h>
 #include <tny-camel-pop-store-account.h>
 #include <tny-folder-store-query.h>
 #include <tny-camel-stream.h>
 #include <tny-camel-pop-store-account.h>
+#include <tny-camel-pop-folder.h>
+#include <tny-camel-imap-folder.h>
 #include <tny-simple-list.h>
 #include <tny-send-queue.h>
 #include <tny-status.h>
 #include <tny-simple-list.h>
 #include <tny-send-queue.h>
 #include <tny-status.h>
@@ -70,7 +72,8 @@ static void     get_msg_status_cb (GObject *obj,
                                   TnyStatus *status,  
                                   gpointer user_data);
 
                                   TnyStatus *status,  
                                   gpointer user_data);
 
-static void     modest_mail_operation_notify_end (ModestMailOperation *self);
+static void     modest_mail_operation_notify_end (ModestMailOperation *self,
+                                                 gboolean need_lock);
 
 static gboolean did_a_cancel = FALSE;
 
 
 static gboolean did_a_cancel = FALSE;
 
@@ -105,6 +108,7 @@ struct _ModestMailOperationPrivate {
 
 typedef struct _GetMsgAsyncHelper {    
        ModestMailOperation *mail_op;
 
 typedef struct _GetMsgAsyncHelper {    
        ModestMailOperation *mail_op;
+       TnyHeader *header;
        GetMsgAsyncUserCallback user_callback;  
        gpointer user_data;
 } GetMsgAsyncHelper;
        GetMsgAsyncUserCallback user_callback;  
        gpointer user_data;
 } GetMsgAsyncHelper;
@@ -364,16 +368,15 @@ modest_mail_operation_cancel (ModestMailOperation *self)
                return FALSE;
        }
 
                return FALSE;
        }
 
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
-
        did_a_cancel = TRUE;
 
        /* Set new status */
        priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
        did_a_cancel = TRUE;
 
        /* Set new status */
        priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
-       
-       modest_mail_operation_queue_cancel_all (modest_runtime_get_mail_operation_queue());
 
 
+       /* This emits progress-changed on which the mail operation queue is
+        * listening, so the mail operation is correctly removed from the
+        * queue without further explicit calls. */
+       modest_mail_operation_notify_end (self, FALSE);
        
        return TRUE;
 }
        
        return TRUE;
 }
@@ -477,6 +480,8 @@ modest_mail_operation_clone_state (ModestMailOperation *self)
        state->done = priv->done;
        state->total = priv->total;
        state->finished = modest_mail_operation_is_finished (self);
        state->done = priv->done;
        state->total = priv->total;
        state->finished = modest_mail_operation_is_finished (self);
+       state->bytes_done = 0;
+       state->bytes_total = 0;
 
        return state;
 }
 
        return state;
 }
@@ -501,6 +506,8 @@ modest_mail_operation_send_mail (ModestMailOperation *self,
 
        /* Get account and set it into mail_operation */
        priv->account = g_object_ref (transport_account);
 
        /* Get account and set it into mail_operation */
        priv->account = g_object_ref (transport_account);
+       priv->done = 1;
+       priv->total = 1;
 
        send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
        if (!TNY_IS_SEND_QUEUE(send_queue)) {
 
        send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
        if (!TNY_IS_SEND_QUEUE(send_queue)) {
@@ -508,11 +515,17 @@ modest_mail_operation_send_mail (ModestMailOperation *self,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "modest: could not find send queue for account\n");
        } else {
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "modest: could not find send queue for account\n");
        } else {
+               /* TODO: connect to the msg-sent in order to know when
+                  the mail operation is finished */
                tny_send_queue_add (send_queue, msg, &(priv->error));
                tny_send_queue_add (send_queue, msg, &(priv->error));
+               /* TODO: we're setting always success, do the check in
+                  the handler */
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
 
        }
 
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       /* TODO: do this in the handler of the "msg-sent"
+          signal.Notify about operation end */
+       modest_mail_operation_notify_end (self, FALSE);
 }
 
 void
 }
 
 void
@@ -536,9 +549,6 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self,
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
-       /* Get account and set it into mail_operation */
-       priv->account = g_object_ref (transport_account);
-
        /* Check parametters */
        if (to == NULL) {
                /* Set status failed and set an error */
        /* Check parametters */
        if (to == NULL) {
                /* Set status failed and set an error */
@@ -612,6 +622,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
                msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
        }
        if (!msg) {
                msg = modest_tny_msg_new_html_plain (to, from, cc, bcc, subject, html_body, plain_body, (GSList *) attachments_list);
        }
        if (!msg) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
                             "modest: failed to create a new msg\n");
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED,
                             "modest: failed to create a new msg\n");
@@ -624,6 +635,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
 
        folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
        if (!folder) {
 
        folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (transport_account), TNY_FOLDER_TYPE_DRAFTS);
        if (!folder) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "modest: failed to create a new msg\n");
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "modest: failed to create a new msg\n");
@@ -634,13 +646,17 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
                header = tny_msg_get_header (draft_msg);
                /* Remove the old draft expunging it */
                tny_folder_remove_msg (folder, header, NULL);
                header = tny_msg_get_header (draft_msg);
                /* Remove the old draft expunging it */
                tny_folder_remove_msg (folder, header, NULL);
-               tny_folder_sync (folder, TRUE, NULL);
+               tny_folder_sync (folder, FALSE, &(priv->error));  /* FALSE --> don't expunge */
                g_object_unref (header);
        }
        
                g_object_unref (header);
        }
        
-       tny_folder_add_msg (folder, msg, &(priv->error));
-       if (priv->error)
-               goto end;
+       if (!priv->error)
+               tny_folder_add_msg (folder, msg, &(priv->error));
+
+       if (!priv->error)
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       else
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
 
 end:
        if (msg)
 
 end:
        if (msg)
@@ -648,7 +664,7 @@ end:
        if (folder)
                g_object_unref (G_OBJECT(folder));
 
        if (folder)
                g_object_unref (G_OBJECT(folder));
 
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, FALSE);
 }
 
 typedef struct 
 }
 
 typedef struct 
@@ -660,6 +676,8 @@ typedef struct
        gint retrieve_limit;
        gchar *retrieve_type;
        gchar *account_name;
        gint retrieve_limit;
        gchar *retrieve_type;
        gchar *account_name;
+       UpdateAccountCallback callback;
+       gpointer user_data;
 } UpdateAccountInfo;
 
 /***** I N T E R N A L    F O L D E R    O B S E R V E R *****/
 } UpdateAccountInfo;
 
 /***** I N T E R N A L    F O L D E R    O B S E R V E R *****/
@@ -819,14 +837,15 @@ idle_notify_progress_once (gpointer data)
  * loop. We call it inside an idle call to achieve that
  */
 static gboolean
  * loop. We call it inside an idle call to achieve that
  */
 static gboolean
-notify_update_account_queue (gpointer data)
+idle_notify_update_account_queue (gpointer data)
 {
        ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
        ModestMailOperationPrivate *priv = NULL;
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_op);
 {
        ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
        ModestMailOperationPrivate *priv = NULL;
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(mail_op);
-       
-       modest_mail_operation_notify_end (mail_op);
+
+       /* Do not need to block, the notify end will do it for us */    
+       modest_mail_operation_notify_end (mail_op, TRUE);
        g_object_unref (mail_op);
 
        return FALSE;
        g_object_unref (mail_op);
 
        return FALSE;
@@ -856,6 +875,8 @@ compare_headers_by_date (gconstpointer a,
 static gboolean 
 set_last_updated_idle (gpointer data)
 {
 static gboolean 
 set_last_updated_idle (gpointer data)
 {
+       gdk_threads_enter ();
+
        /* It does not matter if the time is not exactly the same than
           the time when this idle was called, it's just an
           approximation and it won't be very different */
        /* It does not matter if the time is not exactly the same than
           the time when this idle was called, it's just an
           approximation and it won't be very different */
@@ -865,6 +886,8 @@ set_last_updated_idle (gpointer data)
                                    time(NULL), 
                                    TRUE);
 
                                    time(NULL), 
                                    TRUE);
 
+       gdk_threads_leave ();
+
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -874,11 +897,11 @@ update_account_thread (gpointer thr_user_data)
        static gboolean first_time = TRUE;
        UpdateAccountInfo *info;
        TnyList *all_folders = NULL;
        static gboolean first_time = TRUE;
        UpdateAccountInfo *info;
        TnyList *all_folders = NULL;
-       GPtrArray *new_headers;
+       GPtrArray *new_headers = NULL;
        TnyIterator *iter = NULL;
        TnyFolderStoreQuery *query = NULL;
        TnyIterator *iter = NULL;
        TnyFolderStoreQuery *query = NULL;
-       ModestMailOperationPrivate *priv;
-       ModestTnySendQueue *send_queue;
+       ModestMailOperationPrivate *priv = NULL;
+       ModestTnySendQueue *send_queue = NULL;
 
        info = (UpdateAccountInfo *) thr_user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
 
        info = (UpdateAccountInfo *) thr_user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
@@ -922,7 +945,7 @@ update_account_thread (gpointer thr_user_data)
           Gtk+. We use a timeout in order to provide more status
           information, because the sync tinymail call does not
           provide it for the moment */
           Gtk+. We use a timeout in order to provide more status
           information, because the sync tinymail call does not
           provide it for the moment */
-       gint timeout = g_timeout_add (250, idle_notify_progress, info->mail_op);
+       gint timeout = g_timeout_add (100, idle_notify_progress, info->mail_op);
 
        /* Refresh folders */
        new_headers = g_ptr_array_new ();
 
        /* Refresh folders */
        new_headers = g_ptr_array_new ();
@@ -936,8 +959,6 @@ update_account_thread (gpointer thr_user_data)
                /* Refresh the folder */
                /* Our observer receives notification of new emails during folder refreshes,
                 * so we can use observer->new_headers.
                /* Refresh the folder */
                /* Our observer receives notification of new emails during folder refreshes,
                 * so we can use observer->new_headers.
-                * TODO: This does not seem to be providing accurate numbers.
-                * Possibly the observer is notified asynchronously.
                 */
                observer = g_object_new (internal_folder_observer_get_type (), NULL);
                tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
                 */
                observer = g_object_new (internal_folder_observer_get_type (), NULL);
                tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
@@ -975,12 +996,15 @@ update_account_thread (gpointer thr_user_data)
                }
                tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
                g_object_unref (observer);
                }
                tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer));
                g_object_unref (observer);
-               observer = NULL;
+               observer = NULL;                        
 
 
+               g_object_unref (G_OBJECT (folder));
                if (priv->error)
                if (priv->error)
+               {
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-               g_object_unref (G_OBJECT (folder));
+                       goto out;
+               }
+               
                tny_iterator_next (iter);
        }
 
                tny_iterator_next (iter);
        }
 
@@ -1000,11 +1024,11 @@ update_account_thread (gpointer thr_user_data)
                 * user to download them all,
                 * as per the UI spec "Retrieval Limits" section in 4.4: 
                 */
                 * user to download them all,
                 * as per the UI spec "Retrieval Limits" section in 4.4: 
                 */
-               printf ("************************** DEBUG: %s: account=%s, len=%d, retrieve_limit = %d\n", __FUNCTION__, 
-                       tny_account_get_id (priv->account), new_headers->len, info->retrieve_limit);
                if (new_headers->len > info->retrieve_limit) {
                if (new_headers->len > info->retrieve_limit) {
-                       /* TODO: Ask the user, instead of just failing, showing mail_nc_msg_count_limit_exceeded, 
-                        * with 'Get all' and 'Newest only' buttons. */
+                       /* TODO: Ask the user, instead of just
+                        * failing, showing
+                        * mail_nc_msg_count_limit_exceeded, with 'Get
+                        * all' and 'Newest only' buttons. */
                        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_RETRIEVAL_NUMBER_LIMIT,
                             "The number of messages to retrieve exceeds the chosen limit for account %s\n", 
                        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_RETRIEVAL_NUMBER_LIMIT,
                             "The number of messages to retrieve exceeds the chosen limit for account %s\n", 
@@ -1040,7 +1064,7 @@ update_account_thread (gpointer thr_user_data)
                g_ptr_array_foreach (new_headers, (GFunc) g_object_unref, NULL);
                g_ptr_array_free (new_headers, FALSE);
        }
                g_ptr_array_foreach (new_headers, (GFunc) g_object_unref, NULL);
                g_ptr_array_free (new_headers, FALSE);
        }
-
+       
        /* Perform send */
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
        priv->done = 0;
        /* Perform send */
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
        priv->done = 0;
@@ -1077,7 +1101,16 @@ update_account_thread (gpointer thr_user_data)
        /* Notify about operation end. Note that the info could be
           freed before this idle happens, but the mail operation will
           be still alive */
        /* Notify about operation end. Note that the info could be
           freed before this idle happens, but the mail operation will
           be still alive */
-       g_idle_add (notify_update_account_queue, g_object_ref (info->mail_op));
+       g_idle_add (idle_notify_update_account_queue, g_object_ref (info->mail_op));
+
+       if (info->callback) {
+               /* This thread is not in the main lock */
+               gdk_threads_enter ();
+               info->callback (info->mail_op, 
+                               (new_headers) ? new_headers->len : 0, 
+                               info->user_data);
+               gdk_threads_leave ();
+       }
        
        /* Frees */
        g_object_unref (query);
        
        /* Frees */
        g_object_unref (query);
@@ -1094,7 +1127,9 @@ update_account_thread (gpointer thr_user_data)
 
 gboolean
 modest_mail_operation_update_account (ModestMailOperation *self,
 
 gboolean
 modest_mail_operation_update_account (ModestMailOperation *self,
-                                     const gchar *account_name)
+                                     const gchar *account_name,
+                                     UpdateAccountCallback callback,
+                                     gpointer user_data)
 {
        GThread *thread;
        UpdateAccountInfo *info;
 {
        GThread *thread;
        UpdateAccountInfo *info;
@@ -1106,13 +1141,6 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
        g_return_val_if_fail (account_name, FALSE);
 
        g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
        g_return_val_if_fail (account_name, FALSE);
 
-       /* Make sure that we have a connection, and request one 
-        * if necessary:
-        * TODO: Is there some way to trigger this for every attempt to 
-        * use the network? */
-       if (!modest_platform_connect_and_wait(NULL))
-               return FALSE;
-       
        /* Init mail operation. Set total and done to 0, and do not
           update them, this way the progress objects will know that
           we have no clue about the number of the objects */
        /* Init mail operation. Set total and done to 0, and do not
           update them, this way the progress objects will know that
           we have no clue about the number of the objects */
@@ -1120,7 +1148,7 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        priv->total = 0;
        priv->done  = 0;
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
        priv->total = 0;
        priv->done  = 0;
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-       
+
        /* Get the Modest account */
        modest_account = (TnyStoreAccount *)
                modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
        /* Get the Modest account */
        modest_account = (TnyStoreAccount *)
                modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
@@ -1128,13 +1156,10 @@ modest_mail_operation_update_account (ModestMailOperation *self,
                                                                     TNY_ACCOUNT_TYPE_STORE);
 
        if (!modest_account) {
                                                                     TNY_ACCOUNT_TYPE_STORE);
 
        if (!modest_account) {
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "cannot get tny store account for %s\n", account_name);
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "cannot get tny store account for %s\n", account_name);
-               modest_mail_operation_notify_end (self);
-
-               return FALSE;
+               goto error;
        }
 
        
        }
 
        
@@ -1144,13 +1169,10 @@ modest_mail_operation_update_account (ModestMailOperation *self,
                modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
                                                                                    account_name);
        if (!transport_account) {
                modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
                                                                                    account_name);
        if (!transport_account) {
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "cannot get tny transport account for %s\n", account_name);
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
                             "cannot get tny transport account for %s\n", account_name);
-               modest_mail_operation_notify_end (self);
-
-               return FALSE;
+               goto error;
        }
 
        /* Create the helper object */
        }
 
        /* Create the helper object */
@@ -1158,6 +1180,8 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        info->mail_op = self;
        info->account = modest_account;
        info->transport_account = transport_account;
        info->mail_op = self;
        info->account = modest_account;
        info->transport_account = transport_account;
+       info->callback = callback;
+       info->user_data = user_data;
 
        /* Get the message size limit */
        info->max_size  = modest_conf_get_int (modest_runtime_get_conf (), 
 
        /* Get the message size limit */
        info->max_size  = modest_conf_get_int (modest_runtime_get_conf (), 
@@ -1187,6 +1211,13 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        thread = g_thread_create (update_account_thread, info, FALSE, NULL);
 
        return TRUE;
        thread = g_thread_create (update_account_thread, info, FALSE, NULL);
 
        return TRUE;
+
+ error:
+       priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+       if (callback) 
+               callback (self, 0, user_data);
+       modest_mail_operation_notify_end (self, FALSE);
+       return FALSE;
 }
 
 /* ******************************************************************* */
 }
 
 /* ******************************************************************* */
@@ -1220,6 +1251,13 @@ modest_mail_operation_create_folder (ModestMailOperation *self,
                }
        }
 
                }
        }
 
+       if (!strcmp (name, " ") || strchr (name, '/')) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                            _("mail_in_ui_folder_create_error"));
+       }
+
        if (!priv->error) {
                /* Create the folder */
                new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
        if (!priv->error) {
                /* Create the folder */
                new_folder = tny_folder_store_create_folder (parent, name, &(priv->error));
@@ -1229,7 +1267,7 @@ modest_mail_operation_create_folder (ModestMailOperation *self,
        }
 
        /* Notify about operation end */
        }
 
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, FALSE);
 
        return new_folder;
 }
 
        return new_folder;
 }
@@ -1284,7 +1322,7 @@ modest_mail_operation_remove_folder (ModestMailOperation *self,
 
  end:
        /* Notify about operation end */
 
  end:
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, FALSE);
 }
 
 static void
 }
 
 static void
@@ -1318,7 +1356,8 @@ static void
 transfer_folder_cb (TnyFolder *folder, 
                    TnyFolderStore *into, 
                    gboolean cancelled, 
 transfer_folder_cb (TnyFolder *folder, 
                    TnyFolderStore *into, 
                    gboolean cancelled, 
-                   TnyFolder *new_folder, GError **err, 
+                   TnyFolder *new_folder, 
+                   GError **err, 
                    gpointer user_data)
 {
        ModestMailOperation *self = NULL;
                    gpointer user_data)
 {
        ModestMailOperation *self = NULL;
@@ -1346,11 +1385,9 @@ transfer_folder_cb (TnyFolder *folder,
        /* Free */
        g_object_unref (folder);
        g_object_unref (into);
        /* Free */
        g_object_unref (folder);
        g_object_unref (into);
-       if (new_folder != NULL)
-               g_object_unref (new_folder);
 
        /* Notify about operation end */
 
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, TRUE);
 }
 
 void
 }
 
 void
@@ -1360,11 +1397,10 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
                                   gboolean delete_original)
 {
        ModestMailOperationPrivate *priv = NULL;
                                   gboolean delete_original)
 {
        ModestMailOperationPrivate *priv = NULL;
-       ModestTnyFolderRules parent_rules, rules;
+       ModestTnyFolderRules parent_rules = 0, rules; 
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_FOLDER (folder));
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_FOLDER (folder));
-       g_return_if_fail (TNY_IS_FOLDER (parent));
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
@@ -1374,14 +1410,12 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
 
        /* Get folder rules */
        rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
 
        /* Get folder rules */
        rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
-       parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
-
-       if (!TNY_IS_FOLDER_STORE (parent)) {
-               
-       }
+       if (TNY_IS_FOLDER (parent))
+               parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent));
        
        /* The moveable restriction is applied also to copy operation */
        if ((!TNY_IS_FOLDER_STORE (parent)) || (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
        
        /* The moveable restriction is applied also to copy operation */
        if ((!TNY_IS_FOLDER_STORE (parent)) || (rules & MODEST_FOLDER_RULES_FOLDER_NON_MOVEABLE)) {
+               printf("DEBUG: %s: Not allowing the move.\n", __FUNCTION__);
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
@@ -1389,8 +1423,9 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
                             _("mail_in_ui_folder_move_target_error"));
 
                /* Notify the queue */
                             _("mail_in_ui_folder_move_target_error"));
 
                /* Notify the queue */
-               modest_mail_operation_notify_end (self);
-       } else if (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
+               modest_mail_operation_notify_end (self, FALSE);
+       } else if (TNY_IS_FOLDER (parent) && 
+                  (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE)) {
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
@@ -1398,7 +1433,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self,
                             _("FIXME: parent folder does not accept new folders"));
 
                /* Notify the queue */
                             _("FIXME: parent folder does not accept new folders"));
 
                /* Notify the queue */
-               modest_mail_operation_notify_end (self);
+               modest_mail_operation_notify_end (self, FALSE);
        } else {
                /* Pick references for async calls */
                g_object_ref (folder);
        } else {
                /* Pick references for async calls */
                g_object_ref (folder);
@@ -1442,19 +1477,25 @@ modest_mail_operation_rename_folder (ModestMailOperation *self,
                             _("FIXME: unable to rename"));
 
                /* Notify about operation end */
                             _("FIXME: unable to rename"));
 
                /* Notify about operation end */
-               modest_mail_operation_notify_end (self);
+               modest_mail_operation_notify_end (self, FALSE);
+       } else if (!strcmp (name, " ") || strchr (name, '/')) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
+                            _("FIXME: unable to rename"));
+               /* Notify about operation end */
+               modest_mail_operation_notify_end (self, FALSE);
        } else {
        } else {
-               /* Rename. Camel handles folder subscription/unsubscription */
                TnyFolderStore *into;
 
                TnyFolderStore *into;
 
+               /* Rename. Camel handles folder subscription/unsubscription */
                into = tny_folder_get_folder_store (folder);
                tny_folder_copy_async (folder, into, name, TRUE,
                                 transfer_folder_cb,
                                 transfer_folder_status_cb,
                                 self);
                if (into)
                into = tny_folder_get_folder_store (folder);
                tny_folder_copy_async (folder, into, name, TRUE,
                                 transfer_folder_cb,
                                 transfer_folder_status_cb,
                                 self);
                if (into)
-                       g_object_unref (into);
-               
+                       g_object_unref (into);          
        }
  }
 
        }
  }
 
@@ -1488,6 +1529,12 @@ void modest_mail_operation_get_msg (ModestMailOperation *self,
                helper->mail_op = self;
                helper->user_callback = user_callback;
                helper->user_data = user_data;
                helper->mail_op = self;
                helper->user_callback = user_callback;
                helper->user_data = user_data;
+               helper->header = g_object_ref (header);
+
+               // The callback's reference so that the mail op is not
+               // finalized until the async operation is completed even if
+               // the user canceled the request meanwhile.
+               g_object_ref (G_OBJECT (helper->mail_op));
 
                tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
 
 
                tny_folder_get_msg_async (folder, header, get_msg_cb, get_msg_status_cb, helper);
 
@@ -1500,7 +1547,7 @@ void modest_mail_operation_get_msg (ModestMailOperation *self,
                             _("Error trying to get a message. No folder found for header"));
 
                /* Notify the queue */
                             _("Error trying to get a message. No folder found for header"));
 
                /* Notify the queue */
-               modest_mail_operation_notify_end (self);
+               modest_mail_operation_notify_end (self, FALSE);
        }
 }
 
        }
 }
 
@@ -1536,19 +1583,31 @@ get_msg_cb (TnyFolder *folder,
                goto out;
        }
 
                goto out;
        }
 
-       priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       /* The mail operation might have been canceled in which case we do not
+          want to notify anyone anymore. */
+       if(priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
 
 
-       /* If user defined callback function was defined, call it */
-       if (helper->user_callback) {
-               helper->user_callback (self, NULL, msg, helper->user_data);
+               /* If user defined callback function was defined, call it */
+               if (helper->user_callback) {
+                       /* This callback is called into an iddle by tinymail,
+                          and idles are not in the main lock */
+                       gdk_threads_enter ();
+                       helper->user_callback (self, helper->header, msg, helper->user_data);
+                       gdk_threads_leave ();
+               }
        }
 
  out:
        /* Free */
        }
 
  out:
        /* Free */
+       g_object_unref (helper->header);
        g_slice_free (GetMsgAsyncHelper, helper);
                
        /* Notify about operation end */
        g_slice_free (GetMsgAsyncHelper, helper);
                
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);        
+       if(priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED)
+               modest_mail_operation_notify_end (self, TRUE);
+
+       g_object_unref (G_OBJECT (self));
 }
 
 static void     
 }
 
 static void     
@@ -1570,6 +1629,9 @@ get_msg_status_cb (GObject *obj,
        self = helper->mail_op;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
        self = helper->mail_op;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
 
+       if(priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED)
+               return;
+
        if ((status->position == 1) && (status->of_total == 100))
                return;
 
        if ((status->position == 1) && (status->of_total == 100))
                return;
 
@@ -1577,6 +1639,8 @@ get_msg_status_cb (GObject *obj,
        priv->total = 1;
 
        state = modest_mail_operation_clone_state (self);
        priv->total = 1;
 
        state = modest_mail_operation_clone_state (self);
+       state->bytes_done = status->position;
+       state->bytes_total = status->of_total;
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
        g_slice_free (ModestMailOperationState, state);
 }
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
        g_slice_free (ModestMailOperationState, state);
 }
@@ -1610,8 +1674,11 @@ notify_get_msgs_full (gpointer data)
 
        info = (NotifyGetMsgsInfo *) data;      
 
 
        info = (NotifyGetMsgsInfo *) data;      
 
-       /* Call the user callback */
+       /* Call the user callback. Idles are not in the main lock, so
+          lock it */
+       gdk_threads_enter ();
        info->user_callback (info->mail_op, info->header, info->msg, info->user_data);
        info->user_callback (info->mail_op, info->header, info->msg, info->user_data);
+       gdk_threads_leave ();
 
        g_slice_free (NotifyGetMsgsInfo, info);
 
 
        g_slice_free (NotifyGetMsgsInfo, info);
 
@@ -1629,8 +1696,11 @@ get_msgs_full_destroyer (gpointer data)
 
        info = (GetFullMsgsInfo *) data;
 
 
        info = (GetFullMsgsInfo *) data;
 
-       if (info->notify)
+       if (info->notify) {
+               gdk_threads_enter ();   
                info->notify (info->user_data);
                info->notify (info->user_data);
+               gdk_threads_leave ();
+       }
 
        /* free */
        g_object_unref (info->headers);
 
        /* free */
        g_object_unref (info->headers);
@@ -1707,7 +1777,7 @@ get_msgs_full_thread (gpointer thr_user_data)
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
 
        /* Notify about operation end */
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
 
        /* Notify about operation end */
-       g_idle_add (notify_update_account_queue, g_object_ref (info->mail_op));
+       g_idle_add (idle_notify_update_account_queue, g_object_ref (info->mail_op));
 
        /* Free thread resources. Will be called after all previous idles */
        g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, get_msgs_full_destroyer, info, NULL);
 
        /* Free thread resources. Will be called after all previous idles */
        g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, get_msgs_full_destroyer, info, NULL);
@@ -1796,7 +1866,7 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
                             MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
                             _("emev_ni_ui_imap_msg_size_exceed_error"));
                /* Remove from queue and free resources */
                             MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT,
                             _("emev_ni_ui_imap_msg_size_exceed_error"));
                /* Remove from queue and free resources */
-               modest_mail_operation_notify_end (self);
+               modest_mail_operation_notify_end (self, FALSE);
                if (notify)
                        notify (user_data);
        }
                if (notify)
                        notify (user_data);
        }
@@ -1804,9 +1874,8 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
 
 
 void 
 
 
 void 
-modest_mail_operation_remove_msg (ModestMailOperation *self,
-                                 TnyHeader *header,
-                                 gboolean remove_to_trash)
+modest_mail_operation_remove_msg (ModestMailOperation *self,  TnyHeader *header,
+                                 gboolean remove_to_trash /*ignored*/)
 {
        TnyFolder *folder;
        ModestMailOperationPrivate *priv;
 {
        TnyFolder *folder;
        ModestMailOperationPrivate *priv;
@@ -1814,6 +1883,9 @@ modest_mail_operation_remove_msg (ModestMailOperation *self,
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_HEADER (header));
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_HEADER (header));
 
+       if (remove_to_trash)
+               g_warning ("remove to trash is not implemented");
+
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
        folder = tny_header_get_folder (header);
 
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
        folder = tny_header_get_folder (header);
 
@@ -1822,44 +1894,21 @@ modest_mail_operation_remove_msg (ModestMailOperation *self,
 
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
 
 
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
 
-       /* Delete or move to trash */
-       if (remove_to_trash) {
-               TnyFolder *trash_folder;
-               TnyStoreAccount *store_account;
-
-               store_account = TNY_STORE_ACCOUNT (modest_tny_folder_get_account (folder));
-               trash_folder = modest_tny_account_get_special_folder (TNY_ACCOUNT(store_account),
-                                                                     TNY_FOLDER_TYPE_TRASH);
-               if (trash_folder) {
-                       TnyList *headers;
 
 
-                       /* Create list */
-                       headers = tny_simple_list_new ();
-                       tny_list_append (headers, G_OBJECT (header));
-                       g_object_unref (header);
-
-                       /* Move to trash */
-                       modest_mail_operation_xfer_msgs (self, headers, trash_folder, TRUE, NULL, NULL);
-                       g_object_unref (headers);
-/*                     g_object_unref (trash_folder); */
-               } else {
-                       ModestMailOperationPrivate *priv;
-
-                       /* Set status failed and set an error */
-                       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
-                       priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-                       g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                                    MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
-                                    _("Error trying to delete a message. Trash folder not found"));
-               }
-
-               g_object_unref (G_OBJECT (store_account));
-       } else {
-               tny_folder_remove_msg (folder, header, &(priv->error));
-               if (!priv->error)
-                       tny_folder_sync(folder, TRUE, &(priv->error));
+       tny_folder_remove_msg (folder, header, &(priv->error));
+       if (!priv->error) {
+               tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED);
+
+               if (TNY_IS_CAMEL_IMAP_FOLDER (folder))
+                       tny_folder_sync(folder, FALSE, &(priv->error)); /* FALSE --> don't expunge */
+               else if (TNY_IS_CAMEL_POP_FOLDER (folder))
+                       tny_folder_sync(folder, TRUE, &(priv->error)); /* TRUE --> expunge */
+               else
+                       /* lcoal folders */
+                       tny_folder_sync(folder, TRUE, &(priv->error)); /* TRUE --> expunge */
        }
        }
-
+       
+       
        /* Set status */
        if (!priv->error)
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        /* Set status */
        if (!priv->error)
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
@@ -1870,7 +1919,7 @@ modest_mail_operation_remove_msg (ModestMailOperation *self,
        g_object_unref (G_OBJECT (folder));
 
        /* Notify about operation end */
        g_object_unref (G_OBJECT (folder));
 
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, FALSE);
 }
 
 static void
 }
 
 static void
@@ -1932,9 +1981,14 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
 
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
 
+       /* Notify about operation end */
+       modest_mail_operation_notify_end (self, TRUE);
+
        /* If user defined callback function was defined, call it */
        if (helper->user_callback) {
        /* If user defined callback function was defined, call it */
        if (helper->user_callback) {
+               gdk_threads_enter ();
                helper->user_callback (priv->source, helper->user_data);
                helper->user_callback (priv->source, helper->user_data);
+               gdk_threads_leave ();
        }
 
        /* Free */
        }
 
        /* Free */
@@ -1944,8 +1998,6 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer
        g_slice_free   (XFerMsgAsyncHelper, helper);
        g_object_unref (folder);
 
        g_slice_free   (XFerMsgAsyncHelper, helper);
        g_object_unref (folder);
 
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
 }
 
 void
 }
 
 void
@@ -1962,6 +2014,9 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
        XFerMsgAsyncHelper *helper;
        TnyHeader *header;
        ModestTnyFolderRules rules;
        XFerMsgAsyncHelper *helper;
        TnyHeader *header;
        ModestTnyFolderRules rules;
+       const gchar *id1 = NULL;
+       const gchar *id2 = NULL;
+       gboolean same_folder = FALSE;
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_LIST (headers));
 
        g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
        g_return_if_fail (TNY_IS_LIST (headers));
@@ -1974,15 +2029,40 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
 
        /* Apply folder rules */
        rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
 
        /* Apply folder rules */
        rules = modest_tny_folder_get_rules (TNY_FOLDER (folder));
-
        if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
        if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
                /* Set status failed and set an error */
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                             MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES,
-                            _("FIXME: folder does not accept msgs"));
+                            _("ckct_ib_unable_to_paste_here"));
                /* Notify the queue */
                /* Notify the queue */
-               modest_mail_operation_notify_end (self);
+               modest_mail_operation_notify_end (self, FALSE);
+               return;
+       }
+               
+       /* Get source folder */
+       iter = tny_list_create_iterator (headers);
+       header = TNY_HEADER (tny_iterator_get_current (iter));
+       src_folder = tny_header_get_folder (header);
+       g_object_unref (header);
+       g_object_unref (iter);
+
+       /* Check folder source and destination */
+       id1 = tny_folder_get_id (src_folder);
+       id2 = tny_folder_get_id (TNY_FOLDER(folder));
+       same_folder = !g_ascii_strcasecmp (id1, id2);
+       if (same_folder) {
+               /* Set status failed and set an error */
+               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
+                            MODEST_MAIL_OPERATION_ERROR_BAD_PARAMETER,
+                            _("mcen_ib_unable_to_copy_samefolder"));
+               
+               /* Notify the queue */
+               modest_mail_operation_notify_end (self, FALSE);
+               
+               /* Free */
+               g_object_unref (src_folder);            
                return;
        }
 
                return;
        }
 
@@ -1994,13 +2074,6 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
        helper->user_callback = user_callback;
        helper->user_data = user_data;
 
        helper->user_callback = user_callback;
        helper->user_data = user_data;
 
-       /* Get source folder */
-       iter = tny_list_create_iterator (headers);
-       header = TNY_HEADER (tny_iterator_get_current (iter));
-       src_folder = tny_header_get_folder (header);
-       g_object_unref (header);
-       g_object_unref (iter);
-
        /* Get account and set it into mail_operation */
        priv->account = modest_tny_folder_get_account (src_folder);
 
        /* Get account and set it into mail_operation */
        priv->account = modest_tny_folder_get_account (src_folder);
 
@@ -2048,8 +2121,11 @@ on_refresh_folder (TnyFolder   *folder,
 
  out:
        /* Call user defined callback, if it exists */
 
  out:
        /* Call user defined callback, if it exists */
-       if (helper->user_callback)
+       if (helper->user_callback) {
+               gdk_threads_enter ();
                helper->user_callback (priv->source, folder, helper->user_data);
                helper->user_callback (priv->source, folder, helper->user_data);
+               gdk_threads_leave ();
+       }
 
        /* Free */
        g_object_unref (helper->mail_op);
 
        /* Free */
        g_object_unref (helper->mail_op);
@@ -2057,7 +2133,7 @@ on_refresh_folder (TnyFolder   *folder,
        g_object_unref (folder);
 
        /* Notify about operation end */
        g_object_unref (folder);
 
        /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+       modest_mail_operation_notify_end (self, TRUE);
 }
 
 static void
 }
 
 static void
@@ -2131,7 +2207,8 @@ modest_mail_operation_refresh_folder  (ModestMailOperation *self,
  * callback).
  */
 static void
  * callback).
  */
 static void
-modest_mail_operation_notify_end (ModestMailOperation *self)
+modest_mail_operation_notify_end (ModestMailOperation *self,
+                                 gboolean need_lock)
 {
        ModestMailOperationState *state;
        ModestMailOperationPrivate *priv = NULL;
 {
        ModestMailOperationState *state;
        ModestMailOperationPrivate *priv = NULL;
@@ -2147,14 +2224,18 @@ modest_mail_operation_notify_end (ModestMailOperation *self)
        
        /* Set the account back to not busy */
        if (priv->account_name) {
        
        /* Set the account back to not busy */
        if (priv->account_name) {
-               modest_account_mgr_set_account_busy(modest_runtime_get_account_mgr(), priv->account_name,
-                                                                                                                                                               FALSE);
+               modest_account_mgr_set_account_busy (modest_runtime_get_account_mgr(), 
+                                                    priv->account_name, FALSE);
                g_free(priv->account_name);
                priv->account_name = NULL;
        }
        
        /* Notify the observers about the mail opertation end */
        state = modest_mail_operation_clone_state (self);
                g_free(priv->account_name);
                priv->account_name = NULL;
        }
        
        /* Notify the observers about the mail opertation end */
        state = modest_mail_operation_clone_state (self);
+       if (need_lock)
+               gdk_threads_enter ();
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
+       if (need_lock)
+               gdk_threads_leave ();
        g_slice_free (ModestMailOperationState, state);
 }
        g_slice_free (ModestMailOperationState, state);
 }