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).
This commit is contained in:
Simon Arlott committed 2023-06-18 08:55:20 +01:00
1 parent d56d68b7ab
commit f49b669052
3 files changed
+39 -5

No files matched your search

+2 -1
View File
@@ -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;
}
@@ -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)
{
@@ -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);