Bug763257 - add line charts to Income/Expense/Asset/Liability reports

This commit is contained in:
Carsten Rinke 2016-03-08 19:30:10 +01:00 committed by Geert Janssens
parent d80bd0387d
commit 927342f208
4 changed files with 294 additions and 175 deletions

View File

@ -62,9 +62,32 @@
(record-constructor <html-linechart>))
(define (gnc:make-html-linechart)
(gnc:make-html-linechart-internal -1 -1 #f #f #f #f '() '() '()
#f #f #f #f #f #f '()
#f #f #f #f #f #f -1 ))
(gnc:make-html-linechart-internal
-1 ;;width
-1 ;;height
#f ;;title
#f ;;subtitle
#f ;;x-axis-label
#f ;;y-axis-label
'() ;;col-labels
'() ;;row-labels
'() ;;col-colors
#f ;;legend-reversed?
#f ;;row-labels-rotated?
#f ;;stacked?
#t ;;markers?
#t ;;major-grid?
#t ;;minor-grid?
'() ;;data
#f ;;button-1-line-urls
#f ;;button-2-line-urls
#f ;;button-3-line-urls
#f ;;button-1-legend-urls
#f ;;button-2-legend-urls
#f ;;button-3-legend-urls
1.5 ;;line-width
)
)
(define gnc:html-linechart-data
(record-accessor <html-linechart> 'data))
@ -373,12 +396,12 @@
(push "var d")
(push series-index)
(push " = [];\n")))
(series-data-add (lambda (series-index x y)
(series-data-add (lambda (series-index date y)
(push (string-append
" d"
(number->string series-index)
".push(["
(number->string x)
"\"" date "\""
", "
(number->string y)
"]);\n"))))
@ -398,6 +421,8 @@
(begin
(push (gnc:html-js-include "jqplot/jquery.min.js"))
(push (gnc:html-js-include "jqplot/jquery.jqplot.js"))
(push (gnc:html-js-include "jqplot/jqplot.cursor.js"))
(push (gnc:html-js-include "jqplot/jqplot.dateAxisRenderer.js"))
(push (gnc:html-js-include "jqplot/jqplot.highlighter.js"))
(push (gnc:html-js-include "jqplot/jqplot.canvasTextRenderer.js"))
(push (gnc:html-js-include "jqplot/jqplot.canvasAxisTickRenderer.js"))
@ -416,20 +441,24 @@
(if (and data (list? data))
(let ((rows (length data))
(cols 0))
(let loop ((col 0) (rowcnt 1))
(let loop ((col 0) (rowcnt 0))
(series-data-start col)
(if (list? (car data))
(begin
(set! cols (length (car data)))))
(for-each
(lambda (row)
(series-data-add col rowcnt
(ensure-numeric (list-ref-safe row col)))
(if (< rowcnt rows)
(series-data-add col
(list-ref (gnc:html-linechart-row-labels linechart) rowcnt)
(ensure-numeric (list-ref-safe row col))
)
)
(set! rowcnt (+ rowcnt 1)))
data)
(series-data-end col (list-ref-safe (gnc:html-linechart-col-labels linechart) col))
(if (< col (- cols 1))
(loop (+ 1 col) 1)))))
(loop (+ 1 col) 0)))))
(push "var options = {
@ -441,7 +470,7 @@
lineWidth: ")
(push (ensure-numeric line-width))
(push ",
showMarker: false,
showMarker: true,
},
series: series,
axesDefaults: {
@ -450,6 +479,7 @@
},
axes: {
xaxis: {
renderer:$.jqplot.DateAxisRenderer,
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: -30,
@ -460,9 +490,9 @@
autoscale: true,
},
},
highlighter: {
tooltipContentEditor: formatTooltip,
tooltipLocation: 'ne',
cursor: {
show: true,
zoom: true
}
};\n")
@ -508,19 +538,20 @@
(push " options.axes.yaxis.label = \"")
(push y-label)
(push "\";\n")))
(if (and (string? row-labels) (> (string-length row-labels) 0))
(begin
(let ((tick-count 1))
(push " options.axes.xaxis.ticks = [")
(for-each
(lambda (val)
(push "[")(push tick-count)
(push ",\"")(push val)
(push "\"],")
(set! tick-count (+ tick-count 1)))
(gnc:html-linechart-row-labels linechart))
(push "];\n"))))
;; adjust the date string format to the one given by the preferences
(push " options.axes.xaxis.tickOptions.formatString = '")
(let ( ;; get the date string for the 2nd January in year 1970
(date-string (gnc-print-date (cons 86400 0)))
)
(cond
((string=? date-string "1970-01-02") (push "%F"))
((string=? date-string "01/02/1970") (push "%v")) ;; US format is not supported by the DateAxisRenderer
((string=? date-string "02/01/1970") (push "%d/%m/%Y"))
((string=? date-string "02.01.1970") (push "%d.%m.%Y"))
)
)
(push "';\n")
(push "$.jqplot.config.enablePlugins = true;")
(push "var plot = $.jqplot('")(push chart-id)(push"', data, options);

View File

@ -1,4 +1,4 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; category-barchart.scm: shows barchart of income/expense categories
;;
;; By Christian Stimming <stimming@tu-harburg.de>
@ -44,23 +44,23 @@
;; spelling errors. The *reportnames* are defined here (and not only
;; once at the very end) because I need them to define the "other"
;; report, thus needing them twice.
(define menuname-income (N_ "Income Barchart"))
(define menuname-expense (N_ "Expense Barchart"))
(define menuname-assets (N_ "Asset Barchart"))
(define menuname-liabilities (N_ "Liability Barchart"))
(define menuname-income (N_ "Income Chart"))
(define menuname-expense (N_ "Expense Chart"))
(define menuname-assets (N_ "Asset Chart"))
(define menuname-liabilities (N_ "Liability Chart"))
;; The names are used in the menu
;; The menu statusbar tips.
(define menutip-income
(N_ "Shows a barchart with the Income per interval \
(N_ "Shows a chart with the Income per interval \
developing over time"))
(define menutip-expense
(N_ "Shows a barchart with the Expenses per interval \
(N_ "Shows a chart with the Expenses per interval \
developing over time"))
(define menutip-assets
(N_ "Shows a barchart with the Assets developing over time"))
(N_ "Shows a chart with the Assets developing over time"))
(define menutip-liabilities
(N_ "Shows a barchart with the Liabilities \
(N_ "Shows a chart with the Liabilities \
developing over time"))
;; The names here are used 1. for internal identification, 2. as
@ -82,7 +82,10 @@ developing over time"))
(define optname-levels (N_ "Show Accounts until level"))
(define optname-fullname (N_ "Show long account names"))
(define optname-stacked (N_ "Use Stacked Bars"))
(define optname-chart-type (N_ "Chart Type"))
(define optname-stacked (N_ "Use Stacked Charts"))
(define optname-slices (N_ "Maximum Bars"))
(define optname-plot-width (N_ "Plot Width"))
(define optname-plot-height (N_ "Plot Height"))
@ -165,24 +168,39 @@ developing over time"))
gnc:pagename-display optname-fullname
"a" (N_ "Show the full account name in legend?") #f))
(add-option
(gnc:make-multichoice-option
gnc:pagename-display optname-chart-type
"b" "Select which chart type to use"
'barchart
(list (vector 'barchart
(N_ "Bar Chart")
(N_ "Use bar charts."))
(vector 'linechart
(N_ "Line Chart")
(N_ "Use line charts."))
)
)
)
(add-option
(gnc:make-simple-boolean-option
gnc:pagename-display optname-stacked
"b"
(N_ "Show barchart as stacked barchart?")
"c"
(N_ "Show charts as stacked charts?")
#t))
(add-option
(gnc:make-number-range-option
gnc:pagename-display optname-slices
"c" (N_ "Maximum number of bars in the chart.") 8
"d" (N_ "Maximum number of stacks in the chart.") 8
2 24 0 1))
(add-option
(gnc:make-simple-boolean-option
gnc:pagename-display
(N_ "Show table")
"d" (N_ "Display a table of the selected data.")
"e" (N_ "Display a table of the selected data.")
#f))
(gnc:options-add-plot-size!
@ -218,7 +236,7 @@ developing over time"))
(gnc:report-options report-obj) section name)))
(gnc:report-starting reportname)
(let ((to-date-tp (gnc:timepair-end-day-time
(let* ((to-date-tp (gnc:timepair-end-day-time
(gnc:date-option-absolute-time
(get-option gnc:pagename-general
optname-to-date))))
@ -240,7 +258,8 @@ developing over time"))
(accounts (get-option gnc:pagename-accounts optname-accounts))
(account-levels (get-option gnc:pagename-accounts optname-levels))
(chart-type (get-option gnc:pagename-display optname-chart-type))
(stacked? (get-option gnc:pagename-display optname-stacked))
(show-fullname? (get-option gnc:pagename-display optname-fullname))
(max-slices (inexact->exact
@ -252,7 +271,11 @@ developing over time"))
(show-table? (get-option gnc:pagename-display (N_ "Show table")))
(document (gnc:make-html-document))
(chart (gnc:make-html-barchart))
(chart
(if (eqv? chart-type 'barchart)
(gnc:make-html-barchart)
(gnc:make-html-linechart)
))
(table (gnc:make-html-table))
(topl-accounts (gnc:filter-accountlist-type
account-types
@ -453,29 +476,58 @@ developing over time"))
(gnc:not-all-zeros (map cadr all-data)))
(begin
;; Set chart title, subtitle etc.
(gnc:html-barchart-set-title! chart report-title)
(gnc:html-barchart-set-subtitle!
chart (sprintf #f
(if (eqv? chart-type 'barchart)
(begin
(gnc:html-barchart-set-title! chart report-title)
(gnc:html-barchart-set-subtitle!
chart (sprintf #f
(if do-intervals?
(_ "%s to %s")
(_ "Balances %s to %s"))
(jqplot-escape-string (gnc-print-date from-date-tp))
(jqplot-escape-string (gnc-print-date to-date-tp))))
(gnc:html-barchart-set-width! chart width)
(gnc:html-barchart-set-height! chart height)
(gnc:html-barchart-set-width! chart width)
(gnc:html-barchart-set-height! chart height)
;; row labels etc.
(gnc:html-barchart-set-row-labels! chart date-string-list)
;; FIXME: axis labels are not yet supported by
;; libguppitank.
(gnc:html-barchart-set-y-axis-label!
chart (gnc-commodity-get-mnemonic report-currency))
(gnc:html-barchart-set-row-labels-rotated?! chart #t)
(gnc:html-barchart-set-stacked?! chart stacked?)
;; If this is a stacked barchart, then reverse the legend.
;; Doesn't do what you'd expect. - DRH
;; It does work, but needs Guppi 0.40.4. - cstim
(gnc:html-barchart-set-legend-reversed?! chart stacked?)
)
(begin
(gnc:html-linechart-set-title! chart report-title)
(gnc:html-linechart-set-subtitle!
chart (sprintf #f
(if do-intervals?
(_ "%s to %s")
(_ "Balances %s to %s"))
(jqplot-escape-string (gnc-print-date from-date-tp))
(jqplot-escape-string (gnc-print-date to-date-tp))))
(gnc:html-linechart-set-width! chart width)
(gnc:html-linechart-set-height! chart height)
;; row labels etc.
(gnc:html-barchart-set-row-labels! chart date-string-list)
;; FIXME: axis labels are not yet supported by
;; libguppitank.
(gnc:html-barchart-set-y-axis-label!
chart (gnc-commodity-get-mnemonic report-currency))
(gnc:html-barchart-set-row-labels-rotated?! chart #t)
(gnc:html-barchart-set-stacked?! chart stacked?)
;; If this is a stacked barchart, then reverse the legend.
;; Doesn't do what you'd expect. - DRH
;; It does work, but needs Guppi 0.40.4. - cstim
(gnc:html-barchart-set-legend-reversed?! chart stacked?)
;; row labels etc.
(gnc:html-linechart-set-row-labels! chart date-string-list)
;; FIXME: axis labels are not yet supported by
;; libguppitank.
(gnc:html-linechart-set-y-axis-label!
chart (gnc-commodity-get-mnemonic report-currency))
(gnc:html-linechart-set-row-labels-rotated?! chart #t)
(gnc:html-linechart-set-stacked?! chart stacked?)
;; If this is a stacked linechart, then reverse the legend.
;; Doesn't do what you'd expect. - DRH
;; It does work, but needs Guppi 0.40.4. - cstim
(gnc:html-linechart-set-legend-reversed?! chart stacked?)
)
)
;; If we have too many categories, we sum them into a new
;; 'other' category and add a link to a new report with just
@ -508,64 +560,100 @@ developing over time"))
;; transposes the data, i.e. swaps rows and columns. Pretty
;; cool, eh? Courtesy of dave_p.
(gnc:report-percent-done 92)
(if (not (null? all-data))
(gnc:html-barchart-set-data!
chart
(apply zip (map cadr all-data))))
(if (eqv? chart-type 'barchart)
(begin ;; bar chart
(if (not (null? all-data))
(gnc:html-barchart-set-data!
chart
(apply zip (map cadr all-data))))
;; Labels and colors
(gnc:report-percent-done 94)
(gnc:html-barchart-set-col-labels!
chart (map (lambda (pair)
;; Labels and colors
(gnc:report-percent-done 94)
(gnc:html-barchart-set-col-labels!
chart (map (lambda (pair)
(if (string? (car pair))
(car pair)
((if show-fullname?
gnc-account-get-full-name
xaccAccountGetName) (car pair))))
all-data))
(gnc:html-barchart-set-col-colors!
chart
(gnc:assign-colors (length all-data)))
all-data))
(gnc:html-barchart-set-col-colors!
chart
(gnc:assign-colors (length all-data)))
)
(begin ;; line chart
(if (not (null? all-data))
(gnc:html-linechart-set-data!
chart
(apply zip (map cadr all-data))))
;; Labels and colors
(gnc:report-percent-done 94)
(gnc:html-linechart-set-col-labels!
chart (map (lambda (pair)
(if (string? (car pair))
(car pair)
((if show-fullname?
gnc-account-get-full-name
xaccAccountGetName) (car pair))))
all-data))
(gnc:html-linechart-set-col-colors!
chart
(gnc:assign-colors (length all-data)))
)
)
;; set the URLs; the slices are links to other reports
(gnc:report-percent-done 96)
(let
((urls
(map
(lambda (pair)
(if
(string? (car pair))
other-anchor
(let* ((acct (car pair))
(subaccts
(gnc-account-get-children acct)))
(if (null? subaccts)
;; if leaf-account, make this an anchor
;; to the register.
(gnc:account-anchor-text acct)
;; if non-leaf account, make this a link
;; to another report which is run on the
;; immediate subaccounts of this account
;; (and including this account).
(gnc:make-report-anchor
reportguid
report-obj
(list
(list gnc:pagename-accounts optname-accounts
(cons acct subaccts))
(list gnc:pagename-accounts optname-levels
(+ 1 tree-depth))
(list gnc:pagename-general
gnc:optname-reportname
((if show-fullname?
gnc-account-get-full-name
xaccAccountGetName) acct))))))))
all-data)))
(gnc:html-barchart-set-button-1-bar-urls!
chart (append urls urls))
;; The legend urls do the same thing.
(gnc:html-barchart-set-button-1-legend-urls!
chart (append urls urls)))
;; (gnc:report-percent-done 96)
;; (let
;; ((urls
;; (map
;; (lambda (pair)
;; (if
;; (string? (car pair))
;; other-anchor
;; (let* ((acct (car pair))
;; (subaccts
;; (gnc-account-get-children acct)))
;; (if (null? subaccts)
;; ;; if leaf-account, make this an anchor
;; ;; to the register.
;; (gnc:account-anchor-text acct)
;; ;; if non-leaf account, make this a link
;; ;; to another report which is run on the
;; ;; immediate subaccounts of this account
;; ;; (and including this account).
;; (gnc:make-report-anchor
;; reportguid
;; report-obj
;; (list
;; (list gnc:pagename-accounts optname-accounts
;; (cons acct subaccts))
;; (list gnc:pagename-accounts optname-levels
;; (+ 1 tree-depth))
;; (list gnc:pagename-general
;; gnc:optname-reportname
;; ((if show-fullname?
;; gnc-account-get-full-name
;; xaccAccountGetName) acct))))))))
;; all-data)))
;; (if (eqv? chart-type 'barchart)
;; (begin ;; bar chart
;; (gnc:html-barchart-set-button-1-bar-urls!
;; chart (append urls urls))
;; ;; The legend urls do the same thing.
;; (gnc:html-barchart-set-button-1-legend-urls!
;; chart (append urls urls))
;; )
;; (begin ;; line chart
;; (gnc:html-linechart-set-button-1-line-urls!
;; chart (append urls urls))
;; ;; The legend urls do the same thing.
;; (gnc:html-linechart-set-button-1-legend-urls!
;; chart (append urls urls))
;; )
;; )
;; )
(gnc:report-percent-done 98)
(gnc:html-document-add-object! document chart)

View File

@ -364,39 +364,39 @@
'("green") '())))
;; URLs for income/expense or asset/liabilities bars.
(if show-sep?
(let ((urls
(list
(gnc:make-report-anchor
(if inc-exp?
category-barchart-income-uuid
category-barchart-asset-uuid)
report-obj
(list
(list gnc:pagename-display
"Use Stacked Bars" #t)
(list gnc:pagename-general
gnc:optname-reportname
(if inc-exp?
(_ "Income Chart")
(_ "Asset Chart")))))
(gnc:make-report-anchor
(if inc-exp?
category-barchart-expense-uuid
category-barchart-liability-uuid)
report-obj
(list
(list gnc:pagename-display
"Use Stacked Bars" #t)
(list gnc:pagename-general
gnc:optname-reportname
(if inc-exp?
(_ "Expense Chart")
(_ "Liability Chart"))))))))
(gnc:html-barchart-set-button-1-bar-urls!
chart urls)
(gnc:html-barchart-set-button-1-legend-urls!
chart urls)))
;; (if show-sep?
;; (let ((urls
;; (list
;; (gnc:make-report-anchor
;; (if inc-exp?
;; category-barchart-income-uuid
;; category-barchart-asset-uuid)
;; report-obj
;; (list
;; (list gnc:pagename-display
;; "Use Stacked Bars" #t)
;; (list gnc:pagename-general
;; gnc:optname-reportname
;; (if inc-exp?
;; (_ "Income Chart")
;; (_ "Asset Chart")))))
;; (gnc:make-report-anchor
;; (if inc-exp?
;; category-barchart-expense-uuid
;; category-barchart-liability-uuid)
;; report-obj
;; (list
;; (list gnc:pagename-display
;; "Use Stacked Bars" #t)
;; (list gnc:pagename-general
;; gnc:optname-reportname
;; (if inc-exp?
;; (_ "Expense Chart")
;; (_ "Liability Chart"))))))))
;; (gnc:html-barchart-set-button-1-bar-urls!
;; chart urls)
;; (gnc:html-barchart-set-button-1-legend-urls!
;; chart urls)))
;; Test for all-zero data here.
(if non-zeros

View File

@ -408,39 +408,39 @@
chart markers)
;; URLs for income/expense or asset/liabilities bars.
(if show-sep?
(let ((urls
(list
(gnc:make-report-anchor
(if inc-exp?
category-barchart-income-uuid
category-barchart-asset-uuid)
report-obj
(list
(list gnc:pagename-display
"Use Stacked Lines" #t)
(list gnc:pagename-general
gnc:optname-reportname
(if inc-exp?
(_ "Income Chart")
(_ "Asset Chart")))))
(gnc:make-report-anchor
(if inc-exp?
category-barchart-expense-uuid
category-barchart-liability-uuid)
report-obj
(list
(list gnc:pagename-display
"Use Stacked Lines" #t)
(list gnc:pagename-general
gnc:optname-reportname
(if inc-exp?
(_ "Expense Chart")
(_ "Liability Chart"))))))))
(gnc:html-linechart-set-button-1-line-urls!
chart urls)
(gnc:html-linechart-set-button-1-legend-urls!
chart urls)))
;; (if show-sep?
;; (let ((urls
;; (list
;; (gnc:make-report-anchor
;; (if inc-exp?
;; category-barchart-income-uuid
;; category-barchart-asset-uuid)
;; report-obj
;; (list
;; (list gnc:pagename-display
;; "Use Stacked Lines" #t)
;; (list gnc:pagename-general
;; gnc:optname-reportname
;; (if inc-exp?
;; (_ "Income Chart")
;; (_ "Asset Chart")))))
;; (gnc:make-report-anchor
;; (if inc-exp?
;; category-barchart-expense-uuid
;; category-barchart-liability-uuid)
;; report-obj
;; (list
;; (list gnc:pagename-display
;; "Use Stacked Lines" #t)
;; (list gnc:pagename-general
;; gnc:optname-reportname
;; (if inc-exp?
;; (_ "Expense Chart")
;; (_ "Liability Chart"))))))))
;; (gnc:html-linechart-set-button-1-line-urls!
;; chart urls)
;; (gnc:html-linechart-set-button-1-legend-urls!
;; chart urls)))
;; Test for all-zero data here.
(if non-zeros