gnucash stable: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Sat Jun 3 20:00:02 EDT 2023


Updated	 via  https://github.com/Gnucash/gnucash/commit/ccc75cfc (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6fc36914 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/90471560 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/8628ca87 (commit)
	from  https://github.com/Gnucash/gnucash/commit/81902ba8 (commit)



commit ccc75cfc880ca44ddd3671b669ea556173bd14bc
Merge: 6fc3691401 9047156017
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Jun 4 07:58:31 2023 +0800

    Merge branch 'scrub-optimize' into stable

diff --cc libgnucash/engine/Scrub.c
index 79be580a95,8ac3d21b58..ce1c074e73
--- a/libgnucash/engine/Scrub.c
+++ b/libgnucash/engine/Scrub.c
@@@ -350,44 -334,49 +352,87 @@@ split_scrub_or_dry_run (Split *split, b
  
  /* ================================================================ */
  
+ 
+ static void
+ AccountScrubImbalance (Account *acc, bool descendants,
+                        QofPercentageFunc percentagefunc)
+ {
+     const char *message = _( "Looking for imbalances in transaction date %s: %u of %u");
+ 
+     if (!acc) return;
+ 
+     QofBook *book = qof_session_get_book (gnc_get_current_session ());
+     Account *root = gnc_book_get_root_account (book);
+     GList *transactions = get_all_transactions (acc, descendants);
+     guint count = g_list_length (transactions), curr_trans = 0;
+ 
+     scrub_depth++;
+     for (GList *node = transactions; node; node = node->next, curr_trans++)
+     {
+         Transaction *trans = node->data;
+         if (abort_now) break;
+ 
+         PINFO("Start processing transaction %d of %d", curr_trans + 1, count);
+ 
+         if (curr_trans % 10 == 0)
+         {
+             char *date = qof_print_date (xaccTransGetDate (trans));
+             char *progress_msg = g_strdup_printf (message, date, curr_trans, count);
+             (percentagefunc)(progress_msg, (100 * curr_trans) / count);
+             g_free (progress_msg);
+             g_free (date);
+         }
+ 
+         TransScrubOrphansFast (trans, root);
+         xaccTransScrubCurrency(trans);
+         xaccTransScrubImbalance (trans, root, NULL);
+ 
+         PINFO("Finished processing transaction %d of %d", curr_trans + 1, count);
+     }
+     (percentagefunc)(NULL, -1.0);
+     scrub_depth--;
+ 
+     g_list_free (transactions);
+ }
+ 
 +void
 +xaccTransScrubSplits (Transaction *trans)
 +{
 +    if (!trans) return;
 +
 +    gnc_commodity *currency = xaccTransGetCurrency (trans);
 +    if (!currency)
 +        PERR ("Transaction doesn't have a currency!");
 +
 +    bool must_scrub = false;
 +
 +    for (GList *n = xaccTransGetSplitList (trans); !must_scrub && n; n = g_list_next (n))
 +        if (split_scrub_or_dry_run (n->data, true))
 +            must_scrub = true;
 +
 +    if (!must_scrub)
 +        return;
 +
 +    xaccTransBeginEdit(trans);
 +    /* The split scrub expects the transaction to have a currency! */
 +
 +    for (GList *n = xaccTransGetSplitList (trans); n; n = g_list_next (n))
 +        xaccSplitScrub (n->data);
 +
 +    xaccTransCommitEdit(trans);
 +}
 +
 +/* ================================================================ */
 +
 +void
 +xaccSplitScrub (Split *split)
 +{
 +    split_scrub_or_dry_run (split, false);
 +}
 +
 +/* ================================================================ */
 +
 +
  void
  xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
  {

commit 6fc36914016d9f709242ac60444050ffe09fc041
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Jun 4 07:55:04 2023 +0800

    Consolidate owner title setter into gnc_owner_window_set_title
    
    8d44c1c38c rewritten to call common code.

diff --git a/gnucash/gnome-utils/dialog-utils.c b/gnucash/gnome-utils/dialog-utils.c
index a231fc82fa..01f8c49b75 100644
--- a/gnucash/gnome-utils/dialog-utils.c
+++ b/gnucash/gnome-utils/dialog-utils.c
@@ -832,3 +832,22 @@ gnc_get_negative_color (void)
 
     return gdk_rgba_to_string (&color);
 }
+
+void
+gnc_owner_window_set_title (GtkWindow *window, const char *header,
+                            GtkWidget *owner_entry, GtkWidget *id_entry)
+{
+    const char *name = gtk_entry_get_text (GTK_ENTRY (owner_entry));
+    if (!name || *name == '\0')
+        name = _("<No name>");
+
+    const char *id = gtk_entry_get_text (GTK_ENTRY (id_entry));
+
+    char *title = (id && *id) ?
+        g_strdup_printf ("%s - %s (%s)", header, name, id) :
+        g_strdup_printf ("%s - %s", header, name);
+
+    gtk_window_set_title (window, title);
+
+    g_free (title);
+}
diff --git a/gnucash/gnome-utils/dialog-utils.h b/gnucash/gnome-utils/dialog-utils.h
index c72e77d1e9..efeb3d734d 100644
--- a/gnucash/gnome-utils/dialog-utils.h
+++ b/gnucash/gnome-utils/dialog-utils.h
@@ -169,6 +169,12 @@ gnc_cost_policy_select_new (void);
  */
 gchar* gnc_get_negative_color (void);
 
+
+
+/** This function sets the title of an owner dialog */
+void gnc_owner_window_set_title (GtkWindow*, const char*, GtkWidget*, GtkWidget*);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/gnucash/gnome/dialog-customer.c b/gnucash/gnome/dialog-customer.c
index 4f98c97632..3fa9778ddd 100644
--- a/gnucash/gnome/dialog-customer.c
+++ b/gnucash/gnome/dialog-customer.c
@@ -399,27 +399,13 @@ void
 gnc_customer_name_changed_cb (GtkWidget *widget, gpointer data)
 {
     CustomerWindow *cw = data;
-    char *title;
-
     if (!cw)
         return;
 
-    const char *header = (cw->dialog_type == EDIT_CUSTOMER) ?
-        _("Edit Customer") : _("New Customer");
-
-    const char *name = gtk_entry_get_text (GTK_ENTRY (cw->company_entry));
-    if (!name || *name == '\0')
-        name = _("<No name>");
-
-    const char *id = gtk_entry_get_text (GTK_ENTRY (cw->id_entry));
-    if (id && *id)
-        title = g_strdup_printf ("%s - %s (%s)", header, name, id);
-    else
-        title = g_strdup_printf ("%s - %s", header, name);
-
-    gtk_window_set_title (GTK_WINDOW (cw->dialog), title);
-
-    g_free (title);
+    gnc_owner_window_set_title (GTK_WINDOW (cw->dialog),
+                                (cw->dialog_type == EDIT_CUSTOMER) ?
+                                _("Edit Customer") : _("New Customer"),
+                                cw->company_entry, cw->id_entry);
 }
 
 void
diff --git a/gnucash/gnome/dialog-employee.c b/gnucash/gnome/dialog-employee.c
index 64e111ab8c..7fe19129e7 100644
--- a/gnucash/gnome/dialog-employee.c
+++ b/gnucash/gnome/dialog-employee.c
@@ -280,27 +280,13 @@ void
 gnc_employee_name_changed_cb (GtkWidget *widget, gpointer data)
 {
     EmployeeWindow *ew = data;
-    char *title;
-
     if (!ew)
         return;
 
-    const char *header = (ew->dialog_type == EDIT_EMPLOYEE) ?
-        _("Edit Employee") : _("New Employee");
-
-    const char *name = gtk_entry_get_text (GTK_ENTRY (ew->name_entry));
-    if (!name || *name == '\0')
-        name = _("<No name>");
-
-    const char *id = gtk_entry_get_text (GTK_ENTRY (ew->id_entry));
-    if (id && *id)
-        title = g_strdup_printf ("%s - %s (%s)", header, name, id);
-    else
-        title = g_strdup_printf ("%s - %s", header, name);
-
-    gtk_window_set_title (GTK_WINDOW (ew->dialog), title);
-
-    g_free (title);
+    gnc_owner_window_set_title (GTK_WINDOW (ew->dialog),
+                                (ew->dialog_type == EDIT_EMPLOYEE) ?
+                                _("Edit Employee") : _("New Employee"),
+                                ew->name_entry, ew->id_entry);
 }
 
 void
diff --git a/gnucash/gnome/dialog-job.c b/gnucash/gnome/dialog-job.c
index 40c31b7450..91bee53260 100644
--- a/gnucash/gnome/dialog-job.c
+++ b/gnucash/gnome/dialog-job.c
@@ -237,27 +237,13 @@ void
 gnc_job_name_changed_cb (GtkWidget *widget, gpointer data)
 {
     JobWindow *jw = data;
-    char *title;
-
     if (!jw)
         return;
 
-    const char *header = (jw->dialog_type == EDIT_JOB) ?
-        _("Edit Job") : _("New Job");
-
-    const char *name = gtk_entry_get_text (GTK_ENTRY (jw->name_entry));
-    if (!name || *name == '\0')
-        name = _("<No name>");
-
-    const char *id = gtk_entry_get_text (GTK_ENTRY (jw->id_entry));
-    if (id && *id)
-        title = g_strdup_printf ("%s - %s (%s)", header, name, id);
-    else
-        title = g_strdup_printf ("%s - %s", header, name);
-
-    gtk_window_set_title (GTK_WINDOW (jw->dialog), title);
-
-    g_free (title);
+    gnc_owner_window_set_title (GTK_WINDOW (jw->dialog),
+                                (jw->dialog_type == EDIT_JOB) ?
+                                _("Edit Job") : _("New Job"),
+                                jw->name_entry, jw->id_entry);
 }
 
 static void
diff --git a/gnucash/gnome/dialog-vendor.c b/gnucash/gnome/dialog-vendor.c
index 61575f2d12..10b6ab52bf 100644
--- a/gnucash/gnome/dialog-vendor.c
+++ b/gnucash/gnome/dialog-vendor.c
@@ -267,27 +267,13 @@ void
 gnc_vendor_name_changed_cb (GtkWidget *widget, gpointer data)
 {
     VendorWindow *vw = data;
-    char *title;
-
     if (!vw)
         return;
 
-    const char *header = (vw->dialog_type == EDIT_VENDOR) ?
-        _("Edit Vendor") : _("New Vendor");
-
-    const char *name = gtk_entry_get_text (GTK_ENTRY (vw->company_entry));
-    if (!name || *name == '\0')
-        name = _("<No name>");
-
-    const char *id = gtk_entry_get_text (GTK_ENTRY (vw->id_entry));
-    if (id && *id)
-        title = g_strdup_printf ("%s - %s (%s)", header, name, id);
-    else
-        title = g_strdup_printf ("%s - %s", header, name);
-
-    gtk_window_set_title (GTK_WINDOW (vw->dialog), title);
-
-    g_free (title);
+    gnc_owner_window_set_title (GTK_WINDOW (vw->dialog),
+                                (vw->dialog_type == EDIT_VENDOR) ?
+                                _("Edit Vendor") : _("New Vendor"),
+                                vw->company_entry, vw->id_entry);
 }
 
 void

commit 9047156017ea20e8e6458d73490c313739a6d2f9
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed May 31 08:23:34 2023 +0800

    [Scrub.c] refactor xaccAccountTreeScrubOrphans

diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c
index d603a2b2ae..8ac3d21b58 100644
--- a/libgnucash/engine/Scrub.c
+++ b/libgnucash/engine/Scrub.c
@@ -107,47 +107,27 @@ get_all_transactions (Account *account, bool descendants)
 
 /* ================================================================ */
 
-void
-xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
-{
-    if (!acc) return;
-
-    if (abort_now)
-        (percentagefunc)(NULL, -1.0);
-
-    scrub_depth ++;
-    xaccAccountScrubOrphans (acc, percentagefunc);
-    gnc_account_foreach_descendant(acc,
-                                   (AccountCb)xaccAccountScrubOrphans, percentagefunc);
-    scrub_depth--;
-}
-
 static void
 TransScrubOrphansFast (Transaction *trans, Account *root)
 {
-    GList *node;
-    gchar *accname;
+    g_return_if_fail (trans && trans->common_currency && root);
 
-    if (!trans) return;
-    g_return_if_fail (root);
-    g_return_if_fail (trans->common_currency);
-
-    for (node = trans->splits; node; node = node->next)
+    for (GList *node = trans->splits; node; node = node->next)
     {
         Split *split = node->data;
-        Account *orph;
         if (abort_now) break;
 
         if (split->acc) continue;
 
         DEBUG ("Found an orphan\n");
 
-        accname = g_strconcat (_("Orphan"), "-",
-                               gnc_commodity_get_mnemonic (trans->common_currency),
-                               NULL);
-        orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency,
-                                                 accname, ACCT_TYPE_BANK,
-                                                 FALSE, TRUE);
+        gchar *accname = g_strconcat
+            (_("Orphan"), "-", gnc_commodity_get_mnemonic (trans->common_currency),
+             NULL);
+
+        Account *orph = xaccScrubUtilityGetOrMakeAccount
+            (root, trans->common_currency, accname, ACCT_TYPE_BANK, false, true);
+
         g_free (accname);
         if (!orph) continue;
 
@@ -155,43 +135,47 @@ TransScrubOrphansFast (Transaction *trans, Account *root)
     }
 }
 
