From 9ac452ac9a046897f12fefbe4223ae274c8a53fb Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Tue, 10 Jun 2008 17:33:29 +0000 Subject: [PATCH] * Fixes NB#84725, retrieve messages when the option "messages and attchaments" is selected in send&receive * Fixes NB#85622, fixes a crash in tny_folder_add_observer pmo-trunk-r4636 --- src/maemo/modest-main-window.c | 3 - src/modest-mail-operation.c | 320 +++++++++++++++++++++++--------------- src/modest-tny-account-store.c | 3 +- src/modest-ui-actions.c | 12 +- src/widgets/modest-folder-view.c | 3 +- src/widgets/modest-header-view.c | 33 ++-- src/widgets/modest-header-view.h | 1 + 7 files changed, 233 insertions(+), 142 deletions(-) diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 9050341..586a6f3 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -2525,9 +2525,6 @@ set_account_visible(ModestMainWindow *self, const gchar *acc_name) } } - modest_folder_view_select_first_inbox_or_local (priv->folder_view); - - /* Free */ if (settings) { g_object_unref (store_settings); diff --git a/src/modest-mail-operation.c b/src/modest-mail-operation.c index 5595993..23c6136 100644 --- a/src/modest-mail-operation.c +++ b/src/modest-mail-operation.c @@ -95,9 +95,7 @@ static void notify_progress_of_multiple_messages (ModestMailOperation *self, gint total_bytes, gboolean increment_done); -static guint compute_message_list_size (TnyList *headers); - -static guint compute_message_array_size (GPtrArray *headers); +static guint compute_message_list_size (TnyList *headers, guint num_elements); static int compare_headers_by_date (gconstpointer a, gconstpointer b); @@ -109,6 +107,35 @@ static void sync_folder_finish_callback (TnyFolder *self, static gboolean _check_memory_low (ModestMailOperation *mail_op); +/* Helpers for the update account operation (send & receive)*/ +typedef struct +{ + ModestMailOperation *mail_op; + gchar *account_name; + UpdateAccountCallback callback; + gpointer user_data; + TnyList *folders; + gint pending_calls; + gboolean poke_all; + TnyFolderObserver *inbox_observer; + RetrieveAllCallback retrieve_all_cb; + gboolean interactive; + gboolean msg_readed; +} UpdateAccountInfo; + +static void destroy_update_account_info (UpdateAccountInfo *info); + +static void update_account_send_mail (UpdateAccountInfo *info); + +static void update_account_get_msg_async_cb (TnyFolder *folder, + gboolean canceled, + TnyMsg *msg, + GError *err, + gpointer user_data); + +static void update_account_notify_user_and_free (UpdateAccountInfo *info, + TnyList *new_headers); + enum _ModestMailOperationSignals { PROGRESS_CHANGED_SIGNAL, @@ -1228,21 +1255,6 @@ internal_folder_observer_class_init (InternalFolderObserverClass *klass) object_class->finalize = internal_folder_observer_finalize; } -typedef struct -{ - ModestMailOperation *mail_op; - gchar *account_name; - UpdateAccountCallback callback; - gpointer user_data; - TnyList *folders; - gint pending_calls; - gboolean poke_all; - TnyFolderObserver *inbox_observer; - RetrieveAllCallback retrieve_all_cb; - gboolean interactive; -} UpdateAccountInfo; - - static void destroy_update_account_info (UpdateAccountInfo *info) { @@ -1252,6 +1264,49 @@ destroy_update_account_info (UpdateAccountInfo *info) g_slice_free (UpdateAccountInfo, info); } + +static void +update_account_send_mail (UpdateAccountInfo *info) +{ + TnyTransportAccount *transport_account = NULL; + + /* Get the transport account */ + transport_account = (TnyTransportAccount *) + modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(), + info->account_name); + + if (transport_account) { + ModestTnySendQueue *send_queue; + TnyFolder *outbox; + guint num_messages; + + send_queue = modest_runtime_get_send_queue (transport_account, TRUE); + g_object_unref (transport_account); + + if (TNY_IS_SEND_QUEUE (send_queue)) { + /* Get outbox folder */ + outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue)); + if (outbox) { /* this could fail in some cases */ + num_messages = tny_folder_get_all_count (outbox); + g_object_unref (outbox); + } else { + g_warning ("%s: could not get outbox", __FUNCTION__); + num_messages = 0; + } + + if (num_messages != 0) { + /* Reenable suspended items */ + modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue)); + + /* Try to send */ + tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue)); + modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), + info->interactive); + } + } + } +} + static void update_account_get_msg_async_cb (TnyFolder *folder, gboolean canceled, @@ -1260,12 +1315,55 @@ update_account_get_msg_async_cb (TnyFolder *folder, gpointer user_data) { GetMsgInfo *msg_info = (GetMsgInfo *) user_data; + ModestMailOperationPrivate *priv; + + priv = MODEST_MAIL_OPERATION_GET_PRIVATE (msg_info->mail_op); + priv->done++; + + if (TNY_IS_MSG (msg)) { + TnyHeader *header = tny_msg_get_header (msg); + + if (header) { + ModestMailOperationState *state; + state = modest_mail_operation_clone_state (msg_info->mail_op); + msg_info->sum_total_bytes += tny_header_get_message_size (header); + state->bytes_done = msg_info->sum_total_bytes; + state->bytes_total = msg_info->total_bytes; + + /* Notify the status change. Only notify about changes + referred to bytes */ + g_signal_emit (G_OBJECT (msg_info->mail_op), + signals[PROGRESS_CHANGED_SIGNAL], + 0, state, NULL); - /* Just delete the helper. Don't do anything with the new - msg. There is also no need to check for errors */ - g_object_unref (msg_info->mail_op); - g_object_unref (msg_info->header); - g_slice_free (GetMsgInfo, msg_info); + g_object_unref (header); + g_slice_free (ModestMailOperationState, state); + } + } + + if (priv->done == priv->total) { + TnyList *new_headers; + UpdateAccountInfo *info; + + /* After getting all the messages send the ones in the + outboxes */ + info = (UpdateAccountInfo *) msg_info->user_data; + update_account_send_mail (info); + + /* Check if the operation was a success */ + if (!priv->error) + priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; + + /* Call the user callback and free */ + new_headers = tny_iterator_get_list (msg_info->more_msgs); + update_account_notify_user_and_free (info, new_headers); + g_object_unref (new_headers); + + /* Delete the helper */ + g_object_unref (msg_info->more_msgs); + g_object_unref (msg_info->mail_op); + g_slice_free (GetMsgInfo, msg_info); + } } static void @@ -1304,7 +1402,6 @@ inbox_refreshed_cb (TnyFolder *inbox, ModestAccountRetrieveType retrieve_type; TnyList *new_headers = NULL; gboolean headers_only, ignore_limit; - TnyTransportAccount *transport_account = NULL; info = (UpdateAccountInfo *) user_data; priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op); @@ -1322,6 +1419,10 @@ inbox_refreshed_cb (TnyFolder *inbox, MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED, "canceled"); + tny_folder_remove_observer (inbox, info->inbox_observer); + g_object_unref (info->inbox_observer); + info->inbox_observer = NULL; + /* Notify the user about the error and then exit */ update_account_notify_user_and_free (info, NULL); return; @@ -1343,25 +1444,30 @@ inbox_refreshed_cb (TnyFolder *inbox, /* Create the new headers array. We need it to sort the new headers by date */ new_headers_array = g_ptr_array_new (); - new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_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) < max_size) - g_ptr_array_add (new_headers_array, g_object_ref (header)); - - g_object_unref (header); - tny_iterator_next (new_headers_iter); + if (info->inbox_observer) { + new_headers_iter = tny_list_create_iterator (((InternalFolderObserver *) info->inbox_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) < max_size) + g_ptr_array_add (new_headers_array, g_object_ref (header)); + + g_object_unref (header); + tny_iterator_next (new_headers_iter); + } + g_object_unref (new_headers_iter); + + tny_folder_remove_observer (inbox, info->inbox_observer); + g_object_unref (info->inbox_observer); + info->inbox_observer = NULL; } - g_object_unref (new_headers_iter); - tny_folder_remove_observer (inbox, info->inbox_observer); - g_object_unref (info->inbox_observer); - info->inbox_observer = NULL; - if (new_headers_array->len == 0) + if (new_headers_array->len == 0) { + g_ptr_array_free (new_headers_array, FALSE); goto send_mail; + } /* Get per-account message amount retrieval limit */ retrieve_limit = modest_account_mgr_get_retrieve_limit (mgr, info->account_name); @@ -1388,87 +1494,64 @@ inbox_refreshed_cb (TnyFolder *inbox, new_headers_array->len, retrieve_limit); } + + /* 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); - if (!headers_only) { + if (!headers_only && (tny_list_get_length (new_headers) > 0)) { gint msg_num = 0; - const gint msg_list_size = compute_message_array_size (new_headers_array); + TnyIterator *iter; + GetMsgInfo *msg_info; priv->done = 0; if (ignore_limit) - priv->total = new_headers_array->len; + priv->total = tny_list_get_length (new_headers); else - priv->total = MIN (new_headers_array->len, 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); - GetMsgInfo *msg_info; + priv->total = MIN (tny_list_get_length (new_headers), retrieve_limit); - /* Create the message info */ - msg_info = g_slice_new0 (GetMsgInfo); - msg_info->mail_op = g_object_ref (info->mail_op); - msg_info->header = g_object_ref (header); - msg_info->total_bytes = msg_list_size; + iter = tny_list_create_iterator (new_headers); + + /* Create the message info */ + msg_info = g_slice_new0 (GetMsgInfo); + msg_info->mail_op = g_object_ref (info->mail_op); + msg_info->total_bytes = compute_message_list_size (new_headers, priv->total); + msg_info->more_msgs = g_object_ref (iter); + msg_info->user_data = info; + + while ((msg_num < priv->total ) && !tny_iterator_is_done (iter)) { + TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter)); + TnyFolder *folder = tny_header_get_folder (header); /* Get message in an async way */ tny_folder_get_msg_async (folder, header, update_account_get_msg_async_cb, - get_msg_status_cb, msg_info); + NULL, msg_info); g_object_unref (folder); msg_num++; + tny_iterator_next (iter); } - } + g_object_unref (iter); - /* 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)); + /* The mail operation will finish when the last + message is retrieved */ + return; } - g_ptr_array_foreach (new_headers_array, (GFunc) g_object_unref, NULL); - g_ptr_array_free (new_headers_array, FALSE); - send_mail: - /* Get the transport account */ - transport_account = (TnyTransportAccount *) - modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(), - info->account_name); - - if (transport_account) { - ModestTnySendQueue *send_queue; - TnyFolder *outbox; - guint num_messages; - - send_queue = modest_runtime_get_send_queue (transport_account, TRUE); - g_object_unref (transport_account); - - if (TNY_IS_SEND_QUEUE (send_queue)) { - /* Get outbox folder */ - outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (send_queue)); - if (outbox) { /* this could fail in some cases */ - num_messages = tny_folder_get_all_count (outbox); - g_object_unref (outbox); - } else { - g_warning ("%s: could not get outbox", __FUNCTION__); - num_messages = 0; - } - - if (num_messages != 0) { - /* Reenable suspended items */ - modest_tny_send_queue_wakeup (MODEST_TNY_SEND_QUEUE (send_queue)); - - /* Try to send */ - tny_camel_send_queue_flush (TNY_CAMEL_SEND_QUEUE (send_queue)); - modest_tny_send_queue_set_requested_send_receive (MODEST_TNY_SEND_QUEUE (send_queue), - info->interactive); - } - } - } - + /* If we don't have to retrieve the new messages then + simply send mail */ + update_account_send_mail (info); + /* Check if the operation was a success */ if (!priv->error) priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS; - + /* Call the user callback and free */ update_account_notify_user_and_free (info, new_headers); } @@ -2469,7 +2552,7 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self, g_object_unref (iterator); } - msg_list_size = compute_message_list_size (header_list); + msg_list_size = compute_message_list_size (header_list, 0); modest_mail_operation_notify_start (self); iter = tny_list_create_iterator (header_list); @@ -2817,39 +2900,33 @@ transfer_msgs_cb (TnyFolder *folder, gboolean cancelled, GError *err, gpointer u } } +/* Computes the size of the messages the headers in the list belongs + to. If num_elements is different from 0 then it only takes into + account the first num_elements for the calculation */ static guint -compute_message_list_size (TnyList *headers) +compute_message_list_size (TnyList *headers, + guint num_elements) { TnyIterator *iter; - guint size = 0; + guint size = 0, element = 0; + + /* If num_elements is not valid then take all into account */ + if ((num_elements <= 0) || (num_elements > tny_list_get_length (headers))) + num_elements = tny_list_get_length (headers); iter = tny_list_create_iterator (headers); - while (!tny_iterator_is_done (iter)) { + while (!tny_iterator_is_done (iter) && element < num_elements) { TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter)); size += tny_header_get_message_size (header); g_object_unref (header); tny_iterator_next (iter); + element++; } g_object_unref (iter); return size; } -static guint -compute_message_array_size (GPtrArray *headers) -{ - guint size = 0; - gint i; - - for (i = 0; i < headers->len; i++) { - TnyHeader *header = TNY_HEADER (g_ptr_array_index (headers, i)); - size += tny_header_get_message_size (header); - } - - return size; -} - - void modest_mail_operation_xfer_msgs (ModestMailOperation *self, TnyList *headers, @@ -2933,7 +3010,7 @@ modest_mail_operation_xfer_msgs (ModestMailOperation *self, helper->user_data = user_data; helper->last_total_bytes = 0; helper->sum_total_bytes = 0; - helper->total_bytes = compute_message_list_size (headers); + helper->total_bytes = compute_message_list_size (headers, 0); /* Get account and set it into mail_operation */ priv->account = modest_tny_folder_get_account (src_folder); @@ -3123,8 +3200,7 @@ modest_mail_operation_refresh_folder (ModestMailOperation *self, state->total = 0; g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, state, NULL); - - /* FIXME: we're leaking the state here, or? valgrind thinks so */ + g_slice_free (ModestMailOperationState, state); tny_folder_refresh_async (folder, on_refresh_folder, diff --git a/src/modest-tny-account-store.c b/src/modest-tny-account-store.c index 0d380e3..540446c 100644 --- a/src/modest-tny-account-store.c +++ b/src/modest-tny-account-store.c @@ -1136,6 +1136,7 @@ modest_tny_account_store_alert (TnyAccountStore *self, case TNY_SERVICE_ERROR_UNKNOWN: return FALSE; default: + g_debug ("Unexpected error %d", error->code); g_return_val_if_reached (FALSE); } @@ -1544,7 +1545,7 @@ connection_status_changed (TnyAccount *account, /* Perform a send receive */ account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account); main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (), FALSE); - modest_ui_actions_do_send_receive (account_name, FALSE, FALSE, FALSE, main_window); + modest_ui_actions_do_send_receive (account_name, FALSE, FALSE, TRUE, main_window); } } diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 7712173..c7e72d5 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -2367,11 +2367,16 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view, } } else { if (TNY_IS_FOLDER (folder_store) && selected) { - + TnyAccount *account; + const gchar *account_name = NULL; + gboolean refresh; + /* Update the active account */ - TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store)); + account = modest_tny_folder_get_account (TNY_FOLDER (folder_store)); if (account) { set_active_account_from_tny_account (account, MODEST_WINDOW (main_window)); + account_name = + modest_tny_account_get_parent_modest_account_name_for_server_account (account); g_object_unref (account); account = NULL; } @@ -2382,6 +2387,8 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view, modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS); + refresh = !modest_account_mgr_account_is_busy (modest_runtime_get_account_mgr (), account_name); + /* Set folder on header view. This function will call tny_folder_refresh_async so we pass a callback that will be called when @@ -2389,6 +2396,7 @@ modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view, empty view if there are no messages */ modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), TNY_FOLDER (folder_store), + refresh, folder_refreshed_cb, main_window); diff --git a/src/widgets/modest-folder-view.c b/src/widgets/modest-folder-view.c index a7db870..41ad4b1 100644 --- a/src/widgets/modest-folder-view.c +++ b/src/widgets/modest-folder-view.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include "modest-folder-view.h" @@ -1080,7 +1081,7 @@ on_account_changed (TnyAccountStore *account_store, /* Select the first INBOX if the currently selected folder belongs to the account that is being deleted */ - if (same_account) + if (same_account && !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account)) g_idle_add (on_idle_select_first_inbox_or_local, self); } diff --git a/src/widgets/modest-header-view.c b/src/widgets/modest-header-view.c index 723ad7c..6338898 100644 --- a/src/widgets/modest-header-view.c +++ b/src/widgets/modest-header-view.c @@ -981,6 +981,9 @@ set_folder_intern_get_headers_async_cb (TnyFolder *folder, self = MODEST_HEADER_VIEW (user_data); priv = MODEST_HEADER_VIEW_GET_PRIVATE(self); + if (cancelled || err) + return; + /* Add IDLE observer (monitor) and another folder observer for new messages (self) */ g_mutex_lock (priv->observers_lock); @@ -1225,11 +1228,11 @@ refresh_folder_error_handler (ModestMailOperation *mail_op, void modest_header_view_set_folder (ModestHeaderView *self, TnyFolder *folder, + gboolean refresh, RefreshAsyncUserCallback callback, gpointer user_data) { ModestHeaderViewPrivate *priv; - SetFolderHelper *info; ModestWindow *main_win; g_return_if_fail (self); @@ -1257,8 +1260,9 @@ modest_header_view_set_folder (ModestHeaderView *self, } if (folder) { - ModestMailOperation *mail_op = NULL; GtkTreeSelection *selection; + SetFolderHelper *info; + ModestMailOperation *mail_op = NULL; /* Set folder in the model */ modest_header_view_set_folder_intern (self, folder); @@ -1279,7 +1283,7 @@ modest_header_view_set_folder (ModestHeaderView *self, 0, TRUE, NULL); /* create the helper */ - info = g_malloc0 (sizeof(SetFolderHelper)); + info = g_malloc0 (sizeof (SetFolderHelper)); info->header_view = g_object_ref (self); info->cb = callback; info->user_data = user_data; @@ -1288,15 +1292,18 @@ modest_header_view_set_folder (ModestHeaderView *self, mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(main_win), refresh_folder_error_handler, NULL, NULL); - modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), - mail_op); - - /* Refresh the folder asynchronously */ - modest_mail_operation_refresh_folder (mail_op, - folder, - folder_refreshed_cb, - info); - + if (refresh) { + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + + /* Refresh the folder asynchronously */ + modest_mail_operation_refresh_folder (mail_op, + folder, + folder_refreshed_cb, + info); + } else { + folder_refreshed_cb (mail_op, folder, info); + } /* Free */ g_object_unref (mail_op); } else { @@ -1890,7 +1897,7 @@ modest_header_view_clear (ModestHeaderView *self) { g_return_if_fail (self && MODEST_IS_HEADER_VIEW(self)); - modest_header_view_set_folder (self, NULL, NULL, NULL); + modest_header_view_set_folder (self, NULL, FALSE, NULL, NULL); } void diff --git a/src/widgets/modest-header-view.h b/src/widgets/modest-header-view.h index b2f6d00..c59d4db 100644 --- a/src/widgets/modest-header-view.h +++ b/src/widgets/modest-header-view.h @@ -160,6 +160,7 @@ GtkWidget* modest_header_view_new (TnyFolder *folder, */ void modest_header_view_set_folder (ModestHeaderView *self, TnyFolder *folder, + gboolean refresh, RefreshAsyncUserCallback callback, gpointer user_data); -- 1.7.9.5