gnucash maint: [auto-clear] provide live feedback when a valid end_amount is input

Christopher Lam clam at code.gnucash.org
Thu Nov 5 09:51:37 EST 2020


Updated	 via  https://github.com/Gnucash/gnucash/commit/afcf1765 (commit)
	from  https://github.com/Gnucash/gnucash/commit/7e4f120f (commit)



commit afcf1765f6c56931d5b4545613d32b8d60c4e7bc
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Nov 1 11:39:12 2020 +0800

    [auto-clear] provide live feedback when a valid end_amount is input

diff --git a/gnucash/gnome/window-autoclear.c b/gnucash/gnome/window-autoclear.c
index f5270be82..d7dec2eab 100644
--- a/gnucash/gnome/window-autoclear.c
+++ b/gnucash/gnome/window-autoclear.c
@@ -52,6 +52,7 @@ struct _AutoClearWindow
     GtkWidget *cancel_button;
     GtkWidget *show_cleared_splits_button;
     GtkLabel *status_label;
+    GList *toclear_list;
 };
 
 /** Callback prototypes************************************************/
@@ -122,47 +123,44 @@ void
 gnc_autoclear_window_ok_cb (GtkWidget *widget,
                             AutoClearWindow *data)
 {
-    GList *toclear_list;
     gnc_numeric toclear_value;
     gchar *errmsg = NULL;
 
     g_return_if_fail (widget && data);
 
-    toclear_value = gnc_amount_edit_get_amount(data->end_value);
+    /* sanity check: if toclear_list is null, bail out. but this
+       should not happen because the OK button is disabled if there is
+       autoclear error, and toclear_list is null */
+    g_return_if_fail (data->toclear_list);
 
-    if (gnc_reverse_balance(data->account))
-        toclear_value = gnc_numeric_neg (toclear_value);
-
-    toclear_value = gnc_numeric_convert
-        (toclear_value, xaccAccountGetCommoditySCU(data->account), GNC_HOW_RND_ROUND);
+    xaccAccountBeginEdit (data->account);
+    for (GList *node = data->toclear_list; node; node = node->next)
+        xaccSplitSetReconcile (node->data, CREC);
+    xaccAccountCommitEdit (data->account);
 
-    toclear_list = gnc_account_get_autoclear_splits
-        (data->account, toclear_value, &errmsg);
+    if (gtk_toggle_button_get_active
+        (GTK_TOGGLE_BUTTON (data->show_cleared_splits_button)))
+        show_cleared_splits (data->toclear_list);
 
-    if (errmsg)
-    {
-        gtk_label_set_text (data->status_label, errmsg);
-        gnc_amount_edit_set_amount (data->end_value, toclear_value);
-        gtk_editable_select_region (GTK_EDITABLE (data->end_value), 0, -1);
-        g_free (errmsg);
-    }
-    else
-    {
-        xaccAccountBeginEdit (data->account);
-        for (GList *node = toclear_list; node; node = node->next)
-            xaccSplitSetReconcile (node->data, CREC);
-        xaccAccountCommitEdit (data->account);
-
-        if (gtk_toggle_button_get_active
-            (GTK_TOGGLE_BUTTON (data->show_cleared_splits_button)))
-            show_cleared_splits (toclear_list);
+    /* Close window */
+    gnc_autoclear_window_cancel_cb (widget, data);
+}
 
-        g_list_free (toclear_list);
+static gboolean
+gnc_autoclear_window_delete_cb (GtkWidget *widget, GdkEvent  *event,
+                                AutoClearWindow *data)
+{
+    if (data->toclear_list)
+        g_list_free (data->toclear_list);
+    g_free(data);
+    return FALSE;
+}
 
-        /* Close window */
-        gtk_widget_destroy (data->window);
-        g_free (data);
-    }
+static void
+gnc_autoclear_end_value_activate_cb (GtkWidget *widget, AutoClearWindow *data)
+{
+    if (data->toclear_list)
+        gnc_autoclear_window_ok_cb (widget, data);
 }
 
 void