-void
-xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
+static void
+AccountScrubOrphans (Account *acc, bool descendants, QofPercentageFunc percentagefunc)
 {
-    GList *node, *splits;
-    const char *str;
-    const char *message = _( "Looking for orphans in account %s: %u of %u");
-    guint total_splits = 0;
-    guint current_split = 0;
-
     if (!acc) return;
     scrub_depth++;
 
-    str = xaccAccountGetName (acc);
-    str = str ? str : "(null)";
-    PINFO ("Looking for orphans in account %s\n", str);
-    splits = xaccAccountGetSplitList(acc);
-    total_splits = g_list_length (splits);
+    GList *transactions = get_all_transactions (acc, descendants);
+    gint total_trans = g_list_length (transactions);
+    const char *message = _( "Looking for orphans in transaction: %u of %u");
+    guint current_trans = 0;
 
-    for (node = splits; node; node = node->next)
+    for (GList *node = transactions; node; current_trans++, node = node->next)
     {
-        Split *split = node->data;
-        if (current_split % 10 == 0)
+        Transaction *trans = node->data;
+        if (current_trans % 10 == 0)
         {
-            char *progress_msg = g_strdup_printf (message, str, current_split, total_splits);
-            (percentagefunc)(progress_msg, (100 * current_split) / total_splits);
+            char *progress_msg = g_strdup_printf (message, current_trans, total_trans);
+            (percentagefunc)(progress_msg, (100 * current_trans) / total_trans);
             g_free (progress_msg);
             if (abort_now) break;
         }
 
-        TransScrubOrphansFast (xaccSplitGetParent (split),
-                               gnc_account_get_root (acc));
-        current_split++;
+        TransScrubOrphansFast (trans, gnc_account_get_root (acc));
     }
     (percentagefunc)(NULL, -1.0);
     scrub_depth--;
+
+    g_list_free (transactions);
 }
 
