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;
/* 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;
}
/* 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
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");
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");
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)
if (folder)
g_object_unref (G_OBJECT(folder));
- modest_mail_operation_notify_end (self);
+ modest_mail_operation_notify_end (self, FALSE);
}
typedef struct
static gboolean
idle_notify_progress (gpointer data)
{
+ gdk_threads_enter ();
+
ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
ModestMailOperationState *state;
g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL);
g_slice_free (ModestMailOperationState, state);
+ gdk_threads_leave ();
+
return TRUE;
}
static gboolean
idle_notify_progress_once (gpointer data)
{
+ gdk_threads_enter ();
+
ModestPair *pair;
pair = (ModestPair *) data;
g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second);
g_object_unref (pair->first);
+ gdk_threads_leave ();
+
return FALSE;
}
* 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;
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 */
time(NULL),
TRUE);
+ gdk_threads_leave ();
+
return FALSE;
}
/* 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);
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;
}
}
/* Notify about operation end */
- modest_mail_operation_notify_end (self);
+ modest_mail_operation_notify_end (self, FALSE);
return new_folder;
}
end:
/* Notify about operation end */
- modest_mail_operation_notify_end (self);
+ modest_mail_operation_notify_end (self, FALSE);
}
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;
/* 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
_("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;
_("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);
_("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;
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));
_("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);
}
}
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:
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
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;
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);
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);
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);
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);
}
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
/* 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 */
g_object_unref (folder);
/* Notify about operation end */
- modest_mail_operation_notify_end (self);
+ modest_mail_operation_notify_end (self, TRUE);
}
void
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;
}
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);
g_object_unref (folder);
/* Notify about operation end */
- modest_mail_operation_notify_end (self);
+ modest_mail_operation_notify_end (self, TRUE);
}
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;
/* 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);
}