gnucash maint: Multiple changes pushed

Robert Fewell bobit at code.gnucash.org
Thu Oct 22 08:52:10 EDT 2020


Updated	 via  https://github.com/Gnucash/gnucash/commit/8e5e3480 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/794b31a9 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/1be3b780 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/122cd682 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/6ee537e1 (commit)
	from  https://github.com/Gnucash/gnucash/commit/94a68dca (commit)



commit 8e5e3480ad691b803e9a742d2bd82059a752095b
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Oct 20 14:45:44 2020 +0100

    Bug 797984 - Infinite loop while Check&Repair AR and AP accounts
    
    If using the Check&Repair option from the Chart of Accounts on 'Account
    Receivable or Payable' add has a voided transaction will cause an
    infinite loop.
    
    This occurs from checking the transaction split amount is zero in
    gncScrubBusinessSplit and trying to delete it. As the transaction is
    read only as a result of being voided this fails so add a further
    condition for the 'else if' statement to include !is_void.

diff --git a/libgnucash/engine/ScrubBusiness.c b/libgnucash/engine/ScrubBusiness.c
index 818cdeae2..3c02531b5 100644
--- a/libgnucash/engine/ScrubBusiness.c
+++ b/libgnucash/engine/ScrubBusiness.c
@@ -582,7 +582,7 @@ gncScrubBusinessSplit (Split *split)
          * Such splits may be the result of scrubbing the business lots, which can
          * merge splits together while reducing superfluous lot links
          */
-        else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn))
+        else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn) && !is_void)
         {
             GNCLot *lot = xaccSplitGetLot (split);
             time64 pdate = xaccTransGetDate (txn);

commit 794b31a98e2f58bde5d094409885f74cdc2498a1
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Oct 20 14:45:14 2020 +0100

    Change Registers abort_scrub to use gnc_*_abort_scrub functions

diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c
index 8e5785f6d..9010465af 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -1923,7 +1923,6 @@ gnc_plugin_page_register_update_edit_menu (GncPluginPage* page, gboolean hide)
     gtk_action_set_visible (action,  !hide || can_paste);
 }
 
-static gboolean abort_scrub = FALSE;
 static gboolean is_scrubbing = FALSE;
 static gboolean show_abort_verify = TRUE;
 
@@ -1942,7 +1941,7 @@ finish_scrub (GncPluginPage* page)
         show_abort_verify = FALSE;
 
         if (ret)
-            abort_scrub = TRUE;
+            gnc_set_abort_scrub (TRUE);
     }
     return ret;
 }
@@ -5018,9 +5017,15 @@ scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
     switch (event->keyval)
     {
     case GDK_KEY_Escape:
-        abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
-                           _("'Check & Repair' is currently running, do you want to abort it?"));
-        return TRUE;
+        {
+            gboolean abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
+                 _("'Check & Repair' is currently running, do you want to abort it?"));
+        
+            if (abort_scrub)
+                gnc_set_abort_scrub (TRUE);
+        
+            return TRUE;
+        }
     default:
         break;
     }
@@ -5053,7 +5058,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
 
     gnc_suspend_gui_refresh();
     is_scrubbing = TRUE;
-    abort_scrub = FALSE;
+    gnc_set_abort_scrub (FALSE);
     window = GNC_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
     scrub_kp_handler_ID = g_signal_connect (G_OBJECT (window), "key-press-event",
                                             G_CALLBACK (scrub_kp_handler), NULL);
@@ -5061,7 +5066,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
 
     splits = qof_query_run (query);
     split_count = g_list_length (splits);
