patches from Dave Peticolas Date: Sat, 05 Feb 2000 02:40:06 -0800

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2007 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2000-02-07 05:27:35 +00:00
parent 653ae23d9c
commit 8eb597be35
52 changed files with 3470 additions and 1612 deletions

340
ChangeLog
View File

@ -1,3 +1,307 @@
2000-02-05 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/report/hello-world.scm: renamed from dummy.scm. Added
documentation to the source code and additional help text in the
report. This is intended to be an example for how to write reports.
* src/gnome/window-report.c (reportAnchorCB): use gnome_url_show
to display the anchors.
* src/gnome/window-help.c (helpAnchorCB): use gnome_url_show to
display the other anchor types.
* src/gnome/dialog-utils.c: removed tooltip setting function. I was
using tooltips the wrong way. Instead of having one tooltips object
for each tip, you use one tooltips object for each logical group of
tips, i.e., all the tips on a dialog. Also, changed the dialogs to
use this method.
* src/gnome/dialog-transfer.c: use labels with colons.
2000-02-04 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/extensions.scm: removed cruft functions
* src/register/gnome/gnucash-item-list.c (gnc_item_list_select):
set the focus row to the selected row.
* src/register/gnome/combocell-gnome.c (ComboMV): auto-pop the
list on input, according to the option value below.
* src/scm/prefs.scm: added option to auto-raise register list on
input.
2000-02-03 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/gnome/combocell-gnome.c (enterCombo): sort the list
before popping up.
* src/engine/Query.c: do num sorting using numerical values where
possible.
* src/register/gnome/gnucash-item-edit.c: added new functions for
cutting, copying, and pasting the clipboard. We have to do this
manually instead of relying in the gtk_entry, as it screws up the
selection handling.
* src/register/gnome/gnucash-sheet.c (gnucash_sheet_insert_cb):
fixed bug where new text was being copied incorrectly for
insertions longer than a character.
2000-02-02 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/gnome/gnucash-sheet.c (compute_optimal_width):
return optimal width if possible
* src/register/gnome/gnucash-style.c
(gnucash_style_default_width): new function, compute optimal sheet
width
* src/gnome/option-util.c: interfaced with the guile option callback
mechanism.
* Changed all existing callbacks to use guile callbacks. Touched
many files.
* src/scm/options.scm: added an option change callback mechanism.
2000-02-01 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/options.scm: new file. Moved the general options code
here. Modularized the options code.
2000-01-31 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/SplitLedger.c: use the last date entered in the blank split
for the date of the new blank split.
* src/scm/prefs.scm: use hash for storing options
2000-01-30 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/bootstrap.scm.in: deleted hash-for-each. This is defined
in slib2c6, which we are requiring anyway. Not the thunk for this
should accept two args: the key and the value.
* src/register/QuickFill.c: add sorting option to choose between
LIFO and alphabetic orders.
2000-01-29 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/bootstrap.scm.in: Used Matt Martin's guile error catching
code to print errors from gnc:load.
2000-01-27 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/splitreg.c (xaccInitSplitRegister): set format of
price cell in stock registers to 4 decimal places.
* src/register/gnome/gnucash-sheet.c (gnucash_sheet_scroll_event):
new function. Do mouse wheel scrolling in gnome register.
* src/register/gnome/gnucash-style.c (gnucash_style_layout_init):
use printDate to find a date width using the current date style.
(gnucash_style_layout_init): use i18n'd string to set transfer
from field width.
* Removed uses of nana and dependencies on nana.
* src/scm/report/transaction-report.scm: change to handle new
reports.
* src/scm/report/dummy.scm: change to handle new reports.
* src/scm/report.scm: Change reports so that they have a function
which generates a new set of options. Change the report running
functions to accomodate this.
* src/FileDialog.c: avoid showing multiple error dialogs.
* src/guile/gfec.c (gfec_catcher): new file with functions for
running scheme code with error handlers. Grabbed this off the
guile faq and made a few mods.
* src/gnome/window-report.c: modify to use the new gfec routines.
2000-01-27 Robert Graham Merkel <rgmerk@mira.net>
* src/scm/report/transaction-report.scm
(tr-report-primary-key-op),(tr-report-primary-order-op)
(tr-report-secondary-key-op),(tr-report-secondary-order-op):
new options controlling sorting order for transaction report
display.
(gnc:tr-report-get-first-acc-name): get the name of the first
"other" account" of a split's transaction
(gnc:sort-predicate-component): return a predicate for comparing
two split-scm's on a certain component
(gnc:tr-report-make-sort-predicate): process sorting options,
return a corresponding sorting predicate
"Account Transactions" report: added sorting.
2000-01-25 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/gnome/window-register.c (regRefresh): refresh the window name
* src/gnome/dialog-edit.c: Rob Merkel's patch to reparent accounts.
* src/engine/Account.c (xaccAccountHasAncestor): new function to
determine whether an account has another as an ancestor.
* src/gnome/account-tree.c (gnc_account_tree_set_filter): add a
filter function to an account tree to select a subset of accounts.
* src/engine/Query.c: some new functions for setting the date
ranges.
* src/gnome/window-register.c: add 'show earliest' and 'show
latest' options to the date range window.
2000-01-25 Heath Martin <martinh@pegasus.cc.ucf.edu>
* src/register/gnome/gnucash-grid.c (gnucash_grid_init):
Initialize the fonts here.
* src/register/gnome/gnucash-style.c
(gnucash_sheet_style_compile): Use sheet->grid->normal_font for
all the computations. style->fonts[][] is now only used for
drawing in gnucash-grid, etc. when it's non-NULL.
2000-01-24 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/splitreg.c (xaccInitSplitRegister): make the action
cell accept strings not in the list.
* src/register/gnome/combocell-gnome.c (xaccComboCellSetStrict):
new function that determines whether the combo accepts strings
not in the list. Defaults to 'does not accept'.
2000-01-23 Heath Martin <martinh@pegasus.cc.ucf.edu>
* src/register/gnome/gnucash-style.c: Many functions touched.
Fairly extensive changes to how the layouts and dimensions are
handled. We now lump together cursors which should have same
dimensions (e.g. all the single line cursors have the same layout
and dimension data).
2000-01-21 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/gnome/gnucash-sheet.c
(gnucash_sheet_key_press_event): oh, what a hack! The extra stuff
is to make sure the selection is changed appropriately according
to the key that is pressed. Some of the logic is extracted from
gtkentry.c so the behavior is similar. We have to do this because
the entry widget is not realized and thus does not change its
selection as usual. However, we can't realize it, see the
explanation below.
* src/register/gnome/combocell-gnome.c: added quickfilling
* src/register/quickfillcell.c (quick_modify): new code for gnome,
old code for motif. motif doesn't support the cursor position and
selection args.
* src/register/gnome/gnucash-sheet.c (gnucash_sheet_new): ok,
*don't* put the entry in a widget. We can't have it realized
because it screws up the selection changes during the insert/
delete callbacks. We're going to have to fake the other
functionality.
* src/register/QuickFill.c: make quickfill work on non-alphabet
characters.
(xaccGetQuickFillStr): new function search for a prefix match on
more than one character at a time.
* src/register/gnome/gnucash-sheet.c
(gnucash_button_release_event): new function to track button
release for dragging purposes.
(gnucash_motion_event): new function for tracking mouse movement
and updating the selection region.
(gnucash_sheet_init): initialize top_block_offset
(gnucash_sheet_set_top_row): adjust the new top row to show as many
rows as possible.
(gnucash_sheet_vadjustment_value_changed): compute visible range
after adjusting top block in smooth scrolling.
(gnucash_sheet_compute_visible_range): start at the top_block_offset
(gnucash_sheet_update_adjustments): scroll faster
2000-01-20 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/gnome/gnucash-sheet.c (gnucash_button_press_event):
if we're mousing in the current cell, don't bother going through
modify_update and all that jazz, but only if we are currently
editing. This makes sure the reconcile cell still gets its enters.
* src/register/gnome/gnucash-item-edit.c
(item_edit_set_cursor_pos): add option to extend selection.
2000-01-20 Robert Graham Merkel <rgmerk@mira.net>
* src/scm/report/transaction-report.scm: Fixed date bug, ensuring
"to" date is treated as a <= rather than a <.
2000-01-20 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/register/gnome/gnucash-sheet.c (gnucash_sheet_new): put the
editing entry into a canvas item so it will get realized. It needs
to be realized for full functionality.
(gnucash_sheet_modify_current_cell): add new args to modify update.
(gnucash_sheet_insert_cb): new args for modify update
(gnucash_sheet_delete_cb): new args for modify update
* src/register/gnome/gnucash-item-edit.c (item_edit_destroy): only
disconnect if the editor hasn't been destroyed.
* src/register/gnome/gnucash-sheet.c
(gnucash_sheet_activate_cursor_cell): added new args for enter
update. change entry widget appropriately.
* src/register/table-allgui.c (gnc_table_enter_update): added args
to set cursor position and highlited selection.
* src/scm/prefs.scm (gnc:save-options): truncate the options file
when opening.
* src/register/gnome/gnucash-item-edit.c (item_edit_draw_info):
calc regions for the highlited portion of the text.
(item_edit_draw): draw the hightlited portion of the text.
2000-01-19 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/guile/gnucash.c (gnucash_lowlev_app_init): use DEBUG and PERR
instead of print(stderr, ...);
* src/scm/prefs.scm: new technique for saving options. Easier
to generalize to other option databases.
* src/gnome/window-html.c (gnc_html_load): set button states at
the beginning, in case report doesn't work.
* src/scm/report.scm: catch exceptions in executing the report
* src/gnome/window-report.c (reportJumpCB): report errors that occur
in executing the report.
* src/register/table-allgui.c (gnc_table_traverse_update): use the
return value consistently to indicate no move.
* src/scm/path.scm (gnc:make-home-dir): new function. creates gnc dir
* src/scm/main.scm: don't abort if user config file fails
* src/scm/prefs.scm: make options save to ~/.gnucash/config.auto
* src/gnome/dialog-options.c (gnc_option_create_account_widget):
if not multiple selection, use browse mode so user has to select
an account.
(gnc_option_set_ui_widget): when making account list widget, connect
the signals after the value has been set so the dialog isn't already
in a changed state.
2000-01-17 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/scm/bootstrap.scm.in: add a test for slib >= 2c6.
2000-01-16 Dave Peticolas <peticola@cs.ucdavis.edu>
* src/gnome/dialog-add.c (gnc_ui_accWindow_list_box_create): Put
@ -33,6 +337,42 @@
redo them. Don't bother defining GNC_RUNTIME_* vars as they are
not substituted using AC_OUTPUT.
2000-01-15 Heath Martin <martinh@pegasus.cc.ucf.edu>
* src/register/gnome/gnucash-style.c (struct _CellLayoutInfo):
Add new flags for attributes the user can change interactively.
* src/register/gnome/gnucash-style.c (compute_cell_origins_[xy]):
Precompute these since they stay fixed until dimensions change.
* src/register/gnome/gnucash-header.c (gnucash_header_draw):
Be sure rect.width is non-negative. Also, we draw all the
rows in the header now.
(gnucash_header_set_arg): Remove the ARG_ROW argument.
For ARG_CURSOR_TYPE, only reconfigure the header
when the type changes. This optimizes the drawing a bit.
(gnucash_header_reconfigure): We're drawing all rows now, so
use the proper height.
(gnucash_header_event): Implement resizing of columns. This is
a bit rough in places, because we have to take cell alignments
into account. Need to work more on the styles.
(gnucash_header_draw): Support dynamic resizing in the header,
to give the user feedback during the resize.
* src/register/gnome/gnucash-grid.c (gnucash_grid_draw): Optimize
so it draws only the needed cells, not the entire row.
* src/register/gnome/gnucash-sheet.c (gnucash_sheet_init): Add a
compile time option for smooth vertical scrolling. Later we can
add user selectable scrolling if we decide it's worth it.
(gnucash_sheet_make_cell_visible): support smooth scrolling.
(gnucash_sheet_update_adjustments): ditto
(gnucash_sheet_vadjustment_value_changed): ditto
(gnucash_sheet_create): ditto
(gnucash_sheet_y_pixel_to_block): New function. Convert a canvas
y-coordinate to a virtual row.
2000-01-14 Robert Graham Merkel <rgmerk@mira.net>
* src/scm/report/transaction-report.scm: Added initial balance

View File

@ -163,7 +163,7 @@
<h2>Lead Developers</h2>
<dl>
<dt> <a href="mailto:rclark@hmc.edu> Robin Clark</a></dt>
<dt> <a href="mailto:rclark@hmc.edu"> Robin Clark</a></dt>
<dd>wrote the original X-Accountant in Motif as a school
project, taking it to version 0.9 by October 1997.</dd>
@ -182,14 +182,16 @@
code completely redesigned and made mostly Motif-(and
GUI-)independent. Did some prototype OFX work.</dd>
<dt> <a href="mailto:jcollins@gnucash.org"> Jeremy Collins</a></dt>
<dt> <a href="mailto:jcollins@gnucash.org"> Jeremy
Collins</a></dt>
<dd>publicized the GnoMoney project widely and broadly, and
then changed its name to GnuCash. Jeremy created the
gnucash.org web site, registered the domain, got the initial
GTK/gnome code working.</dd>
<dt> <a href="mailto:rlb@cs.utexas.edu"> Rob Browning</a></dt>
<dt> <a href="mailto:rlb@cs.utexas.edu"> Rob
Browning</a></dt>
<dd>abused everyone for not using perl, and then added
guile/scheme support. Rob maintains the build infrastructure,
@ -337,6 +339,11 @@
<dd>gnome and register patches</dd>
<dt> <a href="mailto:mgmartin@abacusnet.net"> Matt
Martin</a></dt>
<dd>guile error handling code</dd>
<dt> <a href="mailto:rgmerk@mira.net"> Robert Graham
Merkel</a></dt>
@ -415,6 +422,11 @@
<dd>for German text and euro date rework</dd>
<dt> <a href="mailto:detrout@earthlink.net"> Diane
Trout</a></dt>
<dd>scheme qif import patch</dd>
<dt> <a href="mailto:rob@valinux.com"> Rob Walker</a></dt>
<dd>guile and register patches</dd>
@ -451,10 +463,11 @@
"logos/linux.gif"></a> <a href="http://www.sco.com/skunkware">
<img src="logos/skunkware.gif"></a> <a href=
"http://www.bull.de/pub/"><img src="logos/bullogogross.gif">
<img src="logos/ibm.gif"></a> <a href="http://www.sgi.com/">
<img src="logos/sgi.gif"></a> <a href="http://www.debian.org/">
<img src="logos/debian.jpg"></a> <img src=
"logos/NetBSD-banner.gif"></p>
<a href="http://www.ibm.com"> <img src="logos/ibm.gif"></a>
<a href="http://www.sgi.com"> <img src="logos/sgi.gif"></a>
<a href="http://www.debian.org"> <img src="logos/debian.jpg"></a>
<a href="http://www.netbsd.org"> <img src= "logos/NetBSD-banner.gif">
</p>
<h2>History</h2>
The table below shows some historical lines-of-code and

6
README
View File

@ -255,10 +255,6 @@ packages:
libtool -- Used to build our internal version of g-wrap which handles
our guile C wrappers. Available at ftp://ftp.gnu.org/gnu.
RPM's and debs are widely available with most distributions.
nana -- Used to provide a debugging infrastructure.
Any version should work.
http://www.fsf.org/software/nana/nana.html
http://www.cs.ntu.edu.au/homepages/pjm/nana-home/
SWIG -- Used to autogenerate perl wrappers.
available at www.swig.org need 1.1p5 or later ...
@ -549,6 +545,7 @@ Ted Lemon <mellon@andare.fugue.com> for NetBSD port
Yannick Le Ny <y-le-ny@ifrance.com> pour la traduction en francais
Grant Likely <glikely@nortelnetworks.com> gnome and engine patches
Heath Martin <martinh@pegasus.cc.ucf.edu> gnome and register patches
Matt Martin <mgmartin@abacusnet.net> guile error handling code
Robert Graham Merkel <rgmerk@mira.net> reporting, gnome, and config patches.
Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu> port to alpha-dec-osf4.0f
G. Allen Morris III <gam3@ann.softgams.com> for QIF core dump
@ -566,6 +563,7 @@ Christopher Seawood <cls@seawood.org> for XbaeMatrix core dump
Mike Simons <msimons@fsimons01.erols.com> misc configure.in patches
Richard Skelton <rich@brake.demon.co.uk> for Solaris cleanup
Henning Spruth <spruth@bigfoot.com> for German text & euro date rework
Diane Trout <detrout@earthlink.net> scheme qif import patch
Rob Walker <rob@valinux.com> guile and register patches
Ken Yamaguchi <gooch@ic.EECS.Berkeley.EDU> QIF import fixes; MYM import

View File

@ -39,10 +39,6 @@
/* Enable debugging stuff */
#define USE_DEBUG
/* Turn on nana assertion checking */
#define HAVE_NANA_H
#define HAVE_LIBNANA
/* check for stpcpy for Solaris */
#undef HAVE_STPCPY

202
configure vendored
View File

