X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-mail-operation.c;h=678e9c2651dc29b3274d21b8d5bbdbc793245b88;hp=9d48dae2f272bb784397de5e23dab03ec91f0237;hb=b9b928dee5f5169c3317df86b153b4d069b814d0;hpb=362784ce756b3f0e31cd451d9ac5e69b909d4053 diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index 9d48dae..678e9c2 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -45,6 +45,7 @@ #include #include #include "modest-platform.h" +#include "modest-account-mgr-helpers.h" #include #include #include @@ -58,7 +59,6 @@ #include "modest-mail-operation.h" #define KB 1024 -#define GET_SIZE_BUFFER_SIZE 128 /* * Remove all these #ifdef stuff when the tinymail's idle calls become @@ -74,7 +74,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, @@ -130,7 +130,8 @@ typedef struct _XFerMsgAsyncHelper ModestMailOperation *mail_op; TnyList *headers; TnyFolder *dest_folder; - XferMsgsAsynUserCallback user_callback; + XferAsyncUserCallback user_callback; + gboolean delete; gpointer user_data; } XFerMsgAsyncHelper; @@ -143,6 +144,7 @@ static void modest_mail_operation_create_msg (ModestMailOperation *self const gchar *cc, const gchar *bcc, const gchar *subject, const gchar *plain_body, const gchar *html_body, const GList *attachments_list, + const GList *images_list, TnyHeaderFlags priority_flags, ModestMailOperationCreateMsgCallback callback, gpointer userdata); @@ -159,6 +161,7 @@ typedef struct gchar *plain_body; gchar *html_body; GList *attachments_list; + GList *images_list; TnyHeaderFlags priority_flags; ModestMailOperationCreateMsgCallback callback; gpointer userdata; @@ -305,6 +308,7 @@ modest_mail_operation_new_with_error_handling (ModestMailOperationTypeOperation g_return_val_if_fail (error_handler != NULL, obj); priv->error_checking = error_handler; + priv->error_checking_user_data = user_data; return obj; } @@ -357,7 +361,7 @@ modest_mail_operation_get_source (ModestMailOperation *self) return NULL; } - return g_object_ref (priv->source); + return (priv->source) ? g_object_ref (priv->source) : NULL; } ModestMailOperationStatus @@ -556,15 +560,25 @@ modest_mail_operation_send_mail (ModestMailOperation *self, g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND, "modest: could not find send queue for account\n"); + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + } 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)); */ + modest_tny_send_queue_add (MODEST_TNY_SEND_QUEUE(send_queue), + msg, + &(priv->error)); + /* TODO: we're setting always success, do the check in the handler */ priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; } + if (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS) + modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent")); + /* TODO: do this in the handler of the "msg-sent" signal.Notify about operation end */ modest_mail_operation_notify_end (self); @@ -575,13 +589,17 @@ 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 (); + g_object_unref (info->mail_op); if (info->msg) g_object_unref (info->msg); g_slice_free (CreateMsgIdleInfo, info); + gdk_threads_leave (); /* CHECKED */ return FALSE; } @@ -597,22 +615,28 @@ create_msg_thread (gpointer thread_data) if (info->html_body == NULL) { new_msg = modest_tny_msg_new (info->to, info->from, info->cc, info->bcc, info->subject, info->plain_body, - info->attachments_list); /* FIXME: attachments */ + info->attachments_list); } else { new_msg = modest_tny_msg_new_html_plain (info->to, info->from, info->cc, info->bcc, info->subject, info->html_body, - info->plain_body, info->attachments_list); + info->plain_body, info->attachments_list, + info->images_list); } 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; @@ -631,6 +655,8 @@ create_msg_thread (gpointer thread_data) g_free (info->subject); g_list_foreach (info->attachments_list, (GFunc) g_object_unref, NULL); g_list_free (info->attachments_list); + g_list_foreach (info->images_list, (GFunc) g_object_unref, NULL); + g_list_free (info->images_list); if (info->callback) { CreateMsgIdleInfo *idle_info; @@ -659,6 +685,7 @@ modest_mail_operation_create_msg (ModestMailOperation *self, const gchar *subject, const gchar *plain_body, const gchar *html_body, const GList *attachments_list, + const GList *images_list, TnyHeaderFlags priority_flags, ModestMailOperationCreateMsgCallback callback, gpointer userdata) @@ -678,6 +705,8 @@ modest_mail_operation_create_msg (ModestMailOperation *self, info->html_body = g_strdup (html_body); info->attachments_list = g_list_copy ((GList *) attachments_list); g_list_foreach (info->attachments_list, (GFunc) g_object_ref, NULL); + info->images_list = g_list_copy ((GList *) images_list); + g_list_foreach (info->images_list, (GFunc) g_object_ref, NULL); info->priority_flags = priority_flags; info->callback = callback; @@ -701,6 +730,7 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self, TnyFolder *draft_folder = NULL; TnyFolder *outbox_folder = NULL; TnyHeader *header; + GError *err = NULL; if (!msg) { goto end; @@ -728,13 +758,17 @@ modest_mail_operation_send_new_mail_cb (ModestMailOperation *self, * because this function requires it to have a UID. */ header = tny_msg_get_header (info->draft_msg); tny_folder_remove_msg (src_folder, header, NULL); - tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED); - tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN); + + tny_folder_sync (folder, TRUE, &err); /* FALSE --> don't expunge */ +/* tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); /\* expunge *\/ */ + g_object_unref (header); g_object_unref (folder); } end: + if (err != NULL) + g_error_free(err); if (info->draft_msg) g_object_unref (info->draft_msg); if (draft_folder) @@ -756,6 +790,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self, const gchar *subject, const gchar *plain_body, const gchar *html_body, const GList *attachments_list, + const GList *images_list, TnyHeaderFlags priority_flags) { ModestMailOperationPrivate *priv = NULL; @@ -783,7 +818,7 @@ modest_mail_operation_send_new_mail (ModestMailOperation *self, if (draft_msg) g_object_ref (draft_msg); modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body, - attachments_list, priority_flags, + attachments_list, images_list, priority_flags, modest_mail_operation_send_new_mail_cb, info); } @@ -801,7 +836,7 @@ modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self, gpointer userdata) { TnyFolder *src_folder = NULL; - TnyFolder *folder = NULL; + TnyFolder *drafts = NULL; TnyHeader *header = NULL; ModestMailOperationPrivate *priv = NULL; SaveToDraftsInfo *info = (SaveToDraftsInfo *) userdata; @@ -815,8 +850,9 @@ modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self, goto end; } - folder = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account), TNY_FOLDER_TYPE_DRAFTS); - if (!folder) { + drafts = modest_tny_account_get_special_folder (TNY_ACCOUNT (info->transport_account), + TNY_FOLDER_TYPE_DRAFTS); + if (!drafts) { priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND, @@ -824,21 +860,24 @@ modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self, goto end; } - if (info->draft_msg != NULL) { + if (!priv->error) + tny_folder_add_msg (drafts, msg, &(priv->error)); + + if ((!priv->error) && (info->draft_msg != NULL)) { header = tny_msg_get_header (info->draft_msg); src_folder = tny_header_get_folder (header); - /* Remove the old draft expunging it */ + + /* Remove the old draft */ tny_folder_remove_msg (src_folder, header, NULL); - tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED); - tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN); - tny_folder_sync (src_folder, TRUE, &(priv->error)); /* expunge */ + + /* Synchronize to expunge and to update the msg counts */ + tny_folder_sync_async (drafts, TRUE, NULL, NULL, NULL); + tny_folder_sync_async (src_folder, TRUE, NULL, NULL, NULL); + g_object_unref (header); } 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; @@ -848,8 +887,8 @@ modest_mail_operation_save_to_drafts_cb (ModestMailOperation *self, end: - if (folder) - g_object_unref (G_OBJECT(folder)); + if (drafts) + g_object_unref (G_OBJECT(drafts)); if (src_folder) g_object_unref (G_OBJECT(src_folder)); if (info->edit_window) @@ -873,6 +912,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self, const gchar *subject, const gchar *plain_body, const gchar *html_body, const GList *attachments_list, + const GList *images_list, TnyHeaderFlags priority_flags) { ModestMailOperationPrivate *priv = NULL; @@ -896,7 +936,7 @@ modest_mail_operation_save_to_drafts (ModestMailOperation *self, g_object_ref (edit_window); modest_mail_operation_create_msg (self, from, to, cc, bcc, subject, plain_body, html_body, - attachments_list, priority_flags, + attachments_list, images_list, priority_flags, modest_mail_operation_save_to_drafts_cb, info); } @@ -912,7 +952,7 @@ typedef struct gchar *account_name; UpdateAccountCallback callback; gpointer user_data; - gint new_headers; + TnyList *new_headers; } UpdateAccountInfo; typedef struct @@ -1043,13 +1083,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 +1108,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 +1162,21 @@ 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_last_updated can issue 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 (); + modest_account_mgr_set_last_updated (modest_runtime_get_account_mgr (), + (gchar *) data, + time (NULL)); + + gdk_threads_leave (); /* CHECKED - please recheck */ return FALSE; } @@ -1145,64 +1188,44 @@ 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); + if (idle_info->new_headers) + g_object_unref (idle_info->new_headers); g_free (idle_info); return FALSE; } - -static gpointer -update_account_thread (gpointer thr_user_data) +static TnyList * +get_all_folders_from_account (TnyStoreAccount *account, + GError **error) { - static gboolean first_time = TRUE; - UpdateAccountInfo *info = NULL; TnyList *all_folders = NULL; - GPtrArray *new_headers = NULL; TnyIterator *iter = NULL; TnyFolderStoreQuery *query = NULL; - ModestMailOperationPrivate *priv = NULL; - ModestTnySendQueue *send_queue = NULL; - gint num_new_headers = 0; - - info = (UpdateAccountInfo *) thr_user_data; - priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op); - /* Get account and set it into mail_operation */ - priv->account = g_object_ref (info->account); - - /* - * Previousl, we did this for POP3, to do a logout-login upon send/receive, - * because many POP-servers (like Gmail) do not - * show any updates unless we do that. - * But that didn't work with gmail anyway, - * and tinymail now takes care of this itself by disconnecting - * automatically after using the connection. - */ - /* - if (!first_time && TNY_IS_CAMEL_POP_STORE_ACCOUNT (priv->account)) - tny_camel_pop_store_account_reconnect (TNY_CAMEL_POP_STORE_ACCOUNT(priv->account)); - */ - - /* Get all the folders. We can do it synchronously because - we're already running in a different thread than the UI */ all_folders = tny_simple_list_new (); query = tny_folder_store_query_new (); tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED); - tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account), + tny_folder_store_get_folders (TNY_FOLDER_STORE (account), all_folders, query, - &(priv->error)); - if (priv->error) { - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - goto out; + error); + + if (*error) { + if (all_folders) + g_object_unref (all_folders); + return NULL; } iter = tny_list_create_iterator (all_folders); @@ -1216,141 +1239,159 @@ update_account_thread (gpointer thr_user_data) } g_object_unref (G_OBJECT (iter)); + return all_folders; +} + + +static gpointer +update_account_thread (gpointer thr_user_data) +{ + static gboolean first_time = TRUE; + UpdateAccountInfo *info = NULL; + TnyList *all_folders = NULL, *new_headers = NULL; + GPtrArray *new_headers_array = NULL; + TnyIterator *iter = NULL; + ModestMailOperationPrivate *priv = NULL; + ModestTnySendQueue *send_queue = NULL; + gint i = 0, timeout = 0; + + info = (UpdateAccountInfo *) thr_user_data; + priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op); + + /* Get account and set it into mail_operation */ + priv->account = g_object_ref (info->account); + + /* Get all the folders. We can do it synchronously because + we're already running in a different thread than the UI */ + all_folders = get_all_folders_from_account (info->account, &(priv->error)); + if (!all_folders) { + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + goto out; + } + /* Update status and notify. We need to call the notification with a source function in order to call it from the main loop. We need that in order not to get into trouble with 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 (100, idle_notify_progress, info->mail_op); + timeout = g_timeout_add (100, idle_notify_progress, info->mail_op); - /* Refresh folders */ - num_new_headers = 0; - new_headers = g_ptr_array_new (); + new_headers_array = g_ptr_array_new (); iter = tny_list_create_iterator (all_folders); while (!tny_iterator_is_done (iter) && !priv->error && priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED) { - InternalFolderObserver *observer; - TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter)); + TnyFolderType folder_type; + TnyFolder *folder = NULL; - /* Refresh the folder */ - /* Our observer receives notification of new emails during folder refreshes, - * so we can use observer->new_headers. - */ - observer = g_object_new (internal_folder_observer_get_type (), NULL); - tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); - - /* This gets the status information (headers) from the server. - * We use the blocking version, because we are already in a separate - * thread. - */ + folder = TNY_FOLDER (tny_iterator_get_current (iter)); + folder_type = tny_folder_get_folder_type (folder); - if (!g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES) || - !g_ascii_strcasecmp (info->retrieve_type, MODEST_ACCOUNT_RETRIEVE_VALUE_MESSAGES_AND_ATTACHMENTS)) { - TnyIterator *iter; + /* Refresh it only if it's the INBOX */ + if (folder_type == TNY_FOLDER_TYPE_INBOX) { + InternalFolderObserver *observer = NULL; + TnyIterator *new_headers_iter = NULL; - /* If the retrieve type is full messages, refresh and get the messages */ + /* Refresh the folder. Our observer receives + * the new emails during folder refreshes, so + * we can use observer->new_headers + */ + observer = g_object_new (internal_folder_observer_get_type (), NULL); + tny_folder_add_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); + tny_folder_refresh (TNY_FOLDER (folder), &(priv->error)); - iter = tny_list_create_iterator (observer->new_headers); - while (!tny_iterator_is_done (iter)) { - TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter)); - + new_headers_iter = tny_list_create_iterator (observer->new_headers); + while (!tny_iterator_is_done (new_headers_iter)) { + TnyHeader *header = NULL; + + header = TNY_HEADER (tny_iterator_get_current (new_headers_iter)); /* Apply per-message size limits */ if (tny_header_get_message_size (header) < info->max_size) - g_ptr_array_add (new_headers, g_object_ref (header)); - + g_ptr_array_add (new_headers_array, g_object_ref (header)); + g_object_unref (header); - tny_iterator_next (iter); + tny_iterator_next (new_headers_iter); } - g_object_unref (iter); + g_object_unref (new_headers_iter); + + tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); + g_object_unref (observer); } else { - /* We do not need to do it the first time + /* We no not need to do it the first time, because it's automatically done by the tree model */ - if (G_UNLIKELY (!first_time)) - tny_folder_poke_status (TNY_FOLDER (folder)); + if (G_LIKELY (!first_time)) + tny_folder_poke_status (folder); } - tny_folder_remove_observer (TNY_FOLDER (folder), TNY_FOLDER_OBSERVER (observer)); - g_object_unref (observer); - observer = NULL; - - if (folder) - g_object_unref (G_OBJECT (folder)); - - if (priv->error) - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + g_object_unref (folder); tny_iterator_next (iter); } - g_object_unref (G_OBJECT (iter)); g_source_remove (timeout); if (priv->status != MODEST_MAIL_OPERATION_STATUS_CANCELED && priv->status != MODEST_MAIL_OPERATION_STATUS_FAILED && - new_headers->len > 0) { + new_headers_array->len > 0) { gint msg_num = 0; /* Order by date */ - g_ptr_array_sort (new_headers, (GCompareFunc) compare_headers_by_date); - - /* Apply message count limit */ - /* If the number of messages exceeds the maximum, ask the - * user to download them all, - * as per the UI spec "Retrieval Limits" section in 4.4: - */ - 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. */ - 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", - tny_account_get_name (TNY_ACCOUNT (info->transport_account))); - priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - goto out; + g_ptr_array_sort (new_headers_array, (GCompareFunc) compare_headers_by_date); + + /* TODO: Ask the user, instead of just failing, + * showing mail_nc_msg_count_limit_exceeded, with 'Get + * all' and 'Newest only' buttons. */ + if (new_headers_array->len > info->retrieve_limit) { + /* TODO */ } - - priv->done = 0; - priv->total = MIN (new_headers->len, info->retrieve_limit); - while (msg_num < priv->total) { - - TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers, msg_num)); - TnyFolder *folder = tny_header_get_folder (header); - TnyMsg *msg = tny_folder_get_msg (folder, header, NULL); - ModestMailOperationState *state; - ModestPair* pair; - - priv->done++; - /* We can not just use the mail operation because the - values of done and total could change before the - idle is called */ - state = modest_mail_operation_clone_state (info->mail_op); - pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE); - g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once, - pair, (GDestroyNotify) modest_pair_free); - - g_object_unref (msg); - g_object_unref (folder); - msg_num++; + /* Should be get only the headers or the message as well? */ + if (g_ascii_strcasecmp (info->retrieve_type, + MODEST_ACCOUNT_RETRIEVE_VALUE_HEADERS_ONLY) != 0) { + priv->done = 0; + priv->total = MIN (new_headers_array->len, info->retrieve_limit); + while (msg_num < priv->total) { + + TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, msg_num)); + TnyFolder *folder = tny_header_get_folder (header); + TnyMsg *msg = tny_folder_get_msg (folder, header, NULL); + ModestMailOperationState *state; + ModestPair* pair; + + priv->done++; + /* We can not just use the mail operation because the + values of done and total could change before the + idle is called */ + state = modest_mail_operation_clone_state (info->mail_op); + pair = modest_pair_new (g_object_ref (info->mail_op), state, FALSE); + g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_notify_progress_once, + pair, (GDestroyNotify) modest_pair_free); + + g_object_unref (msg); + g_object_unref (folder); + + msg_num++; + } } } - /* Get the number of new headers and free them */ - num_new_headers = new_headers->len; - g_ptr_array_foreach (new_headers, (GFunc) g_object_unref, NULL); - g_ptr_array_free (new_headers, FALSE); - if (priv->status == MODEST_MAIL_OPERATION_STATUS_CANCELED) goto out; + /* Copy the headers to a list and free the array */ + new_headers = tny_simple_list_new (); + for (i=0; i < new_headers_array->len; i++) { + TnyHeader *header = TNY_HEADER (g_ptr_array_index (new_headers_array, i)); + tny_list_append (new_headers, G_OBJECT (header)); + } + g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL); + g_ptr_array_free (new_headers_array, FALSE); + + /* 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 +1400,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, @@ -1389,8 +1428,9 @@ update_account_thread (gpointer thr_user_data) /* This thread is not in the main lock */ idle_info = g_malloc0 (sizeof (UpdateAccountInfo)); idle_info->mail_op = g_object_ref (info->mail_op); - idle_info->new_headers = num_new_headers; + idle_info->new_headers = (new_headers) ? g_object_ref (new_headers) : NULL; idle_info->callback = info->callback; + idle_info->user_data = info->user_data; g_idle_add (idle_update_account_cb, idle_info); } @@ -1400,8 +1440,10 @@ update_account_thread (gpointer thr_user_data) g_idle_add (idle_notify_queue, g_object_ref (info->mail_op)); /* Frees */ - g_object_unref (query); - g_object_unref (all_folders); + if (new_headers) + g_object_unref (new_headers); + if (all_folders) + g_object_unref (all_folders); g_object_unref (info->account); g_object_unref (info->transport_account); g_free (info->retrieve_type); @@ -1436,19 +1478,12 @@ modest_mail_operation_update_account (ModestMailOperation *self, priv->done = 0; priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; - /* Get the Modest account */ + /* Get the store account */ store_account = (TnyStoreAccount *) modest_tny_account_store_get_server_account (modest_runtime_get_account_store (), account_name, TNY_ACCOUNT_TYPE_STORE); - /* 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, TNY_ACCOUNT (store_account))) - goto error; - if (!store_account) { g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND, @@ -1487,12 +1522,10 @@ modest_mail_operation_update_account (ModestMailOperation *self, /* Get per-account retrieval type */ mgr = modest_runtime_get_account_mgr (); - info->retrieve_type = modest_account_mgr_get_string (mgr, account_name, - MODEST_ACCOUNT_RETRIEVE, FALSE); + info->retrieve_type = modest_account_mgr_get_retrieve_type (mgr, account_name); /* Get per-account message amount retrieval limit */ - info->retrieve_limit = modest_account_mgr_get_int (mgr, account_name, - MODEST_ACCOUNT_LIMIT_RETRIEVE, FALSE); + info->retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, account_name); if (info->retrieve_limit == 0) info->retrieve_limit = G_MAXINT; @@ -1507,9 +1540,14 @@ modest_mail_operation_update_account (ModestMailOperation *self, return TRUE; error: + if (store_account) + g_object_unref (store_account); + if (transport_account) + g_object_unref (transport_account); priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; - if (callback) - callback (self, 0, user_data); + if (callback) { + callback (self, NULL, user_data); + } modest_mail_operation_notify_end (self); return FALSE; } @@ -1527,28 +1565,19 @@ modest_mail_operation_create_folder (ModestMailOperation *self, ModestMailOperationPrivate *priv; TnyFolder *new_folder = NULL; - TnyList *list = tny_simple_list_new (); - TnyFolderStoreQuery *query = tny_folder_store_query_new (); - g_return_val_if_fail (TNY_IS_FOLDER_STORE (parent), NULL); g_return_val_if_fail (name, NULL); priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); /* Check for already existing folder */ - tny_folder_store_query_add_item (query, name, TNY_FOLDER_STORE_QUERY_OPTION_MATCH_ON_NAME); - tny_folder_store_get_folders (parent, list, query, NULL); - g_object_unref (G_OBJECT (query)); - - if (tny_list_get_length (list) > 0) { + if (modest_tny_folder_has_subfolder_with_name (parent, name)) { priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS, _CS("ckdg_ib_folder_already_exists")); } - g_object_unref (G_OBJECT (list)); - /* Check parent */ if (TNY_IS_FOLDER (parent)) { /* Check folder rules */ @@ -1630,6 +1659,9 @@ modest_mail_operation_remove_folder (ModestMailOperation *self, tny_folder_store_remove_folder (parent, folder, &(priv->error)); CHECK_EXCEPTION (priv, MODEST_MAIL_OPERATION_STATUS_FAILED); + if (!priv->error) + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + if (parent) g_object_unref (G_OBJECT (parent)); } @@ -1663,23 +1695,26 @@ 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, - TnyFolderStore *into, gboolean cancelled, + TnyFolderStore *into, TnyFolder *new_folder, - GError **err, + GError *err, gpointer user_data) { XFerMsgAsyncHelper *helper; @@ -1692,8 +1727,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 +1747,13 @@ transfer_folder_cb (TnyFolder *folder, /* 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 (); + + /* 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->user_data); + /* no gdk_threads_leave () , CHECKED */ } /* Free */ @@ -1756,8 +1795,8 @@ new_name_valid_if_local_account (ModestMailOperationPrivate *priv, new_name)) { priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, - MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES, - _("FIXME: folder name already in use")); + MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS, + _("ckdg_ib_folder_already_exists")); return FALSE; } else return TRUE; @@ -1768,17 +1807,24 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, TnyFolder *folder, TnyFolderStore *parent, gboolean delete_original, - XferMsgsAsynUserCallback user_callback, + XferAsyncUserCallback user_callback, gpointer user_data) { ModestMailOperationPrivate *priv = NULL; ModestTnyFolderRules parent_rules = 0, rules; XFerMsgAsyncHelper *helper = NULL; + const gchar *folder_name = NULL; + const gchar *error_msg; 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); + + /* Set the error msg */ + error_msg = _("mail_in_ui_folder_move_target_error"); /* Get account and set it into mail_operation */ priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder)); @@ -1789,56 +1835,65 @@ modest_mail_operation_xfer_folder (ModestMailOperation *self, if (TNY_IS_FOLDER (parent)) parent_rules = modest_tny_folder_get_rules (TNY_FOLDER (parent)); - /* The moveable restriction is applied also to copy operation */ + /* Apply operation constraints */ 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, - MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES, - _("mail_in_ui_folder_move_target_error")); - - /* Notify the queue */ - modest_mail_operation_notify_end (self); + /* Folder rules */ + goto error; } 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, - MODEST_MAIL_OPERATION_ERROR_FOLDER_RULES, - _("FIXME: parent folder does not accept new folders")); - - /* Notify the queue */ - modest_mail_operation_notify_end (self); - } else { - + /* Folder rules */ + goto error; + } else if (TNY_IS_FOLDER (parent) && + TNY_IS_FOLDER_STORE (folder) && + modest_tny_folder_is_ancestor (TNY_FOLDER (parent), + TNY_FOLDER_STORE (folder))) { + /* Do not move a parent into a child */ + goto error; + } 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 */ + goto error; + } 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), - delete_original, - transfer_folder_cb, - transfer_folder_status_cb, - helper); - } else { - modest_mail_operation_notify_end (self); - } + goto error; + } 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); + return; } + + error: + /* 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, + error_msg); + + /* Call the user callback if exists */ + if (user_callback) + user_callback (self, user_data); + + /* Notify the queue */ + modest_mail_operation_notify_end (self); } void @@ -1930,6 +1985,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; @@ -1957,104 +2018,11 @@ void modest_mail_operation_get_msg (ModestMailOperation *self, } } -static gboolean -idle_get_mime_part_size_cb (gpointer userdata) -{ - GetMimePartSizeInfo *idle_info; - - idle_info = (GetMimePartSizeInfo *) userdata; - - gdk_threads_enter (); - idle_info->callback (idle_info->mail_op, - idle_info->size, - idle_info->userdata); - gdk_threads_leave (); - - g_object_unref (idle_info->mail_op); - g_slice_free (GetMimePartSizeInfo, idle_info); - - return FALSE; -} - -static gpointer -get_mime_part_size_thread (gpointer thr_user_data) -{ - GetMimePartSizeInfo *info; - gchar read_buffer[GET_SIZE_BUFFER_SIZE]; - TnyStream *stream; - gssize readed_size; - gssize total = 0; - ModestMailOperationPrivate *priv; - - info = (GetMimePartSizeInfo *) thr_user_data; - priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op); - - stream = tny_camel_mem_stream_new (); - tny_mime_part_decode_to_stream (info->mime_part, stream); - tny_stream_reset (stream); - if (tny_stream_is_eos (stream)) { - tny_stream_close (stream); - stream = tny_mime_part_get_stream (info->mime_part); - } - - while (!tny_stream_is_eos (stream)) { - readed_size = tny_stream_read (stream, read_buffer, GET_SIZE_BUFFER_SIZE); - total += readed_size; - } - - if (info->callback) { - GetMimePartSizeInfo *idle_info; - - idle_info = g_slice_new0 (GetMimePartSizeInfo); - idle_info->mail_op = g_object_ref (info->mail_op); - idle_info->size = total; - idle_info->callback = info->callback; - idle_info->userdata = info->userdata; - g_idle_add (idle_get_mime_part_size_cb, idle_info); - } - - g_idle_add (idle_notify_queue, g_object_ref (info->mail_op)); - - g_object_unref (info->mail_op); - g_object_unref (stream); - g_object_unref (info->mime_part); - g_slice_free (GetMimePartSizeInfo, info); - - return NULL; -} - -void -modest_mail_operation_get_mime_part_size (ModestMailOperation *self, - TnyMimePart *part, - GetMimePartSizeCallback user_callback, - gpointer user_data, - GDestroyNotify notify) -{ - GetMimePartSizeInfo *info; - ModestMailOperationPrivate *priv; - GThread *thread; - - g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); - g_return_if_fail (TNY_IS_MIME_PART (part)); - - priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); - - priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; - info = g_slice_new0 (GetMimePartSizeInfo); - info->mail_op = g_object_ref (self); - info->mime_part = g_object_ref (part); - info->callback = user_callback; - info->userdata = user_data; - - thread = g_thread_create (get_mime_part_size_thread, info, FALSE, NULL); - -} - static void get_msg_cb (TnyFolder *folder, gboolean cancelled, TnyMsg *msg, - GError **error, + GError *error, gpointer user_data) { GetMsgAsyncHelper *helper = NULL; @@ -2068,8 +2036,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; @@ -2084,11 +2052,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 */ @@ -2125,13 +2094,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); } @@ -2164,11 +2134,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); @@ -2187,9 +2158,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 */ @@ -2217,6 +2192,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; @@ -2376,7 +2357,8 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self, void -modest_mail_operation_remove_msg (ModestMailOperation *self, TnyHeader *header, +modest_mail_operation_remove_msg (ModestMailOperation *self, + TnyHeader *header, gboolean remove_to_trash /*ignored*/) { TnyFolder *folder; @@ -2396,19 +2378,22 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, TnyHeader *header, priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; - + /* remove message from folder */ tny_folder_remove_msg (folder, header, &(priv->error)); if (!priv->error) { tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED); tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN); if (TNY_IS_CAMEL_IMAP_FOLDER (folder)) - tny_folder_sync(folder, FALSE, &(priv->error)); /* FALSE --> don't expunge */ +/* tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* FALSE --> don't expunge *\/ */ + 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 */ +/* tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /\* TRUE --> dont expunge *\/ */ + tny_folder_sync (folder, TRUE, &(priv->error)); /* TRUE --> expunge */ else - /* lcoal folders */ - tny_folder_sync(folder, TRUE, &(priv->error)); /* TRUE --> expunge */ + /* local folders */ +/* tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /\* TRUE --> expunge *\/ */ + tny_folder_sync (folder, TRUE, &(priv->error)); /* TRUE --> expunge */ } @@ -2425,6 +2410,62 @@ modest_mail_operation_remove_msg (ModestMailOperation *self, TnyHeader *header, modest_mail_operation_notify_end (self); } +void +modest_mail_operation_remove_msgs (ModestMailOperation *self, + TnyList *headers, + gboolean remove_to_trash /*ignored*/) +{ + TnyFolder *folder; + ModestMailOperationPrivate *priv; + TnyIterator *iter = NULL; + TnyHeader *header = NULL; + + g_return_if_fail (MODEST_IS_MAIL_OPERATION (self)); + g_return_if_fail (TNY_IS_LIST (headers)); + + if (remove_to_trash) + g_warning ("remove to trash is not implemented"); + + priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self); + + /* Get folder from first header and sync it */ + iter = tny_list_create_iterator (headers); + header = TNY_HEADER (tny_iterator_get_current (iter)); + folder = tny_header_get_folder (header); + + /* Get account and set it into mail_operation */ + priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder)); + + priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS; + + /* remove message from folder */ + tny_folder_remove_msgs (folder, headers, &(priv->error)); + if (!priv->error) { + if (TNY_IS_CAMEL_IMAP_FOLDER (folder) || + TNY_IS_CAMEL_POP_FOLDER (folder)) + tny_folder_sync_async(folder, FALSE, NULL, NULL, NULL); /* FALSE --> don't expunge */ + else + /* local folders */ + tny_folder_sync_async(folder, TRUE, NULL, NULL, NULL); /* TRUE --> expunge */ + } + + + /* Set status */ + if (!priv->error) + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + else + priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; + + /* Free */ + g_object_unref (header); + g_object_unref (iter); + g_object_unref (G_OBJECT (folder)); + + /* Notify about operation end */ + modest_mail_operation_notify_end (self); +} + + static void transfer_msgs_status_cb (GObject *obj, TnyStatus *status, @@ -2449,31 +2490,36 @@ 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; ModestMailOperationPrivate *priv; + TnyIterator *iter = NULL; + TnyHeader *header = NULL; helper = (XFerMsgAsyncHelper *) user_data; 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) { @@ -2485,25 +2531,54 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError **err, gpointer } else { priv->done = 1; priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + + /* Update folder counts */ + tny_folder_poke_status (folder); + tny_folder_poke_status (helper->dest_folder); + } + + + /* Mark headers as deleted and seen */ + if ((helper->delete) && + (priv->status == MODEST_MAIL_OPERATION_STATUS_SUCCESS)) { + iter = tny_list_create_iterator (helper->headers); + while (!tny_iterator_is_done (iter)) { + header = TNY_HEADER (tny_iterator_get_current (iter)); + tny_header_set_flags (header, TNY_HEADER_FLAG_DELETED); + tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN); + g_object_unref (header); + + tny_iterator_next (iter); + } + } + /* Notify about operation end */ modest_mail_operation_notify_end (self); /* 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 (); + /* 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, helper->user_data); + /* no gdk_threads_leave (), CHECKED */ } /* Free */ - g_object_unref (helper->headers); - g_object_unref (helper->dest_folder); - g_object_unref (helper->mail_op); - g_slice_free (XFerMsgAsyncHelper, helper); - g_object_unref (folder); - + if (helper->headers) + g_object_unref (helper->headers); + if (helper->dest_folder) + g_object_unref (helper->dest_folder); + if (helper->mail_op) + g_object_unref (helper->mail_op); + if (folder) + g_object_unref (folder); + if (iter) + g_object_unref (iter); + g_slice_free (XFerMsgAsyncHelper, helper); } void @@ -2511,7 +2586,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, TnyList *headers, TnyFolder *folder, gboolean delete_original, - XferMsgsAsynUserCallback user_callback, + XferAsyncUserCallback user_callback, gpointer user_data) { ModestMailOperationPrivate *priv = NULL; @@ -2520,9 +2595,6 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, XFerMsgAsyncHelper *helper = NULL; TnyHeader *header = NULL; ModestTnyFolderRules rules = 0; - 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)); @@ -2557,10 +2629,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, 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) { + if (src_folder == folder) { /* Set status failed and set an error */ priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED; g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR, @@ -2582,6 +2651,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, helper->headers = g_object_ref(headers); helper->user_callback = user_callback; helper->user_data = user_data; + helper->delete = delete_original; /* Get account and set it into mail_operation */ priv->account = modest_tny_folder_get_account (src_folder); @@ -2600,7 +2670,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; @@ -2611,9 +2681,13 @@ on_refresh_folder (TnyFolder *folder, self = helper->mail_op; priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self); - if (*error) { - priv->error = g_error_copy (*error); + g_return_if_fail(priv!=NULL); + + 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; } @@ -2623,23 +2697,27 @@ 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 */ helper->user_callback (self, folder, helper->user_data); - gdk_threads_leave (); } + out: /* Free */ g_slice_free (RefreshAsyncHelper, helper); /* Notify about operation end */ modest_mail_operation_notify_end (self); + g_object_unref(self); } static void @@ -2666,13 +2744,11 @@ 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 */ g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); -#ifdef TINYMAIL_IDLES_NOT_LOCKED_YET - gdk_threads_leave (); -#endif + g_slice_free (ModestMailOperationState, state); } @@ -2694,7 +2770,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;