+void
+xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
+{
+    AccountScrubOrphans (acc, false, percentagefunc);
+}
+
+void
+xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
+{
+    AccountScrubOrphans (acc, true, percentagefunc);
+}
 
 void
 xaccTransScrubOrphans (Transaction *trans)

commit 8628ca87150835d786909ecc902f3191ea880ecb
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed May 31 00:44:05 2023 +0800

    [Scrub.c] refactor xaccAccountTreeScrubImbalance
    
    The scrubbing routines are transaction oriented. Instead of
    xaccAccountTreeScrubImbalance calling xaccAccountScrubImbalance for
    each descendant, refactor so that the transaction list is generated
    only once. The scrubbing is faster and progress bar is more accurate.

diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c
index f1cd86f75c..d603a2b2ae 100644
--- a/libgnucash/engine/Scrub.c
+++ b/libgnucash/engine/Scrub.c
@@ -43,6 +43,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #include "Account.h"
 #include "AccountP.h"
@@ -52,6 +53,8 @@
 #include "gnc-commodity.h"
 #include "qofinstance-p.h"
 #include "gnc-session.h"
+#include "qofquery.h"
+#include "Query.h"
 
 #undef G_LOG_DOMAIN
 #define G_LOG_DOMAIN "gnc.engine.scrub"