-    for (node = splits; node && !abort_scrub; node = node->next, curr_split_no++)
+    for (node = splits; node && !gnc_get_abort_scrub (); node = node->next, curr_split_no++)
     {
         Split* split = node->data;
 
@@ -5087,7 +5092,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
     gnc_window_show_progress (NULL, -1.0);
     is_scrubbing = FALSE;
     show_abort_verify = TRUE;
-    abort_scrub = FALSE;
+    gnc_set_abort_scrub (FALSE);
 
     gnc_resume_gui_refresh();
     LEAVE (" ");

commit 1be3b7808ddbcb48f898c7eca47155549ee9d601
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Oct 20 14:44:20 2020 +0100

    Allow the Check&Repair to be cancellable on a Register page
    
    Add a callback for a keypress event when on the Register page that
    checks for the Escape key and presents a dialog to confirm whether to
    abort the Check&Repair. A similar dialog is used if you decide to quit
    Gnucash while the Check&Repair is still running.

diff --git a/gnucash/gnome/gnc-plugin-page-register.c b/gnucash/gnome/gnc-plugin-page-register.c
index 5e36244e3..8e5785f6d 100644
--- a/gnucash/gnome/gnc-plugin-page-register.c
+++ b/gnucash/gnome/gnc-plugin-page-register.c
@@ -1925,22 +1925,26 @@ gnc_plugin_page_register_update_edit_menu (GncPluginPage* page, gboolean hide)
 
 static gboolean abort_scrub = FALSE;
 static gboolean is_scrubbing = FALSE;
+static gboolean show_abort_verify = TRUE;
 
 static gboolean
 finish_scrub (GncPluginPage* page)
 {
+    gboolean ret = FALSE;
+
     if (is_scrubbing)
     {
-        gboolean ret = gnc_verify_dialog (GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page))), FALSE, _("'Check & Repair' is currently running, do you want to abort it?"));
+        ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window
+                                (GNC_PLUGIN_PAGE(page))),
+                                FALSE,
+                                _("'Check & Repair' is currently running, do you want to abort it?"));
+        
+        show_abort_verify = FALSE;
+
         if (ret)
-        {
             abort_scrub = TRUE;
-            gnc_resume_gui_refresh (); // This is so quit does not complain about an ongoing operation.
-            return TRUE;
-        }
-        return FALSE;
     }
-    return TRUE;
+    return ret;
 }
 
 static gboolean
@@ -1953,8 +1957,11 @@ gnc_plugin_page_register_finish_pending (GncPluginPage* page)
     const gchar* name;
     gint response;
 
-    if (!finish_scrub (page))
-        return FALSE;
+    if (is_scrubbing && show_abort_verify)
+    {
+        if (!finish_scrub (page))
+            return FALSE;
+    }
 
     reg_page = GNC_PLUGIN_PAGE_REGISTER (page);
     priv = GNC_PLUGIN_PAGE_REGISTER_GET_PRIVATE (reg_page);
@@ -5000,10 +5007,26 @@ gnc_plugin_page_register_cmd_scrub_current (GtkAction* action,
     gnc_suspend_gui_refresh();
     scrub_split (gnc_split_register_get_current_split (reg));
     gnc_resume_gui_refresh();
-
     LEAVE (" ");
 }
 
+static gboolean
+scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    if (event->length == 0) return FALSE;
+
+    switch (event->keyval)
+    {
+    case GDK_KEY_Escape:
+        abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
+                           _("'Check & Repair' is currently running, do you want to abort it?"));
+        return TRUE;
+    default:
+        break;
+    }
+    return FALSE;
+}
+
 static void
 gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
                                         GncPluginPageRegister* plugin_page)
@@ -5013,6 +5036,7 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
     GncWindow* window;
     GList* node, *splits;
     gint split_count = 0, curr_split_no = 0;
+    gulong scrub_kp_handler_ID;
     const char* message = _ ("Checking splits in current register: %u of %u");
 
     g_return_if_fail (GNC_IS_PLUGIN_PAGE_REGISTER (plugin_page));
@@ -5029,7 +5053,10 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
 
     gnc_suspend_gui_refresh();
     is_scrubbing = TRUE;
+    abort_scrub = FALSE;
     window = GNC_WINDOW (GNC_PLUGIN_PAGE (plugin_page)->window);
