From: Sergio Villar Senin Date: Fri, 4 Jul 2008 17:16:52 +0000 (+0000) Subject: * Fixes NB#86753, do not hang when header retrieval starts while retrieving account... X-Git-Tag: git_migration_finished~1276 X-Git-Url: http://git.maemo.org/git/?p=modest;a=commitdiff_plain;h=9706c44c51358632eddc457b39a47e81c513cd87 * Fixes NB#86753, do not hang when header retrieval starts while retrieving account statistics pmo-trunk-r4903 --- diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 009d325..4bfc990 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -1790,6 +1790,75 @@ create_device_name_visual_string (const gchar *device_name, return label; } +typedef struct +{ + GtkWidget *count_label; + GtkWidget *msg_count_label; + GtkWidget *size_label; + gchar *color_markup; +} DetailsWidgets; + +static gchar * +create_uint_label (const gchar *markup, + const gchar *name, + guint count) +{ + return g_markup_printf_escaped ("%s: %d", markup, name, count); +} + +static gchar * +create_gchar_label (const gchar *markup, + const gchar *name, + gchar *count) +{ + return g_markup_printf_escaped ("%s: %s", markup, name, count); +} + +static void +update_folder_stats_status_cb (ModestFolderStats stats, + gpointer user_data) +{ + DetailsWidgets *widgets = (DetailsWidgets *) user_data; + gchar *label, *tmp; + + label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders); + gtk_label_set_markup (GTK_LABEL (widgets->count_label), label); + g_free (label); + + label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count); + gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label); + g_free (label); + + if (widgets->size_label) { + tmp = modest_text_utils_get_display_size (stats.local_size); + label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp); + gtk_label_set_markup (GTK_LABEL (widgets->size_label), label); + g_free (label); + g_free (tmp); + } +} + +static void +update_folder_stats_cb (ModestFolderStats stats, + gpointer user_data) +{ + DetailsWidgets *widgets = (DetailsWidgets *) user_data; + + /* refresh data */ + update_folder_stats_status_cb (stats, user_data); + + /* frees. Note that the widgets could have been destroyed but + we still keep a reference */ + g_free (widgets->color_markup); + if (widgets->count_label) + g_object_unref (widgets->count_label); + if (widgets->msg_count_label) + g_object_unref (widgets->msg_count_label); + if (widgets->size_label) + g_object_unref (widgets->size_label); + g_slice_free (DetailsWidgets, widgets); +} + static GtkWidget * create_details_widget (GtkWidget *styled_widget, TnyAccount *account) { @@ -1799,10 +1868,13 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) GtkWidget *label_w; gchar *label; gchar *gray_color_markup; + DetailsWidgets *widgets; vbox = gtk_vbox_new (FALSE, 0); + widgets = g_slice_new0 (DetailsWidgets); gray_color_markup = get_gray_color_markup (styled_widget); + widgets->color_markup = g_strdup (gray_color_markup); /* Account description: */ if (modest_tny_account_is_virtual_local_folders (account) @@ -1857,43 +1929,39 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) /* Message count */ TnyFolderStore *folder_store = TNY_FOLDER_STORE (account); - label = g_markup_printf_escaped ("%s: %d", - gray_color_markup, _("mcen_fi_rootfolder_messages"), - modest_tny_folder_store_get_message_count (folder_store)); + label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + widgets->msg_count_label = g_object_ref (label_w); + /* Folder count */ - label = g_markup_printf_escaped ("%s: %d", - gray_color_markup, - _("mcen_fi_rootfolder_folders"), - modest_tny_folder_store_get_folder_count (folder_store)); + label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + widgets->count_label = g_object_ref (label_w); + /* Size / Date */ if (modest_tny_account_is_virtual_local_folders (account) || modest_tny_account_is_memory_card_account (account)) { - gchar *size = modest_text_utils_get_display_size ( - modest_tny_folder_store_get_local_size (folder_store)); - - label = g_markup_printf_escaped ("%s: %s", - gray_color_markup, _("mcen_fi_rootfolder_size"), - size); - g_free (size); + label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0"); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + + widgets->size_label = g_object_ref (label_w); + } else if (TNY_IS_ACCOUNT(folder_store)) { TnyAccount *account = TNY_ACCOUNT(folder_store); @@ -1919,6 +1987,12 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) g_free (gray_color_markup); + /* Refresh folder stats asynchronously */ + modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account), + update_folder_stats_cb, + update_folder_stats_status_cb, + widgets); + /* Set alignment */ gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL); diff --git a/src/modest-tny-account.c b/src/modest-tny-account.c index 2115d69..9ee4e85 100644 --- a/src/modest-tny-account.c +++ b/src/modest-tny-account.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #ifdef MODEST_PLATFORM_MAEMO @@ -897,119 +898,109 @@ modest_tny_account_new_for_per_account_local_outbox_folder (ModestAccountMgr *ac -typedef gint (*TnyStatsFunc) (TnyFolderStats *stats); -#define TASK_GET_ALL_COUNT 0 -#define TASK_GET_LOCAL_SIZE 1 -#define TASK_GET_FOLDER_COUNT 2 - -typedef struct _RecurseFoldersHelper { - gint task; - guint sum; - guint folders; -} RecurseFoldersHelper; +typedef struct _RecurseFoldersAsyncHelper { + ModestFolderStats stats; + guint pending_calls; + GetFolderStatsCallback callback; + GetFolderStatsCallback status_callback; + gpointer user_data; +} RecurseFoldersAsyncHelper; -static void -recurse_folders (TnyFolderStore *store, - TnyFolderStoreQuery *query, - RecurseFoldersHelper *helper) +static void +recurse_folders_async_cb (TnyFolderStore *folder_store, + gboolean canceled, + TnyList *list, + GError *err, + gpointer user_data) { - TnyIterator *iter; - TnyList *folders = tny_simple_list_new (); + RecurseFoldersAsyncHelper *helper; + TnyIterator *iter; - tny_folder_store_get_folders (store, folders, query, NULL); - iter = tny_list_create_iterator (folders); + helper = (RecurseFoldersAsyncHelper *) user_data; - helper->folders += tny_list_get_length (folders); + /* A goto just to avoid an indentation level */ + if (err || canceled) + goto next_folder; + /* Retrieve children */ + iter = tny_list_create_iterator (list); while (!tny_iterator_is_done (iter)) { - TnyFolder *folder; - - folder = TNY_FOLDER (tny_iterator_get_current (iter)); - if (folder) { - if (helper->task == TASK_GET_ALL_COUNT) - helper->sum += tny_folder_get_all_count (folder); - - if (helper->task == TASK_GET_LOCAL_SIZE) - helper->sum += tny_folder_get_local_size (folder); - - if (TNY_IS_FOLDER_STORE (folder)) - recurse_folders (TNY_FOLDER_STORE (folder), query, helper); + TnyList *folders = NULL; + TnyFolderStore *folder = NULL; - g_object_unref (folder); + folders = tny_simple_list_new (); + folder = (TnyFolderStore*) tny_iterator_get_current (iter); + + /* Add pending call */ + helper->pending_calls++; + helper->stats.folders++; + if (TNY_IS_FOLDER (folder)) { + helper->stats.msg_count += tny_folder_get_all_count (TNY_FOLDER (folder)); + helper->stats.local_size += tny_folder_get_local_size (TNY_FOLDER (folder)); } + /* notify */ + if (helper->status_callback) + helper->status_callback (helper->stats, helper->user_data); + + /* Avoid the outbox */ + if (!TNY_IS_MERGE_FOLDER (folder) && + (TNY_IS_FOLDER (folder) && + tny_folder_get_folder_type (TNY_FOLDER (folder)) != TNY_FOLDER_TYPE_OUTBOX)) + tny_folder_store_get_folders_async (folder, folders, NULL, + recurse_folders_async_cb, + NULL, helper); + g_object_unref (folders); + g_object_unref (G_OBJECT (folder)); + tny_iterator_next (iter); } - g_object_unref (G_OBJECT (iter)); - g_object_unref (G_OBJECT (folders)); -} - -gint -modest_tny_folder_store_get_folder_count (TnyFolderStore *self) -{ - RecurseFoldersHelper *helper; - gint retval; - - g_return_val_if_fail (TNY_IS_FOLDER_STORE (self), -1); - - /* Create helper */ - helper = g_malloc0 (sizeof (RecurseFoldersHelper)); - helper->task = TASK_GET_FOLDER_COUNT; - helper->folders = 0; - - recurse_folders (self, NULL, helper); - - retval = helper->folders; + g_object_unref (G_OBJECT (iter)); - g_free (helper); - - return retval; -} +next_folder: + /* Remove my own pending call */ + helper->pending_calls--; -gint -modest_tny_folder_store_get_message_count (TnyFolderStore *self) -{ - RecurseFoldersHelper *helper; - gint retval; - - g_return_val_if_fail (TNY_IS_FOLDER_STORE (self), -1); - - /* Create helper */ - helper = g_malloc0 (sizeof (RecurseFoldersHelper)); - helper->task = TASK_GET_ALL_COUNT; - if (TNY_IS_FOLDER (self)) - helper->sum = tny_folder_get_all_count (TNY_FOLDER (self)); + /* This means that we have all the folders */ + if (helper->pending_calls == 0) { + /* notify */ + if (helper->callback) + helper->callback (helper->stats, helper->user_data); - recurse_folders (self, NULL, helper); - - retval = helper->sum; - - g_free (helper); - - return retval; + /* Free resources */ + g_slice_free (RecurseFoldersAsyncHelper, helper); + } } -gint -modest_tny_folder_store_get_local_size (TnyFolderStore *self) +void +modest_tny_folder_store_get_folder_stats (TnyFolderStore *self, + GetFolderStatsCallback callback, + GetFolderStatsCallback status_callback, + gpointer user_data) { - RecurseFoldersHelper *helper; - gint retval; + RecurseFoldersAsyncHelper *helper; + TnyList *folders; - g_return_val_if_fail (TNY_IS_FOLDER_STORE (self), -1); + g_return_if_fail (TNY_IS_FOLDER_STORE (self)); /* Create helper */ - helper = g_malloc0 (sizeof (RecurseFoldersHelper)); - helper->task = TASK_GET_LOCAL_SIZE; - if (TNY_IS_FOLDER (self)) - helper->sum = tny_folder_get_local_size (TNY_FOLDER (self)); - - recurse_folders (self, NULL, helper); - - retval = helper->sum; - - g_free (helper); + helper = g_slice_new0 (RecurseFoldersAsyncHelper); + helper->pending_calls = 1; + helper->callback = callback; + helper->status_callback = status_callback; + helper->user_data = user_data; + + if (TNY_IS_FOLDER (self)) { + helper->stats.msg_count = tny_folder_get_all_count (TNY_FOLDER (self)); + helper->stats.local_size = tny_folder_get_local_size (TNY_FOLDER (self)); + } - return retval; + folders = tny_simple_list_new (); + tny_folder_store_get_folders_async (TNY_FOLDER_STORE (self), + folders, NULL, + recurse_folders_async_cb, + NULL, helper); + g_object_unref (folders); } const gchar* diff --git a/src/modest-tny-account.h b/src/modest-tny-account.h index 1816541..07f613a 100644 --- a/src/modest-tny-account.h +++ b/src/modest-tny-account.h @@ -42,9 +42,12 @@ G_BEGIN_DECLS - - - +typedef struct +{ + guint local_size; + guint msg_count; + guint folders; +} ModestFolderStats; /** * modest_tny_account_new_from_account: @@ -142,36 +145,19 @@ TnyFolder* modest_tny_account_get_special_folder (TnyAccount *self, TnyFolderType special_type); -/** - * modest_tny_folder_store_get_folder_count: - * @self: a #TnyFolderStore - * - * gets the number of folders of the account - * - * Returns: the number of folder, or -1 in case of error - **/ -gint modest_tny_folder_store_get_folder_count (TnyFolderStore *self); +typedef void (*GetFolderStatsCallback) (ModestFolderStats stats, + gpointer user_data); /** - * modest_tny_folder_store_get_message_count: - * @self: - * - * gets the number of messages in the account - * - * Returns: the number of messages, or -1 in case of error - **/ -gint modest_tny_folder_store_get_message_count (TnyFolderStore *self); - -/** - * modest_tny_folder_store_get_local_size: - * @self: - * - * gets the total size occupied by the account in the local storage - * device + * modest_tny_folder_store_get_folder_stats: + * @self: a #TnyFolderStore * - * Returns: the total size in bytes, or -1 in case of error **/ -gint modest_tny_folder_store_get_local_size (TnyFolderStore *self); +void +modest_tny_folder_store_get_folder_stats (TnyFolderStore *self, + GetFolderStatsCallback callback, + GetFolderStatsCallback status_callback, + gpointer user_data); /** * modest_tny_folder_store_is_remote: diff --git a/src/widgets/modest-details-dialog.c b/src/widgets/modest-details-dialog.c index 2aeff6b..1fadc4e 100644 --- a/src/widgets/modest-details-dialog.c +++ b/src/widgets/modest-details-dialog.c @@ -297,13 +297,8 @@ modest_details_dialog_set_folder_default (ModestDetailsDialog *self, gtk_dialog_add_button (GTK_DIALOG (self), _("mcen_bd_close"), GTK_RESPONSE_CLOSE); /* Get data. We use our function because it's recursive */ - if (TNY_IS_FOLDER (folder)) { - count = tny_folder_get_all_count (TNY_FOLDER (folder)); - size = tny_folder_get_local_size (TNY_FOLDER (folder)); - } else { - count = modest_tny_folder_store_get_message_count (TNY_FOLDER_STORE (folder)); - size = modest_tny_folder_store_get_local_size (TNY_FOLDER_STORE (folder)); - } + count = tny_folder_get_all_count (TNY_FOLDER (folder)); + size = tny_folder_get_local_size (TNY_FOLDER (folder)); /* Format count and size */ count_s = g_strdup_printf ("%d", count);