@@ -88,6 +91,22 @@ gnc_get_ongoing_scrub (void)
 
 /* ================================================================ */
 
+static GList*
+get_all_transactions (Account *account, bool descendants)
+{
+    GList *accounts = descendants ? gnc_account_get_descendants (account) : NULL;
+    accounts = g_list_prepend (accounts, account);
+    QofQuery *q = qof_query_create_for (GNC_ID_TRANS);
+    QofBook *book = qof_session_get_book (gnc_get_current_session ());
+    qof_query_set_book (q, book);
+    xaccQueryAddAccountMatch (q, accounts, QOF_GUID_MATCH_ANY, QOF_QUERY_AND);
+    GList *transactions = g_list_copy (qof_query_run (q));
+    qof_query_destroy (q);
+    return transactions;
+}
+
+/* ================================================================ */
+
 void
 xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
 {
@@ -331,78 +350,59 @@ xaccSplitScrub (Split *split)
 
 /* ================================================================ */
 
-void
-xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
-{
-    if (!acc) return;
-
-    if (abort_now)
-        (percentagefunc)(NULL, -1.0);
 
-    scrub_depth++;
-    xaccAccountScrubImbalance (acc, percentagefunc);
-    gnc_account_foreach_descendant(acc,
-                                   (AccountCb)xaccAccountScrubImbalance, percentagefunc);
-    scrub_depth--;
-}
-
-void
-xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
+static void
+AccountScrubImbalance (Account *acc, bool descendants,
+                       QofPercentageFunc percentagefunc)
 {
-    GList *node, *splits;
-    const char *str;
-    const char *message = _( "Looking for imbalances in account %s: %u of %u");
-    gint split_count = 0, curr_split_no = 0;
+    const char *message = _( "Looking for imbalances in transaction date %s: %u of %u");
 
     if (!acc) return;
-    /* If it's a trading account and an imbalanced transaction is
-     * found the trading splits will be replaced, invalidating the
-     * split list in mid-traversal, see
-     * https://bugs.gnucash.org/show_bug.cgi?id=798346. Also the
-     * transactions will get scrubbed at least twice from their "real"
-     * accounts anyway so doing so from the trading accounts is wasted
-     * effort.
-     */
-    if (xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
-         return;
 
-    scrub_depth++;
-
-    str = xaccAccountGetName(acc);
-    str = str ? str : "(null)";
-    PINFO ("Looking for imbalances in account %s\n", str);
+    QofBook *book = qof_session_get_book (gnc_get_current_session ());
+    Account *root = gnc_book_get_root_account (book);
+    GList *transactions = get_all_transactions (acc, descendants);
+    guint count = g_list_length (transactions), curr_trans = 0;
 
-    splits = xaccAccountGetSplitList(acc);
-    split_count = g_list_length (splits);
-    for (node = splits; node; node = node->next)
+    scrub_depth++;
+    for (GList *node = transactions; node; node = node->next, curr_trans++)
     {
-        Split *split = node->data;
-        Transaction *trans = xaccSplitGetParent(split);
+        Transaction *trans = node->data;
         if (abort_now) break;
 
-        PINFO("Start processing split %d of %d",
-              curr_split_no + 1, split_count);
+        PINFO("Start processing transaction %d of %d", curr_trans + 1, count);
 
-        if (curr_split_no % 10 == 0)
+        if (curr_trans % 10 == 0)
         {
-            char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);
-            (percentagefunc)(progress_msg, (100 * curr_split_no) / split_count);
+            char *date = qof_print_date (xaccTransGetDate (trans));
+            char *progress_msg = g_strdup_printf (message, date, curr_trans, count);
+            (percentagefunc)(progress_msg, (100 * curr_trans) / count);
             g_free (progress_msg);
+            g_free (date);
         }
 
-        TransScrubOrphansFast (xaccSplitGetParent (split),
-                               gnc_account_get_root (acc));
-
+        TransScrubOrphansFast (trans, root);
         xaccTransScrubCurrency(trans);
+        xaccTransScrubImbalance (trans, root, NULL);
 
-        xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL);
-
-        PINFO("Finished processing split %d of %d",
-              curr_split_no + 1, split_count);
-        curr_split_no++;
+        PINFO("Finished processing transaction %d of %d", curr_trans + 1, count);
     }
     (percentagefunc)(NULL, -1.0);
     scrub_depth--;
+
+    g_list_free (transactions);
+}
+
+void
+xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
+{
+    AccountScrubImbalance (acc, true, percentagefunc);
+}
+
+void
+xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
+{
+    AccountScrubImbalance (acc, false, percentagefunc);
 }
 
 static Split *



Summary of changes:
 gnucash/gnome-utils/dialog-utils.c |  19 ++++
 gnucash/gnome-utils/dialog-utils.h |   6 ++
 gnucash/gnome/dialog-customer.c    |  22 +---
 gnucash/gnome/dialog-employee.c    |  22 +---
 gnucash/gnome/dialog-job.c         |  22 +---
 gnucash/gnome/dialog-vendor.c      |  22 +---
 libgnucash/engine/Scrub.c          | 205 +++++++++++++++++--------------------
 7 files changed, 135 insertions(+), 183 deletions(-)



More information about the gnucash-changes mailing list