@@ -171,12 +169,80 @@ gnc_autoclear_window_cancel_cb (GtkWidget *widget,
 {
     /* Close window */
     gtk_widget_destroy(data->window);
+    if (data->toclear_list)
+        g_list_free (data->toclear_list);
     g_free(data);
 }
 
-static void clear_status_label_cb (GtkEditable *editable, AutoClearWindow *data)
+#define MAX_LENGTH 50
+
+static void end_value_changed_cb (GtkEditable *editable, AutoClearWindow *data)
 {
-    gtk_label_set_text (data->status_label, "");
+    gnc_numeric toclear_value;
+    gchar *errmsg = NULL;
+
+    if (gnc_amount_edit_expr_is_valid (data->end_value, &toclear_value, TRUE))
+    {
+        gtk_widget_set_sensitive (data->ok_button, FALSE);
+        gtk_label_set_text (data->status_label, "");
+        return;
+    }
+
+    if (gnc_reverse_balance (data->account))
+        toclear_value = gnc_numeric_neg (toclear_value);
+
+    toclear_value = gnc_numeric_convert
+        (toclear_value, xaccAccountGetCommoditySCU(data->account), GNC_HOW_RND_ROUND);
+
+    if (data->toclear_list)
+        g_list_free (data->toclear_list);
+
+    data->toclear_list = gnc_account_get_autoclear_splits
+        (data->account, toclear_value, &errmsg);
+
+    gtk_widget_set_sensitive (data->ok_button, errmsg == NULL);
+
+    if (errmsg)
+    {
+        gtk_widget_set_sensitive (data->ok_button, FALSE);
+        gtk_label_set_text (data->status_label, errmsg);
+        g_free (errmsg);
+    }
+    else
+    {
+        gchar *status = g_strdup (_("The following splits will be cleared:"));
+        GNCPrintAmountInfo p_info = gnc_account_print_info (data->account, TRUE);
+        gboolean reverse = gnc_reverse_balance (data->account);
+        for (GList *node = data->toclear_list; node; node = node->next)
+        {
+            Transaction *trans = xaccSplitGetParent (node->data);
+            gnc_numeric amount = xaccSplitGetAmount (node->data);
+            const gchar *desc = xaccTransGetDescription (trans);
+            gchar *datestr = qof_print_date (xaccTransGetDate (trans));
+            gchar *newdesc, *newstatus;
+
+            if (g_utf8_strlen (desc, -1) > MAX_LENGTH)
+            {
+                gchar *trunc = g_utf8_substring (desc, 0, MAX_LENGTH);
+                newdesc = g_strdup_printf ("%s...", trunc);
+                g_free (trunc);
+            }
+            else
+                newdesc = g_strdup (desc);
+
+            if (reverse)
+                amount = gnc_numeric_neg (amount);
+
+            newstatus = g_strdup_printf ("%s\n%s %s %s", status, datestr,
+                                         newdesc, xaccPrintAmount (amount, p_info));
+            g_free (status);
+            g_free (datestr);
+            g_free (newdesc);
+            status = newstatus;
+        }
+        gtk_label_set_text (data->status_label, status);
+        g_free (status);
+    }
 }
 
 
@@ -212,13 +278,23 @@ autoClearWindow (GtkWidget *parent, Account *account)
     // Set the name for this dialog so it can be easily manipulated with css
     gtk_widget_set_name (GTK_WIDGET(data->window), "gnc-id-auto-clear");
 
+    data->ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button"));
+    gtk_widget_set_sensitive (data->ok_button, FALSE);
+
+    data->cancel_button = GTK_WIDGET (gtk_builder_get_object
+                                      (builder, "cancel_button"));
+
     data->show_cleared_splits_button =
         GTK_WIDGET (gtk_builder_get_object (builder, "show_cleared_splits_button"));
 
     /* Add amount edit box */
     data->end_value = GNC_AMOUNT_EDIT(gnc_amount_edit_new());
     g_signal_connect(GTK_WIDGET(data->end_value), "activate",
+                     G_CALLBACK(gnc_autoclear_end_value_activate_cb), data);
+    g_signal_connect(GTK_WIDGET(data->ok_button), "activate",
                      G_CALLBACK(gnc_autoclear_window_ok_cb), data);
+    g_signal_connect(GTK_WIDGET(data->cancel_button), "activate",
+                     G_CALLBACK(gnc_autoclear_window_cancel_cb), data);
 
     box   = GTK_BOX(gtk_builder_get_object (builder, "end_value_box"));
     gtk_box_pack_start(box, GTK_WIDGET(data->end_value), TRUE, TRUE, 0);
@@ -237,7 +313,10 @@ autoClearWindow (GtkWidget *parent, Account *account)
     data->status_label = GTK_LABEL(gtk_builder_get_object (builder, "status_label"));
 
     g_signal_connect (GTK_WIDGET(data->end_value), "changed",
-                      G_CALLBACK(clear_status_label_cb), data);
+                      G_CALLBACK(end_value_changed_cb), data);
+
+    g_signal_connect (data->window, "delete-event",
+                      G_CALLBACK (gnc_autoclear_window_delete_cb), data);
 
     if (parent != NULL)
         gtk_window_set_transient_for (GTK_WINDOW (data->window), GTK_WINDOW (parent));



Summary of changes:
 gnucash/gnome/window-autoclear.c | 147 ++++++++++++++++++++++++++++++---------
 1 file changed, 113 insertions(+), 34 deletions(-)



More information about the gnucash-changes mailing list