gnucash maint: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Sun Apr 10 00:30:53 EDT 2022


Updated	 via  https://github.com/Gnucash/gnucash/commit/736d2231 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d022651f (commit)
	 via  https://github.com/Gnucash/gnucash/commit/40d5db43 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/0c4d438a (commit)
	 via  https://github.com/Gnucash/gnucash/commit/aab33954 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/ebbf7565 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/c8f1caa9 (commit)
	from  https://github.com/Gnucash/gnucash/commit/6a668df1 (commit)



commit 736d2231987e8578ab2f70cef46cbce4e0e5f17a
Merge: d022651f3 aab33954e
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Apr 10 12:05:08 2022 +0800

    Merge branch 'maint-progress3' into maint #1312


commit d022651f38fdee1a9ceca100c819455db3a1c7b9
Merge: 6a668df16 40d5db43e
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Apr 10 12:04:51 2022 +0800

    Merge branch 'maint-progress2' into maint #1311


commit 40d5db43e63a749ea70af4330a226119b6e6e1b3
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed Apr 6 07:15:39 2022 +0800

    Bug 797163 - qof_book_get_option segfaults when retrieving a non-leaf frame
    
    returns a KvpFrame into a nested list of pairs
    returns a KvpValue GLIST into a list

diff --git a/bindings/guile/gnc-kvp-guile.cpp b/bindings/guile/gnc-kvp-guile.cpp
index e9748ebbf..33c04cf33 100644
--- a/bindings/guile/gnc-kvp-guile.cpp
+++ b/bindings/guile/gnc-kvp-guile.cpp
@@ -1,6 +1,7 @@
 #include <guid.hpp>
 #include <kvp-frame.hpp>
 #include <libguile.h>
+#include <numeric>
 
 extern "C"
 {
@@ -21,6 +22,17 @@ extern "C"
  *       types based only on the scheme type.
  */
 
+static bool scm_is_list_of_string_pairs (SCM val)
+{
+    for (; !scm_is_null (val); val = scm_cdr (val))
+    {
+        if (!(scm_is_pair (val) && scm_is_pair (scm_car (val)) &&
+              scm_is_string (scm_caar (val))))
+            return false;
+    }
+    return true;
+}
+
 KvpValue *
 gnc_scm_to_kvp_value_ptr(SCM val)
 {
@@ -59,16 +71,31 @@ gnc_scm_to_kvp_value_ptr(SCM val)
     {
         return new KvpValue{gnc_scm_to_utf8_string(val)};
     }
-    else if (SWIG_IsPointerOfType(val, SWIG_TypeQuery("_p_KvpFrame")))
+    else if (!scm_is_null (val) && scm_is_list_of_string_pairs (val))
+    {
+        auto frame = new KvpFrame;
+        for (; !scm_is_null (val); val = scm_cdr (val))
+        {
+            auto key_str = scm_to_utf8_stringn (scm_caar (val), nullptr);
+            auto val_scm = scm_cdar (val);
+            auto prev = frame->set ({key_str}, gnc_scm_to_kvp_value_ptr (val_scm));
+            g_free (key_str);
+            // there is a pre-existing key-value
+            if (prev)
+                delete prev;
+        }
+        return new KvpValue (frame);
+    }
+    else if (!scm_is_null (val) && scm_is_list (val))
     {
-#define FUNC_NAME G_STRFUNC
-        auto vp_frame = SWIG_MustGetPtr(val,
-                                        SWIG_TypeQuery("_p_KvpFrame"), 1, 0);
-        KvpFrame *frame = static_cast<KvpFrame*>(vp_frame);
-#undef FUNC_NAME
-        return new KvpValue{frame};
+        GList *kvplist = nullptr;
+        for (; !scm_is_null (val); val = scm_cdr (val))
+        {
+            auto elt = gnc_scm_to_kvp_value_ptr (scm_car (val));
+            kvplist = g_list_prepend (kvplist, elt);
+        }
+        return new KvpValue (g_list_reverse (kvplist));
     }
-    /* FIXME: add list handler here */
     return NULL;
 }
 
@@ -102,12 +129,26 @@ gnc_kvp_value_ptr_to_scm(KvpValue* val)
     break;
     case KvpValue::Type::FRAME:
     {
-        auto frame = val->get<KvpFrame*>();
-        if (frame != nullptr)
-            return SWIG_NewPointerObj(frame, SWIG_TypeQuery("_p_KvpFrame"), 0);
+        auto frame { val->get<KvpFrame*>() };
+        auto acc = [](const auto& rv, const auto& iter)
+        {
+            auto key_scm { scm_from_utf8_string (iter.first) };
+            auto val_scm { gnc_kvp_value_ptr_to_scm (iter.second) };
+            return scm_acons (key_scm, val_scm, rv);
+        };
+        return scm_reverse (std::accumulate (frame->begin(), frame->end(), SCM_EOL, acc));
     }
     break;
     case KvpValue::Type::GLIST:
+    {
+        SCM lst = SCM_EOL;
+        for (GList *n = val->get<GList*>(); n; n = n->next)
+        {
+            auto elt = gnc_kvp_value_ptr_to_scm (static_cast<KvpValue*>(n->data));
+            lst = scm_cons (elt, lst);
+        }
+        return scm_reverse (lst);
+    }
     default:
 	break;
     }
