gnucash stable: Multiple changes pushed
Christopher Lam
clam at code.gnucash.org
Tue Jan 27 10:33:56 EST 2026
Updated via https://github.com/Gnucash/gnucash/commit/dfe7295a (commit)
via https://github.com/Gnucash/gnucash/commit/7825beed (commit)
from https://github.com/Gnucash/gnucash/commit/f0856f7f (commit)
commit dfe7295a080fb13fa73ad350018cfb34ee35ec0e
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Jan 26 05:43:53 2026 +0800
[trep-engine.scm] grid: replace cell data with nested hash tables
Replace the list-based grid-cell storage with nested hash tables keyed
by row and column, with per-cell commodity collectors.
Eliminates repeated list traversals and duplicate filtering when
building and rendering the subtotal table, reducing gc load.
diff --git a/gnucash/report/trep-engine.scm b/gnucash/report/trep-engine.scm
index 5858a0f45a..d85c592c51 100644
--- a/gnucash/report/trep-engine.scm
+++ b/gnucash/report/trep-engine.scm
@@ -56,6 +56,7 @@
(gnucash report html-text))
(use-modules (srfi srfi-11))
(use-modules (srfi srfi-1))
+(use-modules (srfi srfi-2))
(use-modules (srfi srfi-9))
(use-modules (srfi srfi-26))
(use-modules (ice-9 match))
@@ -511,6 +512,17 @@ in the Options panel."))
(define gnc:lists->csv lists->csv)
+;; returns a list of hash keys
+(define (hash-keys hash)
+ (hash-fold (lambda (k _ p) (cons k p)) '() hash))
+
+;; mimics c++ std::map::operator[] - return the value corresponding to key,
+;; creating a new value if there's no existing one
+(define (hash-ref! hash key constructor)
+ (or (hash-ref hash key)
+ (let ((new-value (constructor)))
+ (hash-set! hash key new-value)
+ new-value)))
;;
;; Default Transaction Report
@@ -2072,49 +2084,50 @@ be excluded from periodic reporting.")
(define (make-grid)
- (define-record-type :grid-cell
- (make-grid-cell row col datum)
- grid-cell?
- (row get-grid-row)
- (col get-grid-col)
- (datum get-grid-datum))
-
- (let ((cells '()))
+ ;; cells : row-key â col-key â cell
+ ;; Primary data store. Each cell is a commodity collector.
+ ;;
+ ;; rows : row-key â commodity â #t
+ ;; Tracks which commodities appear in each row so we know which
+ ;; sub-rows to render (one per commodity).
+ ;;
+ ;; cols : col-key â #t
+ ;; Set of all columns that have received any data.
- (define (cell-match? cell row col)
- (and (or (not row) (equal? row (get-grid-row cell)))
- (or (not col) (equal? col (get-grid-col cell)))))
+ (let ((cells (make-hash-table))
+ (rows (make-hash-table))
+ (cols (make-hash-table)))
- (define (grid-get row col)
- (filter (cut cell-match? <> row col) cells))
+ (define (grid-get row col commodity)
+ (and-let* ((row-ht (hash-ref cells row))
+ (coll (hash-ref row-ht col)))
+ (coll 'getmonetary-strict commodity #f)))
(define (grid-rows)
- (delete-duplicates (map get-grid-row cells)))
+ (hash-keys rows))
(define (grid-cols)
- (delete-duplicates (map get-grid-col cells)))
+ (hash-keys cols))
+ ;; Add a list of <gnc:monetary> values into a single grid cell.
+ ;; - Ensures the row and column exist and have commodity collector
+ ;; - Merges amounts into the cellâs commodity collector
+ ;; - Records commodities in this row
(define (grid-add row col data)
- (let lp ((rest cells) (rv '()) (added? #f))
- (match rest
- (() (set! cells (if added? rv (cons (make-grid-cell row col data) rv))))
- (((? (cut cell-match? <> row col) this) . more)
- (let* ((coll (apply gnc:monetaries-add (append (get-grid-datum this) data)))
- (new-cell (make-grid-cell row col (coll 'format gnc:make-gnc-monetary #f))))
- (lp more (cons new-cell rv) #t)))
- ((this . more) (lp more (cons this rv) added?)))))
+ (hash-set! cols col #t)
+ (let* ((cells-row-ht (hash-ref! cells row make-hash-table))
+ (cells-row-col-data (hash-ref! cells-row-ht col gnc:make-commodity-collector))
+ (rows-ht (hash-ref! rows row make-hash-table)))
+ (for-each
+ (lambda (mon)
+ (let ((comm (gnc:gnc-monetary-commodity mon)) (amt (gnc:gnc-monetary-amount mon)))
+ (cells-row-col-data 'add comm amt)
+ (hash-set! rows-ht comm #t)))
+ data)))
(define (row->commodities row)
- (sort!
- (fold (lambda (cell acc)
- (fold (lambda (mon acc2)
- (let ((comm (gnc:gnc-monetary-commodity mon)))
- (if (member comm acc2) acc2 (cons comm acc2))))
- acc
- (get-grid-datum cell)))
- '()
- (grid-get row #f))
- (lambda (a b) (< (gnc-commodity-compare a b) 0))))
+ (sort! (hash-keys (hash-ref rows row (make-hash-table)))
+ (lambda (a b) (< (gnc-commodity-compare a b) 0))))
(define (grid->html-table)
(define (<? a b)
@@ -2137,14 +2150,8 @@ be excluded from periodic reporting.")
(/ amount divisor) scu GNC-HOW-RND-ROUND)))))
(define (make-table-cell row col commodity divisor)
- (let ((cell (grid-get row col)))
- (if (null? cell) ""
- (gnc:make-html-table-cell/markup
- "number-cell"
- (monetary-div
- (find (lambda (mon) (equal? commodity (gnc:gnc-monetary-commodity mon)))
- (get-grid-datum (car cell)))
- divisor)))))
+ (and-let* ((cell (grid-get row col commodity)))
+ (gnc:make-html-table-cell/markup "number-cell" (monetary-div cell divisor))))
(define (make-row row commodity first?)
(append
@@ -2184,10 +2191,10 @@ be excluded from periodic reporting.")
(lambda (msg . args)
(case msg
((add) (apply grid-add args))
- ;; ((get) (apply grid-get args)) ;; (grid 'get row col)
+ ;; ((get) (apply grid-get args)) ;; (grid 'get row col commodity)
;; ((rows) (grid-rows))
;; ((cols) (grid-cols))
- ;; ((clear) (set! cells '()))
+ ;; ((clear) (for-each hash-clear! (list cells rows cols)))
((get-html) (grid->html-table))
(else (error "Unknown grid operation" msg))))))
commit 7825beed0b351e48dbde077b4614f115981279b8
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Tue Jan 27 21:06:42 2026 +0800
[report-utilities.scm] gnc:make-commodity-collector 'getmonetary-strict
will find monetary with desired commodity or #f if does not
exist. this is similar to 'getmonetary but does not return a
zero-amount gnc:monetary object.
diff --git a/gnucash/report/report-utilities.scm b/gnucash/report/report-utilities.scm
index 68160ffdeb..b8bac38efe 100644
--- a/gnucash/report/report-utilities.scm
+++ b/gnucash/report/report-utilities.scm
@@ -20,6 +20,7 @@
(define-module (gnucash report report-utilities))
(use-modules (srfi srfi-1))
+(use-modules (srfi srfi-2))
(use-modules (srfi srfi-13))
(use-modules (srfi srfi-26))
(use-modules (ice-9 format))
@@ -378,6 +379,13 @@
(total (if pair ((cadr pair) 'total #f) 0)))
(gnc:make-gnc-monetary c (if sign? (- total) total))))
+ ;; same as getmonetary, if the commodity doesn't
+ ;; exist in commodity-collector, returns #f
+ (define (getmonetary-strict c sign?)
+ (and-let* ((pair (assoc c commoditylist))
+ (total ((cadr pair) 'total #f)))
+ (gnc:make-gnc-monetary c (if sign? (- total) total))))
+
(define (not-zero? l) (not (zero? ((cadr l) 'total #f))))
;; Dispatch function
@@ -392,6 +400,7 @@
((reset) (set! commoditylist '()))
((getpair) (getpair commodity amount))
((getmonetary) (getmonetary commodity amount))
+ ((getmonetary-strict) (getmonetary-strict commodity amount))
((remove-zeros) (set! commoditylist (filter not-zero? commoditylist)))
((list) commoditylist) ; this one is only for internal use
(else (gnc:warn "bad commodity-collector action: " action))))))
Summary of changes:
gnucash/report/report-utilities.scm | 9 ++++
gnucash/report/trep-engine.scm | 93 ++++++++++++++++++++-----------------
2 files changed, 59 insertions(+), 43 deletions(-)
More information about the gnucash-changes
mailing list