mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
2002-07-24 Joshua Sled <jsled@asynchronous.org>
* src/scm/fin.scm: Made the exposed calcualtion functions output positive values. * src/gnome/window-main.c (gnc_main_window_create_menus): Added accelerators to SX-related menu items. * src/gnome/druid-loan.c: Primary change: actually create the Scheduled Transactions which are setup by the user. Miscellaneous other cleanups, text, layout and consistency changes. * src/gnome/dialog-sxsincelast.c: Support handling of the instance-count in forward-looking transaction creation. Simplfied some of the internal data-representation regarding lists of items to be created [removed autoCreateTuple, now uses toCreateTuple]. Removed some DEBUGging output. Handles setting up the implicit 'i' variable. * src/gnome/dialog-sx-from-trans.c (sxftd_compute_sx): Create SXes with an appropriate initial instance-count value. * src/gnome/dialog-scheduledxaction.c (schedXact_editor_populate): Create SXes with an appropriate initial instance-count value. * src/engine/SchedXaction.[ch]: Added support for an instance-count, in order to support an implicit 'i' [of N] variable to SX formula/function processing. * src/engine/SX-ttinfo.c (gnc_ttsplitinfo_free): Made the ttsplitinfo_free'ing a bit safer. * src/calculation/expression_parser.c: Added support for parsing/handling quoted strings. Intended to be parameters to functions. Fixed bug regarding nested handling of strings in the parser. * src/backend/file/gnc-schedxaction-xml-v2.c: Added support for saving/restoring instance-count field of SXes. * src/app-utils/test/test-exp-parser.c (run_parser_test): Fixed pass/fail indication check. (test_parser): Added tests for string params to functions. * ChangeLog: Added entry I forgot from last time. * src/app-utils/gnc-exp-parser.c (func_op): Added support for typed parameters to functions; params are either numerics or strings. Result of function is now parsed correctly. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7125 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
2a990a6cfd
commit
135289725c
61
ChangeLog
61
ChangeLog
@ -1,3 +1,54 @@
|
||||
2002-07-24 Joshua Sled <jsled@asynchronous.org>
|
||||
|
||||
* src/scm/fin.scm: Made the exposed calcualtion functions output
|
||||
positive values.
|
||||
|
||||
* src/gnome/window-main.c (gnc_main_window_create_menus): Added
|
||||
accelerators to SX-related menu items.
|
||||
|
||||
* src/gnome/druid-loan.c: Primary change: actually create the
|
||||
Scheduled Transactions which are setup by the user. Miscellaneous
|
||||
other cleanups, text, layout and consistency changes.
|
||||
|
||||
* src/gnome/dialog-sxsincelast.c: Support handling of the
|
||||
instance-count in forward-looking transaction creation. Simplfied
|
||||
some of the internal data-representation regarding lists of items
|
||||
to be created [removed autoCreateTuple, now uses toCreateTuple].
|
||||
Removed some DEBUGging output. Handles setting up the implicit
|
||||
'i' variable.
|
||||
|
||||
* src/gnome/dialog-sx-from-trans.c (sxftd_compute_sx): Create SXes
|
||||
with an appropriate initial instance-count value.
|
||||
|
||||
* src/gnome/dialog-scheduledxaction.c
|
||||
(schedXact_editor_populate): Create SXes with an appropriate
|
||||
initial instance-count value.
|
||||
|
||||
* src/engine/SchedXaction.[ch]: Added support for an
|
||||
instance-count, in order to support an implicit 'i' [of N]
|
||||
variable to SX formula/function processing.
|
||||
|
||||
* src/engine/SX-ttinfo.c (gnc_ttsplitinfo_free): Made the
|
||||
ttsplitinfo_free'ing a bit safer.
|
||||
|
||||
* src/calculation/expression_parser.c: Added support for
|
||||
parsing/handling quoted strings. Intended to be parameters to
|
||||
functions. Fixed bug regarding nested handling of strings in the
|
||||
parser.
|
||||
|
||||
* src/backend/file/gnc-schedxaction-xml-v2.c: Added support for
|
||||
saving/restoring instance-count field of SXes.
|
||||
|
||||
* src/app-utils/test/test-exp-parser.c
|
||||
(run_parser_test): Fixed pass/fail indication check.
|
||||
(test_parser): Added tests for string params to functions.
|
||||
|
||||
* ChangeLog: Added entry I forgot from last time.
|
||||
|
||||
* src/app-utils/gnc-exp-parser.c (func_op): Added support for
|
||||
typed parameters to functions; params are either numerics or
|
||||
strings. Result of function is now parsed correctly.
|
||||
|
||||
2002-07-24 Christian Stimming <stimming@tuhh.de>
|
||||
|
||||
* src/import-export/hbci/glade/hbci.glade: Some HBCI GUI work --
|
||||
@ -13,6 +64,16 @@
|
||||
* src/backend/file/gnc-backend-file.c: File permission fix by Matt
|
||||
Brubeck <mbrubeck@cs.hmc.edu>
|
||||
|
||||
2002-07-12 Joshua Sled <jsled@asynchronous.org>
|
||||
|
||||
* src/gnome/glade/sched-xact.glade: Glade-side UI cleanup.
|
||||
|
||||
* src/gnome/druid-loan.c: Many updates; now uses GNCAccountSel,
|
||||
more inter-page consistency checks. UI cleanup
|
||||
|
||||
* src/gnome-utils/gnc-account-sel.[ch]: Added; GTK combobox for
|
||||
selecting an Account.
|
||||
|
||||
2002-07-11 Derek Atkins <derek@ihtfp.com>
|
||||
|
||||
* change gncEntry->account into gncEntry->invAccount and
|
||||
|
@ -350,6 +350,8 @@ func_op( const char *fname,
|
||||
{
|
||||
SCM scmFn, scmArgs, scmTmp;
|
||||
int i;
|
||||
var_store *vs;
|
||||
gchar *str;
|
||||
gnc_numeric n, *result;
|
||||
GString *realFnName;
|
||||
|
||||
@ -365,15 +367,37 @@ func_op( const char *fname,
|
||||
scmArgs = gh_list( SCM_UNDEFINED );
|
||||
for ( i=0; i<argc; i++ ) {
|
||||
/* cons together back-to-front. */
|
||||
n = *(gnc_numeric*)argv[argc - i - 1];
|
||||
vs = (var_store*)argv[argc - i - 1];
|
||||
switch ( vs->type ) {
|
||||
case VST_NUMERIC:
|
||||
n = *(gnc_numeric*)(vs->value);
|
||||
scmTmp = gh_double2scm( gnc_numeric_to_double( n ) );
|
||||
break;
|
||||
case VST_STRING:
|
||||
str = (char*)(vs->value);
|
||||
scmTmp = gh_str2scm( str, strlen(str) );
|
||||
break;
|
||||
default:
|
||||
/* FIXME: error */
|
||||
printf( "argument %d not a numeric or string [type = %d]\n",
|
||||
i, vs->type );
|
||||
return NULL;
|
||||
break; /* notreached */
|
||||
}
|
||||
scmArgs = gh_cons( scmTmp, scmArgs );
|
||||
}
|
||||
scmTmp = gh_apply( scmFn, scmArgs );
|
||||
|
||||
result = g_new0( gnc_numeric, 1 );
|
||||
*result = double_to_gnc_numeric( gh_scm2double(scmTmp), 1,
|
||||
GNC_DENOM_SIGFIG | (6<<8) );
|
||||
*result = double_to_gnc_numeric( gh_scm2double(scmTmp),
|
||||
GNC_DENOM_AUTO,
|
||||
GNC_DENOM_SIGFIGS(6) | GNC_RND_ROUND );
|
||||
/* I'm not sure why this explicit negation step is necessary, but it
|
||||
* doesn't seem like it should be. */
|
||||
if ( gh_scm2double( scmTmp ) < 0 ) {
|
||||
*result = gnc_numeric_neg( *result );
|
||||
}
|
||||
/* FIXME: cleanup scmArgs = gh_list, cons'ed cells? */
|
||||
return (void*)result;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "gnc-numeric.h"
|
||||
#include "test-stuff.h"
|
||||
|
||||
void real_main (int argc, char **argv);
|
||||
|
||||
static GList *tests = NULL;
|
||||
|
||||
typedef struct
|
||||
@ -62,12 +64,12 @@ run_parser_test (TestNode *node)
|
||||
succeeded = gnc_exp_parser_parse (node->exp, &result, &error_loc);
|
||||
{
|
||||
int pass;
|
||||
pass = succeeded;
|
||||
pass ^= node->should_succeed;
|
||||
pass = !pass;
|
||||
printf( "%0.2f [%s]\n",
|
||||
( ( pass && node->should_succeed ) ?
|
||||
gnc_numeric_to_double( result ) : 0.0 ),
|
||||
pass = (succeeded == node->should_succeed);
|
||||
if ( pass && node->should_succeed ) {
|
||||
pass &= gnc_numeric_equal( result, node->expected_result );
|
||||
}
|
||||
printf( "%0.4f [%s]\n",
|
||||
gnc_numeric_to_double( result ),
|
||||
(pass ? "PASS" : "FAIL" ) );
|
||||
}
|
||||
|
||||
@ -139,7 +141,7 @@ test_parser (void)
|
||||
"- 42.72 + 13.32 + 15.48 + 23.4 + 115.4",
|
||||
gnc_numeric_create(35897, 100) );
|
||||
|
||||
gh_eval_str( "(define (plus a b) (+ a b))" );
|
||||
gh_eval_str( "(define (gnc:plus a b) (+ a b))" );
|
||||
add_pass_test( "plus( 1 : 2 ) + 3", NULL, gnc_numeric_create( 6, 1 ) );
|
||||
add_pass_test( "plus( 1 : 2 ) * 3", NULL, gnc_numeric_create( 9, 1 ) );
|
||||
add_pass_test( "plus( 1 + 2 : 3 ) * 5", NULL, gnc_numeric_create( 30, 1 ) );
|
||||
@ -148,14 +150,31 @@ test_parser (void)
|
||||
add_pass_test( "plus( plus( 1 : 2 ) : 3 )", NULL, gnc_numeric_create( 6, 1 ) );
|
||||
add_pass_test( "plus( 4 : plus( plus( 1 : 2 ) : 3))", NULL, gnc_numeric_create( 10, 1 ) );
|
||||
|
||||
gh_eval_str( "(define (foo a b) (+ a b))" );
|
||||
add_pass_test( "foo( 1 : 2 ) + 4", NULL, gnc_numeric_create( 7, 1 ) );
|
||||
gh_eval_str( "(define (gnc:foo a b) (- a b))" );
|
||||
add_pass_test( "foo( 1 : 2 ) + 4", NULL, gnc_numeric_create( 3, 1 ) );
|
||||
|
||||
add_pass_test( "foo( (1 + 2 * 3) : 4 ) + 5",
|
||||
NULL, gnc_numeric_create( 16, 1 ) );
|
||||
NULL, gnc_numeric_create( 8, 1 ) );
|
||||
add_pass_test( "foo( 1 : 2 ) + foo( 3 : 4 ) + 5",
|
||||
NULL, gnc_numeric_create( 15, 1 ) );
|
||||
add_pass_test( "foo( a = 42 : foo( foo( 1 : 2 ) : 6 * 7 )) + a",
|
||||
NULL, gnc_numeric_create( 129, 1 ) );
|
||||
NULL, gnc_numeric_create( 3, 1 ) );
|
||||
add_pass_test( "foo( a = 42 : foo( plus( 1 : 2 ) : 6 * 7 )) + a",
|
||||
NULL, gnc_numeric_create( 123, 1 ) );
|
||||
|
||||
gh_eval_str( "(define (gnc:test_str str b)"
|
||||
" (+ b (cond ((equal? str \"one\") 1)"
|
||||
" ((equal? str \"two\") 2)"
|
||||
" ((equal? str \"three\") 3)"
|
||||
" (0))))" );
|
||||
add_pass_test( "test_str( \"one\" : 1 )", NULL, gnc_numeric_create( 2, 1 ) );
|
||||
add_pass_test( "test_str( \"two\" : 2 )", NULL, gnc_numeric_create( 4, 1 ) );
|
||||
add_fail_test( "test_str( 3 : \"three\" )", NULL, 0 );
|
||||
add_pass_test( "test_str( \"asdf\" : 1 )", NULL, gnc_numeric_create( 1, 1 ) );
|
||||
add_fail_test( "\"asdf\" + 0", NULL, 0 );
|
||||
|
||||
gh_eval_str( "(define (gnc:blindreturn val) val)" );
|
||||
add_pass_test( "blindreturn( 123.1 )", NULL, gnc_numeric_create( 1231, 10 ) );
|
||||
add_pass_test( "blindreturn( 123.01 )", NULL, gnc_numeric_create( 12301, 100 ) );
|
||||
add_pass_test( "blindreturn( 123.001 )", NULL, gnc_numeric_create( 123001, 1000 ) );
|
||||
|
||||
run_parser_tests ();
|
||||
|
||||
@ -163,7 +182,7 @@ test_parser (void)
|
||||
success ("shutdown expression parser");
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
real_main (int argc, char **argv)
|
||||
{
|
||||
/* set_should_print_success (TRUE); */
|
||||
@ -176,5 +195,5 @@ int main( int argc, char **argv )
|
||||
{
|
||||
/* do things this way so we can test scheme function calls from expressions */
|
||||
gh_enter( argc, argv, real_main );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ static short module = MOD_SX;
|
||||
* <sx:autoCreateNotify>n</sx:autoCreateNotify>
|
||||
* <sx:advanceCreateDays>0</sx:advanceCreateDays>
|
||||
* <sx:advanceRemindDays>5</sx:advanceRemindDays>
|
||||
* <sx:instanceCount>100</sx:instanceCount>
|
||||
* <sx:lastOccur>
|
||||
* <gdate>2001-02-28</gdate>
|
||||
* </sx:lastOccur>
|
||||
@ -80,6 +81,7 @@ static short module = MOD_SX;
|
||||
* <sx:end type="date">
|
||||
* <gdate>2004-03-20</gdate>
|
||||
* </sx:end>
|
||||
* <sx:instanceCount>100</sx:instanceCount>
|
||||
* <sx:freq>
|
||||
* <!-- freqspec tree -->
|
||||
* </sx:freq>
|
||||
@ -88,6 +90,7 @@ static short module = MOD_SX;
|
||||
* <sx:id type="guid">...</sx:id>
|
||||
* <sx:name>Loan 2</sx:name>
|
||||
* <sx:manual-conf>f</sx:manual-conf>
|
||||
* <sx:instanceCount>100</sx:instanceCount>
|
||||
* <sx:start>
|
||||
* <gdate>2000-12-31</gdate>
|
||||
* </sx:start>
|
||||
@ -113,6 +116,7 @@ static short module = MOD_SX;
|
||||
#define SX_AUTOCREATE_NOTIFY "sx:autoCreateNotify"
|
||||
#define SX_ADVANCE_CREATE_DAYS "sx:advanceCreateDays"
|
||||
#define SX_ADVANCE_REMIND_DAYS "sx:advanceRemindDays"
|
||||
#define SX_INSTANCE_COUNT "sx:instanceCount"
|
||||
#define SX_START "sx:start"
|
||||
#define SX_LAST "sx:last"
|
||||
#define SX_NUM_OCCUR "sx:num-occur"
|
||||
@ -139,6 +143,7 @@ gnc_schedXaction_dom_tree_create(SchedXaction *sx)
|
||||
xmlNodePtr ret;
|
||||
xmlNodePtr fsNode;
|
||||
GDate *date;
|
||||
gint instCount;
|
||||
const GUID *templ_acc_guid;
|
||||
|
||||
templ_acc_guid = xaccAccountGetGUID(sx->template_acct);
|
||||
@ -163,6 +168,10 @@ gnc_schedXaction_dom_tree_create(SchedXaction *sx)
|
||||
xmlAddChild(ret, int_to_dom_tree(SX_ADVANCE_REMIND_DAYS,
|
||||
sx->advanceRemindDays));
|
||||
|
||||
instCount = gnc_sx_get_instance_count( sx, NULL );
|
||||
xmlAddChild( ret, int_to_dom_tree( SX_INSTANCE_COUNT,
|
||||
instCount ) );
|
||||
|
||||
xmlAddChild( ret,
|
||||
gdate_to_dom_tree( SX_START,
|
||||
xaccSchedXactionGetStartDate(sx) ) );
|
||||
@ -318,6 +327,22 @@ sx_set_date( xmlNodePtr node, SchedXaction *sx,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
sx_instcount_handler( xmlNodePtr node, gpointer sx_pdata )
|
||||
{
|
||||
struct sx_pdata *pdata = sx_pdata;
|
||||
SchedXaction *sx = pdata->sx;
|
||||
gint64 instanceNum;
|
||||
|
||||
if ( ! dom_tree_to_integer( node, &instanceNum ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gnc_sx_set_instance_count( sx, instanceNum );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
sx_start_handler( xmlNodePtr node, gpointer sx_pdata )
|
||||
@ -436,6 +461,7 @@ struct dom_tree_handler sx_dom_handlers[] = {
|
||||
{ SX_AUTOCREATE_NOTIFY, sx_notify_handler, 1, 0 },
|
||||
{ SX_ADVANCE_CREATE_DAYS, sx_advCreate_handler, 1, 0 },
|
||||
{ SX_ADVANCE_REMIND_DAYS, sx_advRemind_handler, 1, 0 },
|
||||
{ SX_INSTANCE_COUNT, sx_instcount_handler, 0, 0 },
|
||||
{ SX_START, sx_start_handler, 1, 0 },
|
||||
{ SX_LAST, sx_last_handler, 0, 0 },
|
||||
{ SX_NUM_OCCUR, sx_numOccur_handler, 0, 0 },
|
||||
|
@ -388,7 +388,7 @@ typedef struct parser_env
|
||||
const char *parse_str;
|
||||
char radix_point;
|
||||
char group_char;
|
||||
char name[50];
|
||||
char name[128];
|
||||
|
||||
char Token;
|
||||
char asn_op;
|
||||
@ -417,6 +417,7 @@ parser_env;
|
||||
#define ARG_TOKEN ':'
|
||||
#define VAR_TOKEN 'V'
|
||||
#define NUM_TOKEN 'I'
|
||||
#define STR_TOKEN '"'
|
||||
|
||||
#define STACK_INIT 50
|
||||
|
||||
@ -671,6 +672,7 @@ get_named_var (parser_env_ptr pe)
|
||||
else
|
||||
bv->next_var = retp;
|
||||
retp->variable_name = g_strdup (pe->name);
|
||||
retp->type = VST_NUMERIC;
|
||||
retp->value =
|
||||
pe->trans_numeric ("0", pe->radix_point, pe->group_char, NULL);
|
||||
}
|
||||
@ -691,6 +693,7 @@ get_unnamed_var (parser_env_ptr pe)
|
||||
retp = &(pe->unnamed_vars[cntr]);
|
||||
retp->variable_name = NULL;
|
||||
retp->use_flag = USED_VAR;
|
||||
retp->type = VST_NUMERIC;
|
||||
if (retp->value)
|
||||
{
|
||||
pe->free_numeric (retp->value);
|
||||
@ -756,8 +759,8 @@ next_token (parser_env_ptr pe)
|
||||
add_token (pe, *str_parse++);
|
||||
if (*str_parse == ASN_OP)
|
||||
{
|
||||
/* BUG/FIXME: this allows '(=' and ')=' [?], neither of which make
|
||||
* sense. */
|
||||
/* BUG/FIXME: this seems to allow '(=' and ')=' [?], neither of which
|
||||
* make sense. */
|
||||
if (pe->Token != ASN_OP)
|
||||
{
|
||||
str_parse++;
|
||||
@ -768,6 +771,18 @@ next_token (parser_env_ptr pe)
|
||||
pe->error_code = UNDEFINED_CHARACTER;
|
||||
} /* endif */
|
||||
}
|
||||
/* test for string */
|
||||
else if ( *str_parse == '"' ) {
|
||||
nstr = pe->name;
|
||||
/* skip over the '"'. */
|
||||
str_parse++;
|
||||
do {
|
||||
*nstr++ = *str_parse++;
|
||||
} while ( *str_parse != '"' );
|
||||
*nstr = EOS;
|
||||
str_parse++;
|
||||
add_token( pe, STR_TOKEN );
|
||||
}
|
||||
/* test for name */
|
||||
else if (isalpha (*str_parse)
|
||||
|| (*str_parse == '_'))
|
||||
@ -818,15 +833,6 @@ next_token (parser_env_ptr pe)
|
||||
pe->parse_str = str_parse;
|
||||
} /* next_token */
|
||||
|
||||
/* evaluate function operators
|
||||
* <name>( arg0, arg1, ... )
|
||||
*/
|
||||
static void
|
||||
function_op( parser_env_ptr pe )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* evaluate assignment operators,
|
||||
* =
|
||||
* +=
|
||||
@ -834,6 +840,7 @@ function_op( parser_env_ptr pe )
|
||||
* \=
|
||||
* *=
|
||||
*/
|
||||
/* FIXME: add non-numeric checking. */
|
||||
static void
|
||||
assignment_op (parser_env_ptr pe)
|
||||
{
|
||||
@ -913,6 +920,7 @@ assignment_op (parser_env_ptr pe)
|
||||
} /* assignment_op */
|
||||
|
||||
/* evaluate addition, subtraction operators */
|
||||
/* FIXME: add non-numeric checking. */
|
||||
static void
|
||||
add_sub_op (parser_env_ptr pe)
|
||||
{
|
||||
@ -972,6 +980,7 @@ add_sub_op (parser_env_ptr pe)
|
||||
} /* add_sub_op */
|
||||
|
||||
/* evaluate multiplication, division operators */
|
||||
/* FIXME: add non-numeric checking. */
|
||||
static void
|
||||
multiply_divide_op (parser_env_ptr pe)
|
||||
{
|
||||
@ -1036,15 +1045,25 @@ multiply_divide_op (parser_env_ptr pe)
|
||||
* numerics
|
||||
* grouped expressions, "()"
|
||||
* functions [ <name>( [exp, exp, ..., exp] ) ]
|
||||
* strings
|
||||
*/
|
||||
static void
|
||||
primary_exp (parser_env_ptr pe)
|
||||
{
|
||||
var_store_ptr rslt = NULL;
|
||||
char *fnIdent;
|
||||
char *ident = NULL;
|
||||
int funcArgCount;
|
||||
char LToken = pe->Token;
|
||||
|
||||
/* If we are in a state where the non-stacked 'pe->name' is valuable, then
|
||||
* save it before we process the next token. */
|
||||
switch ( LToken ) {
|
||||
case FN_TOKEN:
|
||||
case STR_TOKEN:
|
||||
ident = g_strdup( pe->name );
|
||||
break;
|
||||
}
|
||||
|
||||
next_token (pe);
|
||||
if (pe->error_code)
|
||||
return;
|
||||
@ -1099,7 +1118,6 @@ primary_exp (parser_env_ptr pe)
|
||||
break;
|
||||
|
||||
case FN_TOKEN:
|
||||
fnIdent = pe->name;
|
||||
funcArgCount = 0;
|
||||
|
||||
do {
|
||||
@ -1126,18 +1144,28 @@ primary_exp (parser_env_ptr pe)
|
||||
|
||||
argv = g_new0( void*, funcArgCount );
|
||||
for ( i=0; i<funcArgCount; i++ ) {
|
||||
/* fill back-to-front */
|
||||
/* fill, in back-to-front order, the funcArgCount tokens we just
|
||||
* parsed out of the expression into a argument list to hand back
|
||||
* to the caller's func_op callback. */
|
||||
val = pop(pe);
|
||||
argv[funcArgCount - i - 1] = val->value;
|
||||
argv[funcArgCount - i - 1] = val;
|
||||
}
|
||||
|
||||
rslt = get_unnamed_var(pe);
|
||||
rslt->value = (*pe->func_op)( fnIdent, funcArgCount, argv );
|
||||
rslt->value = (*pe->func_op)( ident, funcArgCount, argv );
|
||||
|
||||
for ( i=0; i<funcArgCount; i++ ) {
|
||||
free_var( argv[i], pe );
|
||||
}
|
||||
g_free( argv );
|
||||
g_free( ident );
|
||||
|
||||
if ( rslt->value == NULL ) {
|
||||
pe->error_code = NOT_A_FUNC;
|
||||
add_token( pe, EOS );
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
next_token(pe);
|
||||
@ -1146,6 +1174,11 @@ primary_exp (parser_env_ptr pe)
|
||||
case VAR_TOKEN:
|
||||
rslt = get_named_var (pe);
|
||||
break;
|
||||
case STR_TOKEN:
|
||||
rslt = get_unnamed_var( pe );
|
||||
rslt->type = VST_STRING;
|
||||
rslt->value = ident;
|
||||
break;
|
||||
} /* endswitch */
|
||||
|
||||
if (rslt != NULL)
|
||||
|
@ -69,11 +69,18 @@ ParseError;
|
||||
*/
|
||||
typedef struct var_store *var_store_ptr;
|
||||
|
||||
/* the type of entity contained in the var_store */
|
||||
typedef enum {
|
||||
VST_NUMERIC = 0,
|
||||
VST_STRING
|
||||
} VarStoreType;
|
||||
|
||||
typedef struct var_store
|
||||
{
|
||||
char *variable_name; /* variable name if variable, NULL otherwise */
|
||||
char use_flag; /* flag if variable has been assigned to */
|
||||
char assign_flag; /* flag if variable is used */
|
||||
VarStoreType type;
|
||||
void *value; /* pointer to implementation defined numeric value */
|
||||
var_store_ptr next_var; /* pointer to next variable in linked list */
|
||||
}
|
||||
|
@ -476,7 +476,6 @@ http://www.interest.com/hugh/calc/mort_links.html
|
||||
|
||||
Druid Feedback:
|
||||
|
||||
|
||||
<Wilddev> jsled: <auspex> Wilddev: The labels need colons, mnemonics, and right-alignment.
|
||||
<Wilddev> <auspex> Wilddev: It may be worthwhile for gnucash to create GtkSpinButton subclasses which show the percent symbol and others within the field.
|
||||
<Wilddev> <auspex> Wilddev: I don't know how complicated that will be.
|
||||
@ -495,3 +494,29 @@ Druid Feedback:
|
||||
<jsled> Hmm. Okay. The between-transaction period is a frequency editor on the Repayment page.
|
||||
<Wilddev> <auspex> I'm wondering if "Original Principal" should be a vulgate
|
||||
such as "Loan Amount"
|
||||
|
||||
----------
|
||||
|
||||
Expression changes, round 2
|
||||
|
||||
We need the following abilities in order to get mortgage/loan repayment
|
||||
working:
|
||||
. Ability to get the original value of an account
|
||||
. [perhaps, ability to reference an external value?]
|
||||
. Ability to get the present value of an account
|
||||
. Ability to get the current i in an "i-of-N" sequence
|
||||
|
||||
As well, it'd be nice to have:
|
||||
. some sort of signature checking on functions in expressions
|
||||
. safe[r] error handling?
|
||||
|
||||
We decide that the original/present value of the account should be handled in
|
||||
scheme, and thus we actually need a way to reference accounts down to the
|
||||
scheme expressions. We decide to use the Quote symbols to refer to a string
|
||||
literal. The expression parser should be modified to parse this.
|
||||
|
||||
----------
|
||||
|
||||
The current 'i' and 'N' are going to be handled by having a list of
|
||||
predefined variables which the user cannot have access to. For the time
|
||||
being, this is 'i' and 'N'.
|
||||
|
@ -191,9 +191,13 @@ gnc_ttsplitinfo_malloc(void)
|
||||
void
|
||||
gnc_ttsplitinfo_free(TTSplitInfo *ttsi)
|
||||
{
|
||||
if ( ttsi->action )
|
||||
g_free(ttsi->action);
|
||||
if ( ttsi->memo )
|
||||
g_free(ttsi->memo);
|
||||
if ( ttsi->credit_formula )
|
||||
g_free(ttsi->credit_formula);
|
||||
if ( ttsi->debit_formula )
|
||||
g_free(ttsi->debit_formula);
|
||||
g_free(ttsi);
|
||||
return;
|
||||
|
@ -47,7 +47,6 @@ void gnc_ttinfo_set_num(TTInfo *tti, const char *num);
|
||||
|
||||
|
||||
/* this one points to a persistent pointer so ownership isn't relevant */
|
||||
|
||||
void gnc_ttinfo_set_currency(TTInfo *tti, gnc_commodity *common_currency);
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@ typedef struct _temporalStateData {
|
||||
GDate end_date;
|
||||
gint num_occur_total;
|
||||
gint num_occur_rem;
|
||||
gint num_inst;
|
||||
} temporalStateData;
|
||||
|
||||
/** Local Prototypes *****/
|
||||
@ -80,6 +81,7 @@ xaccSchedXactionInit( SchedXaction *sx, GNCBook *book)
|
||||
sx->autoCreateNotify = FALSE;
|
||||
sx->advanceCreateDays = 0;
|
||||
sx->advanceRemindDays = 0;
|
||||
sx->instance_num = 0;
|
||||
sx->dirty = TRUE;
|
||||
|
||||
/* create a new template account for our splits */
|
||||
@ -507,6 +509,29 @@ xaccSchedXactionGetInstanceAfter( SchedXaction *sx,
|
||||
return next_occur;
|
||||
}
|
||||
|
||||
gint
|
||||
gnc_sx_get_instance_count( SchedXaction *sx, void *stateData )
|
||||
{
|
||||
gint toRet = -1;
|
||||
temporalStateData *tsd;
|
||||
|
||||
if ( stateData ) {
|
||||
tsd = (temporalStateData*)stateData;
|
||||
toRet = tsd->num_inst;
|
||||
} else {
|
||||
toRet = sx->instance_num;
|
||||
}
|
||||
|
||||
return toRet;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_sx_set_instance_count( SchedXaction *sx, gint instanceNum )
|
||||
{
|
||||
g_return_if_fail( sx );
|
||||
sx->instance_num = instanceNum;
|
||||
}
|
||||
|
||||
GList *
|
||||
xaccSchedXactionGetSplits( SchedXaction *sx )
|
||||
{
|
||||
@ -642,10 +667,11 @@ void
|
||||
xaccSchedXactionIncrSequenceState( SchedXaction *sx,
|
||||
void *stateData )
|
||||
{
|
||||
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
tsd->num_occur_rem -= 1;
|
||||
}
|
||||
tsd->num_inst += 1;
|
||||
}
|
||||
|
||||
void
|
||||
@ -663,6 +689,7 @@ gnc_sx_create_temporal_state_snapshot( SchedXaction *sx )
|
||||
toRet->end_date = sx->end_date;
|
||||
toRet->num_occur_total = sx->num_occurances_total;
|
||||
toRet->num_occur_rem = sx->num_occurances_remain;
|
||||
toRet->num_inst = sx->instance_num;
|
||||
return (void*)toRet;
|
||||
}
|
||||
|
||||
@ -675,6 +702,7 @@ gnc_sx_revert_to_temporal_state_snapshot( SchedXaction *sx, void *stateData )
|
||||
sx->end_date = tsd->end_date;
|
||||
sx->num_occurances_total = tsd->num_occur_total;
|
||||
sx->num_occurances_remain = tsd->num_occur_rem;
|
||||
sx->instance_num = tsd->num_inst;
|
||||
|
||||
sx->dirty = TRUE;
|
||||
}
|
||||
|
@ -118,11 +118,27 @@ void xaccSchedXactionSetNumOccur( SchedXaction *sx, gint numNum );
|
||||
gint xaccSchedXactionGetRemOccur( SchedXaction *sx );
|
||||
void xaccSchedXactionSetRemOccur( SchedXaction *sx, gint numRemain );
|
||||
|
||||
/**
|
||||
* Set the instance count. This is incremented by one for every created
|
||||
* instance of the SX.
|
||||
* @param stateData may be NULL.
|
||||
**/
|
||||
gint gnc_sx_get_instance_count( SchedXaction *sx, void *stateData );
|
||||
/**
|
||||
* Sets the instance count to something other than the default. As the
|
||||
* default is the incorrect value '0', callers should DTRT here.
|
||||
**/
|
||||
void gnc_sx_set_instance_count( SchedXaction *sx, gint instanceNum );
|
||||
|
||||
GList *xaccSchedXactionGetSplits( SchedXaction *sx );
|
||||
void xaccSchedXactionSetSplits( SchedXaction *sx, GList *newSplits );
|
||||
|
||||
void xaccSchedXactionGetAutoCreate( SchedXaction *sx, gboolean *outAutoCreate, gboolean *outNotify );
|
||||
void xaccSchedXactionSetAutoCreate( SchedXaction *sx, gboolean newAutoCreate, gboolean newNotify );
|
||||
void xaccSchedXactionGetAutoCreate( SchedXaction *sx,
|
||||
gboolean *outAutoCreate,
|
||||
gboolean *outNotify );
|
||||
void xaccSchedXactionSetAutoCreate( SchedXaction *sx,
|
||||
gboolean newAutoCreate,
|
||||
gboolean newNotify );
|
||||
|
||||
gint xaccSchedXactionGetAdvanceCreation( SchedXaction *sx );
|
||||
void xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays );
|
||||
@ -177,6 +193,9 @@ void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g );
|
||||
* looking at reminders... and generally thinking about not wanting the
|
||||
* caller to know every possible thing that needs to be kept track of in a
|
||||
* forward-looking sequence of SXes.
|
||||
*
|
||||
* THESE (3) FUNCTIONS ARE DEPRECATED. See/Use the
|
||||
* 'temporal_state_snapshot' functions below.
|
||||
**/
|
||||
void *xaccSchedXactionCreateSequenceState( SchedXaction *sx );
|
||||
void xaccSchedXactionIncrSequenceState( SchedXaction *sx, void *stateData );
|
||||
@ -194,7 +213,8 @@ void xaccSchedXactionDestroySequenceState( void *stateData );
|
||||
* SX without having to rollback all the individual state changes.
|
||||
*
|
||||
* NOTE that this is similar to the above SequenceState interface, and
|
||||
* perhaps can be seen as entailing the above interface.
|
||||
* perhaps can be seen as entailing the above interface. In fact, the above
|
||||
* interface is deprecated in favor of this one.
|
||||
**/
|
||||
void *gnc_sx_create_temporal_state_snapshot( SchedXaction *sx );
|
||||
void gnc_sx_revert_to_temporal_state_snapshot( SchedXaction *sx, void *stateData );
|
||||
|
@ -65,6 +65,9 @@ struct gncp_SchedXaction
|
||||
/* reminaing occurances are as-of the 'last_date'. */
|
||||
gint num_occurances_remain;
|
||||
|
||||
/* the current instance-count of the SX. */
|
||||
gint instance_num;
|
||||
|
||||
gboolean autoCreateOption;
|
||||
gboolean autoCreateNotify;
|
||||
gint advanceCreateDays;
|
||||
|
@ -465,6 +465,7 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
* Do checks on validity and such, interrupting the user if
|
||||
* things aren't right.
|
||||
*
|
||||
* . support formulas [?!]
|
||||
* . balancing the SX if contain numeric-only formula data.
|
||||
* . agreement with create-automagically/notification controls
|
||||
* X the 'will ever be valid' check should take num-occur vals into
|
||||
@ -1429,6 +1430,10 @@ schedXact_editor_populate( SchedXactionEditorDialog *sxed )
|
||||
(gfloat)daysInAdvance );
|
||||
}
|
||||
|
||||
if ( sxed->newsxP ) {
|
||||
gnc_sx_set_instance_count( sxed->sx, 1 );
|
||||
}
|
||||
|
||||
/* populate the ledger */
|
||||
{
|
||||
/* create the split list */
|
||||
|
@ -387,6 +387,8 @@ sxftd_compute_sx(SXFromTransInfo *sxfti)
|
||||
break;
|
||||
}
|
||||
|
||||
gnc_sx_set_instance_count( sx, 1 );
|
||||
|
||||
sxftd_add_template_trans( sxfti );
|
||||
|
||||
return sxftd_errno;
|
||||
|
@ -140,7 +140,7 @@ typedef struct _sxSinceLastData {
|
||||
GtkProgressBar *prog;
|
||||
|
||||
/* Multi-stage processing-related stuff... */
|
||||
GList /* <autoCreateTuple*> */ *autoCreateList;
|
||||
GList /* <toCreateTuple*> */ *autoCreateList;
|
||||
GList /* <toCreateTuple*> */ *toCreateList;
|
||||
GList /* <reminderTuple*> */ *reminderList;
|
||||
GList /* <toDeleteTuple*> */ *toRemoveList;
|
||||
@ -165,12 +165,6 @@ typedef struct _sxSinceLastData {
|
||||
|
||||
} sxSinceLastData;
|
||||
|
||||
|
||||
typedef struct autoCreateTuple_ {
|
||||
SchedXaction *sx;
|
||||
GList /* <GDate*> */ *instanceList;
|
||||
} autoCreateTuple;
|
||||
|
||||
typedef struct toCreateTuple_ {
|
||||
SchedXaction *sx;
|
||||
GList /* <toCreateInstance*> */ *instanceList;
|
||||
@ -179,6 +173,7 @@ typedef struct toCreateTuple_ {
|
||||
typedef struct toCreateInstance_ {
|
||||
GDate *date;
|
||||
GHashTable *varBindings;
|
||||
gint instanceNum;
|
||||
GtkCTreeNode *node;
|
||||
toCreateTuple *parentTCT;
|
||||
} toCreateInstance;
|
||||
@ -197,6 +192,7 @@ typedef struct reminderTuple_ {
|
||||
typedef struct reminderInstanceTuple_ {
|
||||
GDate *endDate;
|
||||
GDate *occurDate;
|
||||
gint instanceNum;
|
||||
gboolean isSelected;
|
||||
reminderTuple *parentRT;
|
||||
} reminderInstanceTuple;
|
||||
@ -453,7 +449,6 @@ reminders_page_prep( sxSinceLastData *sxsld )
|
||||
if ( g_list_length( sxsld->reminderList ) == 0 ) {
|
||||
w = glade_xml_get_widget( sxsld->gxml,
|
||||
AUTO_CREATE_NOTIFY_PG );
|
||||
DEBUG( "Going to auto_create_notify page" );
|
||||
gnome_druid_set_page( sxsld->sincelast_druid,
|
||||
GNOME_DRUID_PAGE(w) );
|
||||
return;
|
||||
@ -510,7 +505,6 @@ auto_create_prep( GnomeDruidPage *druid_page,
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
if ( ! sxsld->autoCreatedSomething ) {
|
||||
DEBUG( "Going to to_create page" );
|
||||
w = glade_xml_get_widget( sxsld->gxml, TO_CREATE_PG );
|
||||
gnome_druid_set_page( sxsld->sincelast_druid,
|
||||
GNOME_DRUID_PAGE(w) );
|
||||
@ -526,7 +520,6 @@ created_prep( GnomeDruidPage *druid_page,
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
if ( !sxsld->createdSomething ) {
|
||||
DEBUG( "Going to obsolete page" );
|
||||
w = glade_xml_get_widget( sxsld->gxml, OBSOLETE_PG );
|
||||
gnome_druid_set_page( sxsld->sincelast_druid,
|
||||
GNOME_DRUID_PAGE(w) );
|
||||
@ -541,7 +534,6 @@ obsolete_prep( GnomeDruidPage *druid_page,
|
||||
GtkWidget *w;
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
if ( g_list_length( sxsld->toRemoveList ) == 0 ) {
|
||||
DEBUG( "Going to finish page" );
|
||||
w = glade_xml_get_widget( sxsld->gxml, FINISH_PG );
|
||||
gnome_druid_set_page( sxsld->sincelast_druid,
|
||||
GNOME_DRUID_PAGE(w) );
|
||||
@ -560,7 +552,6 @@ obsolete_next( GnomeDruidPage *druid_page,
|
||||
toDeleteTuple *tdt;
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
DEBUG( "obsolete_next" );
|
||||
sxList = gnc_book_get_schedxactions( gnc_get_current_book() );
|
||||
cl = GTK_CLIST( glade_xml_get_widget( sxsld->gxml,
|
||||
SX_OBSOLETE_CLIST ) );
|
||||
@ -569,11 +560,7 @@ obsolete_next( GnomeDruidPage *druid_page,
|
||||
toDelPtr;
|
||||
toDelPtr = toDelPtr->next ) {
|
||||
row = (gint)toDelPtr->data;
|
||||
DEBUG( "getting row data for SX_OBSOLETE_CLIST row %d",
|
||||
row );
|
||||
tdt = (toDeleteTuple*)gtk_clist_get_row_data( cl, row );
|
||||
DEBUG( "got tdt with sx with name \"%s\"",
|
||||
xaccSchedXactionGetName( tdt->sx ) );
|
||||
{
|
||||
elt = g_list_find( sxList, tdt->sx );
|
||||
sxList = g_list_remove_link( sxList, elt );
|
||||
@ -699,8 +686,6 @@ to_create_next( GnomeDruidPage *druid_page,
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG( "Done with creation; updating created ledger." );
|
||||
|
||||
oldQuery = gnc_ledger_display_get_query( sxsld->created_ledger );
|
||||
newQuery = xaccQueryMerge( oldQuery, q, QUERY_AND );
|
||||
gnc_ledger_display_set_query( sxsld->created_ledger, newQuery );
|
||||
@ -925,7 +910,7 @@ sxsincelast_init( sxSinceLastData *sxsld )
|
||||
}
|
||||
}
|
||||
|
||||
//reminders_page_prep( sxsld );
|
||||
/*reminders_page_prep( sxsld );*/
|
||||
gtk_widget_show_all( sxsld->sincelast_window );
|
||||
|
||||
process_auto_create_list( sxsld->autoCreateList, sxsld );
|
||||
@ -952,7 +937,8 @@ generate_instances( SchedXaction *sx,
|
||||
GList **reminderList,
|
||||
GList **deadList )
|
||||
{
|
||||
GDate gd, *gdToReturn;
|
||||
GDate gd;
|
||||
toCreateInstance *tci;
|
||||
reminderTuple *rt;
|
||||
reminderInstanceTuple *rit;
|
||||
void *seqStateData;
|
||||
@ -966,9 +952,13 @@ generate_instances( SchedXaction *sx,
|
||||
|
||||
g_date_strftime( tmpBuf, GNC_D_WIDTH, GNC_D_FMT, &gd );
|
||||
|
||||
gdToReturn = g_date_new();
|
||||
*gdToReturn = gd;
|
||||
*instanceList = g_list_append( *instanceList, gdToReturn );
|
||||
tci = g_new0( toCreateInstance, 1 );
|
||||
|
||||
tci->date = g_date_new();
|
||||
*tci->date = gd;
|
||||
tci->instanceNum = gnc_sx_get_instance_count( sx, seqStateData );
|
||||
|
||||
*instanceList = g_list_append( *instanceList, tci );
|
||||
|
||||
xaccSchedXactionIncrSequenceState( sx, seqStateData );
|
||||
gd = xaccSchedXactionGetInstanceAfter( sx, &gd, seqStateData );
|
||||
@ -990,7 +980,9 @@ generate_instances( SchedXaction *sx,
|
||||
rt->instanceList = NULL;
|
||||
while ( g_date_valid(&gd)
|
||||
&& g_date_compare( &gd, reminderEnd ) <= 0 ) {
|
||||
|
||||
g_date_strftime( tmpBuf, GNC_D_WIDTH, GNC_D_FMT, &gd );
|
||||
|
||||
rit = g_new0( reminderInstanceTuple, 1 );
|
||||
rit->endDate = g_date_new();
|
||||
*rit->endDate = *end;
|
||||
@ -998,6 +990,7 @@ generate_instances( SchedXaction *sx,
|
||||
*rit->occurDate = gd;
|
||||
rit->isSelected = FALSE;
|
||||
rit->parentRT = rt;
|
||||
rit->instanceNum = gnc_sx_get_instance_count( sx, seqStateData );
|
||||
|
||||
rt->instanceList = g_list_append( rt->instanceList, rit );
|
||||
|
||||
@ -1072,7 +1065,8 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld )
|
||||
{
|
||||
GList *createdGUIDs = NULL;
|
||||
GList *thisGUID;
|
||||
autoCreateTuple *act;
|
||||
toCreateTuple *tct;
|
||||
toCreateInstance *tci;
|
||||
gboolean autoCreateState, notifyState;
|
||||
Query *q, *dlQuery, *newQuery;
|
||||
GList *instances;
|
||||
@ -1084,18 +1078,19 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld )
|
||||
gtk_progress_configure( GTK_PROGRESS(sxsld->prog), 0, 0,
|
||||
g_list_length( autoCreateList ) );
|
||||
for ( ; autoCreateList ; autoCreateList = autoCreateList->next ) {
|
||||
act = (autoCreateTuple*)autoCreateList->data;
|
||||
tct = (toCreateTuple*)autoCreateList->data;
|
||||
|
||||
xaccSchedXactionGetAutoCreate( act->sx,
|
||||
xaccSchedXactionGetAutoCreate( tct->sx,
|
||||
&autoCreateState,
|
||||
¬ifyState );
|
||||
|
||||
for ( instances = act->instanceList;
|
||||
for ( instances = tct->instanceList;
|
||||
instances;
|
||||
instances = instances->next ) {
|
||||
tci = (toCreateInstance*)instances->data;
|
||||
thisGUID = createdGUIDs = NULL;
|
||||
create_transactions_on( act->sx,
|
||||
(GDate*)instances->data,
|
||||
create_transactions_on( tct->sx,
|
||||
(GDate*)tci->date,
|
||||
NULL, &createdGUIDs );
|
||||
|
||||
count += g_list_length( createdGUIDs );
|
||||
@ -1121,7 +1116,7 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld )
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG( "Finished creating transactions; updating ledger" );
|
||||
/*DEBUG( "Finished creating transactions; updating ledger" );*/
|
||||
|
||||
dlQuery = gnc_ledger_display_get_query( sxsld->ac_ledger );
|
||||
newQuery = xaccQueryMerge( dlQuery, q, QUERY_AND );
|
||||
@ -1141,6 +1136,8 @@ add_to_create_list_to_gui( GList *toCreateList, sxSinceLastData *sxsld )
|
||||
GtkCTreeNode *sxNode;
|
||||
char *rowText[ TO_CREATE_LIST_WIDTH ];
|
||||
GList *insts;
|
||||
int htSize;
|
||||
gpointer unusedkey, unusedvalue;
|
||||
|
||||
ct = GTK_CTREE( glade_xml_get_widget( sxsld->gxml, TO_CREATE_LIST ) );
|
||||
|
||||
@ -1170,7 +1167,13 @@ add_to_create_list_to_gui( GList *toCreateList, sxSinceLastData *sxsld )
|
||||
g_date_strftime( rowText[0], GNC_D_WIDTH, GNC_D_FMT, tci->date );
|
||||
sxsl_get_sx_vars( tci->parentTCT->sx, tci->varBindings );
|
||||
|
||||
if ( g_hash_table_size( tci->varBindings ) == 0 ) {
|
||||
htSize = g_hash_table_size( tci->varBindings );
|
||||
if ( g_hash_table_lookup_extended( tci->varBindings, "i",
|
||||
&unusedkey,
|
||||
&unusedvalue ) ) {
|
||||
htSize -= 1;
|
||||
}
|
||||
if ( htSize == 0 ) {
|
||||
rowText[1] = "y";
|
||||
} else {
|
||||
rowText[1] = "n";
|
||||
@ -1299,41 +1302,45 @@ processSelectedReminderList( GList *goodList, sxSinceLastData *sxsld )
|
||||
{
|
||||
GList *list = NULL;
|
||||
reminderInstanceTuple *rit;
|
||||
autoCreateTuple *act;
|
||||
toCreateTuple *tct;
|
||||
toCreateInstance *tci;
|
||||
gboolean autoCreateOpt, notifyOpt;
|
||||
|
||||
tct = NULL;
|
||||
act = NULL;
|
||||
for ( ; goodList ; goodList = goodList->next ) {
|
||||
rit = (reminderInstanceTuple*)goodList->data;
|
||||
|
||||
DEBUG( "Processing selected reminder \"%s\"",
|
||||
xaccSchedXactionGetName( rit->parentRT->sx ) );
|
||||
|
||||
xaccSchedXactionGetAutoCreate( rit->parentRT->sx,
|
||||
&autoCreateOpt, ¬ifyOpt );
|
||||
if ( autoCreateOpt ) {
|
||||
for ( list = sxsld->autoCreateList;
|
||||
list;
|
||||
list = list->next ) {
|
||||
act = (autoCreateTuple*)list->data;
|
||||
// Find any already-existing toCreateTuples to add to...
|
||||
if ( act->sx == rit->parentRT->sx ) {
|
||||
tct = (toCreateTuple*)list->data;
|
||||
/* Find any already-existing toCreateTuples to add to...*/
|
||||
if ( tct->sx == rit->parentRT->sx ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !list ) {
|
||||
act = g_new0( autoCreateTuple, 1 );
|
||||
act->sx = rit->parentRT->sx;
|
||||
tct = g_new0( toCreateTuple, 1 );
|
||||
tct->sx = rit->parentRT->sx;
|
||||
sxsld->autoCreateList =
|
||||
g_list_append( sxsld->autoCreateList, act );
|
||||
g_list_append( sxsld->autoCreateList, tct );
|
||||
}
|
||||
act->instanceList = g_list_append( act->instanceList,
|
||||
rit->occurDate );
|
||||
|
||||
tci = g_new0( toCreateInstance, 1 );
|
||||
tci->parentTCT = tct;
|
||||
tci->date = rit->occurDate;
|
||||
tci->varBindings = NULL;
|
||||
tci->instanceNum = rit->instanceNum;
|
||||
tci->node = NULL;
|
||||
|
||||
tct->instanceList =
|
||||
g_list_append( tct->instanceList, tci );
|
||||
|
||||
list = NULL;
|
||||
list = g_list_append( list, act );
|
||||
list = g_list_append( list, tct );
|
||||
process_auto_create_list( list, sxsld );
|
||||
list = NULL;
|
||||
} else {
|
||||
@ -1341,7 +1348,7 @@ processSelectedReminderList( GList *goodList, sxSinceLastData *sxsld )
|
||||
list;
|
||||
list = list->next ) {
|
||||
tct = (toCreateTuple*)list->data;
|
||||
// Find any already-existing toCreateTuples to add to...
|
||||
/* Find any already-existing toCreateTuples to add to...*/
|
||||
if ( tct->sx == rit->parentRT->sx ) {
|
||||
break;
|
||||
}
|
||||
@ -1357,6 +1364,7 @@ processSelectedReminderList( GList *goodList, sxSinceLastData *sxsld )
|
||||
tci->date = rit->occurDate;
|
||||
tci->node = NULL;
|
||||
tci->varBindings = NULL;
|
||||
tci->instanceNum = rit->instanceNum;
|
||||
|
||||
tct->instanceList =
|
||||
g_list_append( tct->instanceList, tci );
|
||||
@ -1377,11 +1385,9 @@ sxsincelast_populate( sxSinceLastData *sxsld )
|
||||
SchedXaction *sx;
|
||||
void *sx_state;
|
||||
GDate end, endPlusReminders;
|
||||
GDate *instDate;
|
||||
gint daysInAdvance;
|
||||
gboolean autocreateState, notifyState;
|
||||
gboolean showIt;
|
||||
autoCreateTuple *act;
|
||||
toCreateTuple *tct;
|
||||
toCreateInstance *tci;
|
||||
|
||||
@ -1432,27 +1438,24 @@ sxsincelast_populate( sxSinceLastData *sxsld )
|
||||
xaccSchedXactionGetAutoCreate( sx, &autocreateState,
|
||||
¬ifyState );
|
||||
if ( autocreateState ) {
|
||||
act = g_new0( autoCreateTuple, 1 );
|
||||
act->sx = sx;
|
||||
tct = g_new0( toCreateTuple, 1 );
|
||||
tct->sx = sx;
|
||||
for ( ; instanceList; instanceList = instanceList->next ) {
|
||||
instDate = (GDate*)instanceList->data;
|
||||
act->instanceList =
|
||||
g_list_append( act->instanceList,
|
||||
instDate );
|
||||
tci = (toCreateInstance*)instanceList->data;
|
||||
tci->parentTCT = tct;
|
||||
tct->instanceList =
|
||||
g_list_append( tct->instanceList,
|
||||
tci );
|
||||
}
|
||||
sxsld->autoCreateList =
|
||||
g_list_append( sxsld->autoCreateList,
|
||||
act );
|
||||
tct );
|
||||
} else {
|
||||
tct = g_new0( toCreateTuple, 1 );
|
||||
tct->sx = sx;
|
||||
for ( ; instanceList; instanceList = instanceList->next ) {
|
||||
instDate = (GDate*)instanceList->data;
|
||||
tci = g_new0( toCreateInstance, 1 );
|
||||
tci = (toCreateInstance*)instanceList->data;
|
||||
tci->parentTCT = tct;
|
||||
tci->date = instDate;
|
||||
tci->node = NULL;
|
||||
tci->varBindings = NULL;
|
||||
tct->instanceList =
|
||||
g_list_append( tct->instanceList, tci );
|
||||
}
|
||||
@ -1509,7 +1512,6 @@ sxsincelast_close_handler( gpointer ud )
|
||||
{
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
DEBUG( "sxsincelast_close_handler" );
|
||||
gtk_widget_hide( sxsld->sincelast_window );
|
||||
sxsincelast_save_size( sxsld );
|
||||
clean_sincelast_dlg( sxsld );
|
||||
@ -1521,8 +1523,10 @@ static void
|
||||
andequal_numerics_set( gpointer key, gpointer value, gpointer data )
|
||||
{
|
||||
gboolean *allVarsBound = data;
|
||||
if ( strcmp( (gchar*)key, "i" ) != 0 ) {
|
||||
*allVarsBound &= (value != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
@ -1598,7 +1602,6 @@ sxsincelast_destroy( GtkObject *o, gpointer ud )
|
||||
{
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
DEBUG( "sxsincelast_destroy called\n" );
|
||||
gnc_unregister_gui_component_by_data( DIALOG_SXSINCELAST_CM_CLASS,
|
||||
sxsld->sincelast_window );
|
||||
|
||||
@ -1614,6 +1617,40 @@ sxsincelast_destroy( GtkObject *o, gpointer ud )
|
||||
g_free( sxsld );
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to copy the varBinding GHashTable.
|
||||
**/
|
||||
static
|
||||
void
|
||||
gnc_sxsl_copy_ea_hash( gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data )
|
||||
{
|
||||
gchar *name = (gchar*)key;
|
||||
gnc_numeric *val = (gnc_numeric*)value;
|
||||
gnc_numeric *newVal;
|
||||
GHashTable *table = (GHashTable*)user_data;
|
||||
|
||||
newVal = g_new0( gnc_numeric, 1 );
|
||||
*newVal = gnc_numeric_error( -2 );
|
||||
if ( val )
|
||||
*newVal = *val;
|
||||
|
||||
g_hash_table_insert( table,
|
||||
(gpointer)g_strdup( name ),
|
||||
(gpointer)newVal );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gnc_sxsl_del_vars_table_ea( gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data )
|
||||
{
|
||||
g_free( (gchar*)key );
|
||||
g_free( (gnc_numeric*)value );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_each_transaction_helper( Transaction *t, void *d )
|
||||
{
|
||||
@ -1627,6 +1664,8 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
createData *createUD;
|
||||
toCreateInstance *tci;
|
||||
gnc_commodity *commonCommodity = NULL;
|
||||
GHashTable *actualVars;
|
||||
gnc_numeric *varIValue;
|
||||
|
||||
errFlag = FALSE;
|
||||
|
||||
@ -1637,15 +1676,25 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
/* FIXME: when we copy the trans_onto_trans, we don't want to copy
|
||||
the Split's kvp_frames... */
|
||||
|
||||
/* FIXME: This should setup the predefined variables 'i' and 'N' */
|
||||
|
||||
createUD = (createData*)d;
|
||||
tci = createUD->tci;
|
||||
|
||||
actualVars = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
if ( tci->varBindings != NULL ) {
|
||||
g_hash_table_foreach( tci->varBindings,
|
||||
gnc_sxsl_copy_ea_hash, actualVars );
|
||||
}
|
||||
varIValue = g_new0( gnc_numeric, 1 );
|
||||
*varIValue = gnc_numeric_create( tci->instanceNum, 1 );
|
||||
g_hash_table_insert( actualVars, "i", varIValue );
|
||||
|
||||
newT = xaccMallocTransaction(gnc_get_current_book ());
|
||||
xaccTransBeginEdit( newT );
|
||||
/* the action and description/memo are in the template */
|
||||
gnc_copy_trans_onto_trans( t, newT, FALSE, FALSE );
|
||||
|
||||
/* the date is new [by definition :)] */
|
||||
xaccTransSetDate( newT,
|
||||
g_date_day( tci->date ),
|
||||
g_date_month( tci->date ),
|
||||
@ -1658,7 +1707,8 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
PERR( "\tseen transaction w/o splits. :(" );
|
||||
return FALSE;
|
||||
}
|
||||
do {
|
||||
for ( ; sList && osList ;
|
||||
sList = sList->next, osList = osList->next ) {
|
||||
split = (Split*)sList->data;
|
||||
/* FIXME: Ick. This assumes that the split lists will be
|
||||
ordered identically. :( I think it's fair to say they
|
||||
@ -1683,10 +1733,10 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
acct_guid = kvp_value_get_guid( kvp_val );
|
||||
acct = xaccAccountLookup( acct_guid,
|
||||
gnc_get_current_book ());
|
||||
#if 0
|
||||
#if 0 /* debug */
|
||||
DEBUG( "Got account with name \"%s\"",
|
||||
xaccAccountGetName( acct ) );
|
||||
#endif /* 0 */
|
||||
#endif /* 0 -- debug */
|
||||
if ( commonCommodity != NULL ) {
|
||||
if ( commonCommodity != xaccAccountGetCommodity( acct ) ) {
|
||||
PERR( "Common-commodity difference: old=%s, new=%s\n",
|
||||
@ -1717,17 +1767,18 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
if ( str != NULL
|
||||
&& strlen(str) != 0 ) {
|
||||
if ( ! gnc_exp_parser_parse_separate_vars( str, &credit_num,
|
||||
&parseErrorLoc, tci->varBindings ) ) {
|
||||
&parseErrorLoc,
|
||||
actualVars ) ) {
|
||||
PERR( "Error parsing credit formula \"%s\" at \"%s\": %s",
|
||||
str, parseErrorLoc, gnc_exp_parser_error_string() );
|
||||
errFlag = TRUE;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
#if 0 /* debug */
|
||||
DEBUG( "gnc_numeric::credit: \"%s\" -> %s [%s]",
|
||||
str, gnc_numeric_to_string( credit_num ),
|
||||
gnc_numeric_to_string( gnc_numeric_reduce( credit_num ) ) );
|
||||
#endif /* 0 */
|
||||
#endif /* 0 -- debug */
|
||||
}
|
||||
|
||||
kvp_val = kvp_frame_get_slot_path( split_kvpf,
|
||||
@ -1740,18 +1791,19 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
if ( str != NULL
|
||||
&& strlen(str) != 0 ) {
|
||||
if ( ! gnc_exp_parser_parse_separate_vars( str, &debit_num,
|
||||
&parseErrorLoc, tci->varBindings ) ) {
|
||||
&parseErrorLoc,
|
||||
actualVars ) ) {
|
||||
PERR( "Error parsing debit_formula \"%s\" at \"%s\": %s",
|
||||
str, parseErrorLoc, gnc_exp_parser_error_string() );
|
||||
errFlag = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 0 /* debug */
|
||||
DEBUG( "gnc_numeric::debit: \"%s\" -> %s [%s]",
|
||||
str, gnc_numeric_to_string( debit_num ),
|
||||
gnc_numeric_to_string( gnc_numeric_reduce( debit_num ) ) );
|
||||
#endif /* 0 */
|
||||
#endif /* 0 -- debug */
|
||||
}
|
||||
|
||||
final = gnc_numeric_sub_fixed( debit_num, credit_num );
|
||||
@ -1762,12 +1814,15 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
errFlag = TRUE;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
#if 0 /* debug */
|
||||
DEBUG( "gnc_numeric::final: \"%s\"",
|
||||
gnc_numeric_to_string( final ) );
|
||||
#endif /* 0 */
|
||||
xaccSplitSetBaseValue( split, final, commonCommodity );
|
||||
#endif /* 0 -- debug */
|
||||
|
||||
xaccSplitSetValue( split, final );
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* NOT [YET] USED */
|
||||
kvp_val = kvp_frame_get_slot_path( split_kvpf,
|
||||
@ -1780,12 +1835,17 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
GNC_SX_AMNT,
|
||||
NULL);
|
||||
#endif /* 0 */
|
||||
/* FIXME:
|
||||
* . We'd like to store the variable bindings, but this might be
|
||||
* problematic [if the formulas change in the SX] [?]
|
||||
*/
|
||||
|
||||
} while ( (sList = sList->next) && (osList = osList->next) );
|
||||
}
|
||||
|
||||
/* Cleanup actualVars table. */
|
||||
{
|
||||
g_hash_table_foreach( actualVars,
|
||||
gnc_sxsl_del_vars_table_ea,
|
||||
NULL );
|
||||
g_hash_table_destroy( actualVars );
|
||||
actualVars = NULL;
|
||||
}
|
||||
|
||||
/* set the balancing currency. */
|
||||
if ( commonCommodity == NULL ) {
|
||||
@ -1797,7 +1857,7 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
{
|
||||
kvp_frame *txn_frame;
|
||||
/* set a kvp-frame element in the transaction indicating and
|
||||
pointing-to the SX this was created from. */
|
||||
* pointing-to the SX this was created from. */
|
||||
txn_frame = xaccTransGetSlots( newT );
|
||||
if ( txn_frame == NULL ) {
|
||||
txn_frame = kvp_frame_new();
|
||||
@ -1875,7 +1935,6 @@ create_transactions_on( SchedXaction *sx,
|
||||
createdTCT = TRUE;
|
||||
}
|
||||
|
||||
gnc_suspend_gui_refresh();
|
||||
ag = gnc_book_get_template_group( gnc_get_current_book () );
|
||||
id = guid_to_string( xaccSchedXactionGetGUID(sx) );
|
||||
if(ag && id)
|
||||
@ -1895,9 +1954,19 @@ create_transactions_on( SchedXaction *sx,
|
||||
{
|
||||
g_free( id );
|
||||
}
|
||||
gnc_resume_gui_refresh();
|
||||
|
||||
/* Increment the SX state */
|
||||
{
|
||||
gint tmp;
|
||||
|
||||
xaccSchedXactionSetLastOccurDate( sx, tci->date );
|
||||
tmp = gnc_sx_get_instance_count( sx, NULL );
|
||||
gnc_sx_set_instance_count( sx, tmp+1 );
|
||||
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
tmp = xaccSchedXactionGetRemOccur(sx);
|
||||
xaccSchedXactionSetRemOccur( sx, tmp-1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( createdTCT ) {
|
||||
g_free( tci );
|
||||
@ -1992,7 +2061,6 @@ static gboolean
|
||||
tct_table_entry_key_handle( GtkWidget *widget, GdkEventKey *event, gpointer ud )
|
||||
{
|
||||
gnc_numeric *num;
|
||||
//gchar *entryText;
|
||||
GtkEntry *ent = NULL;
|
||||
GString *str;
|
||||
|
||||
@ -2059,8 +2127,19 @@ sxsincelast_tc_row_sel( GtkCTree *ct,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (varHashSize = g_hash_table_size( tci->varBindings )) == 0 ) {
|
||||
PINFO( "No variables to deal with" );
|
||||
/* Get the count of variables; potentially remove the system-defined
|
||||
* variables if they're present in the expression. */
|
||||
varHashSize = g_hash_table_size( tci->varBindings );
|
||||
{
|
||||
gpointer *foo, *bar;
|
||||
if ( g_hash_table_lookup_extended( tci->varBindings, "i",
|
||||
(gpointer)&foo,
|
||||
(gpointer)&bar ) ) {
|
||||
varHashSize -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( varHashSize == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2072,19 +2151,25 @@ sxsincelast_tc_row_sel( GtkCTree *ct,
|
||||
|
||||
tableIdx = 1;
|
||||
for ( ; varList ; varList = varList->next ) {
|
||||
gchar *varName;
|
||||
GString *gstr;
|
||||
const gchar *numValueStr;
|
||||
gnc_numeric *numValue, *tmpNumValue;
|
||||
|
||||
varName = (gchar*)varList->data;
|
||||
if ( strcmp( varName, "i" ) == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gstr = g_string_sized_new(16);
|
||||
g_string_sprintf( gstr, "%s: ", (gchar*)varList->data );
|
||||
g_string_sprintf( gstr, "%s: ", varName );
|
||||
label = gtk_label_new( gstr->str );
|
||||
gtk_label_set_justify( GTK_LABEL(label), GTK_JUSTIFY_RIGHT );
|
||||
g_string_free( gstr, TRUE );
|
||||
|
||||
entry = gtk_entry_new();
|
||||
gtk_object_set_data( GTK_OBJECT(entry), "varName",
|
||||
varList->data );
|
||||
varName );
|
||||
gtk_object_set_data( GTK_OBJECT(entry), "tci", tci );
|
||||
tmpNumValue = g_new0( gnc_numeric, 1 );
|
||||
*tmpNumValue = gnc_numeric_create( 0, 1 );
|
||||
@ -2099,7 +2184,7 @@ sxsincelast_tc_row_sel( GtkCTree *ct,
|
||||
|
||||
gtk_widget_set_usize( entry, 64, 0 );
|
||||
numValue = (gnc_numeric*)g_hash_table_lookup( tci->varBindings,
|
||||
varList->data );
|
||||
varName );
|
||||
if ( numValue != NULL ) {
|
||||
numValueStr =
|
||||
xaccPrintAmount( *numValue,
|
||||
@ -2144,14 +2229,14 @@ clean_variable_table( sxSinceLastData *sxsld )
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
for( ; children ; children = children->next ) {
|
||||
/* Destroy all children after the first [label-continaing]
|
||||
row... ie, leave the labels in place. */
|
||||
child = (GtkTableChild*)children->data;
|
||||
if ( child->top_attach > 0 ) {
|
||||
toFree = g_list_append( toFree, child->widget );
|
||||
}
|
||||
} while ( (children = children->next) );
|
||||
}
|
||||
|
||||
gtk_table_resize( table, 1, 2 );
|
||||
|
||||
@ -2503,7 +2588,6 @@ sxsld_ledger_get_parent( GNCLedgerDisplay *ld )
|
||||
sxSinceLastData *sxsld;
|
||||
|
||||
sxsld = (sxSinceLastData*)gnc_ledger_display_get_user_data( ld );
|
||||
//return (gncUIWidget)sxsld->reg->sheet->window;
|
||||
return (gncUIWidget)sxsld->sincelast_window;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,10 @@
|
||||
|
||||
#include "druid-loan.h"
|
||||
|
||||
#include "SchedXaction.h"
|
||||
#include "SX-ttinfo.h"
|
||||
#include "gnc-book-p.h"
|
||||
#include "gnc-book.h"
|
||||
#include "gnc-amount-edit.h"
|
||||
#include "gnc-account-sel.h"
|
||||
#include "gnc-component-manager.h"
|
||||
@ -53,7 +57,6 @@
|
||||
# define ORIG_PRINC_GNE "orig_princ_gne"
|
||||
# define ORIG_PRINC_ENTRY "orig_princ_ent"
|
||||
# define IRATE_SPIN "irate_spin"
|
||||
# define TYPE_OPT "type_opt"
|
||||
# define VAR_CONTAINER "type_freq_frame"
|
||||
# define START_DATE "start_gde"
|
||||
# define LENGTH_SPIN "len_spin"
|
||||
@ -61,12 +64,11 @@
|
||||
# define REMAIN_SPIN "rem_spin"
|
||||
#define PG_OPTS "loan_opts_pg"
|
||||
# define OPT_CONTAINER "opt_vbox"
|
||||
# define OPT_ESCROW "opt_escrow"
|
||||
# define OPT_ESCROW "opt_escrow_cb"
|
||||
# define OPT_ESCROW_CONTAINER "opt_escrow_hbox"
|
||||
#define PG_REPAYMENT "repayment_pg"
|
||||
# define TXN_NAME "txn_title"
|
||||
# define REPAY_TABLE "repay_table"
|
||||
# define AMOUNT_GNE "amount_gne"
|
||||
# define AMOUNT_ENTRY "amount_ent"
|
||||
# define REMAINDER_OPT "remain_opt"
|
||||
# define FREQ_CONTAINER "freq_frame"
|
||||
@ -91,6 +93,8 @@
|
||||
* . Frequency <- sensitive
|
||||
**/
|
||||
|
||||
struct LoanDruidData_;
|
||||
|
||||
/**
|
||||
* The data relating to a single "repayment option" -- a potential
|
||||
* [sub-]transaction in the repayment.
|
||||
@ -101,7 +105,7 @@ typedef struct RepayOptData_ {
|
||||
char *txnMemo;
|
||||
float amount;
|
||||
gboolean throughEscrowP;
|
||||
//Account *to;
|
||||
Account *to;
|
||||
Account *from; // If NULL { If throughEscrowP, then through escrowP;
|
||||
// else: undefined.
|
||||
FreqSpec *fs; // If NULL, part of repayment; otherwise: defined here.
|
||||
@ -119,9 +123,9 @@ typedef struct RepayOptDataDefault_ {
|
||||
|
||||
static RepayOptDataDefault REPAY_DEFAULTS[] = {
|
||||
/* { name, default txn memo, throughEscrowP } */
|
||||
{ "Taxes", "Tax Payment", FALSE },
|
||||
{ "Insurance", "Insurance Payment", FALSE },
|
||||
{ "PMI", "PMI Payment", FALSE },
|
||||
{ "Taxes", "Tax Payment", TRUE },
|
||||
{ "Insurance", "Insurance Payment", TRUE },
|
||||
{ "PMI", "PMI Payment", TRUE },
|
||||
{ "Other Expense", "Miscellaneous Payment", FALSE },
|
||||
{ NULL }
|
||||
};
|
||||
@ -130,6 +134,9 @@ static RepayOptDataDefault REPAY_DEFAULTS[] = {
|
||||
* The UI-side storage of the repayment options.
|
||||
**/
|
||||
typedef struct RepayOptUI_ {
|
||||
/* must be stated this way [instead of 'LoanDruidData*'] because of
|
||||
* forward decl. */
|
||||
struct LoanDruidData_ *ldd;
|
||||
GtkCheckButton *optCb;
|
||||
GtkCheckButton *escrowCb;
|
||||
RepayOptData *optData;
|
||||
@ -138,7 +145,8 @@ typedef struct RepayOptUI_ {
|
||||
typedef enum {
|
||||
FIXED = 0,
|
||||
VARIABLE,
|
||||
VARIABLE_5_1 = VARIABLE,
|
||||
VARIABLE_3_1 = VARIABLE,
|
||||
VARIABLE_5_1,
|
||||
VARIABLE_7_1,
|
||||
VARIABLE_10_1,
|
||||
/* ... FIXME */
|
||||
@ -164,6 +172,16 @@ typedef struct LoanData_ {
|
||||
int numPerRemain;
|
||||
PeriodSize perSize;
|
||||
|
||||
char *repMemo;
|
||||
char *repAmount;
|
||||
Account *repFromAcct;
|
||||
Account *repPriAcct;
|
||||
Account *repIntAcct;
|
||||
Account *escrowAcct;
|
||||
int remainderChoice;
|
||||
FreqSpec *repFreq;
|
||||
GDate *repStartDate;
|
||||
|
||||
int repayOptCount;
|
||||
RepayOptData **repayOpts;
|
||||
} LoanData;
|
||||
@ -201,16 +219,17 @@ typedef struct LoanDruidData_ {
|
||||
|
||||
/* opt = options */
|
||||
GtkVBox *optVBox;
|
||||
GtkCheckButton *optEscrowCb;
|
||||
GtkHBox *optEscrowHBox;
|
||||
GNCAccountSel *optEscrowGAS;
|
||||
|
||||
/* rep = repayment */
|
||||
GtkEntry *repTxnName;
|
||||
GtkTable *repTable;
|
||||
GnomeNumberEntry *repAmtGNE;
|
||||
GtkEntry *repAmtEntry;
|
||||
GNCAccountSel *repAssetsFromGAS;
|
||||
GNCAccountSel *repPrincToGAS;
|
||||
GNCAccountSel *repIntToGAS;
|
||||
GNCAccountSel *repEscrowToGAS;
|
||||
GtkEntry *repAmtEntry;
|
||||
GtkOptionMenu *repRemainderOpt;
|
||||
GtkFrame *repFreqFrame;
|
||||
GNCFrequency *repGncFreq;
|
||||
@ -219,7 +238,8 @@ typedef struct LoanDruidData_ {
|
||||
GtkEntry *payTxnName;
|
||||
GnomeNumberEntry *payAmtGNE;
|
||||
GtkEntry *payAmtEntry;
|
||||
GNCAccountSel *payAccountGAS;
|
||||
GNCAccountSel *payAcctFromGAS;
|
||||
GNCAccountSel *payAcctToGAS;
|
||||
GtkTable *payTable;
|
||||
GtkRadioButton *payTxnFreqPartRb;
|
||||
GtkRadioButton *payTxnFreqUniqRb;
|
||||
@ -235,42 +255,32 @@ static void ld_destroy( GtkObject *o, gpointer ud );
|
||||
|
||||
static void ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd );
|
||||
|
||||
static void ld_prm_type_change( GtkButton *b, gpointer ud );
|
||||
static void ld_prm_type_changed( GtkWidget *w, gint index, gpointer ud );
|
||||
|
||||
static void ld_escrow_toggle( GtkToggleButton *tb, gpointer ud );
|
||||
static void ld_opt_toggled( GtkToggleButton *tb, gpointer ud );
|
||||
static void ld_opt_consistency( GtkToggleButton *tb, gpointer ud );
|
||||
static void ld_escrow_tog( GtkToggleButton *tb, gpointer ud );
|
||||
static void ld_escrow_toggled( GtkToggleButton *tb, gpointer ud );
|
||||
|
||||
static void ld_pay_freq_toggle( GtkToggleButton *tb, gpointer ud );
|
||||
|
||||
static gboolean ld_info_save( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_info_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_opts_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_opts_tran( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_opts_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_rep_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_rep_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_rep_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_pay_next ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_pay_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_pay_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_fin_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static gboolean ld_fin_back ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
static void ld_fin_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud );
|
||||
|
||||
struct LoanDruidData_*
|
||||
gnc_ui_sx_loan_druid_create()
|
||||
{
|
||||
static struct {
|
||||
char *pageName;
|
||||
gboolean (*nextFn)();
|
||||
void (*prepFn)();
|
||||
gboolean (*backFn)();
|
||||
void (*finishFn)();
|
||||
/* cancel is handled by the druid itself. */
|
||||
} DRUID_HANDLERS[] = {
|
||||
{ PG_INFO, ld_info_save, ld_info_prep, ld_info_save, NULL },
|
||||
{ PG_OPTS, ld_opts_next, ld_opts_prep, NULL, NULL },
|
||||
{ PG_REPAYMENT, ld_rep_next, ld_rep_prep },
|
||||
{ PG_PAYMENT, ld_pay_next, ld_pay_prep, ld_pay_back, NULL },
|
||||
{ PG_FINISH, NULL, NULL, ld_fin_back, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
int i;
|
||||
LoanDruidData *ldd;
|
||||
|
||||
@ -298,11 +308,11 @@ gnc_ui_sx_loan_druid_create()
|
||||
int left, right, top, bottom;
|
||||
} gas_data[] = {
|
||||
{ &ldd->prmAccountGAS, ldd->prmTable, 1, 4, 0, 1 },
|
||||
{ &ldd->repAssetsFromGAS, ldd->repTable, 1, 2, 2, 3 },
|
||||
{ &ldd->repAssetsFromGAS, ldd->repTable, 1, 4, 2, 3 },
|
||||
{ &ldd->repPrincToGAS, ldd->repTable, 1, 2, 3, 4 },
|
||||
{ &ldd->repIntToGAS, ldd->repTable, 1, 2, 4, 5 },
|
||||
{ &ldd->repEscrowToGAS, ldd->repTable, 1, 2, 5, 6 },
|
||||
{ &ldd->payAccountGAS, ldd->payTable, 1, 2, 2, 3 },
|
||||
{ &ldd->repIntToGAS, ldd->repTable, 3, 4, 3, 4 },
|
||||
{ &ldd->payAcctFromGAS, ldd->payTable, 1, 2, 2, 3 },
|
||||
{ &ldd->payAcctToGAS, ldd->payTable, 3, 4, 2, 3 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -334,9 +344,24 @@ gnc_ui_sx_loan_druid_create()
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive( ldd->prmVarFrame, FALSE );
|
||||
gtk_signal_connect( GTK_OBJECT(ldd->prmType), "clicked",
|
||||
GTK_SIGNAL_FUNC(ld_prm_type_change), (gpointer)ldd );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame), FALSE );
|
||||
{
|
||||
GtkAlignment *a;
|
||||
GNCOptionInfo typeOptInfo[] = {
|
||||
{ "Fixed", "A Fixed-Rate loan", ld_prm_type_changed, ldd },
|
||||
{ "3/1", "A 3/1 ARM", ld_prm_type_changed, ldd },
|
||||
{ "5/1", "A 5/1 ARM", ld_prm_type_changed, ldd },
|
||||
{ "7/1", "A 7/1 ARM", ld_prm_type_changed, ldd },
|
||||
{ "10/1", "A 10/1 ARM", ld_prm_type_changed, ldd },
|
||||
};
|
||||
ldd->prmType =
|
||||
GTK_OPTION_MENU( gnc_build_option_menu( typeOptInfo, 5 ) );
|
||||
a = GTK_ALIGNMENT( gtk_alignment_new( 0.0, 0.5, 0.25, 1.0 ) );
|
||||
gtk_container_add( GTK_CONTAINER(a), GTK_WIDGET(ldd->prmType) );
|
||||
gtk_table_attach( ldd->prmTable, GTK_WIDGET(a),
|
||||
3, 4, 2, 3,
|
||||
0, 0, 2, 2 );
|
||||
}
|
||||
|
||||
{
|
||||
GtkAdjustment *a;
|
||||
@ -365,6 +390,13 @@ gnc_ui_sx_loan_druid_create()
|
||||
gnc_option_menu_init( GTK_WIDGET(ldd->prmLengthType) );
|
||||
gnc_option_menu_init( GTK_WIDGET(ldd->repRemainderOpt) );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT(ldd->optEscrowCb), "toggled",
|
||||
GTK_SIGNAL_FUNC(ld_escrow_toggle), ldd );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), FALSE );
|
||||
ldd->optEscrowGAS = GNC_ACCOUNT_SEL(gnc_account_sel_new());
|
||||
gtk_container_add( GTK_CONTAINER(ldd->optEscrowHBox),
|
||||
GTK_WIDGET(ldd->optEscrowGAS) );
|
||||
|
||||
/* FIXME : too deep, factor out. */
|
||||
{
|
||||
/* . Each RepayOpt gets an entry in the optContainer.
|
||||
@ -387,31 +419,39 @@ gnc_ui_sx_loan_druid_create()
|
||||
vb = GTK_VBOX(gtk_vbox_new( FALSE, OPT_VBOX_SPACING ));
|
||||
|
||||
/* Add payment checkbox. */
|
||||
g_string_sprintf( str, "... pay \"%s\"?", rouid->optData->name );
|
||||
g_string_sprintf( str, "... pay \"%s\"?",
|
||||
rouid->optData->name );
|
||||
rouid->optCb =
|
||||
GTK_CHECK_BUTTON(gtk_check_button_new_with_label( str->str ));
|
||||
gtk_box_pack_start( GTK_BOX(vb), GTK_WIDGET(rouid->optCb),
|
||||
GTK_CHECK_BUTTON(
|
||||
gtk_check_button_new_with_label(
|
||||
str->str ));
|
||||
gtk_box_pack_start( GTK_BOX(vb),
|
||||
GTK_WIDGET(rouid->optCb),
|
||||
FALSE, FALSE, 2 );
|
||||
rouid->escrowCb =
|
||||
GTK_CHECK_BUTTON(gtk_check_button_new_with_label( _("via Escrow account?") ));
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb), FALSE );
|
||||
subOptAlign = GTK_ALIGNMENT(gtk_alignment_new( 0.5, 0.5, 0.75, 1.0 ));
|
||||
GTK_CHECK_BUTTON(
|
||||
gtk_check_button_new_with_label(
|
||||
_("via Escrow account?") ));
|
||||
gtk_widget_set_sensitive(
|
||||
GTK_WIDGET(rouid->escrowCb),
|
||||
FALSE );
|
||||
subOptAlign =
|
||||
GTK_ALIGNMENT(
|
||||
gtk_alignment_new(
|
||||
0.5, 0.5, 0.75, 1.0 ));
|
||||
gtk_container_add( GTK_CONTAINER(subOptAlign),
|
||||
GTK_WIDGET(rouid->escrowCb) );
|
||||
gtk_box_pack_start( GTK_BOX(vb), GTK_WIDGET(subOptAlign),
|
||||
FALSE, FALSE, 2 );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->optCb ),
|
||||
"toggled",
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->optCb ), "toggled",
|
||||
GTK_SIGNAL_FUNC(ld_opt_toggled),
|
||||
(gpointer)rouid );
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->optCb ),
|
||||
"toggled",
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->optCb ), "toggled",
|
||||
GTK_SIGNAL_FUNC(ld_opt_consistency),
|
||||
(gpointer)rouid->escrowCb );
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->escrowCb ),
|
||||
"toggled",
|
||||
GTK_SIGNAL_FUNC(ld_escrow_tog),
|
||||
(gpointer)rouid );
|
||||
gtk_signal_connect( GTK_OBJECT( rouid->escrowCb ), "toggled",
|
||||
GTK_SIGNAL_FUNC(ld_escrow_toggled),
|
||||
(gpointer)rouid );
|
||||
|
||||
optAlign = GTK_ALIGNMENT(gtk_alignment_new( 0.5, 0.5, 0.75, 1.0 ));
|
||||
@ -445,14 +485,22 @@ gnc_ui_sx_loan_druid_create()
|
||||
GTK_WIDGET(ldd->payGncFreq) );
|
||||
}
|
||||
|
||||
gnc_register_gui_component( DIALOG_LOAN_DRUID_CM_CLASS,
|
||||
NULL, /* no refresh handler */
|
||||
(GNCComponentCloseHandler*)ld_close_handler,
|
||||
ldd );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT(ldd->dialog), "destroy",
|
||||
GTK_SIGNAL_FUNC(ld_destroy),
|
||||
ldd );
|
||||
{
|
||||
static struct {
|
||||
char *pageName;
|
||||
gboolean (*nextFn)();
|
||||
void (*prepFn)();
|
||||
gboolean (*backFn)();
|
||||
void (*finishFn)();
|
||||
/* cancel is handled by the druid itself. */
|
||||
} DRUID_HANDLERS[] = {
|
||||
{ PG_INFO, ld_info_save, ld_info_prep, ld_info_save, NULL },
|
||||
{ PG_OPTS, ld_opts_tran, ld_opts_prep, ld_opts_tran, NULL },
|
||||
{ PG_REPAYMENT, ld_rep_next, ld_rep_prep, ld_rep_back },
|
||||
{ PG_PAYMENT, ld_pay_next, ld_pay_prep, ld_pay_back, NULL },
|
||||
{ PG_FINISH, NULL, ld_fin_prep, ld_fin_back, ld_fin_fin },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/* setup page-transition handlers */
|
||||
/* setup druid-global handler for cancel */
|
||||
@ -492,6 +540,16 @@ gnc_ui_sx_loan_druid_create()
|
||||
ldd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gnc_register_gui_component( DIALOG_LOAN_DRUID_CM_CLASS,
|
||||
NULL, /* no refresh handler */
|
||||
(GNCComponentCloseHandler)ld_close_handler,
|
||||
ldd );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT(ldd->dialog), "destroy",
|
||||
GTK_SIGNAL_FUNC(ld_destroy),
|
||||
ldd );
|
||||
|
||||
gtk_widget_show_all( ldd->dialog );
|
||||
return ldd;
|
||||
@ -515,6 +573,12 @@ gnc_loan_druid_data_init( LoanDruidData *ldd )
|
||||
ldd->ld.varStartDate = g_date_new();
|
||||
g_date_set_time( ldd->ld.startDate, time(NULL) );
|
||||
ldd->ld.loanFreq = xaccFreqSpecMalloc( gnc_get_current_book() );
|
||||
ldd->ld.repFreq = xaccFreqSpecMalloc( gnc_get_current_book() );
|
||||
xaccFreqSpecSetMonthly( ldd->ld.repFreq, ldd->ld.startDate, 1 );
|
||||
xaccFreqSpecSetUIType( ldd->ld.repFreq, UIFREQ_MONTHLY );
|
||||
|
||||
ldd->ld.repAmount = NULL;
|
||||
ldd->ld.repStartDate = g_date_new();
|
||||
ldd->ld.repayOptCount = optCount;
|
||||
ldd->ld.repayOpts = g_new0( RepayOptData*, optCount );
|
||||
/* copy all the default lines into the LDD */
|
||||
@ -523,6 +587,8 @@ gnc_loan_druid_data_init( LoanDruidData *ldd )
|
||||
g_assert( REPAY_DEFAULTS[i].name != NULL );
|
||||
|
||||
ldd->repayOptsUI[i] = g_new0( RepayOptUIData, 1 );
|
||||
ldd->repayOptsUI[i]->ldd = ldd;
|
||||
|
||||
optData = ldd->ld.repayOpts[i]
|
||||
= ldd->repayOptsUI[i]->optData
|
||||
= g_new0( RepayOptData, 1 );
|
||||
@ -555,8 +621,6 @@ gnc_loan_druid_get_widgets( LoanDruidData *ldd )
|
||||
GET_CASTED_WIDGET( GTK_TABLE, PARAM_TABLE );
|
||||
ldd->prmIrateSpin =
|
||||
GET_CASTED_WIDGET( GTK_SPIN_BUTTON, IRATE_SPIN );
|
||||
ldd->prmType =
|
||||
GET_CASTED_WIDGET( GTK_OPTION_MENU, TYPE_OPT );
|
||||
ldd->prmVarFrame =
|
||||
GET_CASTED_WIDGET( GTK_FRAME, VAR_CONTAINER );
|
||||
ldd->prmStartDateGDE =
|
||||
@ -571,14 +635,16 @@ gnc_loan_druid_get_widgets( LoanDruidData *ldd )
|
||||
/* opt = options */
|
||||
ldd->optVBox =
|
||||
GET_CASTED_WIDGET( GTK_VBOX, OPT_CONTAINER );
|
||||
ldd->optEscrowCb =
|
||||
GET_CASTED_WIDGET( GTK_CHECK_BUTTON, OPT_ESCROW );
|
||||
ldd->optEscrowHBox =
|
||||
GET_CASTED_WIDGET( GTK_HBOX, OPT_ESCROW_CONTAINER );
|
||||
|
||||
/* rep = repayment */
|
||||
ldd->repTxnName =
|
||||
GET_CASTED_WIDGET( GTK_ENTRY, TXN_NAME );
|
||||
ldd->repTable =
|
||||
GET_CASTED_WIDGET( GTK_TABLE, REPAY_TABLE );
|
||||
ldd->repAmtGNE =
|
||||
GET_CASTED_WIDGET( GNOME_NUMBER_ENTRY, AMOUNT_GNE );
|
||||
ldd->repAmtEntry =
|
||||
GET_CASTED_WIDGET( GTK_ENTRY, AMOUNT_ENTRY );
|
||||
ldd->repRemainderOpt =
|
||||
@ -644,13 +710,56 @@ ld_cancel_check( GnomeDruid *gd, LoanDruidData *ldd )
|
||||
|
||||
static
|
||||
void
|
||||
ld_prm_type_change( GtkButton *b, gpointer ud )
|
||||
ld_prm_type_changed( GtkWidget *w, gint index, gpointer ud )
|
||||
{
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
gtk_widget_set_sensitive( ldd->prmVarFrame,
|
||||
gnc_option_menu_get_active( ldd->prmType ) );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame),
|
||||
index != FIXED );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_escrow_toggle( GtkToggleButton *tb, gpointer ud )
|
||||
{
|
||||
int i;
|
||||
gboolean newState;
|
||||
RepayOptUIData *rouid;
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
newState = gtk_toggle_button_get_active(tb);
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), newState );
|
||||
/* deal with escrow options. */
|
||||
for ( i=0; i<ldd->ld.repayOptCount; i++ ) {
|
||||
rouid = ldd->repayOptsUI[i];
|
||||
/* If we're going off, then uncheck and desensitize all escrow opts. */
|
||||
/* If we're going on, then sensitize all escrow opts. */
|
||||
|
||||
/* prevent the toggle handler from running and "trashing" the
|
||||
* state of the throughEscrowP selection */
|
||||
gtk_signal_handler_block_by_func( GTK_OBJECT(rouid->escrowCb),
|
||||
GTK_SIGNAL_FUNC(ld_escrow_toggled),
|
||||
rouid );
|
||||
gtk_toggle_button_set_active(
|
||||
GTK_TOGGLE_BUTTON(rouid->escrowCb),
|
||||
newState
|
||||
&& gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) )
|
||||
&& rouid->optData->throughEscrowP );
|
||||
gtk_widget_set_sensitive(
|
||||
GTK_WIDGET(rouid->escrowCb),
|
||||
newState
|
||||
&& gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) ) );
|
||||
gtk_signal_handler_unblock_by_func( GTK_OBJECT(rouid->escrowCb),
|
||||
GTK_SIGNAL_FUNC(ld_escrow_toggled),
|
||||
rouid );
|
||||
if ( newState ) {
|
||||
rouid->optData->from = ldd->ld.escrowAcct;
|
||||
} else {
|
||||
rouid->optData->from = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@ -668,20 +777,25 @@ void
|
||||
ld_opt_consistency( GtkToggleButton *tb, gpointer ud )
|
||||
{
|
||||
GtkToggleButton *escrowCb;
|
||||
RepayOptUIData *rouid;
|
||||
|
||||
escrowCb = GTK_TOGGLE_BUTTON(ud);
|
||||
rouid = (RepayOptUIData*)ud;
|
||||
escrowCb = GTK_TOGGLE_BUTTON(rouid->escrowCb);
|
||||
/* make sure the escrow option is only selected if we're active. */
|
||||
gtk_toggle_button_set_state( escrowCb,
|
||||
gtk_toggle_button_get_active(escrowCb)
|
||||
& gtk_toggle_button_get_active(tb) );
|
||||
/* make sure the escrow option is only sensitive if we're active. */
|
||||
rouid->optData->throughEscrowP
|
||||
&& gtk_toggle_button_get_active(tb) );
|
||||
/* make sure the escrow option is only sensitive if we're active, and
|
||||
* the escrow account is enabled */
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(escrowCb),
|
||||
gtk_toggle_button_get_active(tb) );
|
||||
gtk_toggle_button_get_active(tb)
|
||||
&& gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(rouid->ldd->optEscrowCb)) );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_escrow_tog( GtkToggleButton *tb, gpointer ud )
|
||||
ld_escrow_toggled( GtkToggleButton *tb, gpointer ud )
|
||||
{
|
||||
RepayOptUIData *rouid;
|
||||
|
||||
@ -693,27 +807,15 @@ static
|
||||
gboolean
|
||||
ld_info_save( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
gchar *txt;
|
||||
float amt;
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
|
||||
/* FIXME: account */
|
||||
ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
|
||||
#if 0
|
||||
txt = gtk_editable_get_chars( GTK_EDITABLE(ldd->prmOrigPrincEntry),
|
||||
0, -1 );
|
||||
amt = -1.0;
|
||||
amt = (float)strtod( txt, NULL );
|
||||
if ( amt < 0 ) {
|
||||
gnc_error_dialog( _("The original principal must "
|
||||
"be a valid number.") );
|
||||
return TRUE;
|
||||
ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
|
||||
if ( ! ldd->ld.repPriAcct ) {
|
||||
ldd->ld.repPriAcct = ldd->ld.primaryAcct;
|
||||
}
|
||||
ldd->ld.principal = amt;
|
||||
g_free( txt );
|
||||
#endif /* 0 */
|
||||
ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
|
||||
ldd->ld.interestRate =
|
||||
gtk_spin_button_get_value_as_float( ldd->prmIrateSpin );
|
||||
ldd->ld.type = gnc_option_menu_get_active( GTK_WIDGET(ldd->prmType) );
|
||||
@ -731,7 +833,9 @@ ld_info_save( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
tmpTT = gnome_date_edit_get_date( ldd->prmStartDateGDE );
|
||||
tmpTm = localtime( &tmpTT );
|
||||
g_date_set_dmy( ldd->ld.startDate,
|
||||
1, (tmpTm->tm_mon+1), tmpTm->tm_mday );
|
||||
tmpTm->tm_mday,
|
||||
(tmpTm->tm_mon+1),
|
||||
(1900 + tmpTm->tm_year) );
|
||||
}
|
||||
|
||||
/* len / periods */
|
||||
@ -754,17 +858,7 @@ ld_info_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
/* FIXME: account. */
|
||||
gnc_amount_edit_set_amount( ldd->prmOrigPrincGAE, ldd->ld.principal );
|
||||
#if 0
|
||||
{
|
||||
GString *str;
|
||||
str = g_string_sized_new( 16 );
|
||||
g_string_sprintf( str, "%0.2f", ldd->principal );
|
||||
gtk_entry_set_text( ldd->prmOrigPrincEntry, str->str );
|
||||
g_string_free( str, TRUE );
|
||||
}
|
||||
#endif /* 0 */
|
||||
gtk_spin_button_set_value( ldd->prmIrateSpin, ldd->ld.interestRate );
|
||||
gtk_option_menu_set_history( ldd->prmType, ldd->ld.type );
|
||||
if ( ldd->ld.type != FIXED ) {
|
||||
@ -787,20 +881,29 @@ ld_info_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
|
||||
/* length: total and remaining */
|
||||
{
|
||||
// prmLengthSpin
|
||||
gtk_spin_button_set_value( ldd->prmLengthSpin, ldd->ld.numPer );
|
||||
// prmLengthType
|
||||
gtk_option_menu_set_history( ldd->prmLengthType, ldd->ld.perSize );
|
||||
// prmRemainSpin
|
||||
gtk_spin_button_set_value( ldd->prmRemainSpin, ldd->ld.numPerRemain );
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
ld_opts_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
void
|
||||
ld_opts_save_state( LoanDruidData *ldd )
|
||||
{
|
||||
/* FIXME: do anything here? */
|
||||
if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb) ) ) {
|
||||
ldd->ld.escrowAcct =
|
||||
gnc_account_sel_get_account( ldd->optEscrowGAS );
|
||||
} else {
|
||||
ldd->ld.escrowAcct = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
ld_opts_tran( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
ld_opts_save_state( (LoanDruidData*)ud );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -808,7 +911,66 @@ static
|
||||
void
|
||||
ld_opts_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
/* FIXME: setup the options */
|
||||
int i;
|
||||
RepayOptUIData *rouid;
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
if ( ldd->ld.escrowAcct ) {
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb),
|
||||
TRUE );
|
||||
gnc_account_sel_set_account( ldd->optEscrowGAS, ldd->ld.escrowAcct );
|
||||
}
|
||||
for ( i=0; i<ldd->ld.repayOptCount; i++ ) {
|
||||
rouid = ldd->repayOptsUI[i];
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->optCb),
|
||||
rouid->optData->enabled );
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->escrowCb),
|
||||
rouid->optData->throughEscrowP
|
||||
&& rouid->optData->enabled
|
||||
&& ldd->ld.escrowAcct );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb),
|
||||
rouid->optData->enabled
|
||||
&& ldd->ld.escrowAcct );
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_rep_save( LoanDruidData *ldd )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( ldd->ld.repMemo )
|
||||
g_free( ldd->ld.repMemo );
|
||||
ldd->ld.repMemo =
|
||||
gtk_editable_get_chars( GTK_EDITABLE(ldd->repTxnName), 0, -1 );
|
||||
|
||||
if ( ldd->ld.repAmount )
|
||||
g_free( ldd->ld.repAmount );
|
||||
ldd->ld.repAmount =
|
||||
gtk_editable_get_chars( GTK_EDITABLE(ldd->repAmtEntry), 0, -1 );
|
||||
|
||||
ldd->ld.repFromAcct =
|
||||
gnc_account_sel_get_account( ldd->repAssetsFromGAS );
|
||||
ldd->ld.repPriAcct =
|
||||
gnc_account_sel_get_account( ldd->repPrincToGAS );
|
||||
ldd->ld.repIntAcct =
|
||||
gnc_account_sel_get_account( ldd->repIntToGAS );
|
||||
ldd->ld.remainderChoice =
|
||||
gnc_option_menu_get_active( GTK_WIDGET(ldd->repRemainderOpt) );
|
||||
gnc_frequency_save_state( ldd->repGncFreq,
|
||||
ldd->ld.repFreq,
|
||||
ldd->ld.repStartDate );
|
||||
|
||||
/* Set the 'from' accounts of the various options to be the
|
||||
* Assets-From account, if they're not already something else. */
|
||||
for ( i=0; i<ldd->ld.repayOptCount; i++ ) {
|
||||
RepayOptData *rod = ldd->ld.repayOpts[i];
|
||||
if ( ! rod->from ) {
|
||||
rod->from = ldd->ld.repFromAcct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@ -818,6 +980,9 @@ ld_rep_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
|
||||
ld_rep_save( ldd );
|
||||
|
||||
if ( (ldd->currentIdx < 0)
|
||||
|| (ldd->currentIdx >= ldd->ld.repayOptCount)
|
||||
|| !ldd->ld.repayOpts[ldd->currentIdx]->enabled ) {
|
||||
@ -839,11 +1004,56 @@ ld_rep_next( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
gboolean
|
||||
ld_rep_back( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
ld_rep_save(ldd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_rep_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
/* do anything? */
|
||||
LoanDruidData *ldd;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
|
||||
if ( !ldd->ld.repAmount ) {
|
||||
GString *str;
|
||||
str = g_string_sized_new( 64 );
|
||||
|
||||
g_string_sprintfa( str, "pmt( %.4f / 12 : %d : %0.2f : 0 : 0 )",
|
||||
(ldd->ld.interestRate / 100),
|
||||
ldd->ld.numPer,
|
||||
gnc_numeric_to_double(ldd->ld.principal) );
|
||||
|
||||
ldd->ld.repAmount = str->str;
|
||||
g_string_free( str, FALSE );
|
||||
}
|
||||
|
||||
if ( ldd->ld.repMemo )
|
||||
gtk_entry_set_text( ldd->repTxnName, ldd->ld.repMemo );
|
||||
|
||||
if ( ldd->ld.repAmount )
|
||||
gtk_entry_set_text( ldd->repAmtEntry, ldd->ld.repAmount );
|
||||
|
||||
gnc_account_sel_set_account( ldd->repAssetsFromGAS,
|
||||
ldd->ld.repFromAcct );
|
||||
gnc_account_sel_set_account( ldd->repPrincToGAS,
|
||||
ldd->ld.repPriAcct );
|
||||
gnc_account_sel_set_account( ldd->repIntToGAS,
|
||||
ldd->ld.repIntAcct );
|
||||
gtk_option_menu_set_history( ldd->repRemainderOpt,
|
||||
ldd->ld.remainderChoice );
|
||||
gnc_frequency_setup( ldd->repGncFreq,
|
||||
ldd->ld.repFreq,
|
||||
ldd->ld.repStartDate );
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
@ -870,8 +1080,8 @@ ld_pay_prep( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
g_string_sprintf( str, "%0.2f", rod->amount );
|
||||
gtk_entry_set_text( ldd->payAmtEntry, str->str );
|
||||
|
||||
gnc_account_sel_set_account( ldd->payAccountGAS,
|
||||
rod->from );
|
||||
gnc_account_sel_set_account( ldd->payAcctFromGAS, rod->from );
|
||||
gnc_account_sel_set_account( ldd->payAcctToGAS, rod->to );
|
||||
|
||||
uniq = (rod->fs != NULL);
|
||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb),
|
||||
@ -912,7 +1122,8 @@ ld_pay_save_current( LoanDruidData *ldd )
|
||||
rod->amount = (float)strtod( tmpStr, NULL );
|
||||
g_free( tmpStr );
|
||||
|
||||
rod->from = gnc_account_sel_get_account( ldd->payAccountGAS );
|
||||
rod->from = gnc_account_sel_get_account( ldd->payAcctFromGAS );
|
||||
rod->to = gnc_account_sel_get_account( ldd->payAcctToGAS );
|
||||
|
||||
/* if ( rb toggled )
|
||||
* ensure freqspec/startdate setup
|
||||
@ -1035,6 +1246,257 @@ ld_pay_freq_toggle( GtkToggleButton *tb, gpointer ud )
|
||||
g_assert( ldd->currentIdx >= 0 );
|
||||
g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
|
||||
|
||||
uniq = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
|
||||
uniq = gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqAlign), uniq );
|
||||
|
||||
if ( uniq ) {
|
||||
RepayOptData *rod;
|
||||
rod = ldd->ld.repayOpts[ ldd->currentIdx ];
|
||||
|
||||
if ( rod->fs == NULL ) {
|
||||
rod->fs = xaccFreqSpecMalloc( gnc_get_current_book() );
|
||||
xaccFreqSpecSetMonthly( rod->fs, ldd->ld.startDate, 1 );
|
||||
xaccFreqSpecSetUIType( rod->fs, UIFREQ_MONTHLY );
|
||||
}
|
||||
if ( rod->startDate == NULL ) {
|
||||
rod->startDate = g_date_new();
|
||||
*rod->startDate = *ldd->ld.startDate;
|
||||
}
|
||||
gnc_frequency_setup( ldd->payGncFreq,
|
||||
rod->fs, rod->startDate );
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_fin_prep ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
/* FIXME? */
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_free_ttsi( gpointer data, gpointer ud )
|
||||
{
|
||||
gnc_ttsplitinfo_free( (TTSplitInfo*)data );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_gnc_ttinfo_free( gpointer data, gpointer ud )
|
||||
{
|
||||
gnc_ttinfo_free( (TTInfo*)data );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
ld_fin_fin ( GnomeDruidPage *gdp, gpointer arg1, gpointer ud )
|
||||
{
|
||||
LoanDruidData *ldd;
|
||||
int i;
|
||||
TTInfo *tti;
|
||||
TTSplitInfo *ttsi;
|
||||
RepayOptData *rod;
|
||||
SchedXaction *tmpSX;
|
||||
GList *repTTList;
|
||||
GList *repSplits;
|
||||
gchar *tmpStr;
|
||||
GString *repAssetsDebitFormula, *tmpGS;
|
||||
GList *sxList;
|
||||
|
||||
ldd = (LoanDruidData*)ud;
|
||||
|
||||
/* Create a string for the Asset-account debit, which we will build
|
||||
* up in the processing of the LoanData and Options. */
|
||||
repAssetsDebitFormula = g_string_sized_new( 64 );
|
||||
repTTList = NULL;
|
||||
|
||||
/* first, start to deal with the repayment uber-SX */
|
||||
{
|
||||
repSplits = NULL;
|
||||
|
||||
/* Just add the repayment amount to a string for the moment;
|
||||
* create the split out of it after we've processed the
|
||||
* options [and gotten their contributions to the asset debit
|
||||
* formula]. */
|
||||
g_string_sprintf( repAssetsDebitFormula, ldd->ld.repAmount );
|
||||
|
||||
/* Principal credit */
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
gnc_ttsplitinfo_set_memo( ttsi, "Repayment - Principal Portion" );
|
||||
tmpStr = xaccAccountGetFullName( ldd->ld.repPriAcct,
|
||||
gnc_get_account_separator() );
|
||||
g_free( tmpStr );
|
||||
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repPriAcct );
|
||||
tmpGS = g_string_sized_new( 64 );
|
||||
g_string_sprintf( tmpGS, "ppmt( %.4f / 12 : i : %d : %0.2f : 0 : 0 )",
|
||||
(ldd->ld.interestRate / 100),
|
||||
ldd->ld.numPer,
|
||||
gnc_numeric_to_double(ldd->ld.principal));
|
||||
gnc_ttsplitinfo_set_debit_formula( ttsi, tmpGS->str );
|
||||
g_string_free( tmpGS, FALSE );
|
||||
repSplits = g_list_append( repSplits, ttsi );
|
||||
|
||||
/* Interest credit */
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
gnc_ttsplitinfo_set_memo( ttsi, "Repayment - Interest Portion" );
|
||||
tmpStr = xaccAccountGetFullName( ldd->ld.repIntAcct,
|
||||
gnc_get_account_separator() );
|
||||
g_free( tmpStr );
|
||||
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repIntAcct );
|
||||
tmpGS = g_string_sized_new( 64 );
|
||||
g_string_sprintf( tmpGS, "ipmt( %.4f / 12 : i : %d : %0.2f : 0 : 0 )",
|
||||
(ldd->ld.interestRate / 100),
|
||||
ldd->ld.numPer,
|
||||
gnc_numeric_to_double( ldd->ld.principal ) );
|
||||
gnc_ttsplitinfo_set_debit_formula( ttsi, tmpGS->str );
|
||||
g_string_free( tmpGS, FALSE );
|
||||
repSplits = g_list_append( repSplits, ttsi );
|
||||
}
|
||||
|
||||
/* Process the options. */
|
||||
for ( i=0; i<ldd->ld.repayOptCount; i++ ) {
|
||||
Account *fromAcct;
|
||||
GList *optSplits;
|
||||
GList *optTTList;
|
||||
|
||||
optSplits = NULL;
|
||||
optTTList = NULL;
|
||||
rod = ldd->ld.repayOpts[i];
|
||||
|
||||
if ( !rod->enabled )
|
||||
continue;
|
||||
|
||||
fromAcct = rod->from;
|
||||
if ( rod->throughEscrowP ) {
|
||||
GString *amt = g_string_sized_new( 5 );
|
||||
g_string_sprintf( amt, "%0.2f", rod->amount );
|
||||
|
||||
/* Add assets -> escrow Splits. */
|
||||
g_string_sprintfa( repAssetsDebitFormula, " + %s", amt->str );
|
||||
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
|
||||
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.escrowAcct );
|
||||
gnc_ttsplitinfo_set_debit_formula( ttsi, amt->str );
|
||||
repSplits = g_list_append( repSplits, ttsi );
|
||||
|
||||
g_string_free( amt, TRUE );
|
||||
fromAcct = ldd->ld.escrowAcct;
|
||||
}
|
||||
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
|
||||
gnc_ttsplitinfo_set_account( ttsi, fromAcct );
|
||||
|
||||
tmpStr = xaccAccountGetFullName( fromAcct,
|
||||
gnc_get_account_separator() );
|
||||
g_free( tmpStr );
|
||||
{
|
||||
GString *amt = g_string_sized_new(5);
|
||||
g_string_sprintf( amt, "%0.2f", rod->amount );
|
||||
gnc_ttsplitinfo_set_credit_formula( ttsi, amt->str );
|
||||
g_string_free( amt, TRUE );
|
||||
}
|
||||
optSplits = g_list_append( optSplits, ttsi );
|
||||
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
gnc_ttsplitinfo_set_memo( ttsi, rod->txnMemo );
|
||||
gnc_ttsplitinfo_set_account( ttsi, rod->to );
|
||||
tmpStr = xaccAccountGetFullName( rod->to,
|
||||
gnc_get_account_separator() );
|
||||
g_free( tmpStr );
|
||||
{
|
||||
GString *amt = g_string_sized_new( 5 );
|
||||
g_string_sprintf( amt, "%0.2f", rod->amount );
|
||||
gnc_ttsplitinfo_set_debit_formula( ttsi, amt->str );
|
||||
g_string_free( amt, TRUE );
|
||||
}
|
||||
optSplits = g_list_append( optSplits, ttsi );
|
||||
|
||||
tti = gnc_ttinfo_malloc();
|
||||
gnc_ttinfo_set_description( tti, ldd->ld.repMemo );
|
||||
gnc_ttinfo_set_template_splits( tti, optSplits );
|
||||
/* we're no longer responsible for this list. */
|
||||
optSplits = NULL;
|
||||
|
||||
if ( rod->fs ) {
|
||||
GList *ttList;
|
||||
|
||||
ttList = NULL;
|
||||
/* Create new SX with given FreqSpec */
|
||||
ttList = g_list_append( ttList, tti );
|
||||
|
||||
tmpSX = xaccSchedXactionMalloc( gnc_get_current_book() );
|
||||
/* FIXME? Get name from Liability/LoanAccount name? */
|
||||
xaccSchedXactionSetName( tmpSX, ldd->ld.repMemo );
|
||||
xaccSchedXactionSetFreqSpec( tmpSX, rod->fs );
|
||||
xaccSchedXactionSetStartDate( tmpSX, rod->startDate );
|
||||
xaccSchedXactionSetLastOccurDate( tmpSX, rod->startDate );
|
||||
/* FIXME ... what are these values? */
|
||||
xaccSchedXactionSetNumOccur( tmpSX, ldd->ld.numPer );
|
||||
xaccSchedXactionSetRemOccur( tmpSX, ldd->ld.numPerRemain );
|
||||
xaccSchedXactionSetTemplateTrans( tmpSX, ttList,
|
||||
gnc_get_current_book() );
|
||||
|
||||
sxList = gnc_book_get_schedxactions( gnc_get_current_book() );
|
||||
sxList = g_list_append( sxList, tmpSX );
|
||||
gnc_book_set_schedxactions( gnc_get_current_book(), sxList );
|
||||
|
||||
gnc_ttinfo_free( tti );
|
||||
g_list_free( ttList );
|
||||
ttList = NULL;
|
||||
|
||||
} else {
|
||||
/* Add transaction to existing repayment SX. */
|
||||
repTTList = g_list_append( repTTList, tti );
|
||||
}
|
||||
}
|
||||
|
||||
/* Create repayment assets debit split. */
|
||||
ttsi = gnc_ttsplitinfo_malloc();
|
||||
tmpStr = xaccAccountGetFullName( ldd->ld.repPriAcct,
|
||||
gnc_get_account_separator() );
|
||||
g_free( tmpStr );
|
||||
gnc_ttsplitinfo_set_memo( ttsi, ldd->ld.repMemo );
|
||||
gnc_ttsplitinfo_set_account( ttsi, ldd->ld.repFromAcct );
|
||||
gnc_ttsplitinfo_set_credit_formula( ttsi, repAssetsDebitFormula->str );
|
||||
repSplits = g_list_append( repSplits, ttsi );
|
||||
|
||||
tti = gnc_ttinfo_malloc();
|
||||
gnc_ttinfo_set_description( tti, ldd->ld.repMemo );
|
||||
gnc_ttinfo_set_template_splits( tti, repSplits );
|
||||
/* we're no longer responsible for this list. */
|
||||
repSplits = NULL;
|
||||
|
||||
repTTList = g_list_append( repTTList, tti );
|
||||
|
||||
/* Actually create the SX for the repayment. */
|
||||
tmpSX = xaccSchedXactionMalloc( gnc_get_current_book() );
|
||||
xaccSchedXactionSetName( tmpSX, ldd->ld.repMemo );
|
||||
xaccSchedXactionSetStartDate( tmpSX, ldd->ld.repStartDate );
|
||||
xaccSchedXactionSetLastOccurDate( tmpSX, ldd->ld.repStartDate );
|
||||
xaccSchedXactionSetFreqSpec( tmpSX, ldd->ld.repFreq );
|
||||
/* FIXME: we should compare these values with the user-specified
|
||||
* repayment frequency. */
|
||||
xaccSchedXactionSetNumOccur( tmpSX, ldd->ld.numPer );
|
||||
xaccSchedXactionSetRemOccur( tmpSX, ldd->ld.numPerRemain );
|
||||
xaccSchedXactionSetTemplateTrans( tmpSX, repTTList,
|
||||
gnc_get_current_book() );
|
||||
|
||||
gnc_sx_set_instance_count( tmpSX,
|
||||
ldd->ld.numPer - ldd->ld.numPerRemain + 1 );
|
||||
|
||||
sxList = gnc_book_get_schedxactions( gnc_get_current_book() );
|
||||
sxList = g_list_append( sxList, tmpSX );
|
||||
gnc_book_set_schedxactions( gnc_get_current_book(), sxList );
|
||||
|
||||
g_list_foreach( repTTList, ld_gnc_ttinfo_free, NULL );
|
||||
g_list_free( repTTList );
|
||||
repTTList = NULL;
|
||||
|
||||
g_string_free( repAssetsDebitFormula, TRUE );
|
||||
|
||||
ld_close_handler( ldd );
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -916,14 +916,14 @@ gnc_main_window_create_menus(GNCMDIInfo * maininfo)
|
||||
static GnomeUIInfo gnc_sched_xaction_tools_submenu_template[] =
|
||||
{
|
||||
{ GNOME_APP_UI_ITEM,
|
||||
N_("List and Editor"),
|
||||
N_("_List and Editor"),
|
||||
N_("The list of Scheduled Transactions"),
|
||||
gnc_main_window_sched_xaction_cb, NULL, NULL,
|
||||
GNOME_APP_PIXMAP_NONE, NULL,
|
||||
0, 0, NULL
|
||||
},
|
||||
{ GNOME_APP_UI_ITEM,
|
||||
N_("Since Last Run..."),
|
||||
N_("_Since Last Run..."),
|
||||
N_("Create Scheduled Transactions since the last time run."),
|
||||
gnc_main_window_sched_xaction_slr_cb, NULL, NULL,
|
||||
GNOME_APP_PIXMAP_NONE, NULL,
|
||||
@ -931,7 +931,7 @@ gnc_main_window_create_menus(GNCMDIInfo * maininfo)
|
||||
},
|
||||
GNOMEUIINFO_SEPARATOR,
|
||||
{ GNOME_APP_UI_ITEM,
|
||||
N_( "Mortgage/Loan Repayment Setup" ),
|
||||
N_( "_Mortgage/Loan Repayment Setup" ),
|
||||
N_( "Setup scheduled transactions for repayment of a loan" ),
|
||||
gnc_main_window_sx_loan_druid_cb, NULL, NULL,
|
||||
GNOME_APP_PIXMAP_NONE, NULL,
|
||||
@ -942,7 +942,7 @@ gnc_main_window_create_menus(GNCMDIInfo * maininfo)
|
||||
|
||||
static GnomeUIInfo gnc_actions_menu_template[] =
|
||||
{
|
||||
GNOMEUIINFO_SUBTREE( N_("Scheduled Transactions"),
|
||||
GNOMEUIINFO_SUBTREE( N_("_Scheduled Transactions"),
|
||||
gnc_sched_xaction_tools_submenu_template ),
|
||||
GNOMEUIINFO_END
|
||||
};
|
||||
|
@ -16,26 +16,37 @@
|
||||
;; Boston, MA 02111-1307, USA gnu@gnu.org
|
||||
|
||||
;; Copyright 2002 Joshua Sled <jsled@asynchronous.org>
|
||||
;; pretty literal copies of similar code from gnumeric-1.0.8
|
||||
;;
|
||||
;; pretty literal copies of similar code from gnumeric-1.0.8, except we want
|
||||
;; positive values to be returned [as gnucash will handle the credit/debit
|
||||
;; appropriately]
|
||||
|
||||
(define (gnc:ipmt rate nper per pv fv type)
|
||||
(* rate
|
||||
(define (gnc:ipmt rate per nper pv fv type)
|
||||
(* -1 (* rate
|
||||
(- 0 (calc-principal pv
|
||||
(calc-pmt rate nper pv fv type)
|
||||
rate (- per 1))
|
||||
)
|
||||
)
|
||||
rate (- per 1)))
|
||||
))
|
||||
)
|
||||
|
||||
(define (gnc:ppmt rate nper per pv fv type)
|
||||
(let ((pmt (calc-pmt rate nper pv fv type)))
|
||||
(let ((ipmt (* rate
|
||||
(- 0 (calc-principal pv pmt rate (- per 1))))))
|
||||
(- pmt ipmt)))
|
||||
(define (gnc:ppmt rate per nper pv fv type)
|
||||
(let* ((pmt (calc-pmt rate nper pv fv type))
|
||||
(ipmt (* rate
|
||||
(calc-principal pv pmt rate (- per 1)))))
|
||||
(* -1 (-
|
||||
pmt
|
||||
(* -1 ipmt))))
|
||||
)
|
||||
|
||||
(define (gnc:pmt rate nper pv fv type)
|
||||
(calc-pmt rate nper pv fv type))
|
||||
(* -1 (calc-pmt rate nper pv fv type)))
|
||||
|
||||
(define (gnc:foobar val) val)
|
||||
|
||||
;;;;;
|
||||
;; below: not-exposed/"private" functions, used by the "public" functions
|
||||
;; above.
|
||||
;;;;;
|
||||
|
||||
(define (calc-pmt rate nper pv fv type)
|
||||
(let ((pvif (calc-pvif rate nper))
|
||||
|
Loading…
Reference in New Issue
Block a user