gnucash stable: Multiple changes pushed

John Ralls jralls at code.gnucash.org
Thu Jun 22 16:56:51 EDT 2023


Updated	 via  https://github.com/Gnucash/gnucash/commit/6b48c6ce (commit)
	 via  https://github.com/Gnucash/gnucash/commit/f49b6690 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d56d68b7 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/9ac12db6 (commit)
	from  https://github.com/Gnucash/gnucash/commit/cf3d2f36 (commit)



commit 6b48c6ced73fb435e2627e20dbeca94c02195f30
Merge: cf3d2f3656 f49b669052
Author: John Ralls <jralls at ceridwen.us>
Date:   Thu Jun 22 13:53:36 2023 -0700

    Merge Simon Arlott's 'bug-798564' into stable.


commit f49b6690529d90cc31a67f77faf269921d28f35d
Author: Simon Arlott <sa.me.uk>
Date:   Sat Jun 17 20:19:29 2023 +0100

    Bug 798564 - GnuCash is slow when there are a lot of open registers
    
    When loading the book on startup, GnuCash takes a long time. This is partly
    because gnc_restore_all_state() is loading data for every register page and
    I have 35+ registers open.
    
    Register loads should be deferred on tabs that are not visible until those
    tabs are focused, like what already happens for restored open reports.
    
    Every time a change to a transaction is saved by navigating away from it,
    the UI freezes for almost a second. This is because
    gnc_split_register_move_cursor() calls gnc_gui_refresh_internal() which
    refreshes all the registers.
    
    Register refreshes should be deferred on tabs that are not visible until
    those tabs are focused again.
    
    Use focus information to suppress the last part of the refresh_handler()
    if the ledger isn't currently visible. When it becomes visible again, run
    the deferred refresh step.
    
    Don't immediately load or refresh the ledger (this will happen the first
    time it is focused instead).

diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c
index 5e045ee16a..7b6ab22111 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -1176,6 +1176,8 @@ gnc_plugin_page_register_focus (GncPluginPage* plugin_page,
 
     // set the sheet focus setting
     gnc_split_reg_set_sheet_focus (gsr, priv->page_focus);
+
+    gnc_ledger_display_set_focus (priv->ledger, priv->page_focus);
 }
 
 static GtkWidget*
@@ -1742,7 +1744,6 @@ gnc_plugin_page_register_recreate_page (GtkWidget* window,
 
     /* enable the refresh */
     priv->enable_refresh = TRUE;
-    gnc_ledger_display_refresh (priv->ledger);
     LEAVE (" ");
     return page;
 }
diff --git a/gnucash/register/ledger-core/gnc-ledger-display.c b/gnucash/register/ledger-core/gnc-ledger-display.c
index 3b603d7230..bf0f48a183 100644
--- a/gnucash/register/ledger-core/gnc-ledger-display.c
+++ b/gnucash/register/ledger-core/gnc-ledger-display.c
@@ -66,6 +66,8 @@ struct gnc_ledger_display
 
     gboolean loading;
     gboolean use_double_line_default;
+    gboolean visible; /* focus */
+    gboolean needs_refresh;
 
     GNCLedgerDisplayDestroy destroy;
     GNCLedgerDisplayGetParent get_parent;
@@ -617,7 +619,15 @@ refresh_handler (GHashTable* changes, gpointer user_data)
         }
     }
 
-    gnc_ledger_display_refresh (ld);
+    if (ld->visible)
+    {
+        DEBUG ("immediate refresh because ledger is visible");
+        gnc_ledger_display_refresh (ld);
+    }
+    else
+    {
+        ld->needs_refresh = TRUE;
+    }
     LEAVE (" ");
 }
 
@@ -808,6 +818,8 @@ gnc_ledger_display_internal (Account* lead_account, Query* q,
     ld->query = NULL;
     ld->ld_type = ld_type;
     ld->loading = FALSE;
+    ld->visible = FALSE;
+    ld->needs_refresh = TRUE;
     ld->destroy = NULL;
     ld->get_parent = NULL;
     ld->user_data = NULL;
@@ -837,10 +849,13 @@ gnc_ledger_display_internal (Account* lead_account, Query* q,
 
     gnc_split_register_set_data (ld->reg, ld, gnc_ledger_display_parent);
 
-    /* We don't need to recreate the query, so skip that refresh step by
-     * bypassing gnc_ledger_display_refresh().
+    /* Must call this before gnc_table_realize_gui() gets called or all the
+     * combo boxes will be empty. Use an empty list of splits instad of running
+     * the query when we're not in focus yet.
      */
-    gnc_ledger_display_refresh_internal (ld);
+    ld->loading = TRUE;
+    gnc_split_register_load (ld->reg, NULL, gnc_ledger_display_leader (ld));
+    ld->loading = FALSE;
     return ld;
 }
 
@@ -894,6 +909,7 @@ gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld)
     gnc_split_register_load (ld->reg, splits,
                              gnc_ledger_display_leader (ld));
 
