[balsa] Fix expand-on-open



commit b11f00d62c68f88572c706c6f06c9f2a2d2980cd
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Mon Jan 6 19:33:04 2020 -0500

    Fix expand-on-open
    
    See https://mail.gnome.org/archives/balsa-list/2019-August/msg00008.html
    Because of a race among idle callbacks, we could call
    gtk_tree_view_expand_all() before the message tree was populated
    and threaded. So when it was populated and threaded, threads
    were in the default state, collapsed.
    
    * libbalsa/mailbox.c (libbalsa_mailbox_close), (lbm_set_threading),
      (libbalsa_mailbox_get_messages_loaded),
      (libbalsa_mailbox_get_messages_threaded),
      (libbalsa_mailbox_set_has_unread_messages),
      (libbalsa_mailbox_set_messages_loaded),
      (libbalsa_mailbox_set_messages_threaded): add messages_loaded
      and messages_threaded members to the private structure, and
      manage access to them;
    * libbalsa/mailbox.h: add accessors;
    * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_set_threading):
      set messages_threaded;
    * libbalsa/mailbox_local.c (lbml_load_messages_idle_cb): set
      messages_loaded;
      (lbml_set_threading): if messages have been loaded, set
      messages_threaded;
    * src/balsa-index.c (bndx_scroll_on_open_idle): if messages have
      not been loaded and threaded, reschedule the timeout;
      (balsa_index_scroll_on_open): use a 10 millisecond timeout
      instead of an idle call, to avoid a flurry of rescheduling.

 ChangeLog                | 30 +++++++++++++++++++++++++++++
 libbalsa/mailbox.c       | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
 libbalsa/mailbox.h       |  6 ++++++
 libbalsa/mailbox_imap.c  |  1 +
 libbalsa/mailbox_local.c |  5 +++++
 src/balsa-index.c        | 15 ++++++++++++---
 6 files changed, 103 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f4bc4f10b..297fbb809 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2020-01-06  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Fix expand-on-open
+
+       See https://mail.gnome.org/archives/balsa-list/2019-August/msg00008.html
+       Because of a race among idle callbacks, we could call
+       gtk_tree_view_expand_all() before the message tree was populated
+       and threaded. So when it was populated and threaded, threads
+       were in the default state, collapsed.
+
+       * libbalsa/mailbox.c (libbalsa_mailbox_close), (lbm_set_threading),
+       (libbalsa_mailbox_get_messages_loaded),
+       (libbalsa_mailbox_get_messages_threaded),
+       (libbalsa_mailbox_set_has_unread_messages),
+       (libbalsa_mailbox_set_messages_loaded),
+       (libbalsa_mailbox_set_messages_threaded): add messages_loaded
+       and messages_threaded members to the private structure, and
+       manage access to them;
+       * libbalsa/mailbox.h: add accessors;
+       * libbalsa/mailbox_imap.c (libbalsa_mailbox_imap_set_threading):
+       set messages_threaded;
+       * libbalsa/mailbox_local.c (lbml_load_messages_idle_cb): set
+       messages_loaded;
+       (lbml_set_threading): if messages have been loaded, set
+       messages_threaded;
+       * src/balsa-index.c (bndx_scroll_on_open_idle): if messages have
+       not been loaded and threaded, reschedule the timeout;
+       (balsa_index_scroll_on_open): use a 10 millisecond timeout
+       instead of an idle call, to avoid a flurry of rescheduling.
+
 2020-01-06  Peter Bloomfield  <pbloomfield bellsouth net>
 
        main-window: Disconnect from a network monitor signal
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index cd21c09d2..e4830411c 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -161,6 +161,10 @@ struct _LibBalsaMailboxPrivate {
     guint queue_check_idle_id;
     guint need_threading_idle_id;
     guint run_filters_idle_id;
+
+    /* Whether messages have been loaded and threaded. */
+    gboolean messages_loaded;
+    gboolean messages_threaded;
 };
 
 G_DEFINE_TYPE_WITH_CODE(LibBalsaMailbox,
@@ -646,6 +650,8 @@ libbalsa_mailbox_close(LibBalsaMailbox * mailbox, gboolean expunge)
         libbalsa_mailbox_free_mindex(mailbox);
         priv->stamp++;
        priv->state = LB_MAILBOX_STATE_CLOSED;
+        priv->messages_loaded = FALSE;
+        priv->messages_threaded = FALSE;
     }
 
     libbalsa_unlock_mailbox(mailbox);
