gnucash stable: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Mon Jun 2 20:45:39 EDT 2025


Updated	 via  https://github.com/Gnucash/gnucash/commit/2fd89a27 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d89792a4 (commit)
	from  https://github.com/Gnucash/gnucash/commit/7b5d13b3 (commit)



commit 2fd89a2748aa15f1b9bc208a74a23356948d11a9
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Jun 1 21:26:29 2025 +0800

    [reports] delay generation of reports from a report.
    
    Previously a report with multiple linked reports will cause them to be
    generated.
    
    This change will delay the reports generation, simply storing the
    required data report into a integer-keyed hash table, and is retrieved
    when the link is clicked.

diff --git a/gnucash/gnome/gnc-plugin-page-report.cpp b/gnucash/gnome/gnc-plugin-page-report.cpp
index a700a233c2..3e21c1f195 100644
--- a/gnucash/gnome/gnc-plugin-page-report.cpp
+++ b/gnucash/gnome/gnc-plugin-page-report.cpp
@@ -674,7 +674,12 @@ gnc_plugin_page_report_load_cb (GncHtml * html, URLType type,
             && (strlen(location) > 3)
             && !strncmp("id=", location, 3))
     {
-        report_id = atoi(location + 3);
+        report_id = gnc_report_id_string_to_report_id (location + 3);
+        if (report_id < 0)
+        {
+            LEAVE ("id_string error %s", location);
+            return;
+        }
         DEBUG( "parsed id=%d", report_id );
     }
     else if (!g_strcmp0( type, URL_TYPE_OPTIONS)
diff --git a/gnucash/report/gnc-report.cpp b/gnucash/report/gnc-report.cpp
index 4181ecc039..0a3974d3a7 100644
--- a/gnucash/report/gnc-report.cpp
+++ b/gnucash/report/gnc-report.cpp
@@ -257,12 +257,29 @@ gnc_report_name( SCM report )
     return gnc_scm_call_1_to_string(get_name, report);
 }
 
