X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-mail-operation.c;h=4f0f94227e47f3c2f5e9a84626f056a3171530e5;hp=05899643963ae58c4bc0bed89201ae06f685a96b;hb=152ee6945dc5142b5e63f2a6ac6efc2dbb94df0c;hpb=33a576813e95e526144e8fa4b3b0c2d29162f7d8 diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index 0589964..4f0f942 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -73,7 +73,7 @@ static void modest_mail_operation_finalize (GObject *obj); static void get_msg_cb (TnyFolder *folder, gboolean cancelled, TnyMsg *msg, - GError **err, + GError *rr, gpointer user_data); static void get_msg_status_cb (GObject *obj, @@ -575,9 +575,13 @@ idle_create_msg_cb (gpointer idle_data) { CreateMsgIdleInfo *info = (CreateMsgIdleInfo *) idle_data; - gdk_threads_enter (); + /* This is a GDK lock because we are an idle callback and + * info->callback can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ info->callback (info->mail_op, info->msg, info->userdata); - gdk_threads_leave (); + gdk_threads_leave (); /* CHECKED */ + g_object_unref (info->mail_op); if (info->msg) g_object_unref (info->msg); @@ -606,13 +610,18 @@ create_msg_thread (gpointer thread_data) if (new_msg) { TnyHeader *header; + TnyHeaderFlags flags = 0; + /* Set priority flags in message */ header = tny_msg_get_header (new_msg); if (info->priority_flags != 0) - tny_header_set_flags (header, info->priority_flags); - if (info->attachments_list != NULL) { - tny_header_set_flags (header, TNY_HEADER_FLAG_ATTACHMENTS); - } + flags |= info->priority_flags; + + /* Set attachment flags in message */ + if (info->attachments_list != NULL) + flags |= TNY_HEADER_FLAG_ATTACHMENTS; + + tny_header_set_flags (header, flags); g_object_unref (G_OBJECT(header)); } else { priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; @@ -1043,13 +1052,14 @@ idle_notify_progress (gpointer data) ModestMailOperationState *state; state = modest_mail_operation_clone_state (mail_op); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif + + /* This is a GDK lock because we are an idle callback and + * the handlers of this signal can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + gdk_threads_leave (); /* CHECKED */ + g_slice_free (ModestMailOperationState, state); return TRUE; @@ -1067,13 +1077,12 @@ idle_notify_progress_once (gpointer data) pair = (ModestPair *) data; -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif + /* This is a GDK lock because we are an idle callback and + * the handlers of this signal can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ g_signal_emit (G_OBJECT (pair->first), signals[PROGRESS_CHANGED_SIGNAL], 0, pair->second, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + gdk_threads_leave (); /* CHECKED */ /* Free the state and the reference to the mail operation */ g_slice_free (ModestMailOperationState, (ModestMailOperationState*)pair->second); @@ -1122,18 +1131,23 @@ compare_headers_by_date (gconstpointer a, static gboolean set_last_updated_idle (gpointer data) { - gdk_threads_enter (); + + /* This is a GDK lock because we are an idle callback and + * modest_account_mgr_set_int can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED - please recheck */ /* 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 */ + modest_account_mgr_set_int (modest_runtime_get_account_mgr (), (gchar *) data, MODEST_ACCOUNT_LAST_UPDATED, time(NULL), TRUE); - gdk_threads_leave (); + gdk_threads_leave (); /* CHECKED - please recheck */ return FALSE; } @@ -1145,11 +1159,14 @@ idle_update_account_cb (gpointer data) idle_info = (UpdateAccountInfo *) data; - gdk_threads_enter (); + /* This is a GDK lock because we are an idle callback and + * idle_info->callback can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ idle_info->callback (idle_info->mail_op, idle_info->new_headers, idle_info->user_data); - gdk_threads_leave (); + gdk_threads_leave (); /* CHECKED */ /* Frees */ g_object_unref (idle_info->mail_op); @@ -1350,7 +1367,6 @@ update_account_thread (gpointer thr_user_data) goto out; /* Perform send (if operation was not cancelled) */ -/* priv->op_type = MODEST_MAIL_OPERATION_TYPE_SEND; */ priv->done = 0; priv->total = 0; if (priv->account != NULL) @@ -1359,9 +1375,7 @@ update_account_thread (gpointer thr_user_data) send_queue = modest_runtime_get_send_queue (info->transport_account); if (send_queue) { -/* timeout = g_timeout_add (250, idle_notify_progress, info->mail_op); */ modest_tny_send_queue_try_to_send (send_queue); -/* g_source_remove (timeout); */ } else { g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED, @@ -1391,6 +1405,7 @@ update_account_thread (gpointer thr_user_data) idle_info->mail_op = g_object_ref (info->mail_op); idle_info->new_headers = num_new_headers; idle_info->callback = info->callback; + idle_info->user_data = info->user_data; g_idle_add (idle_update_account_cb, idle_info); } @@ -1663,23 +1678,25 @@ transfer_folder_status_cb (GObject *obj, priv->total = status->of_total; state = modest_mail_operation_clone_state (self); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif - g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + + /* This is not a GDK lock because we are a Tinymail callback + * which is already GDK locked by Tinymail */ + + /* no gdk_threads_enter (), CHECKED */ + + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); + + /* no gdk_threads_leave (), CHECKED */ + g_slice_free (ModestMailOperationState, state); } static void -transfer_folder_cb (TnyFolder *folder, +transfer_folder_cb (TnyFolder *folder, gboolean cancelled, TnyFolderStore *into, - gboolean cancelled, TnyFolder *new_folder, - GError **err, + GError *err, gpointer user_data) { XFerMsgAsyncHelper *helper; @@ -1692,8 +1709,8 @@ transfer_folder_cb (TnyFolder *folder, self = helper->mail_op; priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); - if (*err) { - priv->error = g_error_copy (*err); + if (err) { + priv->error = g_error_copy (err); priv->done = 0; priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; } else if (cancelled) { @@ -1712,9 +1729,13 @@ transfer_folder_cb (TnyFolder *folder, /* If user defined callback function was defined, call it */ if (helper->user_callback) { - gdk_threads_enter (); + + /* This is not a GDK lock because we are a Tinymail callback + * which is already GDK locked by Tinymail */ + + /* no gdk_threads_enter (), CHECKED */ helper->user_callback (priv->source, helper->user_data); - gdk_threads_leave (); + /* no gdk_threads_leave () , CHECKED */ } /* Free */ @@ -1763,6 +1784,31 @@ new_name_valid_if_local_account (ModestMailOperationPrivate *priv, return TRUE; } +/** + * This function checks if @ancestor is an acestor of @folder and + * returns TRUE in that case + */ +static gboolean +folder_is_ancestor (TnyFolder *folder, + TnyFolderStore *ancestor) +{ + TnyFolder *tmp = NULL; + gboolean found = FALSE; + + tmp = folder; + while (!found && tmp && !TNY_IS_ACCOUNT (tmp)) { + TnyFolderStore *folder_store; + + folder_store = tny_folder_get_folder_store (tmp); + if (ancestor == folder_store) + found = TRUE; + else + tmp = g_object_ref (folder_store); + g_object_unref (folder_store); + } + return found; +} + void modest_mail_operation_xfer_folder (ModestMailOperation *self, TnyFolder *folder, @@ -1774,11 +1820,14 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, ModestMailOperationPrivate *priv = NULL; ModestTnyFolderRules parent_rules = 0, rules; XFerMsgAsyncHelper *helper = NULL; + const gchar *folder_name = NULL; g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); g_return_if_fail (TNY_IS_FOLDER (folder)); + g_return_if_fail (TNY_IS_FOLDER_STORE (parent)); priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); + folder_name = tny_folder_get_name (folder); /* Get account and set it into mail_operation */ priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder)); @@ -1793,7 +1842,7 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, if ((gpointer) parent == (gpointer) folder || (!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, @@ -1802,8 +1851,10 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, /* Notify the queue */ modest_mail_operation_notify_end (self); + } 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, @@ -1812,33 +1863,64 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, /* Notify the queue */ modest_mail_operation_notify_end (self); - } else { + } else if (TNY_IS_FOLDER (parent) && + TNY_IS_FOLDER_STORE (folder) && + folder_is_ancestor (TNY_FOLDER (parent), TNY_FOLDER_STORE (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_FOLDER_RULES, + _("mail_in_ui_folder_copy_target_error")); + + /* Notify the queue */ + modest_mail_operation_notify_end (self); + + } else if (TNY_IS_FOLDER_STORE (parent) && + modest_tny_folder_has_subfolder_with_name (parent, folder_name)) { + /* Check that the new folder name is not used by any + parent subfolder */ + /* 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, + _("mail_in_ui_folder_move_target_error")); + + /* Notify the queue */ + modest_mail_operation_notify_end (self); + + } else if (!(new_name_valid_if_local_account (priv, parent, folder_name))) { /* Check that the new folder name is not used by any special local folder */ - if (new_name_valid_if_local_account (priv, parent, - tny_folder_get_name (folder))) { - /* Create the helper */ - helper = g_slice_new0 (XFerMsgAsyncHelper); - helper->mail_op = g_object_ref(self); - helper->dest_folder = NULL; - helper->headers = NULL; - helper->user_callback = user_callback; - helper->user_data = user_data; - - /* Move/Copy folder */ - tny_folder_copy_async (folder, - parent, - tny_folder_get_name (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_FOLDER_RULES, + _("mail_in_ui_folder_move_target_error")); + + /* Notify the queue */ + modest_mail_operation_notify_end (self); + } else { + /* Create the helper */ + helper = g_slice_new0 (XFerMsgAsyncHelper); + helper->mail_op = g_object_ref(self); + helper->dest_folder = NULL; + helper->headers = NULL; + helper->user_callback = user_callback; + helper->user_data = user_data; + + /* Move/Copy folder */ + tny_folder_copy_async (folder, + parent, + tny_folder_get_name (folder), delete_original, - transfer_folder_cb, - transfer_folder_status_cb, - helper); - } else { - modest_mail_operation_notify_end (self); - } - } + transfer_folder_cb, + transfer_folder_status_cb, + helper); + } + } void @@ -1930,6 +2012,12 @@ void modest_mail_operation_get_msg (ModestMailOperation *self, if (folder) { /* Get account and set it into mail_operation */ priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder)); + + /* Check for cached messages */ + if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) + priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN; + else + priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE; helper = g_slice_new0 (GetMsgAsyncHelper); helper->mail_op = self; @@ -1961,7 +2049,7 @@ static void get_msg_cb (TnyFolder *folder, gboolean cancelled, TnyMsg *msg, - GError **error, + GError *error, gpointer user_data) { GetMsgAsyncHelper *helper = NULL; @@ -1975,8 +2063,8 @@ get_msg_cb (TnyFolder *folder, priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); /* Check errors and cancel */ - if (*error) { - priv->error = g_error_copy (*error); + if (error) { + priv->error = g_error_copy (error); priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; } else if (cancelled) { priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED; @@ -1991,11 +2079,12 @@ get_msg_cb (TnyFolder *folder, /* If user defined callback function was defined, call it even if the operation failed*/ if (helper->user_callback) { - /* This callback is called into an iddle by tinymail, - and idles are not in the main lock */ - gdk_threads_enter (); + /* This is not a GDK lock because we are a Tinymail callback + * which is already GDK locked by Tinymail */ + + /* no gdk_threads_enter (), CHECKED */ helper->user_callback (self, helper->header, msg, helper->user_data); - gdk_threads_leave (); + /* no gdk_threads_leave (), CHECKED */ } /* Notify about operation end */ @@ -2032,13 +2121,14 @@ get_msg_status_cb (GObject *obj, state = modest_mail_operation_clone_state (self); state->bytes_done = status->position; state->bytes_total = status->of_total; -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif + + /* This is not a GDK lock because we are a Tinymail callback + * which is already GDK locked by Tinymail */ + + /* no gdk_threads_enter (), CHECKED */ g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + /* no gdk_threads_leave (), CHECKED */ + g_slice_free (ModestMailOperationState, state); } @@ -2071,11 +2161,12 @@ notify_get_msgs_full (gpointer data) info = (NotifyGetMsgsInfo *) data; - /* Call the user callback. Idles are not in the main lock, so - lock it */ - gdk_threads_enter (); + /* This is a GDK lock because we are an idle callback and + * because info->user_callback can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ info->user_callback (info->mail_op, info->header, info->msg, info->user_data); - gdk_threads_leave (); + gdk_threads_leave (); /* CHECKED */ g_slice_free (NotifyGetMsgsInfo, info); @@ -2094,9 +2185,13 @@ get_msgs_full_destroyer (gpointer data) info = (GetFullMsgsInfo *) data; if (info->notify) { - gdk_threads_enter (); + + /* This is a GDK lock because we are an idle callback and + * because info->notify can contain Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ info->notify (info->user_data); - gdk_threads_leave (); + gdk_threads_leave (); /* CHECKED */ } /* free */ @@ -2124,6 +2219,12 @@ get_msgs_full_thread (gpointer thr_user_data) header = TNY_HEADER (tny_iterator_get_current (iter)); folder = tny_header_get_folder (header); + /* Check for cached messages */ + if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) + priv->op_type = MODEST_MAIL_OPERATION_TYPE_OPEN; + else + priv->op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE; + /* Get message from folder */ if (folder) { TnyMsg *msg; @@ -2359,19 +2460,22 @@ transfer_msgs_status_cb (GObject *obj, priv->total = status->of_total; state = modest_mail_operation_clone_state (self); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif + + /* This is not a GDK lock because we are a Tinymail callback and + * Tinymail already acquires the Gdk lock */ + + /* no gdk_threads_enter (), CHECKED */ + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + + /* no gdk_threads_leave (), CHECKED */ + g_slice_free (ModestMailOperationState, state); } static void -transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data) +transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer user_data) { XFerMsgAsyncHelper *helper; ModestMailOperation *self; @@ -2384,8 +2488,8 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); - if (*err) { - priv->error = g_error_copy (*err); + if (err) { + priv->error = g_error_copy (err); priv->done = 0; priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; } else if (cancelled) { @@ -2421,9 +2525,12 @@ 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 (); + /* This is not a GDK lock because we are a Tinymail callback and + * Tinymail already acquires the Gdk lock */ + + /* no gdk_threads_enter (), CHECKED */ helper->user_callback (priv->source, helper->user_data); - gdk_threads_leave (); + /* no gdk_threads_leave (), CHECKED */ } /* Free */ @@ -2536,7 +2643,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, static void on_refresh_folder (TnyFolder *folder, gboolean cancelled, - GError **error, + GError *error, gpointer user_data) { RefreshAsyncHelper *helper = NULL; @@ -2549,9 +2656,11 @@ on_refresh_folder (TnyFolder *folder, g_return_if_fail(priv!=NULL); - if (*error) { - priv->error = g_error_copy (*error); + if (error) { + priv->error = g_error_copy (error); priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + printf("DEBUG: %s: Operation error:\n %s", __FUNCTION__, + error->message); goto out; } @@ -2561,23 +2670,30 @@ on_refresh_folder (TnyFolder *folder, MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND, _("Error trying to refresh the contents of %s"), tny_folder_get_name (folder)); + printf("DEBUG: %s: Operation cancelled.\n", __FUNCTION__); goto out; } priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; - out: + /* Call user defined callback, if it exists */ if (helper->user_callback) { - gdk_threads_enter (); + + /* This is not a GDK lock because we are a Tinymail callback and + * Tinymail already acquires the Gdk lock */ + + /* no gdk_threads_enter (), CHECKED */ helper->user_callback (self, folder, helper->user_data); - gdk_threads_leave (); + /* no gdk_threads_leave (), CHECKED */ } + out: /* Free */ g_slice_free (RefreshAsyncHelper, helper); /* Notify about operation end */ modest_mail_operation_notify_end (self); + g_object_unref(self); } static void @@ -2604,13 +2720,16 @@ on_refresh_folder_status_update (GObject *obj, priv->total = status->of_total; state = modest_mail_operation_clone_state (self); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_enter (); -#endif + + /* This is not a GDK lock because we are a Tinymail callback and + * Tinymail already acquires the Gdk lock */ + + /* no gdk_threads_enter (), CHECKED */ + g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + + /* no gdk_threads_leave (), CHECKED */ + g_slice_free (ModestMailOperationState, state); } @@ -2632,7 +2751,7 @@ modest_mail_operation_refresh_folder (ModestMailOperation *self, /* Create the helper */ helper = g_slice_new0 (RefreshAsyncHelper); - helper->mail_op = self; + helper->mail_op = g_object_ref(self); helper->user_callback = user_callback; helper->user_data = user_data;