aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2013-06-17 22:18:02 +0800
committerMatthew Barnes <mbarnes@redhat.com>2013-06-17 22:18:02 +0800
commit340c64e42d3018942af7bd1ac696d660e57ec082 (patch)
tree775cd1bcde0eb1d4edd643c91b65a6302a532db1
parent0c2b350db0029ff07fff8b2d5d55a9aedafbfe17 (diff)
downloadgsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.tar.gz
gsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.tar.zst
gsoc2013-evolution-340c64e42d3018942af7bd1ac696d660e57ec082.zip
Bug 702454 - EMailBrowser fails to show message
This reworks the MessageList regen scheduling to be a little more intuitive, at least to me. We now set the RegenData immediately, but start the actual regen operation from an idle callback. That way the caller has the remainder of this main loop iteration to make further MessageList changes without triggering additional regens. I think what was happening before was we were triggering multiple regen operations as we were configuring the EMailBrowser, with each new regen cancelling the previous, and the message UID to select wound up getting paired with one of the cancelled regen operations. This resulted in no message UID ever getting selected in the EMailBrowser.
-rw-r--r--mail/message-list.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/mail/message-list.c b/mail/message-list.c
index ffa20e166f..ada7f11871 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -97,7 +97,7 @@ struct _MessageListPrivate {
/* For message list regeneration. */
GMutex regen_lock;
RegenData *regen_data;
- guint regen_timeout_id;
+ guint regen_idle_id;
struct _MLSelection clipboard;
gboolean destroyed;
@@ -5499,7 +5499,7 @@ message_list_regen_done_cb (GObject *source_object,
}
static gboolean
-message_list_regen_timeout_cb (gpointer user_data)
+message_list_regen_idle_cb (gpointer user_data)
{
GSimpleAsyncResult *simple;
RegenData *regen_data;
@@ -5510,7 +5510,7 @@ message_list_regen_timeout_cb (gpointer user_data)
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;
+ regen_data->message_list->priv->regen_idle_id = 0;
g_mutex_unlock (&regen_data->message_list->priv->regen_lock);
if (g_cancellable_is_cancelled (cancellable)) {
@@ -5536,9 +5536,9 @@ mail_regen_cancel (MessageList *message_list)
if (message_list->priv->regen_data != NULL)
regen_data = regen_data_ref (message_list->priv->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;
+ if (message_list->priv->regen_idle_id > 0) {
+ g_source_remove (message_list->priv->regen_idle_id);
+ message_list->priv->regen_idle_id = 0;
}
g_mutex_unlock (&message_list->priv->regen_lock);
@@ -5571,6 +5571,28 @@ mail_regen_list (MessageList *message_list,
return;
}
+ g_mutex_lock (&message_list->priv->regen_lock);
+
+ old_regen_data = message_list->priv->regen_data;
+
+ /* If a regen is scheduled but not yet started, just
+ * apply the argument values without cancelling it. */
+ if (message_list->priv->regen_idle_id > 0) {
+ g_return_if_fail (old_regen_data != NULL);
+
+ if (g_strcmp0 (search, old_regen_data->search) != 0) {
+ g_free (old_regen_data->search);
+ old_regen_data->search = g_strdup (search);
+ }
+
+ old_regen_data->folder_changed = folder_changed;
+
+ /* Avoid cancelling on the way out. */
+ old_regen_data = NULL;
+
+ goto exit;
+ }
+
cancellable = g_cancellable_new ();
new_regen_data = regen_data_new (message_list, cancellable);
@@ -5592,36 +5614,27 @@ mail_regen_list (MessageList *message_list,
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);
+ /* Set the RegenData immediately, but start the actual regen
+ * operation from an idle callback. That way the caller has
+ * the remainder of this main loop iteration to make further
+ * MessageList changes without triggering additional regens. */
- 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;
- }
+ message_list->priv->regen_idle_id =
+ g_idle_add_full (
+ G_PRIORITY_DEFAULT_IDLE,
+ message_list_regen_idle_cb,
+ g_object_ref (simple),
+ (GDestroyNotify) g_object_unref);
- /* 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_object_unref (simple);
+
+ regen_data_unref (new_regen_data);
+ g_object_unref (cancellable);
+
+exit:
g_mutex_unlock (&message_list->priv->regen_lock);
/* Cancel outside the lock, since this will emit a signal. */
@@ -5629,10 +5642,4 @@ mail_regen_list (MessageList *message_list,
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);
}