+gint
+gnc_report_id_string_to_report_id (const char *id_string)
+{
+    g_return_val_if_fail (id_string, -1);
+
+    char *end_ptr;
+    uint rpt_id = std::strtoul (id_string, &end_ptr, 10);
+    if (end_ptr == id_string) return -1;
+    if (*end_ptr == '\0') return rpt_id;
+    if (*end_ptr != '|') return -1;
+
+    auto anchor_str = end_ptr + 1;
+    uint anchor_id = std::strtoul (anchor_str, &end_ptr, 10);
+    if (end_ptr == anchor_str || *end_ptr != '\0') return -1;
+
+    const SCM get_linked = scm_c_eval_string ("gnc:report-get-linked-report");
+    return scm_to_uint (scm_call_2 (get_linked, scm_from_uint (rpt_id), scm_from_uint (anchor_id)));
+}
+
 gboolean
 gnc_run_report_id_string_with_error_handling (const char * id_string, char **data,
                                               gchar **errmsg)
 {
-    gint report_id;
-
     g_return_val_if_fail (id_string, FALSE);
     g_return_val_if_fail (data, FALSE);
     *data = NULL;
@@ -270,7 +287,8 @@ gnc_run_report_id_string_with_error_handling (const char * id_string, char **dat
     if (strncmp ("id=", id_string, 3) != 0)
         return FALSE;
 
-    if (sscanf (id_string + 3, "%d", &report_id) != 1)
+    gint report_id = gnc_report_id_string_to_report_id (id_string + 3);
+    if (report_id < 0)
         return FALSE;
 
     return gnc_run_report_with_error_handling (report_id, data, errmsg);
diff --git a/gnucash/report/gnc-report.h b/gnucash/report/gnc-report.h
index 0b517eeeff..0ea9fd0b22 100644
--- a/gnucash/report/gnc-report.h
+++ b/gnucash/report/gnc-report.h
@@ -41,6 +41,7 @@ extern "C"
  */
 void gnc_report_init(void);
 
+gint gnc_report_id_string_to_report_id (const char *id_string);
 
 gboolean gnc_run_report_with_error_handling(gint report_id,
                                             gchar** data,
diff --git a/gnucash/report/html-utilities.scm b/gnucash/report/html-utilities.scm
index 904184a4bd..847da82abf 100644
--- a/gnucash/report/html-utilities.scm
+++ b/gnucash/report/html-utilities.scm
@@ -167,19 +167,22 @@
 ;; section, name, and value of the function.
 (define (gnc:make-report-anchor reportname src-report
                                 optionlist)
-  (let ((src-options (gnc:report-options src-report))
-        (options (gnc:make-report-options reportname)))
-    (if options
-        (begin
-          (gnc:options-copy-values src-options options)
-          (for-each
-           (lambda (l)
-             (gnc-set-option (gnc:optiondb options) (car l) (cadr l) (caddr l)))
-           optionlist)
-          (let ((id (gnc:make-report reportname options)))
-            (gnc:report-anchor-text id)))
-        (warn "gnc:make-report-anchor: No such report: " reportname))))
-
+  (let ((anchor-id (gnc:report-add-anchor!
+                    src-report (list reportname (gnc:report-options src-report) optionlist))))
+    (gnc-build-url URL-TYPE-REPORT (format #f "id=~a|~a" (gnc:report-id src-report) anchor-id) "")))
+
+(define-public (gnc:report-get-linked-report src-id id)
+  (match (gnc:report-get-anchor (gnc-report-find src-id) id)
+    ((reportname src-options optionlist)
+     (let* ((options (gnc:make-report-options reportname))
+            (db (gnc:optiondb options)))
+       (gnc:options-copy-values src-options options)
+       (for-each
+        (lambda (l)
+          (gnc-set-option db (car l) (cadr l) (caddr l)))
+        optionlist)
+       (gnc:make-report reportname options)))
+    (_ (gnc:error "invalid id " id))))
 
 ;; returns the account name as html-text and anchor to the register.
 (define (gnc:html-account-anchor acct)
diff --git a/gnucash/report/report-core.scm b/gnucash/report/report-core.scm
index 050611ab0a..6828e39538 100644
--- a/gnucash/report/report-core.scm
+++ b/gnucash/report/report-core.scm
@@ -760,6 +760,7 @@ not found.")))
         (and template
              (let* ((renderer (gnc:report-template-renderer template))
                     (stylesheet (gnc:report-stylesheet report))
+                    (_ (report-set-anchors! report (ht:make-hash-table)))
                     (doc (renderer report))
                     (html (cond
                            ((string? doc) doc)

commit d89792a4b7d20952f0b9ba229a153359786a3352
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Sun Jun 1 21:22:45 2025 +0800

    [report-core.scm] add report anchor mechanism
    
    The <report> object contains the data for a report with options. Add a
    mechanism to store the list of anchors contained in it; adding an
    anchor will return the unique integer key referring to the report's
    anchor; retrieval will return the anchor.
    
    Note: each anchor will typically be: (list reportname src-options
    optionlist)
    
    whereby reportname is the desired report guid, src-options is the
    originating report options object, and optionlist is a list of options to be
    set.

diff --git a/gnucash/report/report-core.scm b/gnucash/report/report-core.scm
index b9735d8f91..050611ab0a 100644
--- a/gnucash/report/report-core.scm
+++ b/gnucash/report/report-core.scm
@@ -35,6 +35,7 @@
 (use-modules (srfi srfi-2))
 (use-modules (srfi srfi-9))
 (use-modules (srfi srfi-26))
+(use-modules ((srfi srfi-69) #:prefix ht:))            ;for O(1) hash-table-size
 (use-modules (gnucash report report-register-hooks))
 (use-modules (gnucash report html-style-sheet))
 (use-modules (gnucash report html-document))
@@ -75,6 +76,7 @@
 (export gnc:report-embedded-list)
 (export gnc:report-export-thunk)
 (export gnc:report-export-types)
+(export gnc:report-get-anchor)          ;return anchor by key
 (export gnc:report-id)
 (export gnc:report-is-invoice-report?)
 (export gnc:report-menu-name)
@@ -84,6 +86,7 @@
 (export gnc:report-render-html)
 (export gnc:render-report)
 (export gnc:report-serialize)
+(export gnc:report-add-anchor!)         ;add anchor, returns the integer key
 (export gnc:report-set-ctext!)
 (export gnc:report-set-dirty?!)
 (export gnc:report-set-editor-widget!)
@@ -324,7 +327,7 @@ not found.")))
 
 ;; A <report> represents an instantiation of a particular report type.
 (define-record-type <report>
-  (make-report type id options dirty? needs-save? editor-widget ctext custom-template)
+  (make-report type id options dirty? needs-save? editor-widget ctext custom-template anchors)
   report?
   (type report-type report-set-type!)
   (id report-id report-set-id!)
@@ -333,6 +336,7 @@ not found.")))
   (needs-save? report-needs-save? report-set-needs-save?!)
   (editor-widget report-editor-widget report-set-editor-widget!)
   (ctext report-ctext report-set-ctext!)
+  (anchors report-get-anchors report-set-anchors!)
   (custom-template report-custom-template report-set-custom-template!))
 
 (define gnc:report-type report-type)
@@ -352,6 +356,18 @@ not found.")))
 (define gnc:report-custom-template report-custom-template)
 (define gnc:report-set-custom-template! report-set-custom-template!)
 
+;; add an anchor to the report instance list of anchors. return the
+;; integer key to the anchor.
+(define (gnc:report-add-anchor! report anchor)
+  (let* ((hash (report-get-anchors report))
+         (size (ht:hash-table-size hash)))
+    (ht:hash-table-set! hash size anchor)
+    size))
+
+;; retrieve the anchor from the report instance list of anchors.
+(define (gnc:report-get-anchor report id)
+  (ht:hash-table-ref (report-get-anchors report) id))
+
 (define (gnc:report-set-dirty?! report val)
   (gnc:report-set-dirty?-internal! report val)
   (let* ((template (hash-ref *gnc:_report-templates_* (gnc:report-type report)))
@@ -377,6 +393,7 @@ not found.")))
              #f              ;; editor-widget
              #f              ;; ctext
              custom-template ;; custom-template
+             (ht:make-hash-table)
              ))
          (id (gnc-report-add r)))       ;returns an integer
     (gnc:report-set-id! r id)
@@ -385,7 +402,8 @@ not found.")))
 (define (gnc:restore-report-by-guid-with-custom-template
          id template-id template-name custom-template-id options)
   (if options
-      (let* ((r (make-report template-id id options #t #t #f #f custom-template-id))
+      (let* ((r (make-report template-id id options #t #t #f #f custom-template-id
+                             (ht:make-hash-table)))
              (report-id (gnc-report-add r)))
         (if (number? report-id)
             (gnc:report-set-id! r report-id))



Summary of changes:
 gnucash/gnome/gnc-plugin-page-report.cpp |  7 ++++++-
 gnucash/report/gnc-report.cpp            | 24 +++++++++++++++++++++---
 gnucash/report/gnc-report.h              |  1 +
 gnucash/report/html-utilities.scm        | 29 ++++++++++++++++-------------
 gnucash/report/report-core.scm           | 23 +++++++++++++++++++++--
 5 files changed, 65 insertions(+), 19 deletions(-)



More information about the gnucash-changes mailing list