@ -3041,101 +3041,11 @@ LDFLAGS="$OLDLDFLAGS"
### --------------------------------------------------------------------------
## Nana
# XXX - There should probably be a --without-nana option (e.g., for
# someone who happens to have it installed on his local machine, but
# is building GnuCash for people who might not have it).
# See if the <nana.h> header file can be found.
ac_safe=`echo "nana.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for nana.h""... $ac_c" 1>&6
echo "configure:3054: checking for nana.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3059 "configure"
#include "confdefs.h"
#include <nana.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3064: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
eval "ac_cv_header_$ac_safe=yes"
else
echo "$ac_err" >&5
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_header_$ac_safe=no"
fi
rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
:
else
echo "$ac_t""no" 1>&6
{ echo "configure: error: Can not find nana.h -- do you have nana installed?" 1>&2; exit 1; }
fi
echo $ac_n "checking for L_buffer_create in -lnana""... $ac_c" 1>&6
echo "configure:3087: checking for L_buffer_create in -lnana" >&5
ac_lib_var=`echo nana'_'L_buffer_create | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
LIBS="-lnana $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3095 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char L_buffer_create();
int main() {
L_buffer_create()
; return 0; }
EOF
if { (eval echo configure:3106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=no"
fi
rm -f conftest*
LIBS="$ac_save_LIBS"
fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
ac_tr_lib=HAVE_LIB`echo nana | sed -e 's/[^a-zA-Z0-9_]/_/g' \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
cat >> confdefs.h <<EOF
#define $ac_tr_lib 1
EOF
LIBS="-lnana $LIBS"
else
echo "$ac_t""no" 1>&6
{ echo "configure: error: Can not find a valid nana library -- do you have nana installed?" 1>&2; exit 1; }
fi
### --------------------------------------------------------------------------
# If readline exists, just assume that guile needs it. It probably does.
echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6
echo "configure:3139: checking for readline in -lreadline" >&5
echo "configure:3049: checking for readline in -lreadline" >&5
ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -3143,7 +3053,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lreadline $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3147 "configure"
#line 3057 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -3154,7 +3064,7 @@ int main() {
readline()
; return 0; }
EOF
if { (eval echo configure:3158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -3200,7 +3110,7 @@ fi
if test "${with_guile_config+set}" = set; then
withval="$with_guile_config"
echo $ac_n "checking for guile-config""... $ac_c" 1>&6
echo "configure:3204: checking for guile-config" >&5
echo "configure:3114: checking for guile-config" >&5
echo "$ac_t""${with_guile_config}" 1>&6
GUILE_CONFIG="$with_guile_config"
LIBS="`${GUILE_CONFIG} link` ${LIBS}"
@ -3213,7 +3123,7 @@ if test x"$GUILE_CONFIG" = x; then
# Extract the first word of "guile-config", so it can be a program name with args.
set dummy guile-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3217: checking for $ac_word" >&5
echo "configure:3127: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GUILE_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3269,7 +3179,7 @@ if test x"$GUILE_CONFIG" = x; then
GNC_LIBS_SAFE=${LIBS}
echo $ac_n "checking for guile""... $ac_c" 1>&6
echo "configure:3273: checking for guile" >&5
echo "configure:3183: checking for guile" >&5
if eval "test \"`echo '$''{'ac_cv_lib_guile'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3282,14 +3192,14 @@ else
else
LIBS="${GNC_TEST_LIBS} ${GNC_LIBS_SAFE}"
cat > conftest.$ac_ext <<EOF
#line 3286 "configure"
#line 3196 "configure"
#include "confdefs.h"
#include<guile/gh.h>
int main() {
gh_eval_file;
; return 0; }
EOF
if { (eval echo configure:3293: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
GUILELIBS="${GNC_TEST_LIBS}"
else
@ -3316,7 +3226,7 @@ if test x"$GUILE_CONFIG" != x; then
# Extract the first word of "guile", so it can be a program name with args.
set dummy guile; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3320: checking for $ac_word" >&5
echo "configure:3230: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GUILE_BIN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3355,7 +3265,7 @@ if test x"$GUILE_BIN" = x && test x"$with_guile" != x; then
# Extract the first word of "guile", so it can be a program name with args.
set dummy guile; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3359: checking for $ac_word" >&5
echo "configure:3269: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GUILE_BIN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3394,7 +3304,7 @@ if test x"${GUILE_BIN}" = x; then
# Extract the first word of "guile", so it can be a program name with args.
set dummy guile; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3398: checking for $ac_word" >&5
echo "configure:3308: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GUILE_BIN'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3526,17 +3436,17 @@ fi
ac_safe=`echo "locale.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for locale.h""... $ac_c" 1>&6
echo "configure:3530: checking for locale.h" >&5
echo "configure:3440: checking for locale.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3535 "configure"
#line 3445 "configure"
#include "confdefs.h"
#include <locale.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3540: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:3450: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -3560,19 +3470,19 @@ fi
if test "$ac_cv_header_locale_h" = yes; then
echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6
echo "configure:3564: checking for LC_MESSAGES" >&5
echo "configure:3474: checking for LC_MESSAGES" >&5
if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3569 "configure"
#line 3479 "configure"
#include "confdefs.h"
#include <locale.h>
int main() {
return LC_MESSAGES
; return 0; }
EOF
if { (eval echo configure:3576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
am_cv_val_LC_MESSAGES=yes
else
@ -3593,7 +3503,7 @@ EOF
fi
fi
echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6
echo "configure:3597: checking whether NLS is requested" >&5
echo "configure:3507: checking whether NLS is requested" >&5
# Check whether --enable-nls or --disable-nls was given.
if test "${enable_nls+set}" = set; then
enableval="$enable_nls"
@ -3613,7 +3523,7 @@ fi
EOF
echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6
echo "configure:3617: checking whether included gettext is requested" >&5
echo "configure:3527: checking whether included gettext is requested" >&5
# Check whether --with-included-gettext or --without-included-gettext was given.
if test "${with_included_gettext+set}" = set; then
withval="$with_included_gettext"
@ -3632,17 +3542,17 @@ fi
ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for libintl.h""... $ac_c" 1>&6
echo "configure:3636: checking for libintl.h" >&5
echo "configure:3546: checking for libintl.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3641 "configure"
#line 3551 "configure"
#include "confdefs.h"
#include <libintl.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:3646: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:3556: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -3659,19 +3569,19 @@ fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6
echo "configure:3663: checking for gettext in libc" >&5
echo "configure:3573: checking for gettext in libc" >&5
if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3668 "configure"
#line 3578 "configure"
#include "confdefs.h"
#include <libintl.h>
int main() {
return (int) gettext ("")
; return 0; }
EOF
if { (eval echo configure:3675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
gt_cv_func_gettext_libc=yes
else
@ -3687,7 +3597,7 @@ echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6
if test "$gt_cv_func_gettext_libc" != "yes"; then
echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6
echo "configure:3691: checking for bindtextdomain in -lintl" >&5
echo "configure:3601: checking for bindtextdomain in -lintl" >&5
ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -3695,7 +3605,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lintl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3699 "configure"
#line 3609 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -3706,7 +3616,7 @@ int main() {
bindtextdomain()
; return 0; }
EOF
if { (eval echo configure:3710: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -3722,12 +3632,12 @@ fi
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
echo "$ac_t""yes" 1>&6
echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6
echo "configure:3726: checking for gettext in libintl" >&5
echo "configure:3636: checking for gettext in libintl" >&5
if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
echo $ac_n "checking for gettext in -lintl""... $ac_c" 1>&6
echo "configure:3731: checking for gettext in -lintl" >&5
echo "configure:3641: checking for gettext in -lintl" >&5
ac_lib_var=`echo intl'_'gettext | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -3735,7 +3645,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lintl $LIBS"
cat > conftest.$ac_ext <<EOF
#line 3739 "configure"
#line 3649 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -3746,7 +3656,7 @@ int main() {
gettext()
; return 0; }
EOF
if { (eval echo configure:3750: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -3785,7 +3695,7 @@ EOF
# Extract the first word of "msgfmt", so it can be a program name with args.
set dummy msgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3789: checking for $ac_word" >&5
echo "configure:3699: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3819,12 +3729,12 @@ fi
for ac_func in dcgettext
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:3823: checking for $ac_func" >&5
echo "configure:3733: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 3828 "configure"
#line 3738 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -3847,7 +3757,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:3851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -3874,7 +3784,7 @@ done
# Extract the first word of "gmsgfmt", so it can be a program name with args.
set dummy gmsgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3878: checking for $ac_word" >&5
echo "configure:3788: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3910,7 +3820,7 @@ fi
# Extract the first word of "msgmerge", so it can be a program name with args.
set dummy msgmerge; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3914: checking for $ac_word" >&5
echo "configure:3824: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGMERGE'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3946,7 +3856,7 @@ fi
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:3950: checking for $ac_word" >&5
echo "configure:3860: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -3978,7 +3888,7 @@ else
fi
cat > conftest.$ac_ext <<EOF
#line 3982 "configure"
#line 3892 "configure"
#include "confdefs.h"
int main() {
@ -3986,7 +3896,7 @@ extern int _nl_msg_cat_cntr;
return _nl_msg_cat_cntr
; return 0; }
EOF
if { (eval echo configure:3990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
CATOBJEXT=.gmo
DATADIRNAME=share
@ -4009,7 +3919,7 @@ fi
if test "$CATOBJEXT" = "NONE"; then
echo $ac_n "checking whether catgets can be used""... $ac_c" 1>&6
echo "configure:4013: checking whether catgets can be used" >&5
echo "configure:3923: checking whether catgets can be used" >&5
# Check whether --with-catgets or --without-catgets was given.
if test "${with_catgets+set}" = set; then
withval="$with_catgets"
@ -4022,7 +3932,7 @@ fi
if test "$nls_cv_use_catgets" = "yes"; then
echo $ac_n "checking for main in -li""... $ac_c" 1>&6
echo "configure:4026: checking for main in -li" >&5
echo "configure:3936: checking for main in -li" >&5
ac_lib_var=`echo i'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -4030,14 +3940,14 @@ else
ac_save_LIBS="$LIBS"
LIBS="-li $LIBS"
cat > conftest.$ac_ext <<EOF
#line 4034 "configure"
#line 3944 "configure"
#include "confdefs.h"
int main() {
main()
; return 0; }
EOF
if { (eval echo configure:4041: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:3951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -4065,12 +3975,12 @@ else
fi
echo $ac_n "checking for catgets""... $ac_c" 1>&6
echo "configure:4069: checking for catgets" >&5
echo "configure:3979: checking for catgets" >&5
if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 4074 "configure"
#line 3984 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char catgets(); below. */
@ -4093,7 +4003,7 @@ catgets();
; return 0; }
EOF
if { (eval echo configure:4097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:4007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_catgets=yes"
else
@ -4115,7 +4025,7 @@ EOF
# Extract the first word of "gencat", so it can be a program name with args.
set dummy gencat; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4119: checking for $ac_word" >&5
echo "configure:4029: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GENCAT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4151,7 +4061,7 @@ fi
# Extract the first word of "gmsgfmt", so it can be a program name with args.
set dummy gmsgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4155: checking for $ac_word" >&5
echo "configure:4065: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4188,7 +4098,7 @@ fi
# Extract the first word of "msgfmt", so it can be a program name with args.
set dummy msgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4192: checking for $ac_word" >&5
echo "configure:4102: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4223,7 +4133,7 @@ fi
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4227: checking for $ac_word" >&5
echo "configure:4137: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4281,7 +4191,7 @@ fi
# Extract the first word of "msgfmt", so it can be a program name with args.
set dummy msgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4285: checking for $ac_word" >&5
echo "configure:4195: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4315,7 +4225,7 @@ fi
# Extract the first word of "gmsgfmt", so it can be a program name with args.
set dummy gmsgfmt; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4319: checking for $ac_word" >&5
echo "configure:4229: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4351,7 +4261,7 @@ fi
# Extract the first word of "xgettext", so it can be a program name with args.
set dummy xgettext; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:4355: checking for $ac_word" >&5
echo "configure:4265: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4446,7 +4356,7 @@ fi
LINGUAS=
else
echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6
echo "configure:4450: checking for catalogs to be installed" >&5
echo "configure:4360: checking for catalogs to be installed" >&5
NEW_LINGUAS=
for lang in ${LINGUAS=$ALL_LINGUAS}; do
case "$ALL_LINGUAS" in

View File

@ -337,18 +337,6 @@ LDFLAGS="$OLDLDFLAGS"
AC_SUBST(GNOME_TARGET)
AC_SUBST(GNOME_STATIC_TARGET)
### --------------------------------------------------------------------------
## Nana
# XXX - There should probably be a --without-nana option (e.g., for
# someone who happens to have it installed on his local machine, but
# is building GnuCash for people who might not have it).
# See if the <nana.h> header file can be found.
AC_CHECK_HEADER(nana.h, ,
AC_MSG_ERROR([Can not find nana.h -- do you have nana installed?]))
AC_CHECK_LIB(nana, L_buffer_create, ,
AC_MSG_ERROR([Can not find a valid nana library -- do you have nana installed?]))
### --------------------------------------------------------------------------
# If readline exists, just assume that guile needs it. It probably does.

616
po/de.po

File diff suppressed because it is too large Load Diff

606
po/fr.po

File diff suppressed because it is too large Load Diff

View File

@ -206,18 +206,21 @@ gncPostFileOpen (const char * filename)
/* check for session errors, put up appropriate dialog */
SHOW_LOCK_ERR_MSG (newsess);
/* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error);
if (!uh_oh)
{
/* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error);
/* Umm, came up empty-handed, i.e. the file was not found. */
/* This is almost certainly not what the user wanted. */
if (!newgrp && !io_error)
/* Umm, came up empty-handed, i.e. the file was not found. */
/* This is almost certainly not what the user wanted. */
if (!uh_oh && !newgrp && !io_error)
{
sprintf (buf, FILE_NOT_FOUND_MSG, newfile);
gnc_error_dialog ( buf);
uh_oh = 1;
sprintf (buf, FILE_NOT_FOUND_MSG, newfile);
gnc_error_dialog ( buf);
uh_oh = 1;
}
}
/* going down -- abandon ship */
if (uh_oh)
@ -420,9 +423,12 @@ gncFileSaveAs (void)
/* check for session errors (e.g. file locked by another user) */
SHOW_LOCK_ERR_MSG (newsess);
/* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error);
if (!uh_oh)
{
/* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error);
}
/* going down -- abandon ship */
if (uh_oh)

View File

@ -90,6 +90,7 @@
\********************************************************************/
#include <stdio.h>
#include <time.h>
#include "top-level.h"
@ -119,6 +120,9 @@ struct _SRInfo
/* The default account where new splits are added */
Account *default_source_account;
/* The last date recorded in the blank split */
time_t last_date_entered;
/* User data for users of SplitRegisters */
void *user_data;
@ -166,11 +170,17 @@ static Transaction * xaccSRGetTrans (SplitRegister *reg,
static void
xaccSRInitRegisterData(SplitRegister *reg)
{
SRInfo *info;
assert(reg != NULL);
/* calloc initializes to 0 */
reg->user_data = calloc(1, sizeof(SRInfo));
assert(reg->user_data != NULL);
info = calloc(1, sizeof(SRInfo));
assert(info != NULL);
info->last_date_entered = time(NULL);
reg->user_data = info;
}
static void
@ -1096,10 +1106,14 @@ xaccSRSaveRegEntry (SplitRegister *reg, Transaction *newtrans)
/* If the modified split is the "blank split", then it is now an
* official part of the account. Set the blank split to NULL, so
* we can be sure of getting a new split. */
* we can be sure of getting a new split. Also, save the date for
* the new blank split. */
split = xaccTransGetSplit (trans, 0);
if (split == info->blank_split)
{
info->blank_split = NULL;
info->last_date_entered = xaccTransGetDate(trans);
}
/* If the new transaction is different from the current,
* commit the current and set the pending transaction to NULL. */
@ -1583,7 +1597,7 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
trans = xaccMallocTransaction ();
xaccTransBeginEdit (trans, 1);
xaccTransSetDateToday (trans);
xaccTransSetDateSecs(trans, info->last_date_entered);
xaccTransCommitEdit (trans);
split = xaccTransGetSplit (trans, 0);
info->blank_split = split;

View File

@ -105,6 +105,8 @@ gnc_account_tree_init(GNCAccountTree *tree)
tree->root_account = NULL;
tree->current_accounts = NULL;
tree->ignore_unselect = GNC_F;
tree->filter = NULL;
tree->filter_data = NULL;
gnc_init_account_view_info(&tree->avi);
@ -594,6 +596,27 @@ gnc_init_account_view_info(AccountViewInfo *avi)
avi->show_field[ACCOUNT_BALANCE] = GNC_T;
}
/********************************************************************\
* gnc_account_tree_set_filter *
* sets the account filter to use with the tree *
* *
* Args: tree - the tree to set the filter on *
* filter - the filter function to use *
* user_data - the user_data for the callback *
* Returns: nothing *
\********************************************************************/
void
gnc_account_tree_set_filter(GNCAccountTree *tree,
AccountFilter filter,
gpointer user_data)
{
g_return_if_fail(tree != NULL);
g_return_if_fail(GTK_IS_GNC_ACCOUNT_TREE(tree));
tree->filter = filter;
tree->filter_data = user_data;
}
static void
gnc_account_tree_set_view_info_real(GNCAccountTree *tree)
{
@ -753,6 +776,11 @@ gnc_account_tree_fill(GNCAccountTree *tree,
currentAccount++ )
{
account = xaccGroupGetAccount(accts, currentAccount);
if (tree->filter != NULL)
if (!tree->filter(account, tree->filter_data))
continue;
type = xaccAccountGetType(account);
if (!tree->avi.include_type[type])

View File

@ -38,6 +38,8 @@ typedef struct _GNCAccountTree GNCAccountTree;
typedef struct _GNCAccountTreeClass GNCAccountTreeClass;
typedef struct _AccountViewInfo AccountViewInfo;
typedef gboolean (*AccountFilter) (Account *account, gpointer user_data);
struct _AccountViewInfo
{
gboolean include_type[NUM_ACCOUNT_TYPES];
@ -49,6 +51,9 @@ struct _GNCAccountTree
{
GtkCTree ctree;
AccountFilter filter;
gpointer filter_data;
AccountViewInfo avi;
gint num_columns;
@ -125,6 +130,9 @@ void gnc_account_tree_set_view_info (GNCAccountTree *tree,
void gnc_account_tree_get_view_info (GNCAccountTree *tree,
AccountViewInfo *info);
void gnc_account_tree_set_filter (GNCAccountTree *tree,
AccountFilter filter,
gpointer user_data);
#ifdef __cplusplus
}

View File

@ -452,8 +452,6 @@ gnc_accWindow_create(AccWindow *accData)
widget = gnc_ui_notes_frame_create(&accData->edit_info.notes_entry);
gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
gnc_account_tree_select_account(accData->tree, accData->parentAccount, TRUE);
return dialog;
}
@ -488,6 +486,8 @@ accWindow (AccountGroup *this_is_not_used)
gtk_widget_show_all(dialog);
gnc_account_tree_select_account(accData->tree, accData->parentAccount, TRUE);
while (1)
{
result = gnome_dialog_run(GNOME_DIALOG(dialog));

View File

@ -36,13 +36,13 @@
#include "dialog-utils.h"
#include "messages.h"
#include "util.h"
#include "account-tree.h"
/* From Account.c. One day, maybe this will be configurable. */
extern int unsafe_ops;
/* List of Open edit windows */
static EditAccWindow ** editAccList = NULL;
static EditAccWindow ** editAccList = NULL;
struct _editaccwindow
@ -52,6 +52,11 @@ struct _editaccwindow
Account * account;
AccountEditInfo edit_info;
GtkWidget * parent_tree;
Account * current_parent;
Account * top_level_account;
};
@ -63,6 +68,9 @@ gnc_ui_EditAccWindow_close_cb(GnomeDialog *dialog, gpointer user_data)
REMOVE_FROM_LIST (EditAccWindow,editAccList,acc,account);
xaccFreeAccount(editAccData->top_level_account);
editAccData->top_level_account = NULL;
free(editAccData);
/* really close */
@ -78,14 +86,37 @@ gnc_ui_EditAccWindow_cancel_cb(GtkWidget * widget,
gnome_dialog_close(GNOME_DIALOG(editAccData->dialog));
}
static gboolean
gnc_filter_parent_accounts(Account *account, gpointer data)
{
EditAccWindow *editAccData = data;
if (account == NULL)
return FALSE;
if (account == editAccData->top_level_account)
return TRUE;
if (account == editAccData->account)
return FALSE;
if (xaccAccountHasAncestor(account, editAccData->account))
return FALSE;
return xaccAccountTypesCompatible(xaccAccountGetType(account),
xaccAccountGetType(editAccData->account));
}
static void
gnc_ui_EditAccWindow_ok_cb(GtkWidget * widget,
gpointer data)
{
EditAccWindow *editAccData = (EditAccWindow *) data;
AccountFieldStrings strings;
Account * acc;
char * old;
GNCAccountTree *tree;
Account *new_parent;
Account *account;
char *old;
gnc_ui_extract_field_strings(&strings, &editAccData->edit_info);
@ -99,10 +130,21 @@ gnc_ui_EditAccWindow_ok_cb(GtkWidget * widget,
/* fixme check for unique code, if entered */
acc = editAccData->account;
tree = GNC_ACCOUNT_TREE(editAccData->parent_tree);
new_parent = gnc_account_tree_get_current_account(tree);
/* Parent check, probably not needed, but be safe */
if (!gnc_filter_parent_accounts(new_parent, editAccData))
{
gnc_error_dialog(ACC_BAD_PARENT_MSG);
gnc_ui_free_field_strings(&strings);
return;
}
account = editAccData->account;
/* currency check */
old = xaccAccountGetCurrency(acc);
old = xaccAccountGetCurrency(account);
if (old == NULL)
old = "";
if ((safe_strcmp(old, strings.currency) != 0) &&
@ -123,7 +165,7 @@ gnc_ui_EditAccWindow_ok_cb(GtkWidget * widget,
}
/* security check */
old = xaccAccountGetSecurity(acc);
old = xaccAccountGetSecurity(account);
if (old == NULL)
old = "";
if ((safe_strcmp(old, strings.security) != 0) &&
@ -143,9 +185,16 @@ gnc_ui_EditAccWindow_ok_cb(GtkWidget * widget,
}
}
xaccAccountBeginEdit(acc, 0);
gnc_ui_install_field_strings(acc, &strings, FALSE);
xaccAccountCommitEdit (acc);
xaccAccountBeginEdit(account, 0);
gnc_ui_install_field_strings(account, &strings, FALSE);
if (new_parent != editAccData->current_parent)
{
if (new_parent == editAccData->top_level_account)
xaccGroupInsertAccount(gncGetCurrentGroup(), account);
else
xaccInsertSubAccount(new_parent, account);
}
xaccAccountCommitEdit(account);
gnc_ui_free_field_strings(&strings);
@ -155,6 +204,44 @@ gnc_ui_EditAccWindow_ok_cb(GtkWidget * widget,
gnome_dialog_close(GNOME_DIALOG(editAccData->dialog));
}
static GtkWidget *
gnc_ui_create_parent_acc_frame(EditAccWindow *editAccData)
{
Account *current_parent;
GtkWidget *scroll_win;
GtkWidget *frame;
GtkWidget *tree;
editAccData->top_level_account = xaccMallocAccount();
xaccAccountSetName(editAccData->top_level_account, TOP_ACCT_STR);
frame = gtk_frame_new(PARENT_ACC_STR);
scroll_win = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_border_width(GTK_CONTAINER(frame), 5);
tree = gnc_account_tree_new_with_root(editAccData->top_level_account);
gtk_clist_set_selection_mode(GTK_CLIST(tree), GTK_SELECTION_BROWSE);
gnc_account_tree_hide_all_but_name(GNC_ACCOUNT_TREE(tree));
gtk_clist_column_titles_hide(GTK_CLIST(tree));
gnc_account_tree_set_filter(GNC_ACCOUNT_TREE(tree),
gnc_filter_parent_accounts, editAccData);
gnc_account_tree_refresh(GNC_ACCOUNT_TREE(tree));
editAccData->parent_tree = tree;
/* the initial setting should be the *parent* of the current account */
current_parent = xaccAccountGetParentAccount(editAccData->account);
if (current_parent == NULL)
current_parent = editAccData->top_level_account;
editAccData->current_parent = current_parent;
gtk_container_add(GTK_CONTAINER(scroll_win), tree);
gtk_container_add(GTK_CONTAINER(frame), scroll_win);
return frame;
}
/********************************************************************\
* editAccWindow *
@ -193,7 +280,6 @@ editAccWindow(Account *acc)
gnome_dialog_close_hides(GNOME_DIALOG(dialog), FALSE);
vbox = GNOME_DIALOG(editAccData->dialog)->vbox;
gtk_widget_show (vbox);
/* Account field edit box */
widget = gnc_ui_account_field_box_create_from_account
@ -220,6 +306,10 @@ editAccWindow(Account *acc)
gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
/* Parent Account entry */
widget = gnc_ui_create_parent_acc_frame(editAccData);
gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
/* source menu */
widget = gnc_ui_account_source_box_create_from_account
(acc, &editAccData->edit_info);
@ -252,7 +342,10 @@ editAccWindow(Account *acc)
GTK_SIGNAL_FUNC (gnc_ui_EditAccWindow_close_cb),
editAccData);
gtk_widget_show(dialog);
gtk_widget_show_all(dialog);
gnc_account_tree_select_account(GNC_ACCOUNT_TREE(editAccData->parent_tree),
editAccData->current_parent, TRUE);
return editAccData;
}

View File

@ -227,7 +227,7 @@ default_button_cb(GtkButton *button, gpointer data)
}
static GtkWidget *
gnc_option_create_default_button(GNCOption *option)
gnc_option_create_default_button(GNCOption *option, GtkTooltips *tooltips)
{
GtkWidget *default_button = gtk_button_new_with_label(SET_TO_DEFAULT_STR);
@ -236,6 +236,8 @@ gnc_option_create_default_button(GNCOption *option)
gtk_signal_connect(GTK_OBJECT(default_button), "clicked",
GTK_SIGNAL_FUNC(default_button_cb), option);
gtk_tooltips_set_tip(tooltips, default_button, TOOLTIP_SET_DEFAULT, NULL);
return default_button;
}
@ -388,11 +390,8 @@ gnc_option_create_account_widget(GNCOption *option, char *name)
gnc_account_tree_refresh(GNC_ACCOUNT_TREE(tree));
if (multiple_selection)
gtk_clist_set_selection_mode(GTK_CLIST(tree), GTK_SELECTION_MULTIPLE);
gtk_signal_connect(GTK_OBJECT(tree), "select_account",
GTK_SIGNAL_FUNC(gnc_option_account_cb), option);
gtk_signal_connect(GTK_OBJECT(tree), "unselect_account",
GTK_SIGNAL_FUNC(gnc_option_account_cb), option);
else
gtk_clist_set_selection_mode(GTK_CLIST(tree), GTK_SELECTION_BROWSE);
scroll_win = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
@ -436,7 +435,9 @@ gnc_option_create_account_widget(GNCOption *option, char *name)
}
static void
gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gnc_option_set_ui_widget(GNCOption *option,
GtkBox *page_box,
GtkTooltips *tooltips)
{
GtkWidget *enclosing = NULL;
GtkWidget *value = NULL;
@ -464,7 +465,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gtk_box_pack_start(GTK_BOX(enclosing), value, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(enclosing),
gnc_option_create_default_button(option),
gnc_option_create_default_button(option, tooltips),
FALSE, FALSE, 0);
}
else if (safe_strcmp(type, "string") == 0)
@ -489,7 +490,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gtk_box_pack_start(GTK_BOX(enclosing), label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(enclosing), value, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(enclosing),
gnc_option_create_default_button(option),
gnc_option_create_default_button(option, tooltips),
FALSE, FALSE, 0);
}
else if (safe_strcmp(type, "multichoice") == 0)
@ -510,7 +511,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gtk_box_pack_start(GTK_BOX(enclosing), label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(enclosing), value, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(enclosing),
gnc_option_create_default_button(option),
gnc_option_create_default_button(option, tooltips),
FALSE, FALSE, 0);
}
else if (safe_strcmp(type, "date") == 0)
@ -538,14 +539,14 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gnc_option_set_ui_value(option, FALSE);
entry = GNOME_DATE_EDIT(value)->date_entry;
gnc_set_tooltip(entry, documentation);
gtk_tooltips_set_tip(tooltips, entry, documentation, NULL);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
GTK_SIGNAL_FUNC(gnc_option_changed_cb), option);
if (show_time)
{
entry = GNOME_DATE_EDIT(value)->time_entry;
gnc_set_tooltip(entry, documentation);
gtk_tooltips_set_tip(tooltips, entry, documentation, NULL);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
GTK_SIGNAL_FUNC(gnc_option_changed_cb), option);
}
@ -553,7 +554,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gtk_box_pack_start(GTK_BOX(enclosing), label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(enclosing), value, FALSE, FALSE, 0);
gtk_box_pack_end(GTK_BOX(enclosing),
gnc_option_create_default_button(option),
gnc_option_create_default_button(option, tooltips),
FALSE, FALSE, 0);
}
else if (safe_strcmp(type, "account-list") == 0)
@ -561,7 +562,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
enclosing = gnc_option_create_account_widget(option, name);
value = option->widget;
gnc_set_tooltip(enclosing, documentation);
gtk_tooltips_set_tip(tooltips, enclosing, documentation, NULL);
gtk_box_pack_start(page_box, enclosing, FALSE, FALSE, 5);
packed = TRUE;
@ -570,6 +571,11 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gnc_option_set_ui_value(option, FALSE);
gtk_signal_connect(GTK_OBJECT(value), "select_account",
GTK_SIGNAL_FUNC(gnc_option_account_cb), option);
gtk_signal_connect(GTK_OBJECT(value), "unselect_account",
GTK_SIGNAL_FUNC(gnc_option_account_cb), option);
gtk_clist_set_row_height(GTK_CLIST(value), 0);
gtk_widget_set_usize(value, 0, GTK_CLIST(value)->row_height * 10);
}
@ -582,7 +588,7 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
gtk_box_pack_start(page_box, enclosing, FALSE, FALSE, 0);
if (value != NULL)
gnc_set_tooltip(value, documentation);
gtk_tooltips_set_tip(tooltips, value, documentation, NULL);
if (enclosing != NULL)
gtk_widget_show_all(enclosing);
@ -595,14 +601,17 @@ gnc_option_set_ui_widget(GNCOption *option, GtkBox *page_box)
}
static void
gnc_options_dialog_add_option(GtkWidget *page, GNCOption *option)
gnc_options_dialog_add_option(GtkWidget *page,
GNCOption *option,
GtkTooltips *tooltips)
{
gnc_option_set_ui_widget(option, GTK_BOX(page));
gnc_option_set_ui_widget(option, GTK_BOX(page), tooltips);
}
static void
gnc_options_dialog_append_page(GnomePropertyBox *propertybox,
GNCOptionSection *section)
GNCOptionSection *section,
GtkTooltips *tooltips)
{
GNCOption *option;
GtkWidget *page_label;
@ -616,14 +625,14 @@ gnc_options_dialog_append_page(GnomePropertyBox *propertybox,
page_content_box = gtk_vbox_new(FALSE, 5);
gtk_container_set_border_width(GTK_CONTAINER(page_content_box), 5);
gtk_widget_show(page_content_box);
gnome_property_box_append_page(propertybox, page_content_box, page_label);
num_options = gnc_option_section_num_options(section);
for (i = 0; i < num_options; i++)
{
option = gnc_get_option_section_option(section, i);
gnc_options_dialog_add_option(page_content_box, option);
gnc_options_dialog_add_option(page_content_box, option, tooltips);
}
}
@ -641,13 +650,16 @@ void
gnc_build_options_dialog_contents(GnomePropertyBox *propertybox,
GNCOptionDB *odb)
{
GtkTooltips *tooltips;
GNCOptionSection *section;
gint num_sections = gnc_option_db_num_sections(odb);
gint i;
tooltips = gtk_tooltips_new();
for (i = 0; i < num_sections; i++)
{
section = gnc_option_db_get_section(odb, i);
gnc_options_dialog_append_page(propertybox, section);
gnc_options_dialog_append_page(propertybox, section, tooltips);
}
}

View File

@ -29,7 +29,7 @@
#include "window-reconcile.h"
#include "query-user.h"
#include "account-tree.h"
#include "messages.h"
#include "enriched-messages.h"
#include "ui-callbacks.h"
#include "util.h"
@ -65,7 +65,8 @@ gnc_xfer_dialog_toggle_cb(GtkToggleButton *button, gpointer data)
static GtkWidget *
gnc_xfer_dialog_create_tree_frame(Account *initial, gchar *title,
GNCAccountTree **set_tree)
GNCAccountTree **set_tree,
GtkTooltips *tooltips)
{
GtkWidget *frame, *scrollWin, *accountTree, *vbox, *button;
gboolean is_category;
@ -114,7 +115,7 @@ gnc_xfer_dialog_create_tree_frame(Account *initial, gchar *title,
button = gtk_check_button_new_with_label(SHOW_CATEGORIES_STR);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), is_category);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
gnc_set_tooltip(button, SHOW_CAT_MSG);
gtk_tooltips_set_tip(tooltips, button, SHOW_CAT_MSG, NULL);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
GTK_SIGNAL_FUNC(gnc_xfer_dialog_toggle_cb),
@ -129,6 +130,7 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
XferDialog *xferData)
{
GtkWidget *dialog;
GtkTooltips *tooltips;
dialog = gnome_dialog_new(TRANSFER_STR,
GNOME_STOCK_BUTTON_OK,
@ -149,6 +151,8 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
/* don't close on buttons */
gnome_dialog_set_close(GNOME_DIALOG(dialog), FALSE);
tooltips = gtk_tooltips_new();
/* contains amount, date, description, and notes */
{
GtkWidget *frame, *vbox, *hbox, *label;
@ -171,7 +175,7 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
GtkWidget *amount;
gchar * string;
string = g_strconcat(AMT_STR, " ", CURRENCY_SYMBOL, NULL);
string = g_strconcat(AMOUNT_C_STR, " ", CURRENCY_SYMBOL, NULL);
label = gtk_label_new(string);
g_free(string);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
@ -187,7 +191,7 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
{
GtkWidget *date;
label = gtk_label_new(DATE_STR);
label = gtk_label_new(DATE_C_STR);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
@ -213,11 +217,11 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
vbox = gtk_vbox_new(TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
label = gtk_label_new(DESC_STR);
label = gtk_label_new(DESC_C_STR);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
label = gtk_label_new(MEMO_STR);
label = gtk_label_new(MEMO_C_STR);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
}
@ -249,11 +253,11 @@ gnc_xfer_dialog_create(GtkWidget * parent, Account * initial,
hbox, TRUE, TRUE, 0);
tree = gnc_xfer_dialog_create_tree_frame(initial, XFRM_STR,
&xferData->from);
&xferData->from, tooltips);
gtk_box_pack_start(GTK_BOX(hbox), tree, TRUE, TRUE, 0);
tree = gnc_xfer_dialog_create_tree_frame(initial, XFTO_STR,
&xferData->to);
&xferData->to, tooltips);
gtk_box_pack_start(GTK_BOX(hbox), tree, TRUE, TRUE, 0);
}

View File

@ -22,6 +22,7 @@
#include "account-tree.h"
#include "dialog-utils.h"
#include "global-options.h"
#include "messages.h"
#include "util.h"
@ -687,14 +688,6 @@ char * gnc_ui_get_account_field_value_string(Account *account, int field)
}
void gnc_set_tooltip(GtkWidget *w, const gchar *tip)
{
GtkTooltips *t = gtk_tooltips_new();
gtk_tooltips_set_tip(t, w, tip, NULL);
}
static void
gnc_option_menu_cb(GtkWidget *w, gpointer data)
{
@ -722,6 +715,7 @@ gnc_option_menu_cb(GtkWidget *w, gpointer data)
GtkWidget *
gnc_build_option_menu(GNCOptionInfo *option_info, gint num_options)
{
GtkTooltips *tooltips;
GtkWidget *omenu;
GtkWidget *menu;
GtkWidget *menu_item;
@ -733,10 +727,12 @@ gnc_build_option_menu(GNCOptionInfo *option_info, gint num_options)
menu = gtk_menu_new();
gtk_widget_show(menu);
tooltips = gtk_tooltips_new();
for (i = 0; i < num_options; i++)
{
menu_item = gtk_menu_item_new_with_label(option_info[i].name);
gnc_set_tooltip(menu_item, option_info[i].tip);
gtk_tooltips_set_tip(tooltips, menu_item, option_info[i].tip, NULL);
gtk_widget_show(menu_item);
gtk_object_set_data(GTK_OBJECT(menu_item),
@ -763,3 +759,34 @@ gnc_build_option_menu(GNCOptionInfo *option_info, gint num_options)
return omenu;
}
/********************************************************************\
* gnc_get_toolbar_style *
* returns the current toolbar style for gnucash toolbars *
* *
* Args: none *
* Returns: toolbar style *
\*******************************************************************/
GtkToolbarStyle
gnc_get_toolbar_style()
{
GtkToolbarStyle tbstyle = GTK_TOOLBAR_BOTH;
char *style_string;
style_string = gnc_lookup_multichoice_option("General",
"Toolbar Buttons",
"icons_and_text");
if (safe_strcmp(style_string, "icons_and_text") == 0)
tbstyle = GTK_TOOLBAR_BOTH;
else if (safe_strcmp(style_string, "icons_only") == 0)
tbstyle = GTK_TOOLBAR_ICONS;
else if (safe_strcmp(style_string, "text_only") == 0)
tbstyle = GTK_TOOLBAR_TEXT;
if (style_string != NULL)
free(style_string);
return tbstyle;
}

View File

@ -138,9 +138,9 @@ gchar * gnc_get_source_name(gint source);
gchar * gnc_get_source_code_name(gint source);
gint gnc_get_source_code(gchar * codename);
void gnc_set_tooltip(GtkWidget *w, const gchar *tip);
GtkWidget * gnc_build_option_menu(GNCOptionInfo *option_info,
gint num_options);
GtkToolbarStyle gnc_get_toolbar_style();
#endif

View File

@ -34,8 +34,6 @@
static short module = MOD_GUI;
static GNCOptionDB *global_options = NULL;
static SCM guile_global_options = SCM_UNDEFINED;
static SCM guile_global_options_id = SCM_UNDEFINED;
/********************************************************************\
@ -49,16 +47,17 @@ void
gnc_options_init()
{
SCM func = gh_eval_str("gnc:send-global-options");
SCM options;
if (gh_procedure_p(func))
gh_call0(func);
options = gh_call0(func);
else
{
PERR("gnc_options_init: no guile options!");
return;
}
global_options = gnc_option_db_new();
gnc_option_db_init(global_options, guile_global_options);
global_options = gnc_option_db_new(options);
}
@ -74,28 +73,44 @@ gnc_options_shutdown()
{
gnc_option_db_destroy(global_options);
global_options = NULL;
if (guile_global_options_id != SCM_UNDEFINED)
gnc_unregister_c_side_scheme_ptr_id(guile_global_options_id);
guile_global_options = SCM_UNDEFINED;
guile_global_options_id = SCM_UNDEFINED;
}
/********************************************************************\
* gnc_register_option_change_callback *
* register a callback to be called whenever an option changes *
* this is rather heavy-weight, since all handlers will be called *
* whenever any option changes. We may need to refine it later. *
* *
* Args: callback - the callback function *
* Args: callback - the callback function *
* user_data - the user data for the callback *
* section - the section to get callbacks for. *
* If NULL, get callbacks for any section changes.*
* name - the option name to get callbacks for. *
* If NULL, get callbacks for any option in the *
* section. Only used if section is non-NULL. *
* Returns: SCM handle for unregistering *
\********************************************************************/
SCM
gnc_register_option_change_callback(OptionChangeCallback callback,
void *user_data,
char *section,
char *name)
{
return gnc_option_db_register_change_callback(global_options, callback,
user_data, section, name);
}
/********************************************************************\
* gnc_unregister_option_change_callback_id *
* unregister the change callback associated with the given id *
* *
* Args: callback_id - the callback function id *
* Returns: nothing *
\********************************************************************/
void
gnc_register_option_change_callback(OptionChangeCallback callback,
gpointer user_data)
gnc_unregister_option_change_callback_id(SCM callback_id)
{
gnc_option_db_register_change_callback(global_options, callback, user_data);
gnc_option_db_unregister_change_callback_id(global_options, callback_id);
}
@ -204,21 +219,6 @@ _gnc_option_refresh_ui(SCM guile_option)
}
/********************************************************************\
* _gnc_register_global_options *
* registers the global options. Intended to be called from guile.*
* *
* Args: options - the guile global options *
* Returns: nothing *
\********************************************************************/
void
_gnc_register_global_options(SCM options)
{
guile_global_options = options;
guile_global_options_id = gnc_register_c_side_scheme_ptr(options);
}
static void
gnc_options_dialog_apply_cb(GnomePropertyBox *propertybox,
gint arg1, gpointer user_data)

View File

@ -29,8 +29,12 @@ void gnc_options_init();
void gnc_options_shutdown();
void gnc_show_options_dialog();
void gnc_register_option_change_callback(OptionChangeCallback callback,
gpointer user_data);
SCM gnc_register_option_change_callback(OptionChangeCallback callback,
void *user_data,
char *section,
char *name);
void gnc_unregister_option_change_callback_id(SCM callback_id);
GNCOption * gnc_get_option_by_name(char *section_name, char *name);
GNCOption * gnc_get_option_by_SCM(SCM guile_option);
@ -47,7 +51,6 @@ char * gnc_lookup_multichoice_option(char *section, char *name,
/* private */
void _gnc_option_refresh_ui(SCM option);
void _gnc_register_global_options(SCM options);
#endif /* __GLOBAL_OPTIONS_H__ */

View File

@ -43,18 +43,12 @@ struct _GNCOptionSection
struct _GNCOptionDB
{
SCM guile_options;
SCM guile_options_id;
GSList *option_sections;
gboolean options_dirty;
GSList *change_callbacks;
};
typedef struct _ChangeCBInfo ChangeCBInfo;
struct _ChangeCBInfo
{
OptionChangeCallback callback;
gpointer user_data;
};
typedef struct _Getters Getters;
@ -98,43 +92,15 @@ gnc_option_db_get_handle(GNCOptionDB *odb)
}
/********************************************************************\
* gnc_option_db_new *
* allocate a new option database and initialize its values *
* *
* Args: none *
* Returns: a new option database *
\********************************************************************/
GNCOptionDB *
gnc_option_db_new()
{
GNCOptionDB *odb;
odb = g_new0(GNCOptionDB, 1);
odb->option_sections = NULL;
odb->options_dirty = FALSE;
odb->change_callbacks = NULL;
if (option_dbs == NULL)
option_dbs = g_ptr_array_new();
g_ptr_array_add(option_dbs, odb);
return odb;
}
/********************************************************************\
* gnc_option_db_init *
* initialize the options structures from the guile side *
* *
* Args: odb - the option database to initialize *
* options - the guile options to initialize with *
* Returns: nothing *
\********************************************************************/
void
gnc_option_db_init(GNCOptionDB *odb, SCM options)
static void
gnc_option_db_init(GNCOptionDB *odb)
{
SCM func = gh_eval_str("gnc:send-options");
GNCOptionDBHandle handle;
@ -146,16 +112,41 @@ gnc_option_db_init(GNCOptionDB *odb, SCM options)
return;
}
gh_call2(func, gh_int2scm(handle), options);
gh_call2(func, gh_int2scm(handle), odb->guile_options);
}
static void
gnc_option_free_cbinfo(gpointer data, gpointer not_used)
/********************************************************************\
* gnc_option_db_new *
* allocate a new option database and initialize its values *
* *
* Args: guile_options - SCM handle to options *
* Returns: a new option database *
\********************************************************************/
GNCOptionDB *
gnc_option_db_new(SCM guile_options)
{
g_free(data);
GNCOptionDB *odb;
odb = g_new0(GNCOptionDB, 1);
odb->guile_options = guile_options;
odb->guile_options_id = gnc_register_c_side_scheme_ptr(guile_options);
odb->option_sections = NULL;
odb->options_dirty = FALSE;
if (option_dbs == NULL)
option_dbs = g_ptr_array_new();
g_ptr_array_add(option_dbs, odb);
gnc_option_db_init(odb);
return odb;
}
/********************************************************************\
* gnc_option_db_destroy *
* unregister the scheme options and free all the memory *
@ -186,7 +177,6 @@ gnc_option_db_destroy(GNCOptionDB *odb)
{
option = option_node->data;
/* Should we check return value? */
gnc_unregister_c_side_scheme_ptr_id(option->guile_option_id);
option_node = option_node->next;
@ -199,13 +189,9 @@ gnc_option_db_destroy(GNCOptionDB *odb)
section_node = section_node->next;
}
g_slist_foreach(odb->change_callbacks, gnc_option_free_cbinfo, NULL);
g_slist_free(odb->option_sections);
g_slist_free(odb->change_callbacks);
odb->option_sections = NULL;
odb->change_callbacks = NULL;
odb->options_dirty = FALSE;
if (!g_ptr_array_remove(option_dbs, odb))
@ -219,6 +205,10 @@ gnc_option_db_destroy(GNCOptionDB *odb)
option_dbs = NULL;
}
gnc_unregister_c_side_scheme_ptr_id(odb->guile_options_id);
odb->guile_options = SCM_UNDEFINED;
odb->guile_options_id = SCM_UNDEFINED;
g_free(odb);
}
@ -226,43 +216,117 @@ gnc_option_db_destroy(GNCOptionDB *odb)
/********************************************************************\
* gnc_option_db_register_change_callback *
* register a callback to be called whenever an option changes *
* this is rather heavy-weight, since all handlers will be called *
* whenever any option changes. We may need to refine it later. *
* *
* Args: odb - the option database to register with *
* callback - the callback function to register *
* user_data - the user data for the callback *
* section - the section to get callbacks for. *
* If NULL, get callbacks for any section changes.*
* name - the option name to get callbacks for. *
* If NULL, get callbacks for any option in the *
* section. Only used if section is non-NULL. *
* Returns: SCM handle for unregistering *
\********************************************************************/
SCM
gnc_option_db_register_change_callback(GNCOptionDB *odb,
OptionChangeCallback callback,
void *data,
char *section,
char *name)
{
POINTER_TOKEN pt;
SCM register_proc;
SCM arg;
SCM args;
/* Get the register procedure */
register_proc = gh_eval_str("gnc:options-register-c-callback");
if (!gh_procedure_p(register_proc))
{
PERR("gnc_option_db_register_change_callback2: not a procedure\n");
return SCM_UNDEFINED;
}
/* Now build the args list for apply */
args = gh_eval_str("()");
/* first the guile options database */
args = gh_cons(odb->guile_options, args);
/* next the data */
pt = make_POINTER_TOKEN("void*", data);
arg = POINTER_TOKEN_to_SCM(pt);
args = gh_cons(arg, args);
/* next the callback */
pt = make_POINTER_TOKEN("OptionChangeCallback", callback);
arg = POINTER_TOKEN_to_SCM(pt);
args = gh_cons(arg, args);
/* next the name */
if (name == NULL)
arg = SCM_BOOL_F;
else
arg = gh_str02scm(name);
args = gh_cons(arg, args);
/* next the section */
if (section == NULL)
arg = SCM_BOOL_F;
else
arg = gh_str02scm(section);
args = gh_cons(arg, args);
/* now apply the procedure */
return gh_apply(register_proc, args);
}
/********************************************************************\
* gnc_option_db_unregister_change_callback_id *
* unregister the change callback associated with the given id *
* *
* Args: odb - the option database to register with *
* callback - the callback function to register *
* Returns: nothing *
\********************************************************************/
void
gnc_option_db_register_change_callback(GNCOptionDB *odb,
OptionChangeCallback callback,
gpointer data)
gnc_option_db_unregister_change_callback_id(GNCOptionDB *odb, SCM callback_id)
{
ChangeCBInfo *cbinfo;
SCM proc;
assert(odb != NULL);
if (callback_id == SCM_UNDEFINED)
return;
cbinfo = g_new0(ChangeCBInfo, 1);
cbinfo->callback = callback;
cbinfo->user_data = data;
proc = gh_eval_str("gnc:options-unregister-callback-id");
if (!gh_procedure_p(proc))
{
PERR("gnc_option_db_unregister_change_callback_id: not a procedure\n");
return;
}
odb->change_callbacks = g_slist_prepend(odb->change_callbacks, cbinfo);
gh_call2(proc, callback_id, odb->guile_options);
}
void
_gnc_option_invoke_callback(OptionChangeCallback callback, void *data)
{
callback(data);
}
static void
gnc_call_option_change_callbacks(GNCOptionDB *odb)
{
GSList *node = odb->change_callbacks;
ChangeCBInfo *cbinfo;
SCM proc;
while (node != NULL)
proc = gh_eval_str("gnc:options-run-callbacks");
if (!gh_procedure_p(proc))
{
cbinfo = node->data;
(cbinfo->callback)(cbinfo->user_data);
node = node->next;
PERR("gnc_call_option_change_callbacks: not a procedure\n");
return;
}
gh_call1(proc, odb->guile_options);
}

View File

@ -44,17 +44,21 @@ typedef struct _GNCOptionDB GNCOptionDB;
typedef int GNCOptionDBHandle;
typedef void (*OptionChangeCallback)(gpointer user_data);
typedef void (*OptionChangeCallback)(void * user_data);
/***** Prototypes ********************************************************/
GNCOptionDB * gnc_option_db_new();
void gnc_option_db_init(GNCOptionDB *odb, SCM options);
GNCOptionDB * gnc_option_db_new(SCM guile_options);
void gnc_option_db_destroy(GNCOptionDB *odb);
void gnc_option_db_register_change_callback(GNCOptionDB *odb,
OptionChangeCallback callback,
gpointer data);
SCM gnc_option_db_register_change_callback(GNCOptionDB *odb,
OptionChangeCallback callback,
void *data,
char *section,
char *name);
void gnc_option_db_unregister_change_callback_id(GNCOptionDB *odb,
SCM callback_id);
char * gnc_option_section(GNCOption *option);
char * gnc_option_name(GNCOption *option);
@ -109,6 +113,8 @@ char * gnc_option_db_lookup_multichoice_option(GNCOptionDB *odb,
void _gnc_option_db_register_option(GNCOptionDBHandle handle,
SCM guile_option);
void _gnc_option_invoke_callback(OptionChangeCallback callback, void *data);
/* These should be in src/guile or src/g-wrap, but they use glib */
SCM gnc_account_list_to_scm(GList *account_list);

View File

@ -31,6 +31,7 @@ typedef struct _ScriptInfo ScriptInfo;
struct _ScriptInfo
{
SCM script;
SCM script_id;
GnomeUIInfo info[2];
};
@ -60,7 +61,7 @@ gnc_extensions_create_script_info(char *name, char *hint, SCM script)
si = g_new0(ScriptInfo, 1);
si->script = script;
gnc_register_c_side_scheme_ptr(script);
si->script_id = gnc_register_c_side_scheme_ptr(script);
script_list = g_slist_prepend(script_list, si);
@ -106,7 +107,7 @@ cleanup_script_info(gpointer script_info, gpointer not_used)
{
ScriptInfo *si = (ScriptInfo *) script_info;
gnc_register_c_side_scheme_ptr(si->script);
gnc_unregister_c_side_scheme_ptr_id(si->script_id);
g_free(si->info[0].label);
g_free(si->info[0].hint);

View File

@ -47,9 +47,9 @@
/** PROTOTYPES ******************************************************/
static void gnc_configure_date_format_cb(gpointer);
static void gnc_configure_date_format_cb(void *);
static void gnc_configure_date_format(void);
static void gnc_configure_newacc_currency_cb(gpointer);
static void gnc_configure_newacc_currency_cb(void *);
static void gnc_configure_newacc_currency(void);
/** GLOBALS *********************************************************/
@ -62,6 +62,9 @@ static int gnome_is_running = FALSE;
static int gnome_is_initialized = FALSE;
static int gnome_is_terminating = FALSE;
static SCM date_callback_id = SCM_UNDEFINED;
static SCM currency_callback_id = SCM_UNDEFINED;
/* ============================================================== */
int
@ -110,11 +113,15 @@ gnucash_ui_init()
gnc_options_init();
gnc_configure_date_format();
gnc_register_option_change_callback(gnc_configure_date_format_cb, NULL);
date_callback_id =
gnc_register_option_change_callback(gnc_configure_date_format_cb, NULL,
"International", "Date Format");
gnc_configure_newacc_currency();
gnc_register_option_change_callback(gnc_configure_newacc_currency_cb,
NULL);
currency_callback_id =
gnc_register_option_change_callback(gnc_configure_newacc_currency_cb,
NULL, "International",
"Default Currency");
mainWindow();
@ -159,14 +166,17 @@ gnc_ui_destroy (void)
if (!gnome_is_initialized)
return;
gnc_options_shutdown();
gnc_extensions_shutdown();
gnc_unregister_option_change_callback_id(date_callback_id);
gnc_unregister_option_change_callback_id(currency_callback_id);
if (app != NULL)
{
gtk_widget_destroy(app);
app = NULL;
}
gnc_options_shutdown();
gnc_extensions_shutdown();
}
/* ============================================================== */
@ -220,7 +230,7 @@ gnucash_ui_select_file()
* Returns: Nothing
*/
static void
gnc_configure_date_format_cb(gpointer data)
gnc_configure_date_format_cb(void *data)
{
gnc_configure_date_format();
gnc_group_ui_refresh(gncGetCurrentGroup());
@ -274,7 +284,9 @@ gnc_configure_date_format (void)
}
setDateFormat(df);
free(format_code);
if (format_code != NULL)
free(format_code);
}
/* gnc_configure_date_format_cb
@ -285,7 +297,7 @@ gnc_configure_date_format (void)
* Returns: Nothing
*/
static void
gnc_configure_newacc_currency_cb(gpointer data)
gnc_configure_newacc_currency_cb(void *data)
{
gnc_configure_newacc_currency();
}
@ -305,7 +317,9 @@ gnc_configure_newacc_currency(void)
"Default Currency",
"USD");
xaccSetDefaultNewaccountCurrency(newacc_def_currency);
free(newacc_def_currency);
if (newacc_def_currency != NULL)
free(newacc_def_currency);
}
/****************** END OF FILE **********************/

View File

@ -130,19 +130,13 @@ helpAnchorCB(XmHTMLAnchorCallbackStruct *acbs, HTMLUserData user_data)
return html_data;
/* other types are unsupported, but it would be fun if they were ... */
/* other types use gnome_url_show */
case ANCHOR_FTP:
PERR(" this help window doesn't support ftp: %s\n", acbs->href);
break;
case ANCHOR_HTTP:
PERR (" this help window doesn't support http: %s\n", acbs->href);
break;
case ANCHOR_MAILTO:
PERR(" this help window doesn't support email: %s\n", acbs->href);
break;
case ANCHOR_UNKNOWN:
default:
PERR(" don't know this type of url: %s\n", acbs->href);
gnome_url_show(acbs->href);
break;
}

View File

@ -29,6 +29,8 @@
#include "top-level.h"
#include "window-html.h"
#include "dialog-utils.h"
#include "global-options.h"
#include "messages.h"
#include "File.h"
#include "util.h"
@ -318,6 +320,7 @@ struct _HTMLWindow
GtkWidget *back;
GtkWidget *toolbar;
SCM toolbar_change_callback_id;
HTMLHistory *history;
@ -509,6 +512,18 @@ gnc_html_window_fill_toolbar(HTMLWindow *hw)
}
static void
gnc_html_toolbar_change_cb(void *data)
{
HTMLWindow *hw = data;
GtkToolbarStyle tbstyle;
tbstyle = gnc_get_toolbar_style();
gtk_toolbar_set_style(GTK_TOOLBAR(hw->toolbar), tbstyle);
}
/********************************************************************\
* htmlWindow *
* opens up an html window, and displays html *
@ -550,11 +565,12 @@ htmlWindow(GtkWidget *parent,
GtkWidget *dock;
GtkWidget *dock_item;
GtkWidget *toolbar;
SCM id;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
hw->window = window;
gtk_window_set_policy(GTK_WINDOW (window), TRUE, TRUE, FALSE);
gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, TRUE);
gtk_window_set_default_size(GTK_WINDOW(window), 675, 400);
hw->window = window;
dock = gnome_dock_new();
gtk_container_add(GTK_CONTAINER(window), dock);
@ -566,6 +582,10 @@ htmlWindow(GtkWidget *parent,
gtk_container_add(GTK_CONTAINER(dock_item), toolbar);
hw->toolbar = toolbar;
id = gnc_register_option_change_callback(gnc_html_toolbar_change_cb, hw,
"General", "Toolbar Buttons");
hw->toolbar_change_callback_id = id;
gnome_dock_add_item (GNOME_DOCK(dock), GNOME_DOCK_ITEM(dock_item),
GNOME_DOCK_TOP, 0, 0, 0, TRUE);
@ -589,6 +609,7 @@ htmlWindow(GtkWidget *parent,
gtk_widget_show_all(window);
}
gnc_html_toolbar_change_cb(hw);
htmlSetButtonStates(hw);
}
@ -624,9 +645,10 @@ htmlSetButtonStates(HTMLWindow *hw)
/********************************************************************\
* htmlKeyCB - called when user presses a key *
* *
* Args: widget - the back button *
* Args: widget - the widget getting the key *
* event - the key event *
* data - html window structure *
* Return: none *
* Return: boolean indicating whether we handled the event *
\********************************************************************/
static gboolean
htmlKeyCB(GtkWidget *widget, GdkEventKey *event, gpointer data)
@ -636,9 +658,6 @@ htmlKeyCB(GtkWidget *widget, GdkEventKey *event, gpointer data)
GtkAdjustment *vadj, *hadj;
gfloat v_value, h_value;
if (html->vsba == NULL)
return FALSE;
vadj = GTK_ADJUSTMENT(html->vsba);
hadj = GTK_ADJUSTMENT(html->hsba);
@ -774,6 +793,8 @@ destroyHtmlWinCB(GtkWidget *widget, gpointer data)
hw->htmlwidget = NULL;
gnc_unregister_option_change_callback_id(hw->toolbar_change_callback_id);
g_free(hw);
*hwp = NULL;
@ -845,10 +866,15 @@ gnc_html_load(HTMLWindow *hw)
gtk_window_set_title(GTK_WINDOW(hw->window), data->title);
gnc_html_window_fill_toolbar(hw);
htmlSetButtonStates(hw);
(hw->jump_cb)(data->user_data, &text, &label);
if (text == NULL)
return;
{
text = "";
label = NULL;
}
gtk_xmhtml_source(GTK_XMHTML(hw->htmlwidget), text);
@ -856,8 +882,6 @@ gnc_html_load(HTMLWindow *hw)
XmHTMLAnchorScrollToName(hw->htmlwidget, label);
else
XmHTMLTextScrollToLine(hw->htmlwidget, 0);
htmlSetButtonStates(hw);
}

View File

@ -66,7 +66,7 @@ enum {
static void
gnc_ui_refresh_statusbar()
{
GtkWidget *label;
GNCMainInfo *main_info;
double assets = 0.0;
double profits = 0.0;
AccountGroup *group;
@ -79,6 +79,10 @@ gnc_ui_refresh_statusbar()
int account_type;
int i;
main_info = gnc_get_main_info();
if (main_info == NULL)
return;
group = gncGetCurrentGroup ();
num_accounts = xaccGroupGetNumAccounts(group);
for (i = 0; i < num_accounts; i++)
@ -119,11 +123,8 @@ gnc_ui_refresh_statusbar()
label_string = g_strconcat(ASSETS_STR, ": ", asset_string, " ",
PROFITS_STR, ": ", profit_string, " ",
NULL);
label = gtk_object_get_data(GTK_OBJECT(gnc_get_ui_data()),
"balance_label");
gtk_label_set_text(GTK_LABEL(label), label_string);
gtk_label_set_text(GTK_LABEL(main_info->balance_label), label_string);
g_free(asset_string);
g_free(profit_string);
@ -382,9 +383,9 @@ gnc_ui_filemenu_cb(GtkWidget *widget, gpointer menuItem)
}
static gboolean
gnc_ui_mainWindow_delete_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
gnc_ui_mainWindow_delete_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
/* Don't allow deletes if we're in a modal dialog */
if (gtk_main_level() == 1)
@ -396,23 +397,35 @@ gnc_ui_mainWindow_delete_cb(GtkWidget *widget,
static gboolean
gnc_ui_mainWindow_destroy_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
gnc_ui_mainWindow_destroy_event_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
return FALSE;
}
static void
gnc_ui_mainWindow_destroy_cb(GtkObject *object, gpointer user_data)
{
GNCMainInfo *main_info = user_data;
gnc_unregister_option_change_callback_id(main_info->tree_change_callback_1);
gnc_unregister_option_change_callback_id(main_info->tree_change_callback_2);
gnc_unregister_option_change_callback_id(main_info->toolbar_change_callback);
g_free(main_info);
}
GNCAccountTree *
gnc_get_current_account_tree()
{
GtkWidget *widget;
GNCMainInfo *main_info;
widget = gnc_get_ui_data();
if (widget == NULL)
main_info = gnc_get_main_info();
if (main_info == NULL)
return NULL;
return gtk_object_get_data(GTK_OBJECT(widget), "account_tree");
return GNC_ACCOUNT_TREE(main_info->account_tree);
}
Account *
@ -441,7 +454,7 @@ gnc_account_tree_activate_cb(GNCAccountTree *tree,
}
static void
gnc_configure_account_tree(gpointer data)
gnc_configure_account_tree(void *data)
{
GtkObject *app;
GNCAccountTree *tree;
@ -449,7 +462,7 @@ gnc_configure_account_tree(gpointer data)
AccountViewInfo old_avi;
app = GTK_OBJECT(gnc_get_ui_data());
tree = GNC_ACCOUNT_TREE(gtk_object_get_data(app, "account_tree"));
tree = gnc_get_current_account_tree();
if (tree == NULL)
return;
@ -813,21 +826,57 @@ gnc_main_create_menus(GnomeApp *app, GtkWidget *account_tree)
gnome_popup_menu_attach(popup, account_tree, NULL);
}
static GNCMainInfo *
gnc_get_main_info()
{
GtkObject *app = GTK_OBJECT(gnc_get_ui_data());
return gtk_object_get_data(app, "gnc_main_info");
}
static void
gnc_configure_toolbar(void *data)
{
GnomeApp *app = GNOME_APP(gnc_get_ui_data());
GnomeDockItem *di;
GtkWidget *toolbar;
GtkToolbarStyle tbstyle;
di = gnome_app_get_dock_item_by_name(app, GNOME_APP_TOOLBAR_NAME);
if (di == NULL)
return;
toolbar = gnome_dock_item_get_child(di);
if (toolbar == NULL)
return;
tbstyle = gnc_get_toolbar_style();
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), tbstyle);
}
void
mainWindow()
{
GNCMainInfo *main_info;
GtkWidget *app = gnc_get_ui_data();
GtkWidget *scrolled_win;
GtkWidget *statusbar;
GtkWidget *account_tree;
GtkWidget *label;
account_tree = gnc_account_tree_new();
gtk_object_set_data(GTK_OBJECT (app), "account_tree", account_tree);
gnc_configure_account_tree(NULL);
gnc_register_option_change_callback(gnc_configure_account_tree, NULL);
main_info = g_new0(GNCMainInfo, 1);
gtk_object_set_data(GTK_OBJECT(app), "gnc_main_info", main_info);
gtk_signal_connect(GTK_OBJECT (account_tree), "activate_account",
main_info->account_tree = gnc_account_tree_new();
main_info->tree_change_callback_1 =
gnc_register_option_change_callback(gnc_configure_account_tree, NULL,
"Account Types", NULL);
main_info->tree_change_callback_2 =
gnc_register_option_change_callback(gnc_configure_account_tree, NULL,
"Account Fields", NULL);
gtk_signal_connect(GTK_OBJECT(main_info->account_tree), "activate_account",
GTK_SIGNAL_FUNC (gnc_account_tree_activate_cb), NULL);
/* create statusbar and add it to the application. */
@ -837,13 +886,18 @@ mainWindow()
gnome_app_set_statusbar(GNOME_APP(app), GTK_WIDGET(statusbar));
gnc_main_create_menus(GNOME_APP(app), account_tree);
gnc_main_create_menus(GNOME_APP(app), main_info->account_tree);
gnc_main_create_toolbar(GNOME_APP(app));
gnc_configure_toolbar(NULL);
main_info->toolbar_change_callback =
gnc_register_option_change_callback(gnc_configure_toolbar, NULL,
"General", "Toolbar Buttons");
/* create the label containing the account balances */
label = gtk_label_new("");
gtk_object_set_data (GTK_OBJECT (app), "balance_label", label);
gtk_box_pack_end(GTK_BOX(statusbar), label, GNC_F, GNC_F, 0);
main_info->balance_label = gtk_label_new("");
gtk_box_pack_end(GTK_BOX(statusbar), main_info->balance_label,
GNC_F, GNC_F, 0);
/* create scrolled window */
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
@ -853,7 +907,8 @@ mainWindow()
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add(GTK_CONTAINER(scrolled_win), GTK_WIDGET(account_tree));
gtk_container_add(GTK_CONTAINER(scrolled_win),
GTK_WIDGET(main_info->account_tree));
gtk_window_set_default_size(GTK_WINDOW(app), 0, 400);
@ -870,18 +925,24 @@ mainWindow()
NULL);
gtk_signal_connect (GTK_OBJECT (app), "destroy_event",
GTK_SIGNAL_FUNC (gnc_ui_mainWindow_destroy_cb),
GTK_SIGNAL_FUNC (gnc_ui_mainWindow_destroy_event_cb),
NULL);
gtk_signal_connect (GTK_OBJECT (app), "destroy",
GTK_SIGNAL_FUNC (gnc_ui_mainWindow_destroy_cb),
main_info);
/* Show everything now that it is created */
gtk_widget_show(label);
gtk_widget_show(main_info->balance_label);
gtk_widget_show(statusbar);
gtk_widget_show(account_tree);
gtk_widget_show(main_info->account_tree);
gtk_widget_show(scrolled_win);
gnc_configure_account_tree(NULL);
gnc_refresh_main_window();
gtk_widget_grab_focus(account_tree);
gtk_widget_grab_focus(main_info->account_tree);
}
/********************* END OF FILE **********************************/

View File

@ -26,6 +26,18 @@
#define __WINDOW_MAINP_H__
typedef struct _GNCMainInfo GNCMainInfo;
struct _GNCMainInfo
{
GtkWidget *account_tree;
GtkWidget *balance_label;
SCM tree_change_callback_1;
SCM tree_change_callback_2;
SCM toolbar_change_callback;
};
/** PROTOTYPES ******************************************************/
static void gnc_ui_refresh_statusbar(void);
static void gnc_ui_exit_cb(GtkWidget *widget, gpointer data);
@ -46,12 +58,17 @@ static void gnc_ui_mainWindow_scrub_all(GtkWidget *widget, gpointer data);
static void gnc_ui_options_cb(GtkWidget *widget, gpointer data);
static void gnc_ui_filemenu_cb(GtkWidget *widget, gpointer menuItem);
static GNCMainInfo * gnc_get_main_info();
static gboolean gnc_ui_mainWindow_delete_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
static gboolean gnc_ui_mainWindow_destroy_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
static gboolean gnc_ui_mainWindow_destroy_event_cb(GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
static void gnc_ui_mainWindow_destroy_cb(GtkObject *object,
gpointer user_data);
#endif

View File

@ -567,11 +567,14 @@ recnWindow(GtkWidget *parent, Account *account)
NULL);
{
GtkTooltips *tooltips;
GtkWidget *main_area = gtk_vbox_new(FALSE, 10);
GtkWidget *debcred_area = gtk_hbox_new(FALSE, 15);
GtkWidget *debits_frame;
GtkWidget *credits_frame;
tooltips = gtk_tooltips_new();
debits_frame = gnc_reconcile_window_create_list_frame
(account, RECLIST_DEBIT, recnData,
&recnData->debit, &recnData->total_debit);
@ -603,7 +606,7 @@ recnWindow(GtkWidget *parent, Account *account)
button = gtk_button_new_with_label(NEW_STR);
gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
gnc_set_tooltip(button, TOOLTIP_NEW_TRANS);
gtk_tooltips_set_tip(tooltips, button, TOOLTIP_NEW_TRANS, NULL);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gnc_ui_reconcile_window_new_cb),
recnData);
@ -611,7 +614,7 @@ recnWindow(GtkWidget *parent, Account *account)
button = gtk_button_new_with_label(EDIT_STR);
recnData->edit_button = button;
gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
gnc_set_tooltip(button, TOOLTIP_EDIT_TRANS);
gtk_tooltips_set_tip(tooltips, button, TOOLTIP_EDIT_TRANS, NULL);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gnc_ui_reconcile_window_edit_cb),
recnData);
@ -619,7 +622,7 @@ recnWindow(GtkWidget *parent, Account *account)
button = gtk_button_new_with_label(DELETE_STR);
recnData->delete_button = button;
gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
gnc_set_tooltip(button, TOOLTIP_DEL_TRANS);
gtk_tooltips_set_tip(tooltips, button, TOOLTIP_DEL_TRANS, NULL);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gnc_ui_reconcile_window_delete_cb),
recnData);
@ -629,7 +632,7 @@ recnWindow(GtkWidget *parent, Account *account)
button = gtk_button_new_with_label(s);
gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
gnc_set_tooltip(button, TOOLTIP_ADJUST_END);
gtk_tooltips_set_tip(tooltips, button, TOOLTIP_ADJUST_END, NULL);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gnc_ui_reconcile_window_change_cb),
recnData);

View File

@ -60,8 +60,12 @@ struct _RegDateWindow
{
GtkWidget * window;
GtkWidget * show_earliest;
GtkWidget * start_date;
GtkWidget * show_latest;
GtkWidget * end_date;
GtkWidget * today_button;
};
/* The RegWindow struct contains info needed by an instance of an open
@ -74,6 +78,7 @@ struct _RegWindow
GtkWidget * window;
GtkWidget * toolbar;
SCM toolbar_change_callback_id;
GtkWidget * balance_label;
GtkWidget * cleared_label;
@ -94,6 +99,7 @@ static short module = MOD_GUI;
/** PROTOTYPES ******************************************************/
RegWindow *regWindowLedger(xaccLedgerDisplay *ledger);
static void regRefresh(xaccLedgerDisplay *ledger);
static void gnc_reg_refresh_toolbar(RegWindow *regData);
static void regDestroy(xaccLedgerDisplay *ledger);
static void closeRegWindow(GtkWidget * mw, RegWindow * regData);
@ -233,6 +239,9 @@ gnc_register_get_default_type(SplitRegister *reg)
type |= new_style;
if (style_string != NULL)
free(style_string);
return type;
}
@ -410,8 +419,7 @@ static void
gnc_register_set_date_range(RegWindow *regData)
{
RegDateWindow *regDateData;
time_t start;
time_t end;
GtkToggleButton *toggle;
assert(regData != NULL);
assert(regData->ledger != NULL);
@ -421,13 +429,45 @@ gnc_register_set_date_range(RegWindow *regData)
if (regDateData == NULL)
return;
start = gnome_date_edit_get_date(GNOME_DATE_EDIT(regDateData->start_date));
end = gnome_date_edit_get_date(GNOME_DATE_EDIT(regDateData->end_date));
toggle = GTK_TOGGLE_BUTTON(regDateData->show_earliest);
if (gtk_toggle_button_get_active(toggle))
{
xaccQueryShowEarliestDateFound(regData->ledger->query);
start = gnc_register_min_day_time(start);
end = gnc_register_max_day_time(end);
gtk_widget_set_sensitive(regDateData->start_date, FALSE);
}
else
{
time_t start;
xaccQuerySetDateRange(regData->ledger->query, start, end);
start = gnome_date_edit_get_date(GNOME_DATE_EDIT(regDateData->start_date));
start = gnc_register_min_day_time(start);
xaccQuerySetEarliest(regData->ledger->query, start);
gtk_widget_set_sensitive(regDateData->start_date, TRUE);
}
toggle = GTK_TOGGLE_BUTTON(regDateData->show_latest);
if (gtk_toggle_button_get_active(toggle))
{
xaccQueryShowLatestDateFound(regData->ledger->query);
gtk_widget_set_sensitive(regDateData->end_date, FALSE);
gtk_widget_set_sensitive(regDateData->today_button, FALSE);
}
else
{
time_t end;
end = gnome_date_edit_get_date(GNOME_DATE_EDIT(regDateData->end_date));
end = gnc_register_max_day_time(end);
xaccQuerySetLatest(regData->ledger->query, end);
gtk_widget_set_sensitive(regDateData->end_date, TRUE);
gtk_widget_set_sensitive(regDateData->today_button, TRUE);
}
}
static void
@ -455,6 +495,17 @@ gnc_register_today_cb(GtkWidget *widget, gpointer data)
gnc_register_date_cb(widget, regData);
}
static void
gnc_register_date_toggle_cb(GtkToggleButton *toggle, gpointer data)
{
RegWindow *regData = (RegWindow *) data;
gnc_register_set_date_range(regData);
regData->ledger->dirty = 1;
xaccLedgerDisplayRefresh(regData->ledger);
}
static void
gnc_register_show_date_window(RegWindow *regData)
{
@ -505,64 +556,94 @@ gnc_register_date_window(RegWindow *regData)
GtkWidget *calendar;
GtkWidget *button;
GtkWidget *entry;
GtkWidget *radio;
GtkWidget *date;
GtkWidget *label;
GtkWidget *hbox;
GtkWidget *vbox2;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *line;
time_t time_val;
GSList *group;
hbox = gtk_hbox_new(FALSE, 2);
gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
gtk_container_add(GTK_CONTAINER(frame), hbox);
vbox = gtk_vbox_new(FALSE, 2);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
gtk_container_add(GTK_CONTAINER(frame), vbox);
vbox = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
/* Starting Date */
vbox2 = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0);
label = gtk_label_new(START_DATE_C_STR);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
label = gtk_label_new(END_DATE_C_STR);
gtk_misc_set_alignment(GTK_MISC(label), 0.95, 0.5);
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
radio = gtk_radio_button_new_with_label(NULL, SHOW_EARLIEST_STR);
gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0);
regDateData->show_earliest = radio;
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
vbox = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
radio = gtk_radio_button_new_with_label(group, START_DATE_C_STR);
gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
gtk_signal_connect(GTK_OBJECT(radio), "toggled",
GTK_SIGNAL_FUNC(gnc_register_date_toggle_cb), regData);
date = gnome_date_edit_new(time(NULL), FALSE, FALSE);
gtk_box_pack_start(GTK_BOX(vbox), date, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), date, FALSE, FALSE, 0);
regDateData->start_date = date;
calendar = GNOME_DATE_EDIT(date)->calendar;
gtk_signal_connect(GTK_OBJECT(calendar), "day_selected_double_click",
GTK_SIGNAL_FUNC(gnc_register_date_cb), regData);
entry = GNOME_DATE_EDIT(date)->date_entry;
gtk_signal_connect(GTK_OBJECT(entry), "activate",
GTK_SIGNAL_FUNC(gnc_register_date_cb), regData);
regDateData->start_date = date;
time_val = xaccQueryGetEarliestDateFound(regData->ledger->query);
if (time_val < time(NULL))
gnome_date_edit_set_time(GNOME_DATE_EDIT(date), time_val);
/* Separator line */
line = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(vbox), line, FALSE, FALSE, 5);
/* Ending Date */
vbox2 = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(vbox), vbox2, FALSE, FALSE, 0);
radio = gtk_radio_button_new_with_label(NULL, SHOW_LATEST_STR);
gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0);
regDateData->show_latest = radio;
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio));
radio = gtk_radio_button_new_with_label(group, END_DATE_C_STR);
gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
gtk_signal_connect(GTK_OBJECT(radio), "toggled",
GTK_SIGNAL_FUNC(gnc_register_date_toggle_cb), regData);
date = gnome_date_edit_new(time(NULL), FALSE, FALSE);
gtk_box_pack_start(GTK_BOX(vbox), date, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), date, FALSE, FALSE, 0);
regDateData->end_date = date;
calendar = GNOME_DATE_EDIT(date)->calendar;
gtk_signal_connect(GTK_OBJECT(calendar), "day_selected_double_click",
GTK_SIGNAL_FUNC(gnc_register_date_cb), regData);
entry = GNOME_DATE_EDIT(date)->date_entry;
gtk_signal_connect(GTK_OBJECT(entry), "activate",
GTK_SIGNAL_FUNC(gnc_register_date_cb), regData);
regDateData->end_date = date;
vbox = gtk_vbox_new(TRUE, 2);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
label = gtk_label_new("");
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
button = gtk_button_new_with_label(TODAY_STR);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(gnc_register_today_cb), regData);
regDateData->today_button = button;
}
return regDateData;
@ -577,21 +658,21 @@ gnc_register_create_tool_bar(RegWindow *regData)
{
GNOME_APP_UI_ITEM,
RECORD_STR, TOOLTIP_RECORD,
recordCB, regData, NULL,
recordCB, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_ADD,
0, 0, NULL
},
{
GNOME_APP_UI_ITEM,
CANCEL_STR, TOOLTIP_CANCEL_TRANS,
cancelCB, regData, NULL,
cancelCB, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_UNDELETE,
0, 0, NULL
},
{
GNOME_APP_UI_ITEM,
DELETE_STR, TOOLTIP_DEL_TRANS,
deleteCB, regData, NULL,
deleteCB, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_TRASH,
0, 0, NULL
},
@ -599,14 +680,14 @@ gnc_register_create_tool_bar(RegWindow *regData)
{
GNOME_APP_UI_ITEM,
NEW_STR, TOOLTIP_NEW_TRANS,
new_trans_cb, regData, NULL,
new_trans_cb, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_NEW,
0, 0, NULL
},
{
GNOME_APP_UI_ITEM,
JUMP_STR, TOOLTIP_JUMP_TRANS,
jump_cb, regData, NULL,
jump_cb, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_JUMP_TO,
0, 0, NULL
},
@ -614,7 +695,7 @@ gnc_register_create_tool_bar(RegWindow *regData)
{
GNOME_APP_UI_ITEM,
TRANSFER_STR, TOOLTIP_TRANSFER,
xferCB, regData, NULL,
xferCB, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CONVERT,
0, 0, NULL
},
@ -622,7 +703,7 @@ gnc_register_create_tool_bar(RegWindow *regData)
{
GNOME_APP_UI_ITEM,
CLOSE_STR, TOOLTIP_CLOSE_REG,
closeCB, regData, NULL,
closeCB, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_CLOSE,
0, 0, NULL
},
@ -631,7 +712,8 @@ gnc_register_create_tool_bar(RegWindow *regData)
toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
gnome_app_fill_toolbar(GTK_TOOLBAR(toolbar), toolbar_info, NULL);
gnome_app_fill_toolbar_with_data(GTK_TOOLBAR(toolbar), toolbar_info,
NULL, regData);
regData->toolbar = toolbar;
@ -1001,11 +1083,44 @@ gnc_register_create_popup_menu(RegWindow *regData)
static void
gnc_register_record_cb(GnucashRegister *reg, gpointer data)
{
RegWindow *regData = data;
gncBoolean goto_blank = GNC_F;
/* If we are in single or double line mode and we hit enter
* on the blank split, go to the blank split instead of the
* next row. This prevents the cursor from jumping around
* when you are entering transactions. */
{
SplitRegister *sr = regData->ledger->ledger;
int type = sr->type;
type &= REG_STYLE_MASK;
if ((type == REG_SINGLE_LINE) || (type == REG_DOUBLE_LINE))
{
Split *blank_split;
blank_split = xaccSRGetBlankSplit(sr);
if (blank_split != NULL)
{
Split *current_split;
current_split = xaccSRGetCurrentSplit(sr);
if (blank_split == current_split)
goto_blank = GNC_T;
}
}
}
/* First record the transaction. This will perform a refresh. */
recordCB(GTK_WIDGET(reg), data);
/* Now move down. */
gnucash_register_goto_next_virt_row(reg);
/* Now move. */
if (goto_blank)
gnc_register_jump_to_blank(regData);
else
gnucash_register_goto_next_virt_row(reg);
}
static void
@ -1031,6 +1146,57 @@ gnc_register_get_parent(xaccLedgerDisplay *ledger)
return regData->window;
}
static void
gnc_reg_set_window_name(RegWindow *regData)
{
Account *leader;
gchar *windowname;
gchar *account_name;
gchar *reg_name;
if (regData == NULL)
return;
leader = regData->ledger->leader;
if (leader != NULL)
{
account_name = gnc_ui_get_account_full_name(leader, ":");
switch (regData->ledger->type)
{
case GENERAL_LEDGER:
case INCOME_LEDGER:
reg_name = GENERAL_LEDGER_STR;
break;
case PORTFOLIO:
reg_name = PORTFOLIO_STR;
break;
default:
reg_name = REGISTER_STR;
break;
}
windowname = g_strconcat(account_name, " ", reg_name, NULL);
g_free(account_name);
}
else
windowname = g_strdup(GENERAL_LEDGER_STR);
gtk_window_set_title(GTK_WINDOW(regData->window), windowname);
g_free(windowname);
}
static void
gnc_toolbar_change_cb(void *data)
{
RegWindow *regData = data;
gnc_reg_refresh_toolbar(regData);
}
/********************************************************************\
* regWindowLedger *
* opens up a ledger window for the account list *
@ -1074,39 +1240,7 @@ regWindowLedger(xaccLedgerDisplay *ledger)
regData->close_ledger = GNC_T;
regData->window = register_window;
{ /* pick a window name */
gchar *windowname;
if (ledger->leader)
{
gchar * acc_name = gnc_ui_get_account_full_name(ledger->leader, ":");
gchar * reg_name;
switch (ledger->type)
{
case GENERAL_LEDGER:
case INCOME_LEDGER:
reg_name = GENERAL_LEDGER_STR;
break;
case PORTFOLIO:
reg_name = PORTFOLIO_STR;
break;
default:
reg_name = REGISTER_STR;
break;
}
windowname = g_strconcat(acc_name, " ", reg_name, NULL);
g_free(acc_name);
}
else
windowname = g_strdup(GENERAL_LEDGER_STR);
gtk_window_set_title(GTK_WINDOW(register_window), windowname);
g_free(windowname);
}
gnc_reg_set_window_name(regData);
/* Invoked when window is being destroyed. */
gtk_signal_connect(GTK_OBJECT(regData->window), "destroy",
@ -1138,6 +1272,7 @@ regWindowLedger(xaccLedgerDisplay *ledger)
{
GtkWidget *dock_item;
GtkWidget *toolbar;
SCM id;
dock_item = gnome_dock_item_new("toolbar", GNOME_DOCK_ITEM_BEH_EXCLUSIVE);
@ -1145,6 +1280,10 @@ regWindowLedger(xaccLedgerDisplay *ledger)
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
gtk_container_add(GTK_CONTAINER(dock_item), toolbar);
id = gnc_register_option_change_callback(gnc_toolbar_change_cb, regData,
"General", "Toolbar Buttons");
regData->toolbar_change_callback_id = id;
gnome_dock_add_item (GNOME_DOCK(register_dock), GNOME_DOCK_ITEM(dock_item),
GNOME_DOCK_TOP, 1, 0, 0, TRUE);
}
@ -1176,12 +1315,14 @@ regWindowLedger(xaccLedgerDisplay *ledger)
xaccConfigSplitRegister(ledger->ledger,
gnc_register_get_default_type(ledger->ledger));
/* Allow grow, allow shrink, no auto-shrink */
gtk_window_set_policy(GTK_WINDOW(register_window), TRUE, TRUE, FALSE);
/* Allow grow, allow shrink, auto-shrink */
gtk_window_set_policy(GTK_WINDOW(register_window), TRUE, TRUE, TRUE);
gtk_widget_show_all(register_window);
ledger->dirty = 1;
xaccLedgerDisplayRefresh(ledger);
gnc_reg_refresh_toolbar(regData);
gnc_register_jump_to_blank(regData);
@ -1192,22 +1333,12 @@ regWindowLedger(xaccLedgerDisplay *ledger)
static void
gnc_reg_refresh_toolbar(RegWindow *regData)
{
GtkToolbarStyle tbstyle = GTK_TOOLBAR_BOTH;
char *style_string;
GtkToolbarStyle tbstyle;
if ((regData == NULL) || (regData->toolbar == NULL))
return;
style_string = gnc_lookup_multichoice_option("Register",
"Toolbar Buttons",
"icons_and_text");
if (safe_strcmp(style_string, "icons_and_text") == 0)
tbstyle = GTK_TOOLBAR_BOTH;
else if (safe_strcmp(style_string, "icons_only") == 0)
tbstyle = GTK_TOOLBAR_ICONS;
else if (safe_strcmp(style_string, "text_only") == 0)
tbstyle = GTK_TOOLBAR_TEXT;
tbstyle = gnc_get_toolbar_style();
gtk_toolbar_set_style(GTK_TOOLBAR(regData->toolbar), tbstyle);
}
@ -1219,8 +1350,6 @@ regRefresh(xaccLedgerDisplay *ledger)
RegWindow *regData = (RegWindow *) (ledger->gui_hook);
int print_flags = PRTSYM | PRTSEP;
gnc_reg_refresh_toolbar(regData);
xaccSRLoadXferCells(ledger->ledger, ledger->leader);
if (regData->window != NULL)
@ -1230,6 +1359,8 @@ regRefresh(xaccLedgerDisplay *ledger)
gtk_label_set_text(GTK_LABEL(regData->cleared_label),
xaccPrintAmount(ledger->clearedBalance, print_flags));
gnc_reg_set_window_name(regData);
}
}
@ -1257,8 +1388,7 @@ regDestroy(xaccLedgerDisplay *ledger)
/********************************************************************\
* closeRegWindow *
* frees memory allocated for an regWindow, and other cleanup *
* stuff *
* frees memory for a regWindow, and other cleanup stuff *
* *
* Args: widget - the widget that called us *
* regData - the data struct for this register *
@ -1267,9 +1397,14 @@ regDestroy(xaccLedgerDisplay *ledger)
static void
closeRegWindow(GtkWidget * widget, RegWindow *regData)
{
SCM id;
if (regData->close_ledger)
xaccLedgerDisplayClose(regData->ledger);
id = regData->toolbar_change_callback_id;
gnc_unregister_option_change_callback_id(id);
if (regData->date_window != NULL)
{
if (regData->date_window->window != NULL)

View File

@ -39,6 +39,7 @@
#include "messages.h"
#include "util.h"
#include "FileBox.h"
#include "gfec.h"
static short module = MOD_HTML;
@ -56,9 +57,7 @@ struct _ReportData
SCM rendering_thunk;
SCM rendering_thunk_id;
SCM guile_options;
SCM guile_options_id;
SCM change_callback_id;
};
@ -69,11 +68,9 @@ report_data_new()
report_data = g_new0(ReportData, 1);
report_data->guile_options = SCM_UNDEFINED;
report_data->guile_options_id = SCM_UNDEFINED;
report_data->rendering_thunk = SCM_UNDEFINED;
report_data->rendering_thunk_id = SCM_UNDEFINED;
report_data->change_callback_id = SCM_UNDEFINED;
return report_data;
}
@ -86,6 +83,11 @@ report_data_destroy(HTMLUserData user_data)
g_free(report_data->text);
report_data->text = NULL;
if (report_data->change_callback_id != SCM_UNDEFINED)
gnc_option_db_unregister_change_callback_id
(report_data->odb, report_data->change_callback_id);
report_data->change_callback_id = SCM_UNDEFINED;
gnc_option_db_destroy(report_data->odb);
report_data->odb = NULL;
@ -93,11 +95,6 @@ report_data_destroy(HTMLUserData user_data)
gtk_widget_destroy(report_data->option_dialog);
report_data->option_dialog = NULL;
if (report_data->guile_options_id != SCM_UNDEFINED)
gnc_unregister_c_side_scheme_ptr_id(report_data->guile_options_id);
report_data->guile_options = SCM_UNDEFINED;
report_data->guile_options_id = SCM_UNDEFINED;
if (report_data->rendering_thunk_id != SCM_UNDEFINED)
gnc_unregister_c_side_scheme_ptr_id(report_data->rendering_thunk_id);
report_data->rendering_thunk = SCM_UNDEFINED;
@ -141,35 +138,27 @@ gnc_options_dialog_help_cb(GnomePropertyBox *propertybox,
gnome_ok_dialog("Set the report options you want using this dialog.");
}
static void
report_data_set_guile_options(ReportData *report_data, const SCM guile_options)
{
GnomePropertyBox *prop_box;
if (report_data->guile_options_id != SCM_UNDEFINED)
if (report_data->odb != NULL)
{
gnc_unregister_c_side_scheme_ptr_id(report_data->guile_options_id);
gnc_option_db_destroy(report_data->odb);
report_data->odb = NULL;
}
if (report_data->option_dialog != NULL)
gtk_widget_destroy(report_data->option_dialog);
if (gh_scm2bool(gh_not(guile_options)))
{
report_data->guile_options = SCM_UNDEFINED;
gtk_widget_destroy(report_data->option_dialog);
report_data->option_dialog = NULL;
return;
}
report_data->guile_options = guile_options;
report_data->guile_options_id =
gnc_register_c_side_scheme_ptr(guile_options);
if (guile_options == SCM_BOOL_F)
return;
report_data->odb = gnc_option_db_new();
gnc_option_db_init(report_data->odb, guile_options);
report_data->odb = gnc_option_db_new(guile_options);
report_data->option_dialog = gnome_property_box_new();
gnome_dialog_close_hides(GNOME_DIALOG(report_data->option_dialog), TRUE);
@ -195,35 +184,61 @@ reportAnchorCB(XmHTMLAnchorCallbackStruct *acbs,
{
switch(acbs->url_type)
{
/* a local file with a possible jump to label */
case ANCHOR_FILE_LOCAL:
PERR(" this report window doesn't support ftp: %s\n", acbs->href);
break;
/* other types are unsupported, but it would be fun if they were ... */
case ANCHOR_FTP:
PERR(" this report window doesn't support ftp: %s\n", acbs->href);
break;
case ANCHOR_HTTP:
PERR (" this report window doesn't support http: %s\n", acbs->href);
break;
case ANCHOR_MAILTO:
PERR(" this report window doesn't support email: %s\n", acbs->href);
break;
case ANCHOR_UNKNOWN:
default:
PERR(" don't know this type of url: %s\n", acbs->href);
gnome_url_show(acbs->href);
break;
}
return NULL;
}
static void
gnc_report_error_dialog(const char *message)
{
GtkWindow *parent;
gchar *text;
parent = GTK_WINDOW(gnc_html_window_get_window(reportwindow));
if (message == NULL)
text = REPORT_ERR_MSG;
else
text = g_strconcat(REPORT_ERR_MSG, "\n\n", message, NULL);
gnc_error_dialog_parented(parent, text);
if (message != NULL)
g_free(text);
}
static char *
gnc_run_report(ReportData *report_data)
{
SCM result, nil;
if (!gh_procedure_p(report_data->rendering_thunk))
return NULL;
nil = gh_eval_str("()");
result = gfec_apply(report_data->rendering_thunk, nil,
gnc_report_error_dialog);
if (!gh_string_p(result))
return NULL;
return gh_scm2newstr(result, NULL);
}
static void
reportJumpCB(HTMLUserData user_data, char **set_text, char **set_label)
{
ReportData *report_data = user_data;
char *text;
SCM text_scm;
*set_text = NULL;
*set_label = NULL;
@ -234,15 +249,7 @@ reportJumpCB(HTMLUserData user_data, char **set_text, char **set_label)
return;
}
if (!gh_procedure_p(report_data->rendering_thunk))
return;
text_scm = gh_call0(report_data->rendering_thunk);
if (!gh_string_p(text_scm))
return;
text = gh_scm2newstr(text_scm, NULL);
text = gnc_run_report(report_data);
if (text == NULL)
return;
@ -254,7 +261,7 @@ reportJumpCB(HTMLUserData user_data, char **set_text, char **set_label)
static void
gnc_report_options_changed_cb(gpointer data)
gnc_report_options_changed_cb(void *data)
{
ReportData *report_data = data;
ReportData *real_data;
@ -383,9 +390,10 @@ reportWindow(const char *title, SCM rendering_thunk, SCM guile_options)
report_data_set_guile_options(report_data, guile_options);
if (report_data->odb != NULL)
gnc_option_db_register_change_callback(report_data->odb,
gnc_report_options_changed_cb,
report_data);
report_data->change_callback_id =
gnc_option_db_register_change_callback(report_data->odb,
gnc_report_options_changed_cb,
report_data, NULL, NULL);
if (report_data->option_dialog != NULL)
{

View File

@ -18,7 +18,23 @@
(display "library installed. You need slib2c6 or later\n")
(display "to run GnuCash.\n")
(newline)
(exit))))
(display "Obtain slib at: http://swissnet.ai.mit.edu/~jaffer/SLIB.html\n")
(newline)
(exit 1))))
;; Test for slib >= 2c6.
(let* ((try-slib (lambda () (require 'printf) (sprintf #f "test")))
(handler (lambda args #f))
(result (catch #t try-slib handler)))
(if (not result)
(begin
(newline)
(display "It appears your 'slib' scheme library is out\n")
(display "of date. You need slib2c6 or later to run GnuCash.\n")
(newline)
(display "Obtain slib at: http://swissnet.ai.mit.edu/~jaffer/SLIB.html\n")
(newline)
(exit 1))))
(define (build-path firstelement . restofpath)
@ -36,22 +52,6 @@
(car restofpath))
(cdr restofpath))))
;;; This is a for-each function for use with Guile hash tables.
;;; It is equally usable with all three forms (hash, hashv, hashq)
;;; and is reasonably efficient, effectively being a loop that does
;;; an iteration for each element in the base vector plus an iteration
;;; for each hashed item found. There should not exist an algorithm
;;; with lower time complexity.
(define (hash-for-each fun hashtable)
(array-for-each
(lambda (x)
(if (null? x)
#f
(for-each (lambda (y)
(fun y))
x)))
hashtable))
;; In pre 1.3 guile's you have to do this manually, unless you call
;; scm_shell, which we can't.
(if (or (string=? (version) "1.2")
@ -125,6 +125,13 @@ string and 'directories' must be a list of strings."
the given name and load it. The system will attempt to locate the
file in all of the directories specified by gnc:*load-path*."
(define (make-thunk file-name)
(lambda () (primitive-load file-name) #t))
(define (handler key . args)
(apply display-error #f (current-error-port) args)
#f)
(let* ((path (if (list? gnc:*load-path*)
gnc:*load-path*
(gnc:config-var-value-get gnc:*load-path*)))
@ -132,8 +139,7 @@ file in all of the directories specified by gnc:*load-path*."
(if (not file-name)
#f
(if
(false-if-exception (primitive-load file-name))
;(primitive-load file-name)
(catch #t (make-thunk file-name) handler)
(begin
(gnc:debug "loaded file " file-name)
#t)

View File

@ -1,10 +1,13 @@
(use-modules (ice-9 slib))
(require 'hash-table)
(define gnc:register-c-side-scheme-ptr #f)
(define gnc:unregister-c-side-scheme-ptr-id #f)
(let ((next-registration-id 0)
;; Not sure this has to be prime, and not sure how large it needs
;; to be, but on both fronts, this should be fairly safe...
(pointer-storage (make-vector 313)))
(pointer-storage (make-hash-table 313)))
(define (register-c-side-scheme-ptr ptr)
(let ((id next-registration-id))

View File

@ -1,89 +1,19 @@
(gnc:support "extensions.scm")
(define (gnc:extensions-menu-test-func)
(display "Extension called from scheme.\n"))
(define (gnc:extensions-menu-setup win)
;; Should take window as a parameter?
(gnc:debug "Setting up extensions menu " win "\n")
(gnc:extensions-menu-add-item "Export data as text"
"Export data as text hint"
(gnc:extensions-menu-add-item "Export data as text (Danger: Unfinished)"
"Export data as text."
(lambda ()
(gnc:main-win-export-data-as-text win)))
(gnc:extensions-menu-add-item "Test error dialog"
"Test error dialog hint"
(lambda ()
(gnc:error-dialog
"Some error didn't occur.")))
(gnc:extensions-menu-add-item "QIF File Import"
"Import QIF File - Scripted in Guile"
(gnc:extensions-menu-add-item "QIF File Import (Danger: Unfinished)"
"Import QIF File - Scripted in Guile."
(lambda ()
(gnc:extensions-qif-import win)))
(gnc:extensions-menu-add-item "Test Adding Transactions"
"Test Bed"
(lambda ()
(gnc:extensions-test-add-txns win)))
(gnc:extensions-menu-add-item "Test Adding Accounts"
"Test Bed"
(lambda ()
(gnc:extensions-test-add-accs win)))
(gnc:extensions-menu-add-item
"Test choose item from list dialog"
"Test choose item from list dialog"
(lambda ()
(let ((result (gnc:choose-item-from-list-dialog
"Choose item from list test dialog"
(list
(cons "Item 1"
(lambda ()
(display "Item 1 selected") (newline)
#f))
(cons "Item 2"
(lambda ()
(display "Item 2 selected") (newline)
#f))
(cons "Item 3 (and close dialog)"
(lambda ()
(display "Item 3 selected -- close") (newline)
'some-interesting-result))))))
(cond
((eq? result #f)
(gnc:error-dialog
"Fatal error in choose item from list dialog."))
((eq? result 'cancel)
(gnc:error-dialog "Choose item from list dialog canceled."))
(else
(gnc:error-dialog
(call-with-output-string (lambda (string-port)
(display "Choose item result: "
string-port)
(write result string-port)))))))))
(gnc:extensions-menu-add-item
"Test verify dialog"
"Test verify dialog hint"
(lambda ()
(let ((result (gnc:verify-dialog "Would you like to play a game?" #t)))
(if result
(gnc:info-dialog "You said yes.")
(gnc:info-dialog "You said no.")))))
(gnc:extensions-menu-add-item
"Test info dialog"
"Test info dialog hint"
(lambda () (gnc:info-dialog "This is information.")))
(gnc:extensions-menu-add-item "Simple extension test"
"Simple extension test hint"
gnc:extensions-menu-test-func))
(gnc:extensions-qif-import win))))
(gnc:hook-add-dangler gnc:*main-window-opened-hook* gnc:extensions-menu-setup)

View File

@ -37,8 +37,8 @@
(display account-group) (newline)
(let ((loadfun (lambda (x) (gnc:load x)))
(loadlist '("testbed.scm" "analytical-qifs.scm"
"gc-import-qifs.scm"
"qifutils.scm" "txn-create.scm")))
"gc-import-qifs.scm" "qifutils.scm"
"acc-create.scm" "txn-create.scm")))
(for-each loadfun loadlist))
(begin
(get-all-types)
@ -57,9 +57,9 @@
(display account-group) (newline)
(let ((loadfun (lambda (x) (gnc:load x)))
(loadlist '("testbed.scm" "sstring-qif.scm"
"qifutils.scm" "dates-qif.scm"
"acc-create.scm"
"txn-create.scm"
"qifutils.scm" "dates-qif.scm"
"split-qif.scm" "qifcats.scm"
"parseqif.scm" "qifstate.scm"
"qifstat.scm" "qif2gc.scm"

View File

@ -28,16 +28,20 @@
;;
;; Just load these since we might want to redefine them on the fly
;; and we're going to change this mechanism anyway...
(gnc:load "report/dummy.scm")
(gnc:load "report/hello-world.scm")
(gnc:load "report/balance-and-pnl.scm")
(gnc:load "report/transaction-report.scm")
(gnc:load "report/average-balance.scm")
;; Load the system and user configs
;; Load the system configs
(if (not (gnc:load-system-config-if-needed))
(gnc:shutdown 1))
(if (not (gnc:load-user-config-if-needed))
(gnc:shutdown 1))
;; Load the user configs
(gnc:load-user-config-if-needed)
;; Clear the change flags caused by loading the configs
(gnc:global-options-clear-changes)
(gnc:hook-run-danglers gnc:*startup-hook*)
@ -52,6 +56,7 @@
(gnc:prefs-show-usage)
(gnc:shutdown 0))))
(define (gnc:shutdown exit-status)
(gnc:debug "Shutdown -- exit-status: " exit-status)
@ -86,6 +91,9 @@
;; You can only open single files right now...
(gnc:ui-open-file (car gnc:*command-line-files*)))
;; add a hook to save the user configs on shutdown
(gnc:hook-add-dangler gnc:*shutdown-hook* gnc:save-global-options)
(gnc:hook-add-dangler gnc:*ui-shutdown-hook* gnc:ui-finish)
(gnc:ui-main)

402
src/scm/options.scm Normal file
View File

@ -0,0 +1,402 @@
;; Scheme code for supporting options
(define (gnc:make-option
;; The category of this option
section
name
;; The sort-tag determines the relative ordering of options in
;; this category. It is used by the gui for display.
sort-tag
type
documentation-string
getter
;; The setter is responsible for ensuring that the value is valid.
setter
default-getter
;; Restore form generator should generate an ascii representation
;; of a function taking one argument. The argument will be an
;; option. The function should restore the option to the original
;; value.
generate-restore-form
;; Validation func should accept a value and return (#t value)
;; on success, and (#f "failure-message") on failure. If #t,
;; the supplied value will be used by the gui to set the option.
value-validator
option-data)
(let ((changed-callback #f))
(vector section
name
sort-tag
type
documentation-string
getter
(lambda args
(apply setter args)
(if changed-callback (changed-callback)))
default-getter
generate-restore-form
value-validator
option-data
(lambda (callback) (set! changed-callback callback)))))
(define (gnc:option-section option)
(vector-ref option 0))
(define (gnc:option-name option)
(vector-ref option 1))
(define (gnc:option-sort-tag option)
(vector-ref option 2))
(define (gnc:option-type option)
(vector-ref option 3))
(define (gnc:option-documentation option)
(vector-ref option 4))
(define (gnc:option-getter option)
(vector-ref option 5))
(define (gnc:option-setter option)
(vector-ref option 6))
(define (gnc:option-default-getter option)
(vector-ref option 7))
(define (gnc:option-generate-restore-form option)
(vector-ref option 8))
(define (gnc:option-value-validator option)
(vector-ref option 9))
(define (gnc:option-data option)
(vector-ref option 10))
(define (gnc:option-set-changed-callback option callback)
(let ((cb-setter (vector-ref option 11)))
(cb-setter callback)))
(define (gnc:option-value option)
(let ((getter (gnc:option-getter option)))
(getter)))
(define (gnc:restore-form-generator value->string)
(lambda () (string-append
"(lambda (option) "
"(if option ((gnc:option-setter option) "
(value->string)
")))")))
(define (gnc:make-string-option
section
name
sort-tag
documentation-string
default-value)
(let* ((value default-value)
(value->string (lambda () (string-append "\"" value "\""))))
(gnc:make-option
section name sort-tag 'string documentation-string
(lambda () value)
(lambda (x) (set! value x))
(lambda () default-value)
(gnc:restore-form-generator value->string)
(lambda (x)
(cond ((string? x)(list #t x))
(else (list #f "string-option: not a string"))))
#f )))
(define (gnc:make-simple-boolean-option
section
name
sort-tag
documentation-string
default-value)
(let* ((value default-value)
(value->string (lambda () (if value "#t" "#f"))))
(gnc:make-option
section name sort-tag 'boolean documentation-string
(lambda () value)
(lambda (x) (set! value x))
(lambda () default-value)
(gnc:restore-form-generator value->string)
(lambda (x)
(if (boolean? x)
(list #t x)
(list #f "boolean-option: not a boolean")))
#f )))
;; date options use the option-data as a boolean value. If true,
;; the gui should allow the time to be entered as well.
(define (gnc:make-date-option
section
name
sort-tag
documentation-string
default-getter
show-time)
(define (date-legal date)
(and (pair? date) (exact? (car date)) (exact? (cdr date))))
(let* ((value (default-getter))
(value->string
(lambda ()
(string-append "(" (number->string (car value))
" . " (number->string (cdr value)) ")"))))
(gnc:make-option
section name sort-tag 'date documentation-string
(lambda () value)
(lambda (date)
(if (date-legal date)
(set! value date)
(gnc:error "Illegal date value set")))
default-getter
(gnc:restore-form-generator value->string)
(lambda (date)
(if (date-legal date)
(list #t date)
(list #f "date-option: illegal date")))
show-time )))
;; account-list options use the option-data as a boolean value. If
;; true, the gui should allow the user to select multiple accounts.
;; values are always a list of accounts.
(define (gnc:make-account-list-option
section
name
sort-tag
documentation-string
default-getter
value-validator
multiple-selection)
(let ((option (default-getter))
(option-set #f)
(validator
(if (not value-validator)
(lambda (account-list) (list #t account-list))
value-validator)))
(gnc:make-option
section name sort-tag 'account-list documentation-string
(lambda () (if option-set option (default-getter)))
(lambda (account-list)
(let* ((result (validator account-list))
(valid (car result))
(value (cadr result)))
(if valid
(begin
(set! option value)
(set! option-set #t))
(gnc:error "Illegal account list value set"))))
default-getter
#f
validator
multiple-selection )))
;; multichoice options use the option-data as a list of vectors.
;; Each vector contains a permissible value (scheme symbol) and
;; a description string.
(define (gnc:make-multichoice-option
section
name
sort-tag
documentation-string
default-value
ok-values)
(define (multichoice-legal val p-vals)
(cond ((null? p-vals) #f)
((eq? val (vector-ref (car p-vals) 0)) #t)
(else multichoice-legal (cdr p-vals))))
(let* ((value default-value)
(value->string (lambda ()
(string-append "'" (symbol->string value)))))
(gnc:make-option
section name sort-tag 'multichoice documentation-string
(lambda () value)
(lambda (x)
(if (multichoice-legal x ok-values)
(set! value x)
(gnc:error "Illegal Multichoice option set")))
(lambda () default-value)
(gnc:restore-form-generator value->string)
(lambda (x)
(if (multichoice-legal x ok-values)
(list #t x)
(list #f "multichoice-option: illegal choice")))
ok-values)))
;; Create a new options database
(define (gnc:new-options)
(define option-hash (make-hash-table 23))
(define options-changed #f)
(define changed-hash (make-hash-table 23))
(define callback-hash (make-hash-table 23))
(define last-callback-id 0)
(define (lookup-option section name)
(let ((section-hash (hash-ref option-hash section)))
(if section-hash
(hash-ref section-hash name)
#f)))
(define (option-changed section name)
(set! options-changed #t)
(let ((section-changed-hash (hash-ref changed-hash section)))
(if (not section-changed-hash)
(begin
(set! section-changed-hash (make-hash-table 23))
(hash-set! changed-hash section section-changed-hash)))
(hash-set! section-changed-hash name #t)))
(define (clear-changes)
(set! options-changed #f)
(set! changed-hash (make-hash-table 23)))
(define (register-option new-option)
(let* ((name (gnc:option-name new-option))
(section (gnc:option-section new-option))
(section-hash (hash-ref option-hash section)))
(if (not section-hash)
(begin
(set! section-hash (make-hash-table 23))
(hash-set! option-hash section section-hash)))
(hash-set! section-hash name new-option)
(gnc:option-set-changed-callback
new-option
(lambda () (option-changed section name)))))
; Call (thunk option) for each option in the database
(define (options-for-each thunk)
(define (section-for-each section-hash thunk)
(hash-for-each
(lambda (name option)
(thunk option))
section-hash))
(hash-for-each
(lambda (section hash)
(section-for-each hash thunk))
option-hash))
(define (options-for-each-general section-thunk option-thunk)
(define (section-for-each section-hash thunk)
(hash-for-each
(lambda (name option)
(thunk option))
section-hash))
(hash-for-each
(lambda (section hash)
(section-thunk section hash)
(if option-thunk
(section-for-each hash option-thunk)))
option-hash))
(define (generate-restore-forms options-string)
(define (generate-option-restore-form option restore-code)
(let* ((section (gnc:option-section option))
(name (gnc:option-name option)))
(string-append
"(let ((option (gnc:lookup-option " options-string "\n"
" \"" section "\"\n"
" \"" name "\")))\n"
" (" restore-code " option))\n\n")))
(define (generate-forms port)
(options-for-each-general
(lambda (section hash)
(display
(string-append "\n; Section: " section "\n\n")
port))
(lambda (option)
(let* ((generator (gnc:option-generate-restore-form option))
(restore-code (false-if-exception (generator))))
(if restore-code
(display
(generate-option-restore-form option restore-code)
port))))))
(let ((header "; GnuCash Configuration Options\n\n")
(forms (call-with-output-string generate-forms)))
(string-append header forms)))
(define (register-callback section name callback)
(let ((id last-callback-id)
(data (list section name callback)))
(set! last-callback-id (+ last-callback-id 1))
(hashv-set! callback-hash id data)
id))
(define (unregister-callback-id id)
(if (hashv-ref callback-hash id)
(hashv-remove! callback-hash id)
(gnc:error "options:unregister-callback-id: no such id\n")))
(define (run-callbacks)
(define (run-callback id cbdata)
(let ((section (car cbdata))
(name (cadr cbdata))
(callback (caddr cbdata)))
(if (not section)
(callback)
(let ((section-changed-hash (hash-ref changed-hash section)))
(if section-changed-hash
(if (not name)
(callback)
(if (hash-ref section-changed-hash name)
(callback))))))))
(if options-changed
(hash-for-each run-callback callback-hash))
(clear-changes))
(define (dispatch key)
(cond ((eq? key 'lookup) lookup-option)
((eq? key 'register-option) register-option)
((eq? key 'register-callback) register-callback)
((eq? key 'unregister-callback-id) unregister-callback-id)
((eq? key 'for-each) options-for-each)
((eq? key 'for-each-general) options-for-each-general)
((eq? key 'generate-restore-forms) generate-restore-forms)
((eq? key 'clear-changes) clear-changes)
((eq? key 'run-callbacks) run-callbacks)
(else (gnc:warn "options: bad key: " key "\n"))))
dispatch)
(define (gnc:register-option options new-option)
((options 'register-option) new-option))
(define (gnc:options-register-callback section name callback options)
((options 'register-callback) section name callback))
(define (gnc:options-register-c-callback section name c-callback data options)
(let ((callback (lambda () (gnc:option-invoke-callback c-callback data))))
((options 'register-callback) section name callback)))
(define (gnc:options-unregister-callback-id id options)
((options 'unregister-callback-id) id))
(define (gnc:options-for-each thunk options)
((options 'for-each) thunk))
(define (gnc:options-for-each-general section-thunk option-thunk options)
((options 'for-each-general) section-thunk option-thunk))
(define (gnc:lookup-option options section name)
((options 'lookup) section name))
(define (gnc:generate-restore-forms options options-string)
((options 'generate-restore-forms) options-string))
(define (gnc:options-clear-changes options)
((options 'clear-changes)))
(define (gnc:options-run-callbacks options)
((options 'run-callbacks)))
(define (gnc:send-options db_handle options)
(gnc:options-for-each
(lambda (option)
(gnc:option-db-register-option db_handle option))
options))
(define (gnc:save-options options options-string file)
(let ((code (gnc:generate-restore-forms options options-string))
(port (open file (logior O_WRONLY O_CREAT O_TRUNC))))
(if port (begin
(display code port)
(close port)))))

View File

@ -1,5 +1,9 @@
;;; $Id$
;;;;;;;;;;; QIF Parsing ;;;;;;;;;;;;;;
(use-modules (ice-9 slib))
(require 'hash-table)
(define qif-txn-list '())
(define qif-txn-structure
@ -79,14 +83,16 @@
(display ")")
(newline)
(display "(define category-analysis '" outfile)
(hash-for-each (lambda (x)
(write x outfile)
(hash-for-each (lambda (key value)
(write key outfile)
(write value outfile)
(newline outfile))
category-analysis)
(display ")" outfile)
(display "(define category-analysis '")
(hash-for-each (lambda (x)
(write x)
(hash-for-each (lambda (key value)
(write key)
(write value)
(newline))
category-analysis)
(display ")")

View File

@ -24,18 +24,22 @@
'())))))
(apply append (map path-interpret new-path))))
(define (gnc:make-home-dir)
(let ((home-dir (build-path (getenv "HOME") ".gnucash")))
(if (access? home-dir X_OK) #t (mkdir home-dir #o700))))
(define gnc:load-user-config-if-needed
(let ((user-config-loaded? #f))
(lambda ()
(if (not user-config-loaded?)
(begin
(gnc:debug "loading user configuration")
(let ((user-file
(build-path (getenv "HOME") ".gnucash" "config.user"))
(auto-file
(build-path (getenv "HOME") ".gnucash" "config.auto")))
(if (access? user-file F_OK)
(if (false-if-exception (primitive-load user-file))
(set! user-config-loaded? #t)

View File

@ -2,6 +2,7 @@
(use-modules (ice-9 slib))
(require 'sort)
(require 'hash-table)
;; (define gnc:*double-entry-restriction*
;; (gnc:make-config-var
@ -39,225 +40,28 @@
;; eq?
;; #f))
;; We'd rather use a hash table for this, but until hash-for-each or
;; hash-keys is generally available, we can't...
(define gnc:*options-entries* '())
;; This will be an alist
;; (k v) -> (section-name list-of-option-items)
(define (gnc:make-option
;; The category of this option
section
name
;; The sort-tag determines the relative ordering of options in
;; this category. It is used by the gui for display.
sort-tag
type
documentation-string
getter
;; The setter is responsible for ensuring that the value is valid.
setter
default-getter
generate-restore-form
;; Validation func should accept a value and return (#t value)
;; on success, and (#f "failure-message") on failure. If #t,
;; the supplied value will be used by the gui to set the option.
value-validator
option-data)
(vector section
name
sort-tag
type
documentation-string
getter
setter
default-getter
generate-restore-form
value-validator
option-data))
(define (gnc:make-string-option
section
name
sort-tag
documentation-string
default-value)
(let ((option default-value))
(gnc:make-option section name sort-tag 'string documentation-string
(lambda () option)
(lambda (x) (set! option x))
(lambda () default-value)
#f
(lambda (x)
(cond ((string? x)(list #t x))
(else (list #f "string-option: not a string"))))
#f )))
(define (gnc:make-simple-boolean-option
section
name
sort-tag
documentation-string
default-value)
(let ((option default-value))
(gnc:make-option section name sort-tag 'boolean documentation-string
(lambda () option)
(lambda (x) (set! option x))
(lambda () default-value)
#f
(lambda (x)
(if (boolean? x)
(list #t x)
(list #f "boolean-option: not a boolean")))
#f )))
;; date options use the option-data as a boolean value. If true,
;; the gui should allow the time to be entered as well.
(define (gnc:make-date-option
section
name
sort-tag
documentation-string
default-getter
show-time)
(let ((option (default-getter)))
(define (date-legal date)
(and (pair? date) (exact? (car date)) (exact? (cdr date))))
(gnc:make-option section name sort-tag 'date documentation-string
(lambda () option)
(lambda (date)
(if (date-legal date)
(set! option date)
(gnc:error "Illegal date value set")))
default-getter
#f
(lambda (date)
(if (date-legal date)
(list #t date)
(list #f "date-option: illegal date")))
show-time )))
;; account-list options use the option-data as a boolean value. If
;; true, the gui should allow the user to select multiple accounts.
;; values are always a list of accounts.
(define (gnc:make-account-list-option
section
name
sort-tag
documentation-string
default-getter
value-validator
multiple-selection)
(let ((option (default-getter))
(option-set #f)
(validator
(if (not value-validator)
(lambda (account-list) (list #t account-list))
value-validator)))
(gnc:make-option
section name sort-tag 'account-list documentation-string
(lambda () (if option-set option (default-getter)))
(lambda (account-list)
(let* ((result (validator account-list))
(valid (car result))
(value (cadr result)))
(if valid
(begin
(set! option value)
(set! option-set #t))
(gnc:error "Illegal account list value set"))))
default-getter
#f
validator
multiple-selection )))
;; multichoice options use the option-data as a list of vectors.
;; Each vector contains a permissible value (scheme symbol) and
;; a description string.
(define (gnc:make-multichoice-option
section
name
sort-tag
documentation-string
default-value
ok-values)
(let ((option default-value))
(define (multichoice-legal val p-vals)
(cond ((null? p-vals) #f)
((eq? val (vector-ref (car p-vals) 0)) #t)
(else multichoice-legal (cdr p-vals))))
(gnc:make-option
section name sort-tag 'multichoice documentation-string
(lambda () option)
(lambda (x)
(if (multichoice-legal x ok-values)
(set! option x)
(gnc:error "Illegal Multichoice option set")))
(lambda () default-value)
#f
(lambda (x)
(if (multichoice-legal x ok-values)
(list #t x)
(list #f "multichoice-option: illegal choice")))
ok-values)))
(define (gnc:option-section option)
(vector-ref option 0))
(define (gnc:option-name option)
(vector-ref option 1))
(define (gnc:option-sort-tag option)
(vector-ref option 2))
(define (gnc:option-type option)
(vector-ref option 3))
(define (gnc:option-documentation option)
(vector-ref option 4))
(define (gnc:option-getter option)
(vector-ref option 5))
(define (gnc:option-setter option)
(vector-ref option 6))
(define (gnc:option-default-getter option)
(vector-ref option 7))
(define (gnc:option-generate-restore-form option)
(vector-ref option 8))
(define (gnc:option-value-validator option)
(vector-ref option 9))
(define (gnc:option-data option)
(vector-ref option 10))
(define (gnc:register-option options new-option)
(let* ((section (gnc:option-section new-option))
(existing-entry (assoc-ref options section))
(new-entry (if existing-entry
(cons new-option existing-entry)
(list new-option))))
(assoc-set! options section new-entry)))
(define gnc:*options-entries* (gnc:new-options))
(define (gnc:register-configuration-option new-option)
(set! gnc:*options-entries*
(gnc:register-option gnc:*options-entries* new-option)))
(gnc:register-option gnc:*options-entries* new-option))
(define (gnc:lookup-global-option section name)
(gnc:lookup-option gnc:*options-entries* section name))
(define (gnc:send-global-options) gnc:*options-entries*)
(define (gnc:global-options-clear-changes)
(gnc:options-clear-changes gnc:*options-entries*))
(define (gnc:save-global-options)
(gnc:make-home-dir)
(gnc:save-options gnc:*options-entries*
(symbol->string 'gnc:*options-entries*)
(build-path (getenv "HOME") ".gnucash" "config.auto")))
(define (gnc:send-option-section db_handle section-info)
;; section-info is a pair (section-name . list-of-options)
(for-each
(lambda (option)
(gnc:option-db-register-option db_handle option))
(cdr section-info)))
(define (gnc:send-options db_handle options)
(for-each
(lambda (section-info)
(gnc:send-option-section db_handle section-info))
options))
(define (gnc:send-global-options)
(gnc:register-global-options gnc:*options-entries*))
;;;;;; Create default options and config vars
(gnc:register-configuration-option
(gnc:make-simple-boolean-option
@ -391,10 +195,15 @@
#(auto_double "Auto Double" "Double line mode with multi-line cursor")
)))
(gnc:register-configuration-option
(gnc:make-simple-boolean-option
"Register" "Auto-Raise Lists"
"b" "Automatically raise the list of accounts or actions during input." #t))
(gnc:register-configuration-option
(gnc:make-multichoice-option
"Register" "Toolbar Buttons"
"b" "Choose whether to display icons, text, or both for toolbar buttons"
"General" "Toolbar Buttons"
"a" "Choose whether to display icons, text, or both for toolbar buttons"
'icons_and_text
(list #(icons_and_text "Icons and Text" "Show both icons and text")
#(icons_only "Icons only" "Show icons only")

View File

@ -57,11 +57,11 @@
(hashv-set! gnc-txn-list txnref curtxn)
;;; Fill in gnc-txn-list, gnc-acc-list, gnc-split-list
;;; First, let's fill in curtxn with some values from txn
(gnc-txn-update curtxn 'num (txn 'get 'id))
(gnc-txn-update curtxn 'date-posted (txn 'get 'date))
(gnc-txn-update curtxn 'num (txnget txn 'id))
(gnc-txn-update curtxn 'date-posted (txnget txn 'date))
(gnc-txn-update curtxn 'date-entered '(1999 0903)) ;;; Which should get replaced!
(gnc-txn-update curtxn 'description (txn 'get 'memo))
(gnc-txn-update curtxn 'docref (txn 'get 'id))
(gnc-txn-update curtxn 'description (txnget txn 'memo))
(gnc-txn-update curtxn 'docref (txnget txn 'id))
;;; Now, set up the list of splits...
(let ((mainref (gensym))
(mainsplit ((record-constructor gnc-split-structure)
@ -76,7 +76,7 @@
(gnc-split-update mainsplit 'parenttransaction txnref)
(gnc-split-update mainsplit 'account accountname)
(hashv-set! gnc-split-list mainref mainsplit))
;;;; Chunk of missing code:
;;;; ---> Take a look at the split list in (txnget txn 'splitlist)
;;;; Add a split for each one of these
@ -163,10 +163,10 @@
(define (gnc:set-split-values q-txn q-split)
(let ((g:split (initialize-split))
(g:memo (q-split 'get 'memo))
(g:amount (q-split 'get 'amount))
(g:docref (q-split 'get 'id))
(g:action (q-txn 'get 'status)))
(g:memo (gnc-split-get q-split 'memo))
(g:amount (gnc-split-get q-split 'amount))
(g:docref (gnc-split-get q-split 'id))
(g:action (txnget q-txn 'status)))
(if g:amount (gnc:split-set-value g:split g:amount))
(if g:memo (gnc:split-set-memo g:split g:memo))
(if g:action (gnc:split-set-action g:split g:action))

View File

@ -9,6 +9,9 @@
(define (qif-category-update cat field value)
((record-modifier qif-category-structure field) cat value))
(define (qif-category-get cat field)
((record-accessor qif-category-structure field) cat))
(define (analyze-qif-categories)
(define (analyze-qif-category item)
(let*
@ -46,19 +49,19 @@
qif-cat-list)
(define (analyze-qif-split-category split)
(collect-cat-stats (split 'get 'category) (split 'get 'amount)))
(collect-cat-stats (qif-split-get split 'category)
(qif-split-get split 'amount)))
(define (collect-cat-stats category amount)
(let* ((s (hashv-ref qif-cat-list category)))
(let* ((s (hash-ref qif-cat-list category)))
(if s ;;; Did we find it in qif-cat-list?
(let ((sc (cdr s)))
(qif-category-update sc 'value (+ amount (sc 'get 'value)))
(qif-category-update sc 'count (+ 1 (sc 'get 'count))))
(begin ;;; Yes; found an existing entry so update it's attributes
(qif-category-update s 'value (+ amount (qif-category-get s 'value)))
(qif-category-update s 'count (+ 1 (qif-category-get s 'count))))
(begin ;;; Nope; need to add new entry to qif-cat-list
(let ((nc ((record-constructor qif-category-structure) #f #f #f)))
(qif-category-update nc 'name category)
(qif-category-update nc 'count 1)
(qif-category-update nc 'value amount)
(hashv-set! qif-cat-list category nc))))))
(hash-set! qif-cat-list category nc))))))

View File

@ -56,6 +56,7 @@
(let*
((QIFstates
'(("!Type:Cat" . category)
("!Type:Class" . class) ;;; Additional classification feature
("!Option:AutoSwitch" . accounts)
("!Clear:AutoSwitch" . accounts)
("!Account" . accounts)

View File

@ -1,3 +1,5 @@
(use-modules (ice-9 slib))
(require 'hash-table)
(gnc:support "report.scm")
@ -15,7 +17,7 @@
;; The key is the string naming the report and the value is the
;; rendering thunk.
(define (gnc:run-report report-name)
(define (gnc:run-report report-name options)
;; Return a string consisting of the contents of the report.
(define (display-report-list-item item port)
@ -26,33 +28,38 @@
item))
(else (gnc:warn "gnc:run-report - " item " is the wrong type."))))
(define (report-output->string lines)
(call-with-output-string
(lambda (port)
(for-each
(lambda (item) (display-report-list-item item port))
lines))))
(define (call-report rendering-thunk options)
(let ((lines (rendering-thunk options)))
(report-output->string lines)))
(let ((report (hash-ref *gnc:_report-info_* report-name)))
(if (not report)
#f
(let ((options (gnc:report-options report))
(rendering-thunk (gnc:report-rendering-thunk report)))
(call-with-output-string
(lambda (port)
(for-each
(lambda (item) (display-report-list-item item port))
(rendering-thunk options))))))))
(let ((rendering-thunk (gnc:report-rendering-thunk report)))
(call-report rendering-thunk options)))))
(define (gnc:report-menu-setup win)
;; This should be on a reports menu later...
(hash-for-each
(lambda (report-info)
(let ((name (car report-info))
(report (cdr report-info)))
(gnc:extensions-menu-add-item
(string-append "Report: " name)
(string-append "Display the " name " report.")
(lambda ()
(lambda (name report)
(gnc:extensions-menu-add-item
(string-append "Report: " name)
(string-append "Display the " name " report.")
(lambda ()
(let ((options (false-if-exception (gnc:report-new-options report))))
(gnc:report-window (string-append "Report: " name)
(lambda () (gnc:run-report name))
(gnc:report-options report))))))
(lambda () (gnc:run-report name options))
options)))))
*gnc:_report-info_*))
(define (gnc:define-report version name options rendering-thunk)
(define (gnc:define-report version name option-generator rendering-thunk)
;; For now the version is ignored, but in the future it'll let us
;; change behaviors without breaking older reports.
;;
@ -81,16 +88,22 @@
;; ("<html>" "</html>")
;; ("<html>" " some text " "</html>")
;; ("<html>" ("some" ("other" " text")) "</html>")
(let ((report (vector version name options rendering-thunk)))
(let ((report (vector version name option-generator rendering-thunk)))
(hash-set! *gnc:_report-info_* name report)))
(define (gnc:report-version report)
(vector-ref report 0))
(define (gnc:report-name report)
(vector-ref report 1))
(define (gnc:report-options report)
(define (gnc:report-options-generator report)
(vector-ref report 2))
(define (gnc:report-rendering-thunk report)
(vector-ref report 3))
(define (gnc:report-new-options report)
(let ((generator (gnc:report-options-generator report)))
(if (procedure? generator)
(generator)
#f)))
(gnc:hook-add-dangler gnc:*main-window-opened-hook* gnc:report-menu-setup)

View File

@ -0,0 +1,440 @@
;; -*-scheme-*-
;; average-balance.scm
;; Report history of account balance and other info
;; Also graphs the information with gnuplot
;; Matt Martin <mgmartin@abacusnet.net>
(use-modules (ice-9 slib)(ice-9 regex))
(require 'hash-table)
(require 'printf)
;hack alert - is this line necessary?
(gnc:depend "text-export.scm")
(define datelist '())
;; Add delta to date, return result
(define (incdate adate delta)
(let ((newtm (localtime (car adate))))
(begin
(set-tm:mday newtm (+ (tm:mday newtm) (tm:mday delta)))
(set-tm:mon newtm (+ (tm:mon newtm) (tm:mon delta)))
(set-tm:year newtm (+ (tm:year newtm) (tm:year delta)))
(let ((time (car (mktime newtm))))
(cons time 0))
))
)
;; actual recursion for date list building
(define (dateloop curd endd incr)
(cond ((gnc:timepair-later-date curd endd)
(cons curd (dateloop (incdate curd incr) endd incr)))
(else (list curd))
)
)
;; Create list of dates to report on
(define (generate-datelist beg nd stp)
(set! datelist (dateloop beg nd (eval stp))))
(define (runavg-options-generator)
(define gnc:*runavg-track-options* (gnc:new-options))
;; register a configuration option for the report
(define (gnc:register-runavg-option new-option)
(gnc:register-option gnc:*runavg-track-options* new-option))
;; from date
(gnc:register-runavg-option
(gnc:make-date-option
"Report Options" "From"
"a" "Report Items from this date"
(lambda ()
(let ((bdtime (localtime (current-time))))
(set-tm:sec bdtime 0)
(set-tm:min bdtime 0)
(set-tm:hour bdtime 0)
(set-tm:mday bdtime 1)
(set-tm:mon bdtime 0)
(let ((time (car (mktime bdtime))))
(cons time 0))))
#f))
;; to-date
(gnc:register-runavg-option
(gnc:make-date-option
"Report Options" "To"
"c" "Report items up to and including this date"
(lambda () (cons (current-time) 0))
#f))
;; account(s) to do report on
(gnc:register-runavg-option
(gnc:make-account-list-option
"Report Options" "Account"
"d" "Do transaction report on this account"
(lambda ()
(let ((current-accounts (gnc:get-current-accounts))
(num-accounts (gnc:group-get-num-accounts (gnc:get-current-group)))
(first-account (gnc:group-get-account (gnc:get-current-group) 0)))
(cond ((not (null? current-accounts)) (list (car current-accounts)))
((> num-accounts 0) (list first-account))
(else ()))))
#f #f))
(gnc:register-runavg-option
(gnc:make-multichoice-option
"Report Options" "Step Size"
"b" "Get number at each one of these" 'WeekDelta
(list #(DayDelta "Day" "Day")
#(WeekDelta "Week" "Week")
#(TwoWeekDelta "2Week" "Two Week")
#(MonthDelta "Month" "Month")
#(YearDelta "Year" "Year")
)))
(gnc:register-runavg-option
(gnc:make-multichoice-option
"Report Options" "Plot Type"
"b" "Get number at each one of these" 'NoPlot
(list #(NoPlot "Nothing" "Make No Plot")
#(AvgBalPlot "Average" "Average Balance")
#(GainPlot "Net Gain" "Net Gain")
#(GLPlot "Gain/Loss" "Gain And Loss")
)))
gnc:*runavg-track-options*)
; A reference zero date
(define zdate (let ((zd (localtime 0)))
(set-tm:hour zd 0)
(set-tm:min zd 0)
(set-tm:sec zd 0)
(set-tm:mday zd 0)
(set-tm:mon zd 0)
(set-tm:year zd 0)
(set-tm:yday zd 0)
(set-tm:wday zd 0)
zd
))
(define YearDelta (let ((ddt (eval zdate)))
(set-tm:year ddt 1)
ddt))
(define DayDelta (let ((ddt (eval zdate)))
(set-tm:mday ddt 1)
ddt))
(define WeekDelta (let ((ddt (eval zdate)))
(set-tm:mday ddt 7)
ddt))
(define TwoWeekDelta (let ((ddt (eval zdate)))
(set-tm:mday ddt 14)
ddt))
(define MonthDelta (let ((ddt (eval zdate)))
(set-tm:mon ddt 1)
ddt))
(define AvgBalPlot "using 1:2:3:4 t 'Average Balance' with errorbars")
(define GainPlot "using 1:5 t 'Net Gain' with linespoints")
(define GLPlot "using 1:7 t 'Losses' with lp, '' using 1:6 t 'Gains' with lp")
(define NoPlot "")
;;; applies thunk to each split in account account
(define (gnc:for-each-split-in-account account thunk)
(gnc:for-loop (lambda (x) (thunk (gnc:account-get-split account x)))
0 (gnc:account-get-split-count account) 1))
;; get transactions date from split - needs to be done indirectly
;; as it's stored in the parent transaction
(define (gnc:split-get-transaction-date split)
(gnc:transaction-get-date-posted (gnc:split-get-parent split)))
;; ditto descriptions
(define (gnc:split-get-description-from-parent split)
(gnc:transaction-get-description (gnc:split-get-parent split)))
;; get the account name of a split
(define (gnc:split-get-account-name split)
(gnc:account-get-name (gnc:split-get-account split)))
;; timepair manipulation functions
;; hack alert - these should probably be put somewhere else
;; and be implemented PROPERLY rather than hackily
(define (gnc:timepair-to-datestring tp)
(let ((bdtime (localtime (car tp))))
(strftime "%m/%d/%Y" bdtime)))
;; Find difference in seconds (?) between time 1 and time2
(define (gnc:timepair-delta t1 t2)
(let ((time1 (car (gnc:timepair-canonical-day-time t1)))
(time2 (car (gnc:timepair-canonical-day-time t2))))
(- time2 time1)))
;; Don't know if these can be local+static to reduce-split-list
(define tempmax -1E10)
(define tempmin 1E10)
(define last 0)
(define zdate (cons 0 0))
(define prevdate zdate)
(define avgaccum 0)
(define lossaccum 0)
(define gainaccum 0)
; Convert to string
(define (tostring val)
(cond ((number? val) (sprintf #f "%.2f" val))
(else (call-with-output-string (lambda (p)(display val p))))
))
;;;;;;;;;;;;;;;;;;;;
;; HTML Table
;;;;;;;;;;;;;;;;;;;;
; Create a column entry
(define (html-table-col val)
(sprintf #f "<TD align=right> %s </TD>" (tostring val))
)
; Create an html table row from a list of entries
(define (html-table-row lst)
(string-append
(sprintf #f "<TR>")
(apply string-append (map html-table-col lst))
(sprintf #f "</TR>\n")
)
)
; Create an html table from a list of rows, each containing
; a list of column entries
(define (html-table hdrlst llst)
(string-append
(html-table-header hdrlst)
(apply string-append (map html-table-row llst))
(html-table-footer)
)
)
(define (html-table-headcol val)
(sprintf #f "<TH justify=center> %s </TH>" (tostring val))
)
(define (html-table-header vec)
(apply string-append "<TABLE cellspacing=10>" (map html-table-headcol vec))
)
(define (html-table-footer)
(sprintf #f "</TABLE>")
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Text table
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Create an text table row from a list of entries
(define (text-table-row lst)
(string-append
(tostring (car lst))
(apply string-append (map (lambda (val)
(string-append "\t" (tostring val)))
(cdr lst)))
"\n"
)
)
(define (text-table-header lst)
(string-append
"# "
(text-table-row lst)
))
(define (text-table hdrlst llst)
(string-append
(text-table-header hdrlst)
(apply string-append (map text-table-row llst))
)
)
; Quick and dirty until there is REAL plot support
(define (data-to-gpfile hdrlst llst fn plotcmd)
(let ((oport (open-output-file fn)))
(display
(text-table hdrlst llst)
oport)
(close-output-port oport)
)
)
;; Reset accumulators between time intervals
(define (resetvals bal curdate)
(set! tempmax bal)
(set! tempmin bal)
(set! prevdate curdate)
(set! avgaccum 0)
(set! lossaccum 0)
(set! gainaccum 0)
)
;
; Reduce a list of splits tl to a list of values at each date in datelist dl
;
(define (reduce-split-list dl tl pt)
(cond ((null? dl) '()) ;; End of recursion
(else (let* ((bal last) ;; get Balance and datelist "time"
(ct (car dl))
(val 0))
(begin
(cond ( (not (null? tl))
;; Get latest split values if any remain
(set! bal (gnc:split-get-balance (car tl)))
(set! val (gnc:split-get-value (car tl)))
(set! ct (gnc:split-get-transaction-date (car tl)))
))
(cond ; past time interval bound ?
((or(gnc:timepair-later-date (car dl) ct ) (null? tl))
(cond ; Is this the first interval ?
((= (car zdate) (car prevdate) )
; Start first date interval
(begin
(resetvals bal (car dl))
(reduce-split-list (cdr dl) tl (car dl))
)
)
(else
(set! avgaccum ; sum up to now
(+ avgaccum
(* last (gnc:timepair-delta pt (car dl)))))
(cons ; form list of values for one "row"
(list
(gnc:timepair-to-datestring (car dl))
(let ((dlta (gnc:timepair-delta prevdate (car dl))))
(cond ((= dlta 0) 0); Should never happen !
((= avgaccum 0) bal)
(else (/ avgaccum dlta))))
tempmax
tempmin
(- gainaccum lossaccum)
gainaccum
lossaccum
)
(begin
(resetvals last (car dl))
(reduce-split-list (cdr dl) tl (car dl))
)
)
)))
(else ; mid-interval
(begin
(set! tempmax (max tempmax bal))
(set! tempmin (min tempmin bal))
(set! avgaccum
(+ avgaccum
(* last (gnc:timepair-delta pt ct))))
(cond ((> val 0) (set! gainaccum (+ gainaccum val)))
(else (set! lossaccum (- lossaccum val)))
)
(set! last bal)
(reduce-split-list dl (cdr tl) ct)
))
)
)))))
(define acctcurrency "USD")
(define acctname "")
(gnc:define-report
;; version
1
;; Name
"Account Balance Tracker"
;; Options
runavg-options-generator
;; renderer
(lambda (options)
(let* (
(begindate (gnc:option-value
(gnc:lookup-option options "Report Options" "From")))
(enddate (gnc:lookup-option options "Report Options" "To"))
(stepsize (gnc:lookup-option options "Report Options" "Step Size"))
(plotstr (gnc:option-value
(gnc:lookup-option options "Report Options" "Plot Type")))
(accounts (gnc:option-value
(gnc:lookup-option options
"Report Options" "Account")))
(prefix (list "<HTML>" "<BODY>"))
(suffix (list "</BODY>" "</HTML>"))
(collist
(list "Ending" "Average" "Max" "Min" "Net Gain" "Gain" "Loss"))
(report-lines '())
(rept-data '())
(rept-text "")
)
(generate-datelist
begindate
(gnc:option-value enddate)
(gnc:option-value stepsize))
(if (null? accounts)
(set! report-lines
(list "<TR><TD>You have not selected an account.</TD></TR>"))
(begin
(set! acctname (gnc:account-get-name (car accounts)))
(set! acctcurrency (gnc:account-get-currency (car accounts)))
(gnc:for-each-split-in-account
(car accounts)
(lambda (split)
(set! report-lines
(append! report-lines (list split)))))))
(display (length report-lines))
(display " Splits\n")
(set! prevdate zdate)
(set! rept-data (reduce-split-list datelist report-lines (car datelist)))
(set! rept-text
(html-table
collist
rept-data))
(if (not (equal? NoPlot (eval plotstr)))
(let* ((fn "/tmp/gncplot.dat")
(preplot (string-append
"set xdata time\n"
"set timefmt '%m/%d/%Y'\n"
"set pointsize 2\n"
"set title '" acctname "'\n"
"set ylabel '" acctcurrency "'\n"
"set xlabel 'Period Ending'\n"
)
)
)
(data-to-gpfile collist rept-data fn (eval plotstr))
(system
(string-append "echo \"" preplot "plot '" fn "'" (eval plotstr)
"\"|gnuplot -persist " )))
)
(append prefix (list rept-text) suffix)))
)

View File

@ -147,7 +147,7 @@
1
;; Menu name
"Balance sheet"
;; Options (none currently)
;; Options Generator (none currently)
#f
;; Code to generate the report
(lambda (options)

View File

@ -1,101 +0,0 @@
;; -*-scheme-*-
(begin
(define gnc:*dummy-options* '())
(define (gnc:register-dummy-option new-option)
(set! gnc:*dummy-options*
(gnc:register-option gnc:*dummy-options* new-option))
new-option)
(define boolop
(gnc:register-dummy-option
(gnc:make-simple-boolean-option
"Page One" "Boolean Option"
"a" "This is a boolean option." #t)))
(define multop
(gnc:register-dummy-option
(gnc:make-multichoice-option
"Page Two" "Multi Choice Option"
"a" "This is a multi choice option." 'us
(list #(us "US" "US-style: mm/dd/yyyy")
#(uk "UK" "UK-style dd/mm/yyyy")
#(ce "Europe" "Continental Europe: dd.mm.yyyy")
#(iso "ISO" "ISO Standard: yyyy-mm-dd")
#(locale "Locale" "Take from system locale")))))
(define strop
(gnc:register-dummy-option
(gnc:make-string-option
"Page Two" "String Option"
"b" "This is a string option" "Hello, World.")))
(define dateop
(gnc:register-dummy-option
(gnc:make-date-option
"Time and Date" "Just a Date Option"
"a" "This is a date option"
(lambda () (cons (current-time) 0))
#f)))
(define dateop2
(gnc:register-dummy-option
(gnc:make-date-option
"Time and Date" "Time and Date Option"
"a" "This is a date option with time"
(lambda () (cons (current-time) 0))
#t)))
(define account-list-op
(gnc:register-dummy-option
(gnc:make-account-list-option
"Page One" "An account list option"
"b" "This is an account list option"
(lambda () (gnc:get-current-accounts))
#f #t)))
(define (op-value op)
(let ((getter (gnc:option-getter op)))
(getter)))
(define (account-list)
(let* ((accounts (op-value account-list-op))
(names (map gnc:account-get-name accounts)))
(list "<ul>"
(map (lambda (name) (list "<li>" name "</li>")) names)
"</ul>")))
(gnc:define-report
;; version
1
;; Menu name
"Dummy"
;; Options
gnc:*dummy-options*
;; Rendering thunk. See report.scm for details.
(lambda (options)
(let ((time-string (strftime "%c" (localtime (current-time))))
(date-string (strftime "%x" (localtime (car (op-value dateop)))))
(date-string2 (strftime "%c" (localtime (car (op-value dateop2))))))
(list
"<html>"
"<body bgcolor=#99ccff>"
"The current time is " time-string "."
"<br>"
"The boolean op is " (if (op-value boolop) "true." "false.")
"<br>"
"The multi op is " (symbol->string (op-value multop))
"<br>"
"The string op is " (op-value strop)
"<br>"
"The date op is " date-string
"<br>"
"The date and time op is " date-string2
"<br>"
"The accounts are:"
(account-list)
"</body>"
"</html>"))))
)

View File

@ -6,7 +6,7 @@
1
;; Menu name
"Folio"
;; Options
;; Options Generator
#f
;; Rendering thunk. See report.scm for details.
(lambda (options)

View File

@ -0,0 +1,222 @@
;; -*-scheme-*-
;; This is a sample guile report generator for GnuCash.
;; It illustrates the basic techniques used to create
;; new reports for GnuCash.
;; Putting your functions in a (let ()) block hides them
;; from the rest of guile.
(let ()
;; This function will generate a set of options that GnuCash
;; will use to display a dialog where the user can select
;; values for your report's parameters.
(define (options-generator)
;; This will be the new set of options.
(define gnc:*dummy-options* (gnc:new-options))
;; This is just a helper function for making options.
;; See gnucash/src/scm/options.scm for details.
(define (gnc:register-dummy-option new-option)
(gnc:register-option gnc:*dummy-options* new-option))
;; This is a boolean option. It is in Section 'Page One'
;; and is named 'Boolean Option'. Its sorting key is 'a',
;; thus it will come before options with sorting keys
;; 'b', 'c', etc. in the same section. The default value
;; is #t (true). The phrase 'This is a boolean option'
;; will be displayed as help text when the user puts
;; the mouse pointer over the option.
(gnc:register-dummy-option
(gnc:make-simple-boolean-option
"Page One" "Boolean Option"
"a" "This is a boolean option." #t))
;; This is a multichoice option. The user can choose between
;; the values 'first, 'second, 'third, or 'fourth. These are guile
;; symbols. The value 'first will be displayed as "First Option"
;; and have a help string of "Help for first option.". The default
;; value is 'third.
(gnc:register-dummy-option
(gnc:make-multichoice-option
"Page Two" "Multi Choice Option"
"a" "This is a multi choice option." 'third
(list #(first "First Option" "Help for first option.")
#(second "Second Option" "Help for second option.")
#(third "Third Option" "Help for third option.")
#(fourth "Fourth Options" "The fourth option rules!"))))
;; This is a string option. Users can type anything they want
;; as a value. The default value is "Hello, World". This is
;; in the same section as the option above. It will be shown
;; after the option above because its key is 'b' while the
;; other key is 'a'.
(gnc:register-dummy-option
(gnc:make-string-option
"Page Two" "String Option"
"b" "This is a string option" "Hello, World"))
;; This is a date/time option. The user can pick a date and,
;; possibly, a time. Times are stored as a pair
;; (seconds . nanoseconds) measured from Jan 1, 1970, i.e.,
;; Unix time. The last option is false, so the user can only
;; select a date, not a time. The default value is the current
;; time.
(gnc:register-dummy-option
(gnc:make-date-option
"Time and Date" "Just a Date Option"
"a" "This is a date option"
(lambda () (cons (current-time) 0))
#f))
;; This is another date option, but the user can also select
;; the time.
(gnc:register-dummy-option
(gnc:make-date-option
"Time and Date" "Time and Date Option"
"b" "This is a date option with time"
(lambda () (cons (current-time) 0))
#t))
;; This is an account list option. The user can select one
;; or (possibly) more accounts from the list of accounts
;; in the current file. Values are scheme handles to actual
;; C pointers to accounts. They can be used in conjunction
;; with the wrapped C functions in gnucash/src/g-wrap/gnc.gwp.
;; The #f value indicates that any account will be accepted.
;; Instead of a #f values, you could provide a function that
;; accepts a list of account values and returns a pair. If
;; the first element is #t, the second element is the list
;; of accounts actually accepted. If the first element is
;; #f, the accounts are rejected and the second element is
;; and error string. The last argument is #t which means
;; the user is allowed to select more than one account.
;; The default value for this option is the currently
;; selected account in the main window, if any.
(gnc:register-dummy-option
(gnc:make-account-list-option
"Page One" "An account list option"
"b" "This is an account list option"
(lambda () (gnc:get-current-accounts))
#f #t))
gnc:*dummy-options*)
;; This is a helper function to generate an html list of account names
;; given an account list option.
(define (account-list account-list-op)
(let* ((accounts (gnc:option-value account-list-op))
(names (map gnc:account-get-name accounts)))
(if (null? accounts)
"<p>There are no selected accounts in the account list option.</p>"
(list "<p>"
"The accounts selected in the account list option are:"
"</p>"
"<ul>"
(map (lambda (name) (list "<li>" name "</li>")) names)
"</ul>"))))
;; Here's another helper function. You can guess what it does.
(define (bold string)
(string-append "<b>" string "</b>"))
;; Here we define the actual report with gnc:define-report
(gnc:define-report
;; The version of this report.
1
;; The name of this report. This will be used, among other things,
;; for making its menu item in the main menu.
"Hello, World"
;; The options generator function defined above.
options-generator
;; This is the rendering function. It accepts a group of options
;; and generates a (possibly nested) list of html. The "flattened"
;; and concatenated list should be valid html.
(lambda (options)
;; The first thing we do is make local variables for all the specific
;; options in the set of options given to the function. This set will
;; be generated by the options generator above.
;; Use (gnc:lookup-option options section name) to get the option.
(let ((boolop (gnc:lookup-option options "Page One" "Boolean Option"))
(multop (gnc:lookup-option options
"Page Two" "Multi Choice Option"))
(strop (gnc:lookup-option options "Page Two" "String Option"))
(dateop (gnc:lookup-option options
"Time and Date" "Just a Date Option"))
(dateop2 (gnc:lookup-option options
"Time and Date" "Time and Date Option"))
(account-list-op (gnc:lookup-option options
"Page One"
"An account list option")))
(let ((time-string (strftime "%c" (localtime (current-time))))
(date-string (strftime "%x" (localtime (car (gnc:option-value
dateop)))))
(date-string2 (strftime "%c"
(localtime (car (gnc:option-value
dateop2))))))
;; Here's where we generate the html. A real report would need
;; much more code and involve many more utility functions. See
;; the other reports for details. Note that you can used nested
;; lists here, as well as arbitrary functions.
(list
"<html>"
"<body>"
"<h2>Hello, World Report</h2>"
(list "<p>"
"This is a sample GnuCash report. "
"See the guile (scheme) source code in "
"<tt>" gnc:_share-dir-default_
"/gnucash/scm/report" "</tt>"
" for details on writing your own reports, or extending "
" existing reports."
"</p>")
(list "<p>"
"For help on writing reports, or to contribute your brand "
"new, totally cool report, consult the mailing list "
"<a href=\"mailto:gnucash-devel@gnucash.org\">"
"<tt>gnucash-devel@gnucash.org</tt>" "</a>" ". "
"For details on subscribing to that list, see "
"<a href=\"http://www.gnucash.org\">"
"<tt>www.gnucash.org</tt>" "</a>" "."
"</p>")
(list "<p>"
"The current time is " (bold time-string) "."
"</p>")
(list "<p>"
"The boolean option is "
(bold (if (gnc:option-value boolop) "true" "false")) "."
"</p>")
(list "<p>"
"The multi-choice option is "
(bold (symbol->string (gnc:option-value multop))) "."
"</p>")
(list "<p>"
"The string option is " (bold (gnc:option-value strop)) "."
"</p>")
(list "<p>"
"The date option is " (bold date-string) "."
"</p>")
(list "<p>"
"The date and time option is " (bold date-string2) "."
"</p>")
(account-list account-list-op)
(list "<p>"
"Have a nice day!"
"</p>")
"</body>"
"</html>")))))
)

View File

@ -5,6 +5,7 @@
(use-modules (ice-9 slib))
(require 'printf)
(require 'sort)
;hack alert - is this line necessary?
(gnc:depend "text-export.scm")
@ -30,8 +31,6 @@
(set! gnc:total-outflow 0)
#f))
(define gnc:*transaction-report-options* '())
;;returns a list contains elements of the-list for which predictate is
;; true
(define (gnc:filter-list the-list predicate)
@ -56,15 +55,15 @@
(gnc:inorder-map (cdr the-list) fn)))))
;; register a configuration option for the transaction report
(define (trep-options-generator)
(define (gnc:register-trep-option new-option)
(set! gnc:*transaction-report-options*
(gnc:register-option gnc:*transaction-report-options* new-option))
new-option)
(define gnc:*transaction-report-options* (gnc:new-options))
;; from date
;; hack alert - could somebody set this to an appropriate date?
(define begindate
(define (gnc:register-trep-option new-option)
(gnc:register-option gnc:*transaction-report-options* new-option))
;; from date
;; hack alert - could somebody set this to an appropriate date?
(gnc:register-trep-option
(gnc:make-date-option
"Report Options" "From"
@ -78,27 +77,104 @@
(set-tm:mon bdtime 0)
(let ((time (car (mktime bdtime))))
(cons time 0))))
#f)))
#f))
;; to-date
(define enddate
;; to-date
(gnc:register-trep-option
(gnc:make-date-option
"Report Options" "To"
"b" "Report items up to and including this date"
(lambda () (cons (current-time) 0))
#f)))
#f))
;; account to do report on
;; hack alert - default setting doesn't work!
(define tr-report-account-op
;; account to do report on
(gnc:register-trep-option
(gnc:make-account-list-option
"Report Options" "Account"
"c" "Do transaction report on this account"
(lambda () (list (gnc:group-get-account (gnc:get-current-group) 0)))
#f #f)))
(lambda ()
(let ((current-accounts (gnc:get-current-accounts))
(num-accounts (gnc:group-get-num-accounts (gnc:get-current-group)))
(first-account (gnc:group-get-account (gnc:get-current-group) 0)))
(cond ((not (null? current-accounts)) (list (car current-accounts)))
((> num-accounts 0) (list first-account))
(else ()))))
#f #f))
;; primary sorting criterion
(gnc:register-trep-option
(gnc:make-multichoice-option
"Sorting" "Primary Key"
"a" "Sort by this criterion first"
'date
(list #(date
"Date"
"Sort by date")
#(time
"Time"
"Sort by EXACT entry time")
#(corresponding-acc
"Transfer from/to"
"Sort by account transferred from/to's name")
#(amount
"Amount"
"Sort by amount")
#(description
"Description"
"Sort by description")
#(number
"Number"
"Sort by check/transaction number")
#(memo
"Memo"
"Sort by memo"))))
(gnc:register-trep-option
(gnc:make-multichoice-option
"Sorting" "Primary Sort Order"
"b" "Order of primary sorting"
'ascend
(list #(ascend "Ascending" "smallest to largest, earliest to latest")
#(descend "Descending" "largest to smallest, latest to earliest"))))
(gnc:register-trep-option
(gnc:make-multichoice-option
"Sorting" "Secondary Key"
"c"
"Sort by this criterion second"
'corresponding-acc
(list #(date
"Date"
"Sort by date")
#(time
"Time"
"Sort by EXACT entry time")
#(corresponding-acc
"Transfer from/to"
"Sort by account transferred from/to's name")
#(amount
"Amount"
"Sort by amount")
#(description
"Description"
"Sort by description")
#(number
"Number"
"Sort by check/transaction number")
#(memo
"Memo"
"Sort by memo"))))
(gnc:register-trep-option
(gnc:make-multichoice-option
"Sorting" "Secondary Sort Order"
"d" "Order of Secondary sorting"
'ascend
(list #(ascend "Ascending" "smallest to largest, earliest to latest")
#(descend "Descending" "largest to smallest, latest to earliest"))))
gnc:*transaction-report-options*)
;; extract fields out of the scheme split representation
@ -135,6 +211,13 @@
(define (gnc:tr-report-get-other-splits split-scm)
(vector-ref split-scm 10))
(define (gnc:tr-report-get-first-acc-name split-scm)
(let ((other-splits (gnc:tr-report-get-other-splits split-scm)))
(cond ((= (length other-splits) 0) "")
(else (caar other-splits)))))
;;; something like
;;; for(i = first; i < last; i+= step) { thunk(i);}
@ -190,6 +273,7 @@
0 num-splits 1)
(reverse diff-list)))))
;; takes a C split, extracts relevant data and converts to a scheme
;; representation
@ -214,18 +298,114 @@
(let ((bdtime (localtime (car tp))))
(strftime "%x" bdtime)))
(define (gnc:timepair-earlier-or-eq t1 t2)
(let ((time1 (car t1))
(time2 (car t2)))
;; given a timepair contains any time on a certain day (local time)
;; converts it to be midday that day.
(define (gnc:timepair-canonical-day-time tp)
(let ((bdt (localtime (car tp))))
(set-tm:sec bdt 0)
(set-tm:min bdt 0)
(set-tm:hour bdt 12)
(let ((newtime (car (mktime bdt))))
(cons newtime (* 1000 newtime)))))
(define (gnc:timepair-earlier-or-eq-date t1 t2)
(let ((time1 (car (gnc:timepair-canonical-day-time t1)))
(time2 (car (gnc:timepair-canonical-day-time t2))))
(<= time1 time2)))
(define (gnc:timepair-later t1 t2)
(let ((time1 (car t1))
(time2 (car t2)))
(define (gnc:timepair-later-date t1 t2)
(let ((time1 (car (gnc:timepair-canonical-day-time t1)))
(time2 (car (gnc:timepair-canonical-day-time t2))))
(< time1 time2)))
(define (gnc:timepair-later-or-eq t1 t2)
(gnc:timepair-earlier-or-eq t2 t1))
(define (gnc:timepair-later-or-eq-date t1 t2)
(gnc:timepair-earlier-or-eq-date t2 t1))
(define (gnc:sort-predicate-component component order)
(let ((ascending-order-comparator
(begin
; (display (symbol->string component))
(cond
((eq? component 'date)
(lambda (split-scm-a split-scm-b)
(-
(car
(gnc:timepair-canonical-day-time
(gnc:tr-report-get-date split-scm-a)))
(car
(gnc:timepair-canonical-day-time
(gnc:tr-report-get-date split-scm-b))))))
((eq? component 'time)
(lambda (split-scm-a split-scm-b)
(-
(car (gnc:tr-report-get-date split-scm-a))
(car (gnc:tr-report-get-date split-scm-b)))))
((eq? component 'amount)
(lambda (split-scm-a split-scm-b)
(-
(gnc:tr-report-get-value split-scm-a)
(gnc:tr-report-get-value split-scm-b))))
((eq? component 'description)
(lambda (split-scm-a split-scm-b)
(let ((description-a (gnc:tr-report-get-description split-scm-a))
(description-b (gnc:tr-report-get-description split-scm-b)))
(cond ((string<? description-a description-b) -1)
((string=? description-a description-b) 0)
(else 1)))))
;; hack alert - should probably use something more sophisticated
;; here - perhaps even making it user-definable
((eq? component 'number)
(lambda (split-scm-a split-scm-b)
(let ((num-a (gnc:tr-report-get-num split-scm-a))
(num-b (gnc:tr-report-get-num split-scm-b)))
(cond ((string<? num-a num-b) -1)
((string=? num-a num-b) 0)
(else 1)))))
((eq? component 'corresponding-acc)
(lambda (split-scm-a split-scm-b)
(let ((corr-acc-a (gnc:tr-report-get-first-acc-name split-scm-a))
(corr-acc-b (gnc:tr-report-get-first-acc-name split-scm-b)))
(cond ((string<? corr-acc-a corr-acc-b) -1)
((string=? corr-acc-a corr-acc-b) 0)
(else 1)))))
((eq? component 'memo)
(lambda (split-scm-a split-scm-b)
(let ((memo-a (gnc:tr-report-get-memo split-scm-a))
(memo-b (gnc:tr-report-get-memo split-scm-b)))
(cond ((string<? memo-a memo-b) -1)
((string=? memo-a memo-b) 0)
(else 1)))))
(else (gnc:error (sprintf "illegal sorting option %s- bug in transaction-report.scm" (symbol->string (component)) )))))))
(cond ((eq? order 'descend)
(lambda (my-split-a my-split-b)
(- (ascending-order-comparator my-split-a my-split-b))))
(else ascending-order-comparator))))
;; returns a predicate
(define (gnc:tr-report-make-sort-predicate primary-key-op primary-order-op
secondary-key-op secondary-order-op)
(let ((primary-comp (gnc:sort-predicate-component
(gnc:option-value primary-key-op)
(gnc:option-value primary-order-op)))
(secondary-comp (gnc:sort-predicate-component
(gnc:option-value secondary-key-op)
(gnc:option-value secondary-order-op))))
(lambda (split-a split-b)
(let ((primary-comp-value (primary-comp split-a split-b)))
(cond ((< primary-comp-value 0) #t)
((> primary-comp-value 0) #f)
(else
(let ((secondary-comp-value (secondary-comp split-a split-b)))
(cond ((< secondary-comp-value 0) #t)
(else #f)))))))))
;; returns a predicate that returns true only if a split-scm is
;; between early-date and late-date
@ -233,8 +413,8 @@
(define (gnc:tr-report-make-filter-predicate early-date late-date)
(lambda (split-scm)
(let ((split-date (gnc:tr-report-get-date split-scm)))
(and (gnc:timepair-later-or-eq split-date early-date)
(gnc:timepair-earlier-or-eq split-date late-date)))))
(and (gnc:timepair-later-or-eq-date split-date early-date)
(gnc:timepair-earlier-or-eq-date split-date late-date)))))
;; converts a scheme split representation to a line of HTML,
;; updates the values of total-inflow and total-outflow based
@ -293,7 +473,7 @@
(define (gnc:tr-report-get-starting-balance scm-split-list beginning-date)
(cond ((or
(eq? scm-split-list '())
(gnc:timepair-later
(gnc:timepair-later-date
(gnc:tr-report-get-date (car scm-split-list))
beginning-date))
0)
@ -304,17 +484,31 @@
(cdr scm-split-list) beginning-date))))
(gnc:define-report
;; version
1
;; Name
"Account Transactions"
;; Options
gnc:*transaction-report-options*
trep-options-generator
;; renderer
(lambda (options)
(let* ((prefix (list "<HTML>" "<BODY bgcolor=#99ccff>" "<TABLE>"
(let* ((begindate (gnc:lookup-option options "Report Options" "From"))
(enddate (gnc:lookup-option options "Report Options" "To"))
(tr-report-account-op (gnc:lookup-option options
"Report Options" "Account"))
(tr-report-primary-key-op (gnc:lookup-option options
"Sorting"
"Primary Key"))
(tr-report-primary-order-op (gnc:lookup-option options
"Sorting"
"Primary Sort Order"))
(tr-report-secondary-key-op (gnc:lookup-option options
"Sorting"
"Secondary Key"))
(tr-report-secondary-order-op
(gnc:lookup-option options "Sorting" "Secondary Sort Order"))
(prefix (list "<HTML>" "<BODY bgcolor=#99ccff>" "<TABLE>"
"<TH>Date</TH>"
"<TH>Num</TH>"
"<TH>Description</TH>"
@ -329,14 +523,14 @@
(net-inflow-line '())
(report-lines '())
(date-filter-pred (gnc:tr-report-make-filter-predicate
(op-value begindate)
(op-value enddate)))
(gnc:option-value begindate)
(gnc:option-value enddate)))
(starting-balance 0)
(accounts (op-value tr-report-account-op)))
(accounts (gnc:option-value tr-report-account-op)))
gnc:tr-report-initialize-inflow-and-outflow!
(if (null? accounts)
(set! report-lines
(list "<TR><TD>You have not selected an account.</TD></TR>"))
(list "<TR><TD>There are no accounts to report on.</TD></TR>"))
(begin
(gnc:for-each-split-in-account
@ -347,17 +541,23 @@
(list (gnc:make-split-scheme-data split))))))
(set! starting-balance
(gnc:tr-report-get-starting-balance
report-lines (op-value begindate)))
report-lines (gnc:option-value begindate)))
(set! report-lines (gnc:filter-list report-lines date-filter-pred))
(set! report-lines
(sort!
report-lines
(gnc:tr-report-make-sort-predicate
tr-report-primary-key-op tr-report-primary-order-op
tr-report-secondary-key-op tr-report-secondary-order-op)))
(let ((html-mapper (lambda (split-scm) (gnc:tr-report-split-to-html
split-scm
starting-balance))))
(set! report-lines (gnc:inorder-map report-lines html-mapper)))
(set!
(set!
balance-line
(list "<TR><TD><STRONG>Balance at: "
(gnc:timepair-to-datestring (op-value begindate))
(gnc:timepair-to-datestring (gnc:option-value begindate))
"</STRONG></TD>"
"<TD></TD>"
"<TD></TD>"
@ -393,5 +593,6 @@
"<TD></TD>"
"<TD><STRONG>"
(sprintf #f "%.2f" (- gnc:total-inflow gnc:total-outflow))
"</TD></STRONG></TR>"))
(append prefix balance-line report-lines inflow-outflow-line net-inflow-line suffix))))))
"</TD></STRONG></TR>"))))
(append prefix balance-line report-lines
inflow-outflow-line net-inflow-line suffix))))

View File

@ -12,6 +12,9 @@
(define (qif-split-update split field value)
((record-modifier qif-split-structure field) split value))
(define (qif-split-get split field)
((record-accessor qif-split-structure field) split))
(define (create-qif-split-structure)
((record-constructor qif-split-structure) #f #f #f #f))

View File

@ -9,6 +9,7 @@
(gnc:load "utilities.scm")
(gnc:load "path.scm")
(gnc:load "c-interface.scm")
(gnc:load "options.scm")
(gnc:load "prefs.scm")
(gnc:load "command-line.scm")
(gnc:load "convenience-wrappers.scm")