aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2013-06-22 02:21:48 +0800
committerMatthew Barnes <mbarnes@redhat.com>2013-06-22 02:34:06 +0800
commit77346775da94d527c37c63a3912d4472018d583e (patch)
tree5d76f16236a1d284f42e00759501b752b284ab1a /mail
parente8753f37f844242c65ae238c15a05f71ac3da530 (diff)
downloadgsoc2013-evolution-77346775da94d527c37c63a3912d4472018d583e.tar.gz
gsoc2013-evolution-77346775da94d527c37c63a3912d4472018d583e.tar.zst
gsoc2013-evolution-77346775da94d527c37c63a3912d4472018d583e.zip
Bug 702710 - MessageList: Delay state capture for regen.
Delay capturing MessageList state for a regen operation until the idle callback, so the caller has a chance to configure the MessageList first. Also, move the CamelFolderThread into the private structure and provide thread-safe internal accessor functions for it.
Diffstat (limited to 'mail')
-rw-r--r--mail/message-list.c218
-rw-r--r--mail/message-list.h3
2 files changed, 127 insertions, 94 deletions
diff --git a/mail/message-list.c b/mail/message-list.c
index 90cc18fd6f..df594ba003 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -100,6 +100,9 @@ struct _MessageListPrivate {
RegenData *regen_data;
guint regen_idle_id;
+ GMutex thread_tree_lock;
+ CamelFolderThread *thread_tree;
+
struct _MLSelection clipboard;
gboolean destroyed;
@@ -457,9 +460,6 @@ regen_data_new (MessageList *message_list,
RegenData *regen_data;
EActivity *activity;
EMailSession *session;
- ETreeTableAdapter *adapter;
- gboolean searching;
- gint row_count;
activity = e_activity_new ();
e_activity_set_cancellable (activity, cancellable);
@@ -471,63 +471,6 @@ regen_data_new (MessageList *message_list,
regen_data->message_list = g_object_ref (message_list);
regen_data->last_row = -1;
- /* Capture MessageList state to use for this regen. */
-
- regen_data->folder =
- message_list_ref_folder (message_list);
- regen_data->group_by_threads =
- message_list_get_group_by_threads (message_list);
- regen_data->thread_subject =
- message_list_get_thread_subject (message_list);
-
- if (message_list->thread_tree != NULL) {
- CamelFolderThread *thread_tree;
- gboolean hide_deleted;
-
- thread_tree = message_list->thread_tree;
- hide_deleted = message_list_get_hide_deleted (
- message_list, regen_data->folder);
-
- if (regen_data->group_by_threads && hide_deleted) {
- regen_data->thread_tree = thread_tree;
- camel_folder_thread_messages_ref (thread_tree);
- } else {
- camel_folder_thread_messages_unref (thread_tree);
- message_list->thread_tree = NULL;
- }
- }
-
- searching = (g_strcmp0 (message_list->search, " ") != 0);
-
- adapter = e_tree_get_table_adapter (E_TREE (message_list));
- row_count = e_table_model_row_count (E_TABLE_MODEL (adapter));
-
- if (row_count <= 0) {
- if (gtk_widget_get_visible (GTK_WIDGET (message_list))) {
- gchar *txt;
-
- txt = g_strdup_printf (
- "%s...", _("Generating message list"));
- e_tree_set_info_message (E_TREE (message_list), txt);
- g_free (txt);
- }
-
- } else if (regen_data->group_by_threads &&
- !message_list->just_set_folder &&
- !searching) {
- if (message_list->priv->any_row_changed) {
- /* Something changed. If it was an expand
- * state change, then save the expand state. */
- message_list_save_state (message_list);
- } else {
- /* Remember the expand state and restore it
- * after regen. */
- regen_data->expand_state =
- e_tree_table_adapter_save_expanded_state_xml (
- adapter);
- }
- }
-
g_mutex_init (&regen_data->select_lock);
session = message_list_get_session (message_list);
@@ -591,6 +534,45 @@ regen_data_unref (RegenData *regen_data)
}
}
+static CamelFolderThread *
+message_list_ref_thread_tree (MessageList *message_list)
+{
+ CamelFolderThread *thread_tree = NULL;
+
+ g_return_val_if_fail (IS_MESSAGE_LIST (message_list), NULL);
+
+ g_mutex_lock (&message_list->priv->thread_tree_lock);
+
+ if (message_list->priv->thread_tree != NULL) {
+ thread_tree = message_list->priv->thread_tree;
+ camel_folder_thread_messages_ref (thread_tree);
+ }
+
+ g_mutex_unlock (&message_list->priv->thread_tree_lock);
+
+ return thread_tree;
+}
+
+static void
+message_list_set_thread_tree (MessageList *message_list,
+ CamelFolderThread *thread_tree)
+{
+ g_return_if_fail (IS_MESSAGE_LIST (message_list));
+
+ g_mutex_lock (&message_list->priv->thread_tree_lock);
+
+ if (thread_tree != NULL)
+ camel_folder_thread_messages_ref (thread_tree);
+
+ if (message_list->priv->thread_tree != NULL)
+ camel_folder_thread_messages_unref (
+ message_list->priv->thread_tree);
+
+ message_list->priv->thread_tree = thread_tree;
+
+ g_mutex_unlock (&message_list->priv->thread_tree_lock);
+}
+
static RegenData *
message_list_ref_regen_data (MessageList *message_list)
{
@@ -2538,12 +2520,9 @@ ml_tree_sorting_changed (ETreeTableAdapter *adapter,
group_by_threads = message_list_get_group_by_threads (message_list);
if (group_by_threads && message_list->frozen == 0) {
- if (message_list->thread_tree != NULL) {
- /* free the previous thread_tree to recreate it fully */
- camel_folder_thread_messages_unref (
- message_list->thread_tree);
- message_list->thread_tree = NULL;
- }
+
+ /* Invalidate the thread tree. */
+ message_list_set_thread_tree (message_list, NULL);
mail_regen_list (message_list, message_list->search, FALSE);
@@ -2742,14 +2721,16 @@ message_list_finalize (GObject *object)
g_hash_table_destroy (message_list->normalised_hash);
- if (message_list->thread_tree != NULL)
- camel_folder_thread_messages_unref (message_list->thread_tree);
+ if (message_list->priv->thread_tree != NULL)
+ camel_folder_thread_messages_unref (
+ message_list->priv->thread_tree);
g_free (message_list->search);
g_free (message_list->frozen_search);
g_free (message_list->cursor_uid);
g_mutex_clear (&message_list->priv->regen_lock);
+ g_mutex_clear (&message_list->priv->thread_tree_lock);
clear_selection (message_list, &message_list->priv->clipboard);
@@ -3339,6 +3320,7 @@ message_list_init (MessageList *message_list)
message_list->last_sel_single = FALSE;
g_mutex_init (&message_list->priv->regen_lock);
+ g_mutex_init (&message_list->priv->thread_tree_lock);
/* TODO: Should this only get the selection if we're realised? */
p = message_list->priv;
@@ -4428,10 +4410,8 @@ message_list_set_folder (MessageList *message_list,
g_clear_object (&message_list->priv->folder);
}
- if (message_list->thread_tree != NULL) {
- camel_folder_thread_messages_unref (message_list->thread_tree);
- message_list->thread_tree = NULL;
- }
+ /* Invalidate the thread tree. */
+ message_list_set_thread_tree (message_list, NULL);
g_free (message_list->cursor_uid);
message_list->cursor_uid = NULL;
@@ -4561,6 +4541,9 @@ message_list_set_show_deleted (MessageList *message_list,
g_object_notify (G_OBJECT (message_list), "show-deleted");
+ /* Invalidate the thread tree. */
+ message_list_set_thread_tree (message_list, NULL);
+
/* Changing this property triggers a message list regen. */
if (message_list->frozen == 0)
mail_regen_list (message_list, message_list->search, FALSE);
@@ -5057,10 +5040,8 @@ message_list_set_search (MessageList *message_list,
if (search != NULL && message_list->search != NULL && strcmp (search, message_list->search) == 0)
return;
- if (message_list->thread_tree) {
- camel_folder_thread_messages_unref (message_list->thread_tree);
- message_list->thread_tree = NULL;
- }
+ /* Invalidate the thread tree. */
+ message_list_set_thread_tree (message_list, NULL);
if (message_list->frozen == 0)
mail_regen_list (message_list, search, FALSE);
@@ -5445,16 +5426,26 @@ message_list_regen_thread (GSimpleAsyncResult *simple,
/* update/build a new tree */
if (regen_data->group_by_threads) {
+ CamelFolderThread *thread_tree;
+
ml_sort_uids_by_tree (message_list, uids, cancellable);
- if (regen_data->thread_tree != NULL)
- camel_folder_thread_messages_apply (
- regen_data->thread_tree, uids);
+ thread_tree = message_list_ref_thread_tree (message_list);
+
+ if (thread_tree != NULL)
+ camel_folder_thread_messages_apply (thread_tree, uids);
else
- regen_data->thread_tree =
- camel_folder_thread_messages_new (
- folder, uids,
- regen_data->thread_subject);
+ thread_tree = camel_folder_thread_messages_new (
+ folder, uids, regen_data->thread_subject);
+
+ /* We will build the ETreeModel content from this
+ * CamelFolderThread during regen post-processing.
+ *
+ * We're committed at this point so keep our own
+ * reference in case the MessageList's reference
+ * gets invalidated before regen post-processing. */
+ regen_data->thread_tree = thread_tree;
+
} else {
guint ii;
@@ -5581,11 +5572,8 @@ message_list_regen_done_cb (GObject *source_object,
regen_data->thread_tree,
regen_data->folder_changed);
- if (message_list->thread_tree != NULL)
- camel_folder_thread_messages_unref (
- message_list->thread_tree);
- message_list->thread_tree = regen_data->thread_tree;
- regen_data->thread_tree = NULL;
+ message_list_set_thread_tree (
+ message_list, regen_data->thread_tree);
if (forcing_expand_state || searching) {
if (message_list->priv->folder != NULL &&
@@ -5679,14 +5667,62 @@ message_list_regen_idle_cb (gpointer user_data)
GSimpleAsyncResult *simple;
RegenData *regen_data;
GCancellable *cancellable;
+ MessageList *message_list;
+ ETreeTableAdapter *adapter;
+ gboolean searching;
+ gint row_count;
simple = G_SIMPLE_ASYNC_RESULT (user_data);
regen_data = g_simple_async_result_get_op_res_gpointer (simple);
cancellable = e_activity_get_cancellable (regen_data->activity);
- g_mutex_lock (&regen_data->message_list->priv->regen_lock);
- regen_data->message_list->priv->regen_idle_id = 0;
- g_mutex_unlock (&regen_data->message_list->priv->regen_lock);
+ message_list = regen_data->message_list;
+
+ g_mutex_lock (&message_list->priv->regen_lock);
+
+ /* Capture MessageList state to use for this regen. */
+
+ regen_data->folder =
+ message_list_ref_folder (message_list);
+ regen_data->group_by_threads =
+ message_list_get_group_by_threads (message_list);
+ regen_data->thread_subject =
+ message_list_get_thread_subject (message_list);
+
+ searching = (g_strcmp0 (message_list->search, " ") != 0);
+
+ adapter = e_tree_get_table_adapter (E_TREE (message_list));
+ row_count = e_table_model_row_count (E_TABLE_MODEL (adapter));
+
+ if (row_count <= 0) {
+ if (gtk_widget_get_visible (GTK_WIDGET (message_list))) {
+ gchar *txt;
+
+ txt = g_strdup_printf (
+ "%s...", _("Generating message list"));
+ e_tree_set_info_message (E_TREE (message_list), txt);
+ g_free (txt);
+ }
+
+ } else if (regen_data->group_by_threads &&
+ !message_list->just_set_folder &&
+ !searching) {
+ if (message_list->priv->any_row_changed) {
+ /* Something changed. If it was an expand
+ * state change, then save the expand state. */
+ message_list_save_state (message_list);
+ } else {
+ /* Remember the expand state and restore it
+ * after regen. */
+ regen_data->expand_state =
+ e_tree_table_adapter_save_expanded_state_xml (
+ adapter);
+ }
+ }
+
+ message_list->priv->regen_idle_id = 0;
+
+ g_mutex_unlock (&message_list->priv->regen_lock);
if (g_cancellable_is_cancelled (cancellable)) {
g_simple_async_result_complete (simple);
diff --git a/mail/message-list.h b/mail/message-list.h
index 187b22f4a3..c3233db6a2 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -129,9 +129,6 @@ struct _MessageList {
guint idle_id, seen_id;
gchar *frozen_search; /* to save search took place while we were frozen */
-
- /* the current camel folder thread tree, if any */
- CamelFolderThread *thread_tree;
};
struct _MessageListClass {