aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2013-06-12 23:41:06 +0800
committerMatthew Barnes <mbarnes@redhat.com>2013-06-13 07:45:56 +0800
commitbf4a06883341bb8ffefe997085d3dd71233e535f (patch)
treebe0f20244e9291172f0e607196613531fae5af3c /mail
parent1846b2911ecef37e9cc5bd5a525515c0a37ccfa8 (diff)
downloadgsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar.gz
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar.bz2
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar.lz
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar.xz
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.tar.zst
gsoc2013-evolution-bf4a06883341bb8ffefe997085d3dd71233e535f.zip
Reimplement mail_regen_list().
Reimplement the function to use an EActivity and GSimpleAsyncResult instead of the legacy async framework in mail-mt.c.
Diffstat (limited to 'mail')
-rw-r--r--mail/message-list.c1054
1 files changed, 654 insertions, 400 deletions
diff --git a/mail/message-list.c b/mail/message-list.c
index 4bf6b0cb00..adb4ff437c 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -77,6 +77,12 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), MESSAGE_LIST_TYPE, MessageListPrivate))
+/* Common search expression segments. */
+#define EXCLUDE_DELETED_MESSAGES_EXPR "(not (system-flag \"deleted\"))"
+#define EXCLUDE_JUNK_MESSAGES_EXPR "(not (system-flag \"junk\"))"
+
+typedef struct _RegenData RegenData;
+
struct _MLSelection {
GPtrArray *uids;
CamelFolder *folder;
@@ -87,13 +93,10 @@ struct _MessageListPrivate {
EMailSession *session;
- /* Outstanding regeneration requests. */
- GList *regen;
+ /* For message list regeneration. */
GMutex regen_lock;
- gchar *pending_select_uid;
- gboolean pending_select_fallback;
+ RegenData *regen_data;
guint regen_timeout_id;
- gpointer regen_timeout_msg;
struct _MLSelection clipboard;
gboolean destroyed;
@@ -111,6 +114,40 @@ struct _MessageListPrivate {
const gchar *oldest_unread_uid;
};
+struct _RegenData {
+ volatile gint ref_count;
+
+ EActivity *activity;
+ MessageList *message_list;
+
+ gchar *search;
+
+ gboolean threaded;
+ gboolean hide_deleted;
+ gboolean hide_junk;
+ gboolean thread_subject;
+ CamelFolderThread *tree;
+
+ /* This indicates we're regenerating the message list because
+ * we received a "folder-changed" signal from our CamelFolder. */
+ gboolean folder_changed;
+
+ CamelFolder *folder;
+ GPtrArray *summary;
+
+ gint last_row; /* last selected (cursor) row */
+
+ xmlDoc *expand_state; /* expanded state to be restored */
+
+ /* These may be set during a regen operation. Use the
+ * select_lock to ensure consistency and thread-safety.
+ * These are applied after the operation is finished. */
+ GMutex select_lock;
+ gchar *select_uid;
+ gboolean select_all;
+ gboolean select_use_fallback;
+};
+
enum {
PROP_0,
PROP_COPY_TARGET_LIST,
@@ -196,7 +233,7 @@ static gint on_click (ETree *tree, gint row, ETreePath path, gint col, GdkEvent
static gchar *filter_date (time_t date);
static gchar *filter_size (gint size);
-static void mail_regen_list (MessageList *ml, const gchar *search, const gchar *hideexpr, CamelFolderChangeInfo *changes, gboolean scroll_to_cursor);
+static void mail_regen_list (MessageList *ml, const gchar *search, gboolean folder_changed);
static void mail_regen_cancel (MessageList *ml);
static void clear_info (gchar *key, ETreePath *node, MessageList *ml);
@@ -249,6 +286,115 @@ static const gchar *followup_icons[] = {
"stock_mail-flag-for-followup-done"
};
+static RegenData *
+regen_data_new (MessageList *message_list,
+ GCancellable *cancellable)
+{
+ RegenData *regen_data;
+ EActivity *activity;
+ EMailSession *session;
+ GSettings *settings;
+ gboolean thread_subject;
+
+ /* FIXME This should be a MessageList property. */
+ settings = g_settings_new ("org.gnome.evolution.mail");
+ thread_subject = g_settings_get_boolean (settings, "thread-subject");
+ g_object_unref (settings);
+
+ activity = e_activity_new ();
+ e_activity_set_cancellable (activity, cancellable);
+ e_activity_set_text (activity, _("Generating message list"));
+
+ regen_data = g_slice_new0 (RegenData);
+ regen_data->ref_count = 1;
+ regen_data->activity = g_object_ref (activity);
+ 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 = g_object_ref (message_list->folder);
+ regen_data->threaded = message_list->threaded;
+ regen_data->hide_deleted = message_list->hidedeleted;
+ regen_data->hide_junk = message_list->hidejunk;
+ regen_data->thread_subject = thread_subject;
+
+ g_mutex_init (&regen_data->select_lock);
+
+ session = message_list_get_session (message_list);
+ e_mail_ui_session_add_activity (E_MAIL_UI_SESSION (session), activity);
+
+ g_object_unref (activity);
+
+ return regen_data;
+}
+
+static RegenData *
+regen_data_ref (RegenData *regen_data)
+{
+ g_return_val_if_fail (regen_data != NULL, NULL);
+ g_return_val_if_fail (regen_data->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&regen_data->ref_count);
+
+ return regen_data;
+}
+
+static void
+regen_data_unref (RegenData *regen_data)
+{
+ g_return_if_fail (regen_data != NULL);
+ g_return_if_fail (regen_data->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&regen_data->ref_count)) {
+
+ g_clear_object (&regen_data->activity);
+ g_clear_object (&regen_data->message_list);
+
+ g_free (regen_data->search);
+
+ if (regen_data->tree != NULL)
+ camel_folder_thread_messages_unref (regen_data->tree);
+
+ if (regen_data->summary != NULL) {
+ guint ii, length;
+
+ length = regen_data->summary->len;
+
+ for (ii = 0; ii < length; ii++)
+ camel_folder_free_message_info (
+ regen_data->folder,
+ regen_data->summary->pdata[ii]);
+
+ g_ptr_array_free (regen_data->summary, TRUE);
+ }
+
+ g_clear_object (&regen_data->folder);
+
+ if (regen_data->expand_state != NULL)
+ xmlFreeDoc (regen_data->expand_state);
+
+ g_mutex_clear (&regen_data->select_lock);
+ g_free (regen_data->select_uid);
+
+ g_slice_free (RegenData, regen_data);
+ }
+}
+
+static RegenData *
+message_list_ref_regen_data (MessageList *message_list)
+{
+ RegenData *regen_data = NULL;
+
+ g_mutex_lock (&message_list->priv->regen_lock);
+
+ if (message_list->priv->regen_data != NULL)
+ regen_data = regen_data_ref (message_list->priv->regen_data);
+
+ g_mutex_unlock (&message_list->priv->regen_lock);
+
+ return regen_data;
+}
+
static gint
address_compare (gconstpointer address1,
gconstpointer address2,
@@ -585,7 +731,7 @@ message_list_select_uid (MessageList *message_list,
MessageListPrivate *priv;
GHashTable *uid_nodemap;
ETreePath node = NULL;
- gboolean regen_in_progress;
+ RegenData *regen_data = NULL;
g_return_if_fail (IS_MESSAGE_LIST (message_list));
@@ -599,9 +745,7 @@ message_list_select_uid (MessageList *message_list,
if (uid != NULL)
node = g_hash_table_lookup (uid_nodemap, uid);
- regen_in_progress =
- (message_list->priv->regen != NULL) &&
- (message_list->priv->regen_timeout_id > 0);
+ regen_data = message_list_ref_regen_data (message_list);
/* If we're busy or waiting to regenerate the message list, cache
* the UID so we can try again when we're done. Otherwise if the
@@ -611,10 +755,15 @@ message_list_select_uid (MessageList *message_list,
* 1) Oldest unread message in the list, by date received.
* 2) Newest read message in the list, by date received.
*/
- if (regen_in_progress) {
- g_free (message_list->priv->pending_select_uid);
- message_list->priv->pending_select_uid = g_strdup (uid);
- message_list->priv->pending_select_fallback = with_fallback;
+ if (regen_data != NULL) {
+ g_mutex_lock (&regen_data->select_lock);
+ g_free (regen_data->select_uid);
+ regen_data->select_uid = g_strdup (uid);
+ regen_data->select_use_fallback = with_fallback;
+ g_mutex_unlock (&regen_data->select_lock);
+
+ regen_data_unref (regen_data);
+
} else if (with_fallback) {
if (node == NULL && priv->oldest_unread_uid != NULL)
node = g_hash_table_lookup (
@@ -715,18 +864,6 @@ message_list_select_prev_thread (MessageList *ml)
}
}
-static gboolean
-message_list_select_all_timeout_cb (MessageList *message_list)
-{
- ESelectionModel *etsm;
-
- etsm = e_tree_get_selection_model (E_TREE (message_list));
-
- e_selection_model_select_all (etsm);
-
- return FALSE;
-}
-
/**
* message_list_select_all:
* @message_list: Message List widget
@@ -736,25 +873,25 @@ message_list_select_all_timeout_cb (MessageList *message_list)
void
message_list_select_all (MessageList *message_list)
{
- gboolean regen_pending;
+ RegenData *regen_data = NULL;
g_return_if_fail (IS_MESSAGE_LIST (message_list));
- regen_pending = (message_list->priv->regen_timeout_id > 0);
-
- if (message_list->threaded && regen_pending) {
- /* XXX The timeout below is added so that the execution
- * thread to expand all conversation threads would
- * have completed. The timeout 505 is just to ensure
- * that the value is a small delta more than the
- * timeout value in mail_regen_list(). */
- g_timeout_add (
- 55, (GSourceFunc)
- message_list_select_all_timeout_cb,
- message_list);
- } else
- /* If there is no threading, just select all immediately. */
- message_list_select_all_timeout_cb (message_list);
+ regen_data = message_list_ref_regen_data (message_list);
+
+ if (message_list->threaded && regen_data != NULL) {
+ regen_data->select_all = TRUE;
+ } else {
+ ETree *tree;
+ ESelectionModel *selection_model;
+
+ tree = E_TREE (message_list);
+ selection_model = e_tree_get_selection_model (tree);
+ e_selection_model_select_all (selection_model);
+ }
+
+ if (regen_data != NULL)
+ regen_data_unref (regen_data);
}
typedef struct thread_select_info {
@@ -2406,7 +2543,7 @@ ml_tree_sorting_changed (ETreeTableAdapter *adapter,
ml->thread_tree = NULL;
}
- mail_regen_list (ml, ml->search, NULL, NULL, TRUE);
+ mail_regen_list (ml, ml->search, FALSE);
return TRUE;
}
@@ -2438,9 +2575,6 @@ message_list_init (MessageList *message_list)
(GDestroyNotify) NULL,
(GDestroyNotify) e_poolv_destroy);
- message_list->search = NULL;
- message_list->ensure_uid = NULL;
-
message_list->uid_nodemap = g_hash_table_new (g_str_hash, g_str_equal);
message_list->cursor_uid = NULL;
@@ -2601,11 +2735,6 @@ message_list_finalize (GObject *object)
g_hash_table_destroy (message_list->normalised_hash);
- if (message_list->ensure_uid) {
- g_free (message_list->ensure_uid);
- message_list->ensure_uid = NULL;
- }
-
if (message_list->thread_tree)
camel_folder_thread_messages_unref (message_list->thread_tree);
@@ -3099,8 +3228,7 @@ static void build_subtree_diff (MessageList *ml, ETreePath parent, ETreePath pat
static void
build_tree (MessageList *ml,
CamelFolderThread *thread,
- CamelFolderChangeInfo *changes,
- gboolean can_scroll_to_cursor)
+ gboolean folder_changed)
{
gint row = 0;
ETreeModel *etm = ml->model;
@@ -3135,7 +3263,9 @@ build_tree (MessageList *ml,
build_subtree (ml, ml->tree_root, thread->tree, &row);
- if (!can_scroll_to_cursor && table_item)
+ /* Show the cursor unless we're responding to a
+ * "folder-changed" signal from our CamelFolder. */
+ if (folder_changed && table_item != NULL)
table_item->queue_show_cursor = FALSE;
e_tree_memory_thaw (E_TREE_MEMORY (etm));
@@ -3146,7 +3276,9 @@ build_tree (MessageList *ml,
message_list_set_selected (ml, selected);
em_utils_uids_free (selected);
- if (!can_scroll_to_cursor && table_item)
+ /* Show the cursor unless we're responding to a
+ * "folder-changed" signal from our CamelFolder. */
+ if (folder_changed && table_item != NULL)
table_item->queue_show_cursor = FALSE;
e_tree_memory_thaw (E_TREE_MEMORY (etm));
@@ -3176,7 +3308,9 @@ build_tree (MessageList *ml,
e_tree_set_cursor (E_TREE (ml), node);
- if (!can_scroll_to_cursor && table_item)
+ /* Show the cursor unless we're responding to a
+ * "folder-changed" signal from our CamelFolder. */
+ if (folder_changed && table_item != NULL)
table_item->queue_show_cursor = FALSE;
e_tree_memory_thaw (E_TREE_MEMORY (etm));
@@ -3398,8 +3532,7 @@ build_subtree_diff (MessageList *ml,
static void
build_flat (MessageList *ml,
- GPtrArray *summary,
- CamelFolderChangeInfo *changes)
+ GPtrArray *summary)
{
ETreeModel *etm = ml->model;
gchar *saveuid = NULL;
@@ -3523,13 +3656,14 @@ folder_changed (CamelFolder *folder,
MessageList *ml)
{
CamelFolderChangeInfo *altered_changes = NULL;
+ gboolean need_list_regen = TRUE;
gint i;
if (ml->priv->destroyed)
return;
d (printf ("folder changed event, changes = %p\n", changes));
- if (changes) {
+ if (changes != NULL) {
for (i = 0; i < changes->uid_removed->len; i++)
g_hash_table_remove (
ml->normalised_hash,
@@ -3557,15 +3691,17 @@ folder_changed (CamelFolder *folder,
}
}
- camel_folder_change_info_free (altered_changes);
-
g_signal_emit (ml, message_list_signals[MESSAGE_LIST_BUILT], 0);
- return;
+
+ need_list_regen = FALSE;
}
}
- /* XXX This apparently eats the ChangeFolderChangeInfo. */
- mail_regen_list (ml, ml->search, NULL, altered_changes, FALSE);
+ if (need_list_regen)
+ mail_regen_list (ml, ml->search, TRUE);
+
+ if (altered_changes != NULL)
+ camel_folder_change_info_free (altered_changes);
}
/**
@@ -3700,7 +3836,7 @@ message_list_set_folder (MessageList *message_list,
!(folder->folder_flags & CAMEL_FOLDER_IS_TRASH);
if (message_list->frozen == 0)
- mail_regen_list (message_list, message_list->search, NULL, NULL, TRUE);
+ mail_regen_list (message_list, message_list->search, FALSE);
}
}
@@ -4097,7 +4233,15 @@ message_list_thaw (MessageList *ml)
ml->frozen--;
if (ml->frozen == 0) {
- mail_regen_list (ml, ml->frozen_search ? ml->frozen_search : ml->search, NULL, NULL, TRUE);
+ const gchar *search;
+
+ if (ml->frozen_search != NULL)
+ search = ml->frozen_search;
+ else
+ search = ml->search;
+
+ mail_regen_list (ml, search, FALSE);
+
g_free (ml->frozen_search);
ml->frozen_search = NULL;
}
@@ -4111,7 +4255,7 @@ message_list_set_threaded_expand_all (MessageList *ml)
ml->expand_all = 1;
if (ml->frozen == 0)
- mail_regen_list (ml, ml->search, NULL, NULL, TRUE);
+ mail_regen_list (ml, ml->search, FALSE);
}
}
@@ -4122,7 +4266,7 @@ message_list_set_threaded_collapse_all (MessageList *ml)
ml->collapse_all = 1;
if (ml->frozen == 0)
- mail_regen_list (ml, ml->search, NULL, NULL, TRUE);
+ mail_regen_list (ml, ml->search, FALSE);
}
}
@@ -4134,7 +4278,7 @@ message_list_set_threaded (MessageList *ml,
ml->threaded = threaded;
if (ml->frozen == 0)
- mail_regen_list (ml, ml->search, NULL, NULL, TRUE);
+ mail_regen_list (ml, ml->search, FALSE);
}
}
@@ -4146,7 +4290,7 @@ message_list_set_hidedeleted (MessageList *ml,
ml->hidedeleted = hidedeleted;
if (ml->frozen == 0)
- mail_regen_list (ml, ml->search, NULL, NULL, TRUE);
+ mail_regen_list (ml, ml->search, FALSE);
}
}
@@ -4167,7 +4311,7 @@ message_list_set_search (MessageList *ml,
}
if (ml->frozen == 0)
- mail_regen_list (ml, search, NULL, NULL, TRUE);
+ mail_regen_list (ml, search, FALSE);
else {
g_free (ml->frozen_search);
ml->frozen_search = g_strdup (search);
@@ -4380,456 +4524,566 @@ ml_sort_uids_by_tree (MessageList *ml,
g_object_unref (sort_data.folder);
}
-/* ** REGENERATE MESSAGELIST ********************************************** */
-struct _regen_list_msg {
- MailMsg base;
+static void
+message_list_regen_tweak_search_results (MessageList *message_list,
+ GPtrArray *search_results,
+ CamelFolder *folder,
+ gboolean folder_changed,
+ gboolean show_deleted,
+ gboolean show_junk)
+{
+ CamelMessageInfo *info;
+ CamelMessageFlags flags;
+ const gchar *uid;
+ gboolean needs_tweaking;
+ gboolean uid_is_deleted;
+ gboolean uid_is_junk;
+ gboolean add_uid;
+ guint ii;
+
+ /* If we're responding to a "folder-changed" signal, then the
+ * displayed message may not be included in the search results.
+ * Include the displayed message anyway so it doesn't suddenly
+ * disappear while the user is reading it. */
+ needs_tweaking =
+ (message_list->ensure_uid != NULL) ||
+ (folder_changed && message_list->cursor_uid != NULL);
+
+ if (!needs_tweaking)
+ return;
- gint complete;
+ if (message_list->ensure_uid != NULL)
+ uid = message_list->ensure_uid;
+ else
+ uid = message_list->cursor_uid;
- MessageList *ml;
- gchar *search;
- gchar *hideexpr;
- CamelFolderChangeInfo *changes;
- gboolean dotree; /* we are building a tree */
- gboolean hidedel; /* we want to/dont want to show deleted messages */
- gboolean hidejunk; /* we want to/dont want to show junk messages */
- gboolean thread_subject;
- gboolean scroll_to_cursor; /* whether ensure scrolling to the cursor after rebuild */
- CamelFolderThread *tree;
+ g_return_if_fail (uid != NULL);
- CamelFolder *folder;
- GPtrArray *summary;
+ /* Scan the search results for a particular UID.
+ * If found then the results don't need tweaked. */
+ for (ii = 0; ii < search_results->len; ii++) {
+ if (g_str_equal (uid, search_results->pdata[ii]))
+ return;
+ }
- gint last_row; /* last selected (cursor) row */
+ info = camel_folder_get_message_info (folder, uid);
- xmlDoc *expand_state; /* stored expanded state of the previous view */
-};
+ /* XXX Should we emit a runtime warning here? */
+ if (info == NULL)
+ return;
-/*
- * maintain copy of summary
- *
- * any new messages added
- * any removed removed, etc.
- *
- * use vfolder to implement searches ???
- */
+ flags = camel_message_info_flags (info);
+ uid_is_deleted = ((flags & CAMEL_MESSAGE_DELETED) != 0);
+ uid_is_junk = ((flags & CAMEL_MESSAGE_JUNK) != 0);
-static gchar *
-regen_list_desc (struct _regen_list_msg *m)
-{
- return g_strdup (_("Generating message list"));
+ if (!folder_store_supports_vjunk_folder (folder))
+ uid_is_junk = FALSE;
+
+ add_uid =
+ (!uid_is_junk || show_junk) &&
+ (!uid_is_deleted || show_deleted);
+
+ if (add_uid)
+ g_ptr_array_add (
+ search_results,
+ (gpointer) camel_pstring_strdup (uid));
+
+ camel_folder_free_message_info (folder, info);
}
static void
-regen_list_exec (struct _regen_list_msg *m,
- GCancellable *cancellable,
- GError **error)
+message_list_regen_thread (GSimpleAsyncResult *simple,
+ GObject *source_object,
+ GCancellable *cancellable)
{
+ MessageList *message_list;
+ RegenData *regen_data;
GPtrArray *uids, *searchuids = NULL;
CamelMessageInfo *info;
ETreePath cursor;
ETree *tree;
- gint i;
- gchar *expr = NULL;
+ GString *expr;
GError *local_error = NULL;
- if (m->folder != m->ml->folder)
+ message_list = MESSAGE_LIST (source_object);
+ regen_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_cancellable_is_cancelled (cancellable))
return;
- tree = E_TREE (m->ml);
+ tree = E_TREE (message_list);
cursor = e_tree_get_cursor (tree);
- if (cursor)
- m->last_row = e_tree_table_adapter_row_of_node (e_tree_get_table_adapter (tree), cursor);
-
- /* if we have hidedeleted on, use a search to find it out, merge with existing search if set */
- if (m->hidedel) {
- if (m->hidejunk) {
- if (m->search) {
- expr = g_alloca (strlen (m->search) + 92);
- sprintf (expr, "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))\n %s)", m->search);
- } else
- expr = (gchar *) "(match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))";
+ if (cursor != NULL)
+ regen_data->last_row =
+ e_tree_table_adapter_row_of_node (
+ e_tree_get_table_adapter (tree), cursor);
+
+ /* Construct the search expression. */
+
+ expr = g_string_new ("");
+
+ if (regen_data->hide_deleted && regen_data->hide_junk) {
+ g_string_append_printf (
+ expr, "(match-all (and %s %s))",
+ EXCLUDE_DELETED_MESSAGES_EXPR,
+ EXCLUDE_JUNK_MESSAGES_EXPR);
+ } else if (regen_data->hide_deleted) {
+ g_string_append_printf (
+ expr, "(match-all %s)",
+ EXCLUDE_DELETED_MESSAGES_EXPR);
+ } else if (regen_data->hide_junk) {
+ g_string_append_printf (
+ expr, "(match-all %s)",
+ EXCLUDE_JUNK_MESSAGES_EXPR);
+ }
+
+ if (regen_data->search != NULL) {
+ if (expr->len == 0) {
+ g_string_assign (expr, regen_data->search);
} else {
- if (m->search) {
- expr = g_alloca (strlen (m->search) + 64);
- sprintf (expr, "(and (match-all (not (system-flag \"deleted\")))\n %s)", m->search);
- } else
- expr = (gchar *) "(match-all (not (system-flag \"deleted\")))";
- }
- } else {
- if (m->hidejunk) {
- if (m->search) {
- expr = g_alloca (strlen (m->search) + 64);
- sprintf (expr, "(and (match-all (not (system-flag \"junk\")))\n %s)", m->search);
- } else
- expr = (gchar *) "(match-all (not (system-flag \"junk\")))";
- } else {
- expr = m->search;
+ g_string_prepend (expr, "(and ");
+ g_string_append_c (expr, ' ');
+ g_string_append (expr, regen_data->search);
+ g_string_append_c (expr, ')');
}
}
- if (expr == NULL) {
- uids = camel_folder_get_uids (m->folder);
+ /* Execute the search. */
+
+ if (expr->len == 0) {
+ uids = camel_folder_get_uids (regen_data->folder);
} else {
- gboolean store_has_vjunk = folder_store_supports_vjunk_folder (m->folder);
-
- searchuids = uids = camel_folder_search_by_expression (
- m->folder, expr, cancellable, &local_error);
- /* If m->changes is not NULL, then it means we are called from folder_changed event,
- * thus we will keep the selected message to be sure it doesn't disappear because
- * it no longer belong to our search filter. */
- if (uids && ((m->changes && m->ml->cursor_uid) || m->ml->ensure_uid)) {
- const gchar *looking_for = m->ml->cursor_uid;
- /* ensure_uid has precedence of cursor_uid */
- if (m->ml->ensure_uid)
- looking_for = m->ml->ensure_uid;
-
- for (i = 0; i < uids->len; i++) {
- if (g_str_equal (looking_for, uids->pdata[i]))
- break;
- }
+ uids = camel_folder_search_by_expression (
+ regen_data->folder, expr->str,
+ cancellable, &local_error);
- /* cursor_uid has been filtered out */
- if (i == uids->len) {
- CamelMessageInfo *looking_info = camel_folder_get_message_info (m->folder, looking_for);
+ /* XXX This indicates we need to use a different
+ * "free UID" function for some dumb reason. */
+ searchuids = uids;
- if (looking_info) {
- gboolean is_deleted = (camel_message_info_flags (looking_info) & CAMEL_MESSAGE_DELETED) != 0;
- gboolean is_junk = store_has_vjunk && (camel_message_info_flags (looking_info) & CAMEL_MESSAGE_JUNK) != 0;
+ if (uids != NULL)
+ message_list_regen_tweak_search_results (
+ message_list, uids,
+ regen_data->folder,
+ regen_data->folder_changed,
+ !regen_data->hide_deleted,
+ !regen_data->hide_junk);
+ }
- /* I would really like to check for CAMEL_MESSAGE_FOLDER_FLAGGED on a message,
- * so I would know whether it was changed locally, and then just check the changes
- * struct whether change came from the server, but with periodical save it doesn't
- * matter. So here just check whether the file was deleted and we show it based
- * on the flag whether we can view deleted messages or not. */
+ g_string_free (expr, TRUE);
- if ((!is_deleted || (is_deleted && !m->hidedel)) && (!is_junk || (is_junk && !m->hidejunk)))
- g_ptr_array_add (uids, (gpointer) camel_pstring_strdup (looking_for));
+ /* Handle search error or cancellation. */
- camel_folder_free_message_info (m->folder, looking_info);
- }
- }
- }
- }
+ if (local_error == NULL)
+ g_cancellable_set_error_if_cancelled (
+ cancellable, &local_error);
if (local_error != NULL) {
- g_propagate_error (error, local_error);
- return;
+ g_simple_async_result_take_error (simple, local_error);
+ goto exit;
}
- /* camel_folder_summary_prepare_fetch_all (m->folder->summary, NULL); */
- if (!g_cancellable_is_cancelled (cancellable) && uids) {
- /* update/build a new tree */
- if (m->dotree) {
- ml_sort_uids_by_tree (m->ml, uids, cancellable);
+ /* XXX This check might not be necessary. A successfully completed
+ * search with no results should return an empty UID array, but
+ * still need to verify that. */
+ if (uids == NULL)
+ goto exit;
- if (m->tree)
- camel_folder_thread_messages_apply (m->tree, uids);
- else
- m->tree = camel_folder_thread_messages_new (m->folder, uids, m->thread_subject);
- } else {
- camel_folder_sort_uids (m->ml->folder, uids);
- m->summary = g_ptr_array_new ();
+ /* update/build a new tree */
+ if (regen_data->threaded) {
+ ml_sort_uids_by_tree (message_list, uids, cancellable);
+
+ if (regen_data->tree != NULL)
+ camel_folder_thread_messages_apply (
+ regen_data->tree, uids);
+ else
+ regen_data->tree = camel_folder_thread_messages_new (
+ regen_data->folder, uids,
+ regen_data->thread_subject);
+ } else {
+ guint ii;
- camel_folder_summary_prepare_fetch_all (
- m->folder->summary, NULL);
+ camel_folder_sort_uids (regen_data->folder, uids);
+ regen_data->summary = g_ptr_array_new ();
- for (i = 0; i < uids->len; i++) {
- info = camel_folder_get_message_info (m->folder, uids->pdata[i]);
- if (info)
- g_ptr_array_add (m->summary, info);
- }
- }
+ camel_folder_summary_prepare_fetch_all (
+ regen_data->folder->summary, NULL);
- m->complete = TRUE;
+ for (ii = 0; ii < uids->len; ii++) {
+ info = camel_folder_get_message_info (
+ regen_data->folder, uids->pdata[ii]);
+ if (info != NULL)
+ g_ptr_array_add (regen_data->summary, info);
+ }
}
- if (searchuids)
- camel_folder_search_free (m->folder, searchuids);
- else
- camel_folder_free_uids (m->folder, uids);
+exit:
+ if (searchuids != NULL)
+ camel_folder_search_free (regen_data->folder, searchuids);
+ else if (uids != NULL)
+ camel_folder_free_uids (regen_data->folder, uids);
}
static void
-regen_list_done (struct _regen_list_msg *m)
+message_list_regen_done_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
+ MessageList *message_list;
+ GSimpleAsyncResult *simple;
+ RegenData *regen_data;
+ EActivity *activity;
ETree *tree;
- GCancellable *cancellable;
+ ETreeTableAdapter *adapter;
gboolean searching;
+ GError *local_error = NULL;
- cancellable = m->base.cancellable;
+ message_list = MESSAGE_LIST (source_object);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
- if (m->ml->priv->destroyed)
- return;
+ /* Steal the MessageList's RegenData pointer.
+ * We should have exclusive access to it now. */
+ g_mutex_lock (&message_list->priv->regen_lock);
+ regen_data = message_list->priv->regen_data;
+ message_list->priv->regen_data = NULL;
+ g_mutex_unlock (&message_list->priv->regen_lock);
- if (!m->complete)
- return;
+ g_return_if_fail (regen_data != NULL);
- if (g_cancellable_is_cancelled (cancellable))
- return;
+ activity = regen_data->activity;
- if (m->ml->folder != m->folder)
- return;
+ g_simple_async_result_propagate_error (simple, &local_error);
- tree = E_TREE (m->ml);
+ if (e_activity_handle_cancellation (activity, local_error)) {
+ g_error_free (local_error);
+ goto exit;
- if (m->scroll_to_cursor)
- e_tree_show_cursor_after_reflow (tree);
+ /* FIXME This should be handed off to an EAlertSink. */
+ } else if (local_error != NULL) {
+ g_warning ("%s: %s", G_STRFUNC, local_error->message);
+ g_error_free (local_error);
+ goto exit;
+ }
- g_signal_handlers_block_by_func (e_tree_get_table_adapter (tree), ml_tree_sorting_changed, m->ml);
+ e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
- if (m->ml->search && m->ml->search != m->search)
- g_free (m->ml->search);
- m->ml->search = m->search;
- m->search = NULL;
+ tree = E_TREE (message_list);
+ adapter = e_tree_get_table_adapter (tree);
- searching = m->ml->search && *m->ml->search;
+ /* Show the cursor unless we're responding to a
+ * "folder-changed" signal from our CamelFolder. */
+ if (!regen_data->folder_changed)
+ e_tree_show_cursor_after_reflow (tree);
- if (m->dotree) {
- gboolean forcing_expand_state = m->ml->expand_all || m->ml->collapse_all;
+ g_signal_handlers_block_by_func (
+ adapter, ml_tree_sorting_changed, message_list);
- if (m->ml->just_set_folder) {
- m->ml->just_set_folder = FALSE;
- if (m->expand_state) {
- /* rather load state from disk than use the memory data when changing folders */
- xmlFreeDoc (m->expand_state);
- m->expand_state = NULL;
+ g_free (message_list->search);
+ message_list->search = g_strdup (regen_data->search);
+
+ searching =
+ (message_list->search != NULL) &&
+ (*message_list->search != '\0');
+
+ if (regen_data->threaded) {
+ gboolean forcing_expand_state;
+
+ forcing_expand_state =
+ message_list->expand_all ||
+ message_list->collapse_all;
+
+ if (message_list->just_set_folder) {
+ message_list->just_set_folder = FALSE;
+ if (regen_data->expand_state != NULL) {
+ /* Load state from disk rather than use
+ * the memory data when changing folders. */
+ xmlFreeDoc (regen_data->expand_state);
+ regen_data->expand_state = NULL;
}
}
- if (forcing_expand_state || searching)
- e_tree_force_expanded_state (tree, (m->ml->expand_all || searching) ? 1 : -1);
+ if (forcing_expand_state || searching) {
+ if (message_list->expand_all || searching)
+ e_tree_force_expanded_state (tree, 1);
+ else
+ e_tree_force_expanded_state (tree, -1);
+ }
+
+ /* Show the cursor unless we're responding to a
+ * "folder-changed" signal from our CamelFolder. */
+ build_tree (
+ message_list,
+ regen_data->tree,
+ regen_data->folder_changed);
- build_tree (m->ml, m->tree, m->changes, m->scroll_to_cursor);
- if (m->ml->thread_tree)
- camel_folder_thread_messages_unref (m->ml->thread_tree);
- m->ml->thread_tree = m->tree;
- m->tree = NULL;
+ if (message_list->thread_tree != NULL)
+ camel_folder_thread_messages_unref (
+ message_list->thread_tree);
+ message_list->thread_tree = regen_data->tree;
+ regen_data->tree = NULL;
if (forcing_expand_state || searching) {
- if (m->ml->folder != NULL && tree != NULL && !searching)
- save_tree_state (m->ml);
+ if (message_list->folder != NULL && tree != NULL && !searching)
+ save_tree_state (message_list);
/* do not forget to set this back to use the default value... */
e_tree_force_expanded_state (tree, 0);
- } else
- load_tree_state (m->ml, m->expand_state);
+ } else {
+ load_tree_state (
+ message_list, regen_data->expand_state);
+ }
- m->ml->expand_all = 0;
- m->ml->collapse_all = 0;
- } else
- build_flat (m->ml, m->summary, m->changes);
+ message_list->expand_all = 0;
+ message_list->collapse_all = 0;
+ } else {
+ build_flat (
+ message_list,
+ regen_data->summary);
+ }
- g_mutex_lock (&m->ml->priv->regen_lock);
- m->ml->priv->regen = g_list_remove (m->ml->priv->regen, m);
- g_mutex_unlock (&m->ml->priv->regen_lock);
+ if (regen_data->select_all) {
+ message_list_select_all (message_list);
- if (m->ml->priv->regen == NULL && m->ml->priv->pending_select_uid != NULL) {
- gchar *uid;
- gboolean with_fallback;
+ } else if (regen_data->select_uid != NULL) {
+ message_list_select_uid (
+ message_list,
+ regen_data->select_uid,
+ regen_data->select_use_fallback);
+
+ } else if (message_list->cursor_uid == NULL && regen_data->last_row != -1) {
+ gint row_count;
- uid = m->ml->priv->pending_select_uid;
- m->ml->priv->pending_select_uid = NULL;
- with_fallback = m->ml->priv->pending_select_fallback;
- message_list_select_uid (m->ml, uid, with_fallback);
- g_free (uid);
- } else if (m->ml->priv->regen == NULL && m->ml->cursor_uid == NULL && m->last_row != -1) {
- ETreeTableAdapter *etta = e_tree_get_table_adapter (tree);
+ row_count = e_table_model_row_count (E_TABLE_MODEL (adapter));
- if (m->last_row >= e_table_model_row_count (E_TABLE_MODEL (etta)))
- m->last_row = e_table_model_row_count (E_TABLE_MODEL (etta)) - 1;
+ if (regen_data->last_row >= row_count)
+ regen_data->last_row = row_count;
- if (m->last_row >= 0) {
+ if (regen_data->last_row >= 0) {
ETreePath path;
- path = e_tree_table_adapter_node_at_row (etta, m->last_row);
- if (path)
- select_path (m->ml, path);
+ path = e_tree_table_adapter_node_at_row (
+ adapter, regen_data->last_row);
+ if (path != NULL)
+ select_path (message_list, path);
}
}
- if (gtk_widget_get_visible (GTK_WIDGET (m->ml))) {
- if (e_tree_row_count (E_TREE (m->ml)) <= 0) {
- /* space is used to indicate no search too */
- if (m->ml->search && *m->ml->search && strcmp (m->ml->search, " ") != 0)
- e_tree_set_info_message (tree, _("No message satisfies your search criteria. "
- "Change search criteria by selecting a new Show message filter from "
- "the drop down list above or by running a new search either by clearing "
- "it with Search->Clear menu item or by changing the query above."));
- else
- e_tree_set_info_message (tree, _("There are no messages in this folder."));
- } else
- e_tree_set_info_message (tree, NULL);
- }
-
- g_signal_handlers_unblock_by_func (e_tree_get_table_adapter (tree), ml_tree_sorting_changed, m->ml);
-
- g_signal_emit (m->ml, message_list_signals[MESSAGE_LIST_BUILT], 0);
- m->ml->priv->any_row_changed = FALSE;
-}
-
-static void
-regen_list_free (struct _regen_list_msg *m)
-{
- gint i;
+ if (gtk_widget_get_visible (GTK_WIDGET (message_list))) {
+ const gchar *info_message;
+ gboolean have_search_expr;
+
+ /* space is used to indicate no search too */
+ have_search_expr =
+ (message_list->search != NULL) &&
+ (*message_list->search != '\0') &&
+ (strcmp (message_list->search, " ") != 0);
+
+ if (e_tree_row_count (E_TREE (tree)) > 0) {
+ info_message = NULL;
+ } else if (have_search_expr) {
+ info_message =
+ _("No message satisfies your search criteria. "
+ "Change search criteria by selecting a new "
+ "Show message filter from the drop down list "
+ "above or by running a new search either by "
+ "clearing it with Search->Clear menu item or "
+ "by changing the query above.");
+ } else {
+ info_message =
+ _("There are no messages in this folder.");
+ }
- if (m->summary) {
- for (i = 0; i < m->summary->len; i++)
- camel_folder_free_message_info (m->folder, m->summary->pdata[i]);
- g_ptr_array_free (m->summary, TRUE);
+ e_tree_set_info_message (tree, info_message);
}
- if (m->tree)
- camel_folder_thread_messages_unref (m->tree);
+ g_signal_handlers_unblock_by_func (
+ adapter, ml_tree_sorting_changed, message_list);
- g_free (m->search);
- g_free (m->hideexpr);
+ g_signal_emit (
+ message_list,
+ message_list_signals[MESSAGE_LIST_BUILT], 0);
- g_object_unref (m->folder);
-
- if (m->changes)
- camel_folder_change_info_free (m->changes);
-
- /* we have to poke this here as well since we might've been cancelled and regened wont get called */
- g_mutex_lock (&m->ml->priv->regen_lock);
- m->ml->priv->regen = g_list_remove (m->ml->priv->regen, m);
- g_mutex_unlock (&m->ml->priv->regen_lock);
-
- if (m->expand_state)
- xmlFreeDoc (m->expand_state);
+ message_list->priv->any_row_changed = FALSE;
- g_object_unref (m->ml);
+exit:
+ regen_data_unref (regen_data);
}
-static MailMsgInfo regen_list_info = {
- sizeof (struct _regen_list_msg),
- (MailMsgDescFunc) regen_list_desc,
- (MailMsgExecFunc) regen_list_exec,
- (MailMsgDoneFunc) regen_list_done,
- (MailMsgFreeFunc) regen_list_free
-};
-
static gboolean
-ml_regen_timeout (struct _regen_list_msg *m)
+message_list_regen_timeout_cb (gpointer user_data)
{
- g_mutex_lock (&m->ml->priv->regen_lock);
- m->ml->priv->regen = g_list_prepend (m->ml->priv->regen, m);
- g_mutex_unlock (&m->ml->priv->regen_lock);
- /* TODO: we should manage our own thread stuff, would make cancelling outstanding stuff easier */
- mail_msg_fast_ordered_push (m);
+ GSimpleAsyncResult *simple;
+ RegenData *regen_data;
+ GCancellable *cancellable;
- m->ml->priv->regen_timeout_msg = NULL;
- m->ml->priv->regen_timeout_id = 0;
+ 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_timeout_id = 0;
+ g_mutex_unlock (&regen_data->message_list->priv->regen_lock);
+
+ if (g_cancellable_is_cancelled (cancellable)) {
+ g_simple_async_result_complete (simple);
+ } else {
+ g_simple_async_result_run_in_thread (
+ simple,
+ message_list_regen_thread,
+ G_PRIORITY_DEFAULT,
+ cancellable);
+ }
return FALSE;
}
static void
-mail_regen_cancel (MessageList *ml)
+mail_regen_cancel (MessageList *message_list)
{
- /* cancel any outstanding regeneration requests, not we don't clear, they clear themselves */
- if (ml->priv->regen != NULL) {
- GList *link;
+ RegenData *regen_data = NULL;
- g_mutex_lock (&ml->priv->regen_lock);
+ g_mutex_lock (&message_list->priv->regen_lock);
- for (link = ml->priv->regen; link != NULL; link = link->next) {
- MailMsg *mm = link->data;
- GCancellable *cancellable;
+ if (message_list->priv->regen_data != NULL)
+ regen_data = regen_data_ref (message_list->priv->regen_data);
- cancellable = mm->cancellable;
- g_cancellable_cancel (cancellable);
- }
-
- g_mutex_unlock (&ml->priv->regen_lock);
+ if (message_list->priv->regen_timeout_id > 0) {
+ g_source_remove (message_list->priv->regen_timeout_id);
+ message_list->priv->regen_timeout_id = 0;
}
- /* including unqueued ones */
- if (ml->priv->regen_timeout_id) {
- g_source_remove (ml->priv->regen_timeout_id);
- ml->priv->regen_timeout_id = 0;
- mail_msg_unref (ml->priv->regen_timeout_msg);
- ml->priv->regen_timeout_msg = NULL;
+ g_mutex_unlock (&message_list->priv->regen_lock);
+
+ /* Cancel outside the lock, since this will emit a signal. */
+ if (regen_data != NULL) {
+ e_activity_cancel (regen_data->activity);
+ regen_data_unref (regen_data);
}
}
static void
-mail_regen_list (MessageList *ml,
+mail_regen_list (MessageList *message_list,
const gchar *search,
- const gchar *hideexpr,
- CamelFolderChangeInfo *changes,
- gboolean scroll_to_cursor)
+ gboolean folder_changed)
{
- struct _regen_list_msg *m;
- GSettings *settings;
- gboolean thread_subject;
+ GSimpleAsyncResult *simple;
+ GCancellable *cancellable;
+ RegenData *new_regen_data;
+ RegenData *old_regen_data;
gboolean searching;
- /* report empty search as NULL, not as one/two-space string */
+ /* Report empty search as NULL, not as one/two-space string. */
if (search && (strcmp (search, " ") == 0 || strcmp (search, " ") == 0))
search = NULL;
- if (ml->folder == NULL) {
- if (ml->search != search) {
- g_free (ml->search);
- ml->search = g_strdup (search);
- }
+ /* Can't list messages in a folder until we have a folder. */
+ if (message_list->folder == NULL) {
+ g_free (message_list->search);
+ message_list->search = g_strdup (search);
return;
}
- mail_regen_cancel (ml);
+ cancellable = g_cancellable_new ();
- settings = g_settings_new ("org.gnome.evolution.mail");
- thread_subject = g_settings_get_boolean (settings, "thread-subject");
- g_object_unref (settings);
+ new_regen_data = regen_data_new (message_list, cancellable);
+ new_regen_data->search = g_strdup (search);
+ new_regen_data->folder_changed = folder_changed;
- m = mail_msg_new (&regen_list_info);
- m->ml = g_object_ref (ml);
- m->search = g_strdup (search);
- m->hideexpr = g_strdup (hideexpr);
- m->changes = changes;
- m->dotree = ml->threaded;
- m->hidedel = ml->hidedeleted;
- m->hidejunk = ml->hidejunk;
- m->thread_subject = thread_subject;
- m->scroll_to_cursor = scroll_to_cursor;
- m->folder = g_object_ref (ml->folder);
- m->last_row = -1;
- m->expand_state = NULL;
+ if (message_list->thread_tree != NULL) {
+ CamelFolderThread *thread_tree;
- if ((!m->hidedel || !m->dotree) && ml->thread_tree) {
- camel_folder_thread_messages_unref (ml->thread_tree);
- ml->thread_tree = NULL;
- } else if (ml->thread_tree) {
- m->tree = ml->thread_tree;
- camel_folder_thread_messages_ref (m->tree);
- }
+ thread_tree = message_list->thread_tree;
- searching = ml->search && *ml->search && !g_str_equal (ml->search, " ");
+ if (message_list->threaded && message_list->hidedeleted) {
+ new_regen_data->tree = thread_tree;
+ camel_folder_thread_messages_ref (thread_tree);
+ } else {
+ camel_folder_thread_messages_unref (thread_tree);
+ message_list->thread_tree = NULL;
+ }
+ }
- if (e_tree_row_count (E_TREE (ml)) <= 0) {
- if (gtk_widget_get_visible (GTK_WIDGET (ml))) {
- /* there is some info why the message list is empty, let it be something useful */
- gchar *txt = g_strconcat (_("Generating message list"), "..." , NULL);
+ searching = (g_strcmp0 (message_list->search, " ") != 0);
- e_tree_set_info_message (E_TREE (m->ml), txt);
+ if (e_tree_row_count (E_TREE (message_list)) <= 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 (ml->priv->any_row_changed && m->dotree && !ml->just_set_folder && !searching) {
- /* there has been some change on any row, if it was an expand state change,
- * then let it save; if not, then nothing happen. */
- message_list_save_state (ml);
- } else if (m->dotree && !ml->just_set_folder && !searching) {
- /* remember actual expand state and restore it after regen */
- m->expand_state = e_tree_save_expanded_state_xml (E_TREE (ml));
- }
-
- /* if we're busy already kick off timeout processing, so normal updates are immediate */
- if (ml->priv->regen == NULL)
- ml_regen_timeout (m);
- else {
- ml->priv->regen_timeout_msg = m;
- ml->priv->regen_timeout_id = g_timeout_add (
- 50, (GSourceFunc) ml_regen_timeout, m);
+ } else if (message_list->priv->any_row_changed &&
+ message_list->threaded &&
+ !message_list->just_set_folder &&
+ !searching) {
+ /* Something changed. If it was an expand
+ * state change, then save the expand state. */
+ message_list_save_state (message_list);
+ } else if (message_list->threaded &&
+ !message_list->just_set_folder &&
+ !searching) {
+ /* Remember the expand state and restore it after regen. */
+ new_regen_data->expand_state =
+ e_tree_save_expanded_state_xml (E_TREE (message_list));
+ }
+
+ /* We generate the message list content in a worker thread, and
+ * then supply our own GAsyncReadyCallback to redraw the widget. */
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (message_list),
+ message_list_regen_done_cb,
+ NULL, mail_regen_list);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple,
+ regen_data_ref (new_regen_data),
+ (GDestroyNotify) regen_data_unref);
+
+ /* Swap the old regen data (if present) for the new regen data. */
+
+ g_mutex_lock (&message_list->priv->regen_lock);
+
+ old_regen_data = message_list->priv->regen_data;
+ message_list->priv->regen_data = regen_data_ref (new_regen_data);
+
+ if (message_list->priv->regen_timeout_id > 0) {
+ g_source_remove (message_list->priv->regen_timeout_id);
+ message_list->priv->regen_timeout_id = 0;
+ }
+
+ /* Start the regen after a short timeout, so normal updates
+ * are immediate. XXX Do we still need to do this timeout?
+ * What are "normal" updates? */
+ if (old_regen_data != NULL) {
+ message_list->priv->regen_timeout_id =
+ g_timeout_add_full (
+ G_PRIORITY_DEFAULT, 50,
+ message_list_regen_timeout_cb,
+ g_object_ref (simple),
+ (GDestroyNotify) g_object_unref);
+ } else {
+ g_simple_async_result_run_in_thread (
+ simple,
+ message_list_regen_thread,
+ G_PRIORITY_DEFAULT,
+ cancellable);
+ }
+
+ g_mutex_unlock (&message_list->priv->regen_lock);
+
+ /* Cancel outside the lock, since this will emit a signal. */
+ if (old_regen_data != NULL) {
+ e_activity_cancel (old_regen_data->activity);
+ regen_data_unref (old_regen_data);
}
+
+ g_object_unref (simple);
+
+ regen_data_unref (new_regen_data);
+
+ g_object_unref (cancellable);
}