Saving customized reports (was: GNOME 2: MDI or SDI?)
Christian Stimming
stimming at tuhh.de
Fri Jun 11 05:09:17 EDT 2004
Wesley Leggette schrieb:
> Since it is impossible to conviently store report setups
> (except by manually backing them up) without keeping them open, I like
> to keep them open. (...)
>
> Of course, I suppose just adding the ability to save reports, and even
> better groups of reports, would go a long way. To elaborate, you could
> export or bookmark or whatever your custom configurations for reports.
> You could then also group them together and open the whole group at
> once. Very neat.
This is one of the features most regularly asked for. Although a clean
implementation of that would require additional GUI components and
probably quite some code and time, I nevertheless came up with an idea
that might do already:
The options of an opened report are stored in
~/.gnucash/books/my_book_name as scheme code. The report is restored by
running this scheme code and calling gnc:report-restore (in
src/reports/report-system/report.scm) afterwards. How difficult would it
be to turn these two steps from restoring a report into a new call of
the gnc:define-report function, hence offering a new report? It would be
well sufficient to have a manual procedure involving text file
manipulation, but fully outside gnucash. A step-by-step instruction to
create your own report would read as follows:
1. In gnucash, open the report. Change the options so that it shows what
you want. Close gnucash while leaving that report window opened.
2. Open the file ~/.gnucash/books/<your_book_name> with your favorite
text editor.
3. Find the section entitled ";; options for report <your_report_name>".
For each of your still-opened reports, there is one such section. If you
have multiple reports based on the same template, you need to figure out
which one you want by looking closely at each report's options.
4. Copy the section with the report options into a new text file, e.g.
"my-report.scm". The section starts with the command "(let ((options
..." and it ends with the closing parentheses that closes the opening
parentheses before the "let" command.
5. In "my-report.scm", replace ??? (FIXME: see below) inside your pasted
section by ???.
7. Save "my-report.scm" in your gnucash scheme directory. If your
gnucash installation was installed with the prefix /usr, then this is in
/usr/share/guile-modules/gnucash/reports/ (FIXME: is this correct?)
8. In the file "report-system.scm" that can be found in that very same
directory (FIXME: is this correct?), append the line
(load-from-path "my-report.scm")
at the very end of that file. This makes gnucash aware of your new
report file. If your new file contains any errors that gnucash complains
about, you can always remove this load-from-path command from this file
and gnucash will load normally again. Watch out: Each time you install a
new version of gnucash, the file report-system.scm will be overwritten
and you will have to insert this line again. But all other steps are not
affected by a new installation of gnucash.
As for the code that needs to be added: For sure, the normal report
definition has to be done as usual:
(gnc:define-report
'version 1
'name "My personalized report about my Income"
'options-generator ???
'renderer ???)
The renderer should probably be the very same function that is already
used in the original report definition file, e.g. accsum-renderer from
account-summary.scm for the account summary report. It might be
necessary to add an additional (export accsum-renderer) in that files,
but I'm not too sure about this. OTOH the options-generator is probably
the key to implement this customizing of the report:
Usually, the options-generator is a function that returns the
appropriate options object. In the scheme code from the user's file with
the saved options, we actually already have that options object
available. The saved options code ends with the command
(gnc:restore-report report-id report-type options)
where "options" is precisely the options object as returned by the
original options-generator, but now changed into our customized
settings. So all that we need to do is to replace the gnc:restore-report
command by a gnc:define-report command, where the options-generator now
is a lambda that directly returns this very customized options object.
How about this (with a customized account summary as an example):
(gnc:define-report
'version 1
'name "My customized account summary"
'options-generator (lambda() options)
'renderer accsum-renderer)
To summarize: The full options command before the manual change would
read like this:
;; options for report "My customized summary"
(let ((options (gnc:report-template-new-options/name "Account Summary")))
(let ((option (gnc:lookup-option options "General" "Name")))
((lambda (option) (if option ((gnc:option-setter option) "My
customized summary"))) option))
;; ... more options ...
(gnc:restore-report 1234 "Account Summary" options))
After the manual change, the command would read like this:
;; options for report "My customized summary"
(let ((options (gnc:report-template-new-options/name "Account Summary")))
(let ((option (gnc:lookup-option options "General" "Name")))
((lambda (option) (if option ((gnc:option-setter option) "My
customized summary"))) option))
;; ... more options ...
(gnc:define-report
'version 1
'name "My customized summary"
'options-generator (lambda() options)
'renderer accsum-renderer))
One very last quirk: When defining a new report, the "Report Name" and
"Stylesheet" options are *always* added by the report system (in
gnc:report-template-new-options), not by the original options-generator.
In our case this means that the options object with the customized
settings already contains these options, although gnc:define-report is
going to register them again. What is the behaviour of (hash-set!
section-hash name new-option), if the section-hash already contains an
element with the key "name"? Does it silently overwrite the existing
object, does it fail, or does it create a second entry? Pretty much all
three cases are not what we want. The simplest solution would be to
register these two options in gnc:report-template-new-options (in
report.scm) only if they don't exist yet, i.e. change
(let ((options (generator)))
(gnc:register-option options stylesheet)
(gnc:register-option options namer)
options)
into
(define (lookup-existing-option options option)
(if option
(gnc:lookup-options options (gnc:option-section option)
(gnc:option-name option))
#f))
(let ((options (generator)))
(if (not (lookup-existing-option options stylesheet))
(gnc:register-option options stylesheet))
(if (not (lookup-existing-option options namer))
(gnc:register-option options namer))
options)
More information about the gnucash-devel
mailing list