* Partially reverted last commit, sometimes the gdk_threads_enter blocks, still...
[modest] / src / modest-mail-operation.c
index 7db713e..27cea46 100644 (file)
@@ -365,16 +365,15 @@ modest_mail_operation_cancel (ModestMailOperation *self)
                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;
-       
-       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);
        
        return TRUE;
 }
@@ -620,6 +619,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) {
+               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");
@@ -632,6 +632,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) {
+               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");
@@ -647,8 +648,8 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self,
        }
        
        tny_folder_add_msg (folder, msg, &(priv->error));
-       if (priv->error)
-               goto end;
+       if (!priv->error)
+               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
 
 end:
        if (msg)
@@ -668,6 +669,8 @@ typedef struct
        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 *****/
@@ -882,11 +885,11 @@ update_account_thread (gpointer thr_user_data)
        static gboolean first_time = TRUE;
        UpdateAccountInfo *info;
        TnyList *all_folders = NULL;
-       GPtrArray *new_headers;
+       GPtrArray *new_headers = 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);
@@ -944,8 +947,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.
-                * 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));
@@ -983,12 +984,15 @@ update_account_thread (gpointer thr_user_data)
                }
                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)
+               {
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-               g_object_unref (G_OBJECT (folder));
+                       goto out;
+               }
+               
                tny_iterator_next (iter);
        }
 
@@ -1008,11 +1012,11 @@ update_account_thread (gpointer thr_user_data)
                 * 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) {
-                       /* 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", 
@@ -1048,7 +1052,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);
        }
-
+       
        /* Perform send */
        priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND;
        priv->done = 0;
@@ -1086,6 +1090,15 @@ update_account_thread (gpointer thr_user_data)
           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));
+
+       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);
@@ -1102,7 +1115,9 @@ update_account_thread (gpointer thr_user_data)
 
 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;
@@ -1114,13 +1129,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);
 
-       /* 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 */
@@ -1128,7 +1136,14 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        priv->total = 0;
        priv->done  = 0;
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-       
+
+       /* 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))
+               goto error;
+
        /* Get the Modest account */
        modest_account = (TnyStoreAccount *)
                modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
@@ -1136,13 +1151,10 @@ modest_mail_operation_update_account (ModestMailOperation *self,
                                                                     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);
-               modest_mail_operation_notify_end (self);
-
-               return FALSE;
+               goto error;
        }
 
        
@@ -1152,13 +1164,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) {
-               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);
-               modest_mail_operation_notify_end (self);
-
-               return FALSE;
+               goto error;
        }
 
        /* Create the helper object */
@@ -1166,6 +1175,8 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        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 (), 
@@ -1195,6 +1206,13 @@ modest_mail_operation_update_account (ModestMailOperation *self,
        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);
+       return FALSE;
 }
 
 /* ******************************************************************* */
@@ -1549,7 +1567,11 @@ get_msg_cb (TnyFolder *folder,
 
        /* 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:
@@ -1622,8 +1644,11 @@ notify_get_msgs_full (gpointer 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);
+       gdk_threads_leave ();
 
        g_slice_free (NotifyGetMsgsInfo, info);
 
@@ -1946,7 +1971,9 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer
 
        /* If user defined callback function was defined, call it */
        if (helper->user_callback) {
+               gdk_threads_enter ();
                helper->user_callback (priv->source, helper->user_data);
+               gdk_threads_leave ();
        }
 
        /* Free */
@@ -1986,7 +2013,6 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self,
 
        /* 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;
@@ -2060,8 +2086,11 @@ on_refresh_folder (TnyFolder   *folder,
 
  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);
+/*             gdk_threads_leave (); */
+       }
 
        /* Free */
        g_object_unref (helper->mail_op);