X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-mail-operation.c;h=726cf6dcc475edf62fcbac2219374f15a367ecde;hp=bbe2806cbe1550a8e3e61bdea7d48d0c775de3dd;hb=17d7865c512d65aca2b12dc0a980c3309742319a;hpb=8a821d22130a023dbd639d6a9117245320cb3a2b diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index bbe2806..726cf6d 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -70,7 +70,8 @@ static void get_msg_status_cb (GObject *obj, 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; @@ -373,7 +374,7 @@ modest_mail_operation_cancel (ModestMailOperation *self) /* 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); + modest_mail_operation_notify_end (self, FALSE); return TRUE; } @@ -522,7 +523,7 @@ modest_mail_operation_send_mail (ModestMailOperation *self, /* TODO: do this in the handler of the "msg-sent" signal.Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); } void @@ -619,6 +620,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"); @@ -631,6 +633,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"); @@ -641,13 +644,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); - tny_folder_sync (folder, TRUE, NULL); + tny_folder_sync (folder, TRUE, &(priv->error)); 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) @@ -655,7 +662,7 @@ end: if (folder) g_object_unref (G_OBJECT(folder)); - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); } typedef struct @@ -792,6 +799,8 @@ recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all static gboolean idle_notify_progress (gpointer data) { + gdk_threads_enter (); + ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data); ModestMailOperationState *state; @@ -799,6 +808,8 @@ idle_notify_progress (gpointer data) g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); g_slice_free (ModestMailOperationState, state); + gdk_threads_leave (); + return TRUE; } @@ -810,6 +821,8 @@ idle_notify_progress (gpointer data) static gboolean idle_notify_progress_once (gpointer data) { + gdk_threads_enter (); + ModestPair *pair; pair = (ModestPair *) data; @@ -820,6 +833,8 @@ idle_notify_progress_once (gpointer data) g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second); g_object_unref (pair->first); + gdk_threads_leave (); + return FALSE; } @@ -828,14 +843,15 @@ idle_notify_progress_once (gpointer data) * 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); - - 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; @@ -865,6 +881,8 @@ compare_headers_by_date (gconstpointer a, 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 */ @@ -874,6 +892,8 @@ set_last_updated_idle (gpointer data) time(NULL), TRUE); + gdk_threads_leave (); + return FALSE; } @@ -982,12 +1002,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); } @@ -1047,7 +1070,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; @@ -1084,12 +1107,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 */ - 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) + 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); @@ -1202,7 +1229,7 @@ modest_mail_operation_update_account (ModestMailOperation *self, priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; if (callback) callback (self, 0, user_data); - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); return FALSE; } @@ -1246,7 +1273,7 @@ modest_mail_operation_create_folder (ModestMailOperation *self, } /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); return new_folder; } @@ -1301,7 +1328,7 @@ modest_mail_operation_remove_folder (ModestMailOperation *self, end: /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); } static void @@ -1335,7 +1362,8 @@ static void 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; @@ -1363,11 +1391,9 @@ transfer_folder_cb (TnyFolder *folder, /* Free */ g_object_unref (folder); g_object_unref (into); - if (new_folder != NULL) - g_object_unref (new_folder); /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, TRUE); } void @@ -1406,7 +1432,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, _("mail_in_ui_folder_move_target_error")); /* Notify the queue */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); } else if (parent_rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) { /* Set status failed and set an error */ priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; @@ -1415,7 +1441,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, _("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); @@ -1459,7 +1485,7 @@ modest_mail_operation_rename_folder (ModestMailOperation *self, _("FIXME: unable to rename")); /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); } else { /* Rename. Camel handles folder subscription/unsubscription */ TnyFolderStore *into; @@ -1507,6 +1533,11 @@ void modest_mail_operation_get_msg (ModestMailOperation *self, 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); g_object_unref (G_OBJECT (folder)); @@ -1518,7 +1549,7 @@ void modest_mail_operation_get_msg (ModestMailOperation *self, _("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); } } @@ -1554,11 +1585,19 @@ get_msg_cb (TnyFolder *folder, 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, helper->header, 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: @@ -1567,7 +1606,10 @@ get_msg_cb (TnyFolder *folder, 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 @@ -1589,6 +1631,9 @@ get_msg_status_cb (GObject *obj, 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; @@ -1631,8 +1676,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); @@ -1650,8 +1698,11 @@ get_msgs_full_destroyer (gpointer data) info = (GetFullMsgsInfo *) data; - if (info->notify) + if (info->notify) { + gdk_threads_enter (); info->notify (info->user_data); + gdk_threads_leave (); + } /* free */ g_object_unref (info->headers); @@ -1728,7 +1779,7 @@ get_msgs_full_thread (gpointer thr_user_data) 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); @@ -1817,7 +1868,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_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); if (notify) notify (user_data); } @@ -1891,7 +1942,7 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, 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 @@ -1955,7 +2006,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 */ @@ -1966,7 +2019,7 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer g_object_unref (folder); /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, TRUE); } void @@ -1995,7 +2048,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; @@ -2003,7 +2055,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES, _("FIXME: folder does not accept msgs")); /* Notify the queue */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, FALSE); return; } @@ -2069,8 +2121,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); @@ -2078,7 +2133,7 @@ on_refresh_folder (TnyFolder *folder, g_object_unref (folder); /* Notify about operation end */ - modest_mail_operation_notify_end (self); + modest_mail_operation_notify_end (self, TRUE); } static void @@ -2152,7 +2207,8 @@ modest_mail_operation_refresh_folder (ModestMailOperation *self, * 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; @@ -2168,14 +2224,18 @@ modest_mail_operation_notify_end (ModestMailOperation *self) /* 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); + if (need_lock) + gdk_threads_enter (); g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); + if (need_lock) + gdk_threads_leave (); g_slice_free (ModestMailOperationState, state); }