+    ld->needs_refresh = FALSE;
     ld->loading = FALSE;
 }
 
@@ -943,6 +959,20 @@ gnc_ledger_display_refresh (GNCLedgerDisplay* ld)
     LEAVE (" ");
 }
 
+void gnc_ledger_display_set_focus (GNCLedgerDisplay* ld, gboolean focus)
+{
+    if (!ld)
+        return;
+
+    ld->visible = focus;
+
+    if (ld->visible && ld->needs_refresh)
+    {
+        DEBUG ("deferred refresh because ledger is now visible");
+        gnc_ledger_display_refresh (ld);
+    }
+}
+
 void
 gnc_ledger_display_refresh_by_split_register (SplitRegister* reg)
 {
diff --git a/gnucash/register/ledger-core/gnc-ledger-display.h b/gnucash/register/ledger-core/gnc-ledger-display.h
index fea5078940..6f5faefdfe 100644
--- a/gnucash/register/ledger-core/gnc-ledger-display.h
+++ b/gnucash/register/ledger-core/gnc-ledger-display.h
@@ -121,6 +121,9 @@ GNCLedgerDisplay* gnc_ledger_display_find_by_query (Query* q);
 void gnc_ledger_display_refresh (GNCLedgerDisplay* ledger_display);
 void gnc_ledger_display_refresh_by_split_register (SplitRegister* reg);
 
+/** Mark the ledger as being in focus (refresh immediately) or not. */
+void gnc_ledger_display_set_focus (GNCLedgerDisplay* ld, gboolean focus);
+
 /** close the window */
 void gnc_ledger_display_close (GNCLedgerDisplay* ledger_display);
 

commit d56d68b7abdfb0fde49c2383f0040f2a5bcf8ee5
Author: Simon Arlott <sa.me.uk>
Date:   Sat Jun 3 11:03:32 2023 +0100

    [gnc-plugin-page] Don't automatically focus pages when they are recreated
    
    This has to disregard the "open adjacent" preference to get them to be in
    the right order because the first page will remain focused until the
    restore is complete.
    
    Change the register page so that it doesn't assume it will be in focus on
    creation.

diff --git a/gnucash/gnome-utils/gnc-main-window.cpp b/gnucash/gnome-utils/gnc-main-window.cpp
index 249c8d414c..ea2a3f0239 100644
--- a/gnucash/gnome-utils/gnc-main-window.cpp
+++ b/gnucash/gnome-utils/gnc-main-window.cpp
@@ -3035,7 +3035,8 @@ gnc_main_window_connect (GncMainWindow *window,
     priv = GNC_MAIN_WINDOW_GET_PRIVATE(window);
     notebook = GTK_NOTEBOOK (priv->notebook);
 
-    if (gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_TAB_OPEN_ADJACENT))
+    if (!priv->restoring_pages
+            && gnc_prefs_get_bool (GNC_PREFS_GROUP_GENERAL, GNC_PREF_TAB_OPEN_ADJACENT))
         current_position = g_list_index (priv->installed_pages, priv->current_page) + 1;
 
     priv->installed_pages = g_list_insert (priv->installed_pages, page, current_position);
@@ -3044,7 +3045,8 @@ gnc_main_window_connect (GncMainWindow *window,
                                    tab_hbox, menu_label, current_position);
     gtk_notebook_set_tab_reorderable (notebook, page->notebook_page, TRUE);
     gnc_plugin_page_inserted (page);
-    gtk_notebook_set_current_page (notebook, current_position);
+    if (!priv->restoring_pages)
+        gtk_notebook_set_current_page (notebook, current_position);
 
     if (GNC_PLUGIN_PAGE_GET_CLASS(page)->window_changed)
         (GNC_PLUGIN_PAGE_GET_CLASS(page)->window_changed)(page, GTK_WIDGET(window));
@@ -3187,7 +3189,8 @@ gnc_main_window_open_page (GncMainWindow *window,
 
     if (gnc_main_window_page_exists(page))
     {
-        gnc_main_window_display_page(page);
+        if (!gnc_main_window_is_restoring_pages (window))
+            gnc_main_window_display_page (page);
         return;
     }
 
diff --git a/gnucash/gnome-utils/gnc-plugin-page.c b/gnucash/gnome-utils/gnc-plugin-page.c
index 61a22f5df0..de14e48c01 100644
--- a/gnucash/gnome-utils/gnc-plugin-page.c
+++ b/gnucash/gnome-utils/gnc-plugin-page.c
@@ -888,7 +888,8 @@ gnc_plugin_page_inserted_cb (GncPluginPage *page, gpointer user_data)
                                               page);
 
     // on initial load try and set the page focus
-    (GNC_PLUGIN_PAGE_GET_CLASS(page)->focus_page)(page, TRUE);
+    if (!gnc_main_window_is_restoring_pages (GNC_MAIN_WINDOW(page->window)))
+        (GNC_PLUGIN_PAGE_GET_CLASS(page)->focus_page)(page, TRUE);
 }
 
 
diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c
index 0007542e3f..5e045ee16a 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -1202,8 +1202,6 @@ gnc_plugin_page_register_create_widget (GncPluginPage* plugin_page)
         LEAVE ("existing widget %p", priv->widget);
         return priv->widget;
     }
-    // on create, the page will be the current page so set the focus flag
-    priv->page_focus = TRUE;
 
     priv->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
     gtk_box_set_homogeneous (GTK_BOX (priv->widget), FALSE);

commit 9ac12db68fb9bf6ee7db359c77bb77fdc59c0926
Author: Simon Arlott <sa.me.uk>
Date:   Sat Jun 3 10:24:13 2023 +0100

    [gnc-ledger-display] Consolidate refresh functions
    
    gnc_ledger_display_gl() is called to create the ledger:
    1. Exclude template accounts (unconditionally)
    2. Calls gnc_ledger_display_internal()
    
    gnc_ledger_display_internal():
    1. Run query
    2. Set watches
    3. Load splits
    
    refresh_handler() is called to refresh all pages when a change happens:
    1. Check if the number of subaccounts has changed
    2. Exclude any template accounts (for specific register types)
    3. Run query
    4. Set watches
    5. Load splits
    
    gnc_ledger_display_refresh() is called by the register plugin:
    1. [Doesn't check if the number of subaccounts has changed]
    2. Exclude template accounts (for specific register types)
    3. Run query
    4. Set watches
    5. Load splits
    
    The last two are inconsistent because they don't both check if the number
    of subaccounts has changed.
    
    Make it easier to conditionally refresh the ledger only when it's visible
    by consolidating the code from these functions into one place within
    gnc_ledger_display_refresh() and gnc_ledger_display_refresh_internal().

diff --git a/gnucash/register/ledger-core/gnc-ledger-display.c b/gnucash/register/ledger-core/gnc-ledger-display.c
index 4a69880017..3b603d7230 100644
--- a/gnucash/register/ledger-core/gnc-ledger-display.c
+++ b/gnucash/register/ledger-core/gnc-ledger-display.c
@@ -94,8 +94,8 @@ gnc_ledger_display_internal (Account* lead_account, Query* q,
                              gboolean is_template,
                              gboolean mismatched_commodities);
 
-static void gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld,
-                                                 GList* splits);
+static void
+gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld);
 
 static void gnc_ledger_display_make_query (GNCLedgerDisplay* ld,
                                            gint limit,
@@ -584,7 +584,6 @@ refresh_handler (GHashTable* changes, gpointer user_data)
     GNCLedgerDisplay* ld = user_data;
     const EventInfo* info;
     gboolean has_leader;
-    GList* splits;
 
     ENTER ("changes=%p, user_data=%p", changes, user_data);
 
@@ -618,35 +617,7 @@ refresh_handler (GHashTable* changes, gpointer user_data)
         }
     }
 