diff --git a/bindings/guile/test/CMakeLists.txt b/bindings/guile/test/CMakeLists.txt
index ee48e6f49..75e792795 100644
--- a/bindings/guile/test/CMakeLists.txt
+++ b/bindings/guile/test/CMakeLists.txt
@@ -61,6 +61,7 @@ set (scm_tests_with_srfi64_SOURCES
   test-core-utils.scm
   test-business-core.scm
   test-scm-engine.scm
+  test-scm-kvpvalue.scm
   )
 
 if (HAVE_SRFI64)
diff --git a/bindings/guile/test/test-scm-kvpvalue.scm b/bindings/guile/test/test-scm-kvpvalue.scm
new file mode 100644
index 000000000..a8d36b801
--- /dev/null
+++ b/bindings/guile/test/test-scm-kvpvalue.scm
@@ -0,0 +1,68 @@
+(use-modules (srfi srfi-64))
+(use-modules (tests srfi64-extras))
+(use-modules (gnucash engine))
+(use-modules (gnucash app-utils))
+
+(define (run-test)
+  (test-runner-factory gnc:test-runner)
+  (test-begin "test-app-utils")
+  (test-kvp-access)
+  (test-end "test-app-utils"))
+
+(define (setup book)
+  (qof-book-set-option book "bla" '("top" "lvl1a"))
+  (qof-book-set-option book "arg" '("top" "lvl1b"))
+  (qof-book-set-option book "baf" '("top" "lvl1c" "lvl2" "lvl3")))
+
+(define (teardown)
+  (gnc-clear-current-session))
+
+(define (test-kvp-access)
+  (define book (gnc-get-current-book))
+  (test-begin "kvp-access from guile")
+
+  (setup book)
+
+  (test-equal "top/lvl1a"
+    "bla"
+    (qof-book-get-option book '("top" "lvl1a")))
+
+  (test-equal "top/lvl1b"
+    "arg"
+    (qof-book-get-option book '("top" "lvl1b")))
+
+  (test-equal "top/lvl1c/lvl2/lvl3"
+    "baf"
+    (qof-book-get-option book '("top" "lvl1c" "lvl2" "lvl3")))
+
+  (test-equal "top/lvl1c/lvl2"
+    '(("lvl3" . "baf"))
+    (qof-book-get-option book '("top" "lvl1c" "lvl2")))
+
+  (test-equal "top/lvl1c"
+    '(("lvl2" ("lvl3" . "baf")))
+    (qof-book-get-option book '("top" "lvl1c")))
+
+  ;; this tests the reading & writing of KvpFrame, copying branch
+  ;; from top/lvl1c to top/lvl1d
+  (qof-book-set-option book
+                       (qof-book-get-option book '("top" "lvl1c"))
+                       '("top" "lvl1d"))
+
+  (test-equal "top/lvl1d, after copying from top/lvl1c"
+    '(("lvl2" ("lvl3" . "baf")))
+    (qof-book-get-option book '("top" "lvl1d")))
+
+  (test-equal "top/lvl1c/lvl2/error"
+    #f
+    (qof-book-get-option book '("top" "lvl1c" "lvl2" "error")))
+
+  (test-equal "top"
+    '(("lvl1a" . "bla")
+      ("lvl1b" . "arg")
+      ("lvl1c" ("lvl2" ("lvl3" . "baf")))
+      ("lvl1d" ("lvl2" ("lvl3" . "baf"))))
+    (qof-book-get-option book '("top")))
+
+  (test-end "kvp-access from guile")
+  (teardown))

commit 0c4d438a0e027f2dd295bc5f679adfe56f69f389
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Wed Apr 6 07:15:09 2022 +0800

    [kvp-frame.cpp] expose iterator, skip inexistent frame

diff --git a/libgnucash/engine/kvp-frame.cpp b/libgnucash/engine/kvp-frame.cpp
index 74d33b8fa..56be042d4 100644
--- a/libgnucash/engine/kvp-frame.cpp
+++ b/libgnucash/engine/kvp-frame.cpp
@@ -78,6 +78,8 @@ KvpFrame::get_child_frame_or_nullptr (Path const & path) noexcept
     if (map_iter == m_valuemap.end ())
         return nullptr;
     auto child = map_iter->second->get <KvpFrame *> ();
+    if (!child)
+        return nullptr;
     Path send;
     std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
     return child->get_child_frame_or_nullptr (send);
diff --git a/libgnucash/engine/kvp-frame.hpp b/libgnucash/engine/kvp-frame.hpp
index 253eec318..704d5a3d7 100644
--- a/libgnucash/engine/kvp-frame.hpp
+++ b/libgnucash/engine/kvp-frame.hpp
@@ -226,6 +226,9 @@ struct KvpFrameImpl
     bool empty() const noexcept { return m_valuemap.empty(); }
     friend int compare(const KvpFrameImpl&, const KvpFrameImpl&) noexcept;
 
+    map_type::iterator begin() { return m_valuemap.begin(); }
+    map_type::iterator end() { return m_valuemap.end(); }
+
     private:
     map_type m_valuemap;
 

commit aab33954e73567c21e98bb5c610fefa880640049
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Apr 8 22:34:15 2022 +0800

    [gnc-numeric.cpp] Reduce logging level of gnc_numeric exception message
    
    Exceptions are expected in some use cases.

diff --git a/libgnucash/engine/gnc-numeric.cpp b/libgnucash/engine/gnc-numeric.cpp
index 277e01e0f..3beaddfbb 100644
--- a/libgnucash/engine/gnc-numeric.cpp
+++ b/libgnucash/engine/gnc-numeric.cpp
@@ -1090,7 +1090,7 @@ gnc_numeric_to_decimal(gnc_numeric *a, guint8 *max_decimal_places)
     }
     catch (const std::exception& err)
     {
-        PWARN("%s", err.what());
+        PINFO ("%s", err.what());
         return FALSE;
     }
 }

commit ebbf7565c985dd03dd14135c6cd4b5b6770c74ac
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Tue Apr 5 23:15:26 2022 +0800

    Bug 798496 - gncEntry Quantity and Discount are misusing commodity scu

diff --git a/gnucash/register/ledger-core/gncEntryLedger.c b/gnucash/register/ledger-core/gncEntryLedger.c
index bff49b369..6bcfb8d0c 100644
--- a/gnucash/register/ledger-core/gncEntryLedger.c
+++ b/gnucash/register/ledger-core/gncEntryLedger.c
@@ -265,22 +265,6 @@ gnc_entry_ledger_config_cells (GncEntryLedger *ledger)
     ((ComboCell *)
      gnc_table_layout_get_cell (ledger->table->layout, ENTRY_ACTN_CELL), FALSE);
 
-    /* Use GNC_COMMODITY_MAX_FRACTION for all prices and quantities */
-    gnc_price_cell_set_fraction
-    ((PriceCell *)
-     gnc_table_layout_get_cell (ledger->table->layout, ENTRY_PRIC_CELL),
-     GNC_COMMODITY_MAX_FRACTION);
-
-    gnc_price_cell_set_fraction
-    ((PriceCell *)
-     gnc_table_layout_get_cell (ledger->table->layout, ENTRY_DISC_CELL),
-     GNC_COMMODITY_MAX_FRACTION);
-
-    gnc_price_cell_set_fraction
-    ((PriceCell *) gnc_table_layout_get_cell (ledger->table->layout,
-            ENTRY_QTY_CELL),
-     GNC_COMMODITY_MAX_FRACTION);
-
     /* add menu items for the action and payment cells */
     gnc_entry_ledger_config_action (ledger);
 }

commit c8f1caa95f6d6d9cba215a21d40e12c9164cdc81
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Tue Apr 5 23:15:09 2022 +0800

    Bug 798493 - Invoice Report Quantity & Unit Price fields have limited decimal precision on printed invoices
    
    use xaccPrintAmount which formats number nicely.

diff --git a/gnucash/report/reports/standard/invoice.scm b/gnucash/report/reports/standard/invoice.scm
index ef4263108..02916ff7f 100644
--- a/gnucash/report/reports/standard/invoice.scm
+++ b/gnucash/report/reports/standard/invoice.scm
@@ -447,7 +447,9 @@ for styling the invoice. Please see the exported report for the CSS class names.
           (addif (quantity-col used-columns)
                  (gnc:make-html-table-cell/markup
                   "number-cell"
-                  (gncEntryGetDocQuantity entry credit-note?)))
+                  (xaccPrintAmount
+                   (gncEntryGetDocQuantity entry credit-note?)
+                   (gnc-default-print-info #f))))
 
           (addif (price-col used-columns)
                  (gnc:make-html-table-cell/markup



Summary of changes:
 bindings/guile/gnc-kvp-guile.cpp              | 63 ++++++++++++++++++++-----
 bindings/guile/test/CMakeLists.txt            |  1 +
 bindings/guile/test/test-scm-kvpvalue.scm     | 68 +++++++++++++++++++++++++++
 gnucash/register/ledger-core/gncEntryLedger.c | 16 -------
 gnucash/report/reports/standard/invoice.scm   |  4 +-
 libgnucash/engine/gnc-numeric.cpp             |  2 +-
 libgnucash/engine/kvp-frame.cpp               |  2 +
 libgnucash/engine/kvp-frame.hpp               |  3 ++
 8 files changed, 130 insertions(+), 29 deletions(-)
 create mode 100644 bindings/guile/test/test-scm-kvpvalue.scm



More information about the gnucash-changes mailing list