@@ -2310,6 +2316,7 @@ lbm_set_threading(LibBalsaMailbox * mailbox)
 
     LIBBALSA_MAILBOX_GET_CLASS(mailbox)->set_threading(mailbox,
                                                        priv->view->threading_type);
+
     if (libbalsa_am_i_subthread()) {
         g_idle_add((GSourceFunc) lbm_set_threading_idle_cb, g_object_ref(mailbox));
     } else {
@@ -4851,6 +4858,26 @@ libbalsa_mailbox_get_has_unread_messages(LibBalsaMailbox * mailbox)
     return priv->has_unread_messages;
 }
 
+gboolean
+libbalsa_mailbox_get_messages_loaded(LibBalsaMailbox * mailbox)
+{
+    LibBalsaMailboxPrivate *priv = libbalsa_mailbox_get_instance_private(mailbox);
+
+    g_return_val_if_fail(LIBBALSA_IS_MAILBOX(mailbox), FALSE);
+
+    return priv->messages_loaded;
+}
+
+gboolean
+libbalsa_mailbox_get_messages_threaded(LibBalsaMailbox * mailbox)
+{
+    LibBalsaMailboxPrivate *priv = libbalsa_mailbox_get_instance_private(mailbox);
+
+    g_return_val_if_fail(LIBBALSA_IS_MAILBOX(mailbox), FALSE);
+
+    return priv->messages_threaded;
+}
+
 /*
  * Setters
  */
@@ -4971,6 +4998,28 @@ libbalsa_mailbox_set_has_unread_messages(LibBalsaMailbox * mailbox,
     priv->has_unread_messages = has_unread_messages;
 }
 
+void
+libbalsa_mailbox_set_messages_loaded(LibBalsaMailbox * mailbox,
+                                     gboolean messages_loaded)
+{
+    LibBalsaMailboxPrivate *priv = libbalsa_mailbox_get_instance_private(mailbox);
+
+    g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
+
+    priv->messages_loaded = messages_loaded;
+}
+
+void
+libbalsa_mailbox_set_messages_threaded(LibBalsaMailbox * mailbox,
+                                       gboolean messages_threaded)
+{
+    LibBalsaMailboxPrivate *priv = libbalsa_mailbox_get_instance_private(mailbox);
+
+    g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
+
+    priv->messages_threaded = messages_threaded;
+}
+
 void
 libbalsa_mailbox_set_config_prefix(LibBalsaMailbox * mailbox,
                                    const gchar * config_prefix)
diff --git a/libbalsa/mailbox.h b/libbalsa/mailbox.h
index 3e0f9149e..bba8a7366 100644
--- a/libbalsa/mailbox.h
+++ b/libbalsa/mailbox.h
@@ -619,6 +619,8 @@ guint libbalsa_mailbox_get_open_ref(LibBalsaMailbox * mailbox);
 gboolean libbalsa_mailbox_get_readonly(LibBalsaMailbox * mailbox);
 const gchar * libbalsa_mailbox_get_config_prefix(LibBalsaMailbox * mailbox);
 gboolean libbalsa_mailbox_get_has_unread_messages(LibBalsaMailbox * mailbox);
+gboolean libbalsa_mailbox_get_messages_loaded(LibBalsaMailbox * mailbox);
+gboolean libbalsa_mailbox_get_messages_threaded(LibBalsaMailbox * mailbox);
 
 /*
  * Setters
@@ -636,6 +638,10 @@ void libbalsa_mailbox_set_name(LibBalsaMailbox * mailbox, const gchar * name);
 void libbalsa_mailbox_set_view(LibBalsaMailbox * mailbox, LibBalsaMailboxView * view);
 void libbalsa_mailbox_set_has_unread_messages(LibBalsaMailbox * mailbox,
                                               gboolean has_unread_messages);
+void libbalsa_mailbox_set_messages_loaded(LibBalsaMailbox * mailbox,
+                                          gboolean messages_loaded);
+void libbalsa_mailbox_set_messages_threaded(LibBalsaMailbox * mailbox,
+                                          gboolean messages_threaded);
 void libbalsa_mailbox_set_config_prefix(LibBalsaMailbox * mailbox,
                                         const gchar * config_prefix);
 
diff --git a/libbalsa/mailbox_imap.c b/libbalsa/mailbox_imap.c
index 1fa80f977..7b1569102 100644
--- a/libbalsa/mailbox_imap.c
+++ b/libbalsa/mailbox_imap.c
@@ -3206,6 +3206,7 @@ libbalsa_mailbox_imap_set_threading(LibBalsaMailbox *mailbox,
     imap_search_key_free(filter);
 
     libbalsa_mailbox_set_msg_tree(mailbox, new_tree);
+    libbalsa_mailbox_set_messages_threaded(mailbox, TRUE);
 }
 
 static void
diff --git a/libbalsa/mailbox_local.c b/libbalsa/mailbox_local.c
index cb5fc4bde..39e2a396c 100644
--- a/libbalsa/mailbox_local.c
+++ b/libbalsa/mailbox_local.c
@@ -1079,6 +1079,7 @@ lbml_load_messages_idle_cb(LibBalsaMailbox * mailbox)
             libbalsa_mailbox_local_cache_message(local, msgno,
                                                  msg_info->message);
     }
+    libbalsa_mailbox_set_messages_loaded(mailbox, TRUE);
 
     if (new_messages > 0) {
        libbalsa_mailbox_run_filters_on_reception(mailbox);
@@ -1087,6 +1088,7 @@ lbml_load_messages_idle_cb(LibBalsaMailbox * mailbox)
     }
 
     libbalsa_unlock_mailbox(mailbox);
+
     return FALSE;
 }
 
@@ -1145,6 +1147,9 @@ lbml_set_threading(LibBalsaMailbox * mailbox,
         lbml_threading_flat(mailbox);
         break;
     }
+
+    if (libbalsa_mailbox_get_messages_loaded(mailbox))
+        libbalsa_mailbox_set_messages_threaded(mailbox, TRUE);
 }
 
 typedef struct {
diff --git a/src/balsa-index.c b/src/balsa-index.c
index b95f41ee4..18af005a4 100644
--- a/src/balsa-index.c
+++ b/src/balsa-index.c
@@ -817,10 +817,17 @@ bndx_scroll_on_open_idle(BalsaIndex *bindex)
     GtkTreePath *path;
     gpointer view_on_open;
 
-    bindex->scroll_on_open_idle_id = 0;
+    mailbox = balsa_mailbox_node_get_mailbox(bindex->mailbox_node);
+
+    if (!libbalsa_mailbox_get_messages_threaded(mailbox))
+        return TRUE; /* G_SOURCE_CONTINUE */
 
     balsa_index_update_tree(bindex, balsa_app.expand_tree);
-    mailbox = balsa_mailbox_node_get_mailbox(bindex->mailbox_node);
+
+    /* From here on, we return only G_SOURCE_REMOVE, so we should clear
+     * the id: */
+    bindex->scroll_on_open_idle_id = 0;
+
     first_unread = libbalsa_mailbox_get_first_unread(mailbox);
     if (first_unread > 0) {
        unsigned msgno = first_unread;
@@ -871,9 +878,11 @@ balsa_index_scroll_on_open(BalsaIndex * bindex)
 {
     /* Scroll in an idle handler, because the mailbox is perhaps being
      * opened in its own idle handler. */
+    /* Actually use a 10 millisecond timeout, bacause the handler will
+     * reschedule itself until messages are loaded and threaded. */
     if (bindex->scroll_on_open_idle_id == 0) {
         bindex->scroll_on_open_idle_id =
-            g_idle_add((GSourceFunc) bndx_scroll_on_open_idle, bindex);
+            g_timeout_add(10, (GSourceFunc) bndx_scroll_on_open_idle, bindex);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]