-    /* if subaccount ledger, check to see if still the same number
-     *  of subaccounts, if not recreate the query. */
-    if (ld->ld_type == LD_SUBACCOUNT)
-    {
-        Account* leader = gnc_ledger_display_leader (ld);
-        GList* accounts = gnc_account_get_descendants (leader);
-
-        if (g_list_length (accounts) != ld->number_of_subaccounts)
-            gnc_ledger_display_make_query (ld,
-                                           gnc_prefs_get_float (GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_MAX_TRANS),
-                                           gnc_get_reg_type (leader, ld->ld_type));
-
-        g_list_free (accounts);
-    }
-
-    // Exclude any template accounts for search register and gl
-    if (!ld->reg->is_template && (ld->reg->type == SEARCH_LEDGER || ld->ld_type == LD_GL))
-        exclude_template_accounts (ld->query, ld->excluded_template_acc_hash);
-
-    /* Its not clear if we should re-run the query, or if we should
-     * just use qof_query_last_run().  Its possible that the dates
-     * changed, requiring a full new query.  Similar considerations
-     * needed for multi-user mode.
-     */
-    splits = qof_query_run (ld->query);
-
-    gnc_ledger_display_set_watches (ld, splits);
-
-    gnc_ledger_display_refresh_internal (ld, splits);
+    gnc_ledger_display_refresh (ld);
     LEAVE (" ");
 }
 
@@ -764,7 +735,6 @@ gnc_ledger_display_internal (Account* lead_account, Query* q,
     GNCLedgerDisplay* ld;
     gint limit;
     const char* klass;
-    GList* splits;
 
     switch (ld_type)
     {
@@ -867,12 +837,10 @@ gnc_ledger_display_internal (Account* lead_account, Query* q,
 
     gnc_split_register_set_data (ld->reg, ld, gnc_ledger_display_parent);
 
-    splits = qof_query_run (ld->query);
-
-    gnc_ledger_display_set_watches (ld, splits);
-
-    gnc_ledger_display_refresh_internal (ld, splits);
-
+    /* We don't need to recreate the query, so skip that refresh step by
+     * bypassing gnc_ledger_display_refresh().
+     */
+    gnc_ledger_display_refresh_internal (ld);
     return ld;
 }
 
@@ -902,11 +870,22 @@ gnc_ledger_display_find_by_query (Query* q)
 \********************************************************************/
 
 static void
-gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld, GList* splits)
+gnc_ledger_display_refresh_internal (GNCLedgerDisplay* ld)
 {
-    if (!ld || ld->loading)
+    GList* splits;
+
+    if (ld->loading)
         return;
 
+    /* It's not clear if we should re-run the query, or if we should
+     * just use qof_query_last_run().  It's possible that the dates
+     * changed, requiring a full new query.  Similar considerations
+     * needed for multi-user mode.
+     */
+    splits = qof_query_run (ld->query);
+
+    gnc_ledger_display_set_watches (ld, splits);
+
     if (!gnc_split_register_full_refresh_ok (ld->reg))
         return;
 
@@ -935,11 +914,32 @@ gnc_ledger_display_refresh (GNCLedgerDisplay* ld)
         return;
     }
 
+    /* if subaccount ledger, check to see if still the same number
+     * of subaccounts, if not recreate the query. */
+    if (ld->ld_type == LD_SUBACCOUNT)
+    {
+        Account* leader = gnc_ledger_display_leader (ld);
+        GList* accounts = gnc_account_get_descendants (leader);
+
+        if (g_list_length (accounts) != ld->number_of_subaccounts)
+            gnc_ledger_display_make_query (ld,
+                                        gnc_prefs_get_float (GNC_PREFS_GROUP_GENERAL_REGISTER, GNC_PREF_MAX_TRANS),
+                                        gnc_get_reg_type (leader, ld->ld_type));
+
+        g_list_free (accounts);
+    }
+
+    /* In lieu of not "mis-using" some portion of the infrastructure by writing
+     * a bunch of new code, we just filter out the accounts of the template
+     * transactions.  While these are in a separate Account trees just for this
+     * reason, the query engine makes no distinction between Account trees.
+     * See Gnome Bug 86302.
+     *         -- jsled */
     // Exclude any template accounts for search register and gl
     if (!ld->reg->is_template && (ld->reg->type == SEARCH_LEDGER || ld->ld_type == LD_GL))
         exclude_template_accounts (ld->query, ld->excluded_template_acc_hash);
 
-    gnc_ledger_display_refresh_internal (ld, qof_query_run (ld->query));
+    gnc_ledger_display_refresh_internal (ld);
     LEAVE (" ");
 }
 



Summary of changes:
 gnucash/gnome-utils/gnc-main-window.cpp           |   9 +-
 gnucash/gnome-utils/gnc-plugin-page.c             |   3 +-
 gnucash/gnome/gnc-plugin-page-register.c          |   5 +-
 gnucash/register/ledger-core/gnc-ledger-display.c | 110 ++++++++++++++--------
 gnucash/register/ledger-core/gnc-ledger-display.h |   3 +
 5 files changed, 83 insertions(+), 47 deletions(-)



More information about the gnucash-changes mailing list