+    scrub_kp_handler_ID = g_signal_connect (G_OBJECT (window), "key-press-event",
+                                            G_CALLBACK (scrub_kp_handler), NULL);
     gnc_window_set_progressbar_window (window);
 
     splits = qof_query_run (query);
@@ -5043,22 +5070,26 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction* action,
         PINFO ("Start processing split %d of %d",
                curr_split_no + 1, split_count);
 
+        scrub_split (split);
+
+        PINFO ("Finished processing split %d of %d",
+               curr_split_no + 1, split_count);
+
         if (curr_split_no % 10 == 0)
         {
             char* progress_msg = g_strdup_printf (message, curr_split_no, split_count);
             gnc_window_show_progress (progress_msg, (100 * curr_split_no) / split_count);
             g_free (progress_msg);
         }
-
-        scrub_split (split);
-
-        PINFO ("Finished processing split %d of %d",
-               curr_split_no + 1, split_count);
     }
 
+    g_signal_handler_disconnect (G_OBJECT(window), scrub_kp_handler_ID);
     gnc_window_show_progress (NULL, -1.0);
-    gnc_resume_gui_refresh();
     is_scrubbing = FALSE;
+    show_abort_verify = TRUE;
+    abort_scrub = FALSE;
+
+    gnc_resume_gui_refresh();
     LEAVE (" ");
 }
 

commit 122cd682f621396a5e295b2351079f92d76e27a7
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Oct 20 14:43:39 2020 +0100

    Add some additional places where Check&Repair can be aborted

diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c
index 66a261324..d5007cac1 100644
--- a/libgnucash/engine/Scrub.c
+++ b/libgnucash/engine/Scrub.c
@@ -84,6 +84,10 @@ 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,
@@ -320,6 +324,11 @@ 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,
diff --git a/libgnucash/engine/ScrubBusiness.c b/libgnucash/engine/ScrubBusiness.c
index 60da73794..818cdeae2 100644
--- a/libgnucash/engine/ScrubBusiness.c
+++ b/libgnucash/engine/ScrubBusiness.c
@@ -38,6 +38,7 @@
 #include "Account.h"
 #include "gncInvoice.h"
 #include "gncInvoiceP.h"
+#include "Scrub.h"
 #include "Scrub2.h"
 #include "ScrubBusiness.h"
 #include "Transaction.h"
@@ -614,6 +615,10 @@ gncScrubBusinessAccountLots (Account *acc, QofPercentageFunc percentagefunc)
     const char *message = _( "Checking business lots in account %s: %u of %u");
 
     if (!acc) return;
+
+    if (gnc_get_abort_scrub())
+        (percentagefunc)(NULL, -1.0);
+
     if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
 
     str = xaccAccountGetName(acc);
@@ -664,6 +669,10 @@ gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
     const char *message = _( "Checking business splits in account %s: %u of %u");
 
     if (!acc) return;
+
+    if (gnc_get_abort_scrub())
+        (percentagefunc)(NULL, -1.0);
+
     if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
 
     str = xaccAccountGetName(acc);
@@ -684,6 +693,9 @@ restart:
         PINFO("Start processing split %d of %d",
               curr_split_no + 1, split_count);
 
+        if (gnc_get_abort_scrub ())
+            break;
+
         if (curr_split_no % 100 == 0)
         {
             char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);

commit 6ee537e1a7fd053129c7cdaf2b3dcf7d34aa9cfa
Author: Robert Fewell <14uBobIT at gmail.com>
Date:   Tue Oct 20 14:42:32 2020 +0100

    Allow the Check&Repair routine to be cancellable from CoA
    
    Add a callback for a keypress event when on the Accounts page that
    checks for the Escape key and presents a dialog to confirm whether to
    abort the Check&Repair. A similar dialog is used if you decide to quit
    Gnucash while the Check&Repair is still running.

diff --git a/gnucash/gnome/gnc-plugin-page-account-tree.c b/gnucash/gnome/gnc-plugin-page-account-tree.c
index 7d5352c24..07654d1b7 100644
--- a/gnucash/gnome/gnc-plugin-page-account-tree.c
+++ b/gnucash/gnome/gnc-plugin-page-account-tree.c
@@ -425,6 +425,8 @@ gnc_plugin_page_account_tree_new (void)
 
 G_DEFINE_TYPE_WITH_PRIVATE(GncPluginPageAccountTree, gnc_plugin_page_account_tree, GNC_TYPE_PLUGIN_PAGE)
 
+static gboolean show_abort_verify = TRUE;
+
 static void
 prepare_scrubbing ()
 {
@@ -432,21 +434,42 @@ prepare_scrubbing ()
     gnc_set_abort_scrub (FALSE);
 }
 
+static void
+finish_scrubbing (GncWindow *window, gulong handler_id)
+{
+    g_signal_handler_disconnect (G_OBJECT(window), handler_id);
+    show_abort_verify = TRUE;
+    gnc_resume_gui_refresh ();
+}
+
 static gboolean
-finish (GncPluginPage* page)
+gnc_plugin_page_account_finish_pending (GncPluginPage* page)
 {
     if (gnc_get_ongoing_scrub ())
     {
-        gboolean ret = gnc_verify_dialog (GTK_WINDOW (gnc_plugin_page_get_window (GNC_PLUGIN_PAGE (page))), FALSE, _("'Check & Repair' is currently running, do you want to abort it?"));
-        if (ret)
+        if (show_abort_verify)
         {
-            gnc_set_abort_scrub (TRUE);
-            gnc_resume_gui_refresh (); // This is so quit does not complain about an ongoing operation.
-            return TRUE;
+            gboolean ret = gnc_verify_dialog (GTK_WINDOW(gnc_plugin_page_get_window
+                                             (GNC_PLUGIN_PAGE(page))), FALSE,
+                                             _("'Check & Repair' is currently running, do you want to abort it?"));
+
+            show_abort_verify = FALSE;
+
+            if (ret)
+                gnc_set_abort_scrub (TRUE);
+
+            return ret; // verify response
+        }
+        else
+        {
+            if (gnc_get_abort_scrub ())
+                return TRUE; // close
+            else
+                return FALSE; // no close
         }
-        return FALSE;
     }
-    return TRUE;
+    else
+        return TRUE; // normal close
 }
 
 static void
@@ -466,8 +489,7 @@ gnc_plugin_page_account_tree_class_init (GncPluginPageAccountTreeClass *klass)
     gnc_plugin_class->save_page       = gnc_plugin_page_account_tree_save_page;
     gnc_plugin_class->recreate_page   = gnc_plugin_page_account_tree_recreate_page;
     gnc_plugin_class->focus_page_function = gnc_plugin_page_account_tree_focus_widget;
-    gnc_plugin_class->finish_pending = finish;
-
+    gnc_plugin_class->finish_pending = gnc_plugin_page_account_finish_pending;
 
     plugin_page_signals[ACCOUNT_SELECTED] =
         g_signal_new ("account_selected",
@@ -1955,17 +1977,42 @@ gnc_plugin_page_account_tree_cmd_lots (GtkAction *action,
     gnc_lot_viewer_dialog (GTK_WINDOW(window), account);
 }
 
+static gboolean scrub_kp_handler (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+    if (event->length == 0) return FALSE;
+
+    switch (event->keyval)
+    {
+    case GDK_KEY_Escape:
+        {
+            gboolean abort_scrub = gnc_verify_dialog (GTK_WINDOW(widget), FALSE,
+                 _("'Check & Repair' is currently running, do you want to abort it?"));
+
+            if (abort_scrub)
+                gnc_set_abort_scrub (TRUE);
+
+            return TRUE;
+        }
+    default:
+        break;
+    }
+    return FALSE;
+}
+
 static void
 gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page)
 {
     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
     GncWindow *window;
+    gulong scrub_kp_handler_ID;
 
     g_return_if_fail (account != NULL);
 
     prepare_scrubbing ();
 
     window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+    scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
+                                            G_CALLBACK(scrub_kp_handler), NULL);
     gnc_window_set_progressbar_window (window);
 
     xaccAccountScrubOrphans (account, gnc_window_show_progress);
@@ -1977,8 +2024,7 @@ gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountT
 
     gncScrubBusinessAccount(account, gnc_window_show_progress);
 
-
-    gnc_resume_gui_refresh ();
+    finish_scrubbing (window, scrub_kp_handler_ID);
 }
 
 static void
@@ -1986,12 +2032,15 @@ gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAcco
 {
     Account *account = gnc_plugin_page_account_tree_get_current_account (page);
     GncWindow *window;
+    gulong scrub_kp_handler_ID;
 
     g_return_if_fail (account != NULL);
 
     prepare_scrubbing ();
 
     window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+    scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
+                                            G_CALLBACK(scrub_kp_handler), NULL);
     gnc_window_set_progressbar_window (window);
 
     xaccAccountTreeScrubOrphans (account, gnc_window_show_progress);
@@ -2003,7 +2052,7 @@ gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAcco
 
     gncScrubBusinessAccountTree(account, gnc_window_show_progress);
 
-    gnc_resume_gui_refresh ();
+    finish_scrubbing (window, scrub_kp_handler_ID);
 }
 
 static void
@@ -2011,10 +2060,13 @@ gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAcco
 {
     Account *root = gnc_get_current_root_account ();
     GncWindow *window;
+    gulong scrub_kp_handler_ID;
 
     prepare_scrubbing ();
 
     window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+    scrub_kp_handler_ID = g_signal_connect (G_OBJECT(window), "key-press-event",
+                                            G_CALLBACK(scrub_kp_handler), NULL);
     gnc_window_set_progressbar_window (window);
 
     xaccAccountTreeScrubOrphans (root, gnc_window_show_progress);
@@ -2025,7 +2077,7 @@ gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAcco
 
     gncScrubBusinessAccountTree(root, gnc_window_show_progress);
 
-    gnc_resume_gui_refresh ();
+    finish_scrubbing (window, scrub_kp_handler_ID);
 }
 
 /** @} */
diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c
index a16c0cf91..66a261324 100644
--- a/libgnucash/engine/Scrub.c
+++ b/libgnucash/engine/Scrub.c
@@ -66,6 +66,12 @@ gnc_set_abort_scrub (gboolean abort)
     abort_now = abort;
 }
 
+gboolean
+gnc_get_abort_scrub (void)
+{
+    return abort_now;
+}
+
 gboolean
 gnc_get_ongoing_scrub (void)
 {
diff --git a/libgnucash/engine/Scrub.h b/libgnucash/engine/Scrub.h
index bfaea845a..34ec0e598 100644
--- a/libgnucash/engine/Scrub.h
+++ b/libgnucash/engine/Scrub.h
@@ -74,6 +74,7 @@
  *    any scrubbing operation.
  */
 void gnc_set_abort_scrub (gboolean abort);
+gboolean gnc_get_abort_scrub (void);
 
 /** The gnc_get_ongoing_scrub () method returns TRUE if a scrub operation is ongoing.
  */



Summary of changes:
 gnucash/gnome/gnc-plugin-page-account-tree.c | 80 +++++++++++++++++++++++-----
 gnucash/gnome/gnc-plugin-page-register.c     | 74 ++++++++++++++++++-------
 libgnucash/engine/Scrub.c                    | 15 ++++++
 libgnucash/engine/Scrub.h                    |  1 +
 libgnucash/engine/ScrubBusiness.c            | 14 ++++-
 5 files changed, 150 insertions(+), 34 deletions(-)



More information about the gnucash-changes mailing list