diff --git a/ChangeLog b/ChangeLog index 05ed228fc2..1761f62e7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2001-07-06 Joshua Sled + + * src/gnome/gnc-schedxaction-xml-v2.c: Support for new + SchedXaction options [create/remind-days-in-advance; auto-create, + notify-on-creation]. + + * src/gnome/dialog-scheduledxaction.c (putSchedXactionInClist): + Fix for next-occurance processing. + + * src/engine/SchedXaction.c (xaccSchedXactionGetNextInstance): + Better handling of start date/last-occur date/current dates when + generating the next occurance date. Gotta remember to clear those + g_dates, lest the come up 'valid' due to stack trash... :( + + * src/gnome/gnc-sxlastrun.{h,c}: Added; newer/better + since-last-occur dialog. + + * src/gnome/window-main.c: Added Scheduled Transaction stuff to + "Tools" menu. + + * src/scm/prefs.scm: Added initial cut at Scheduled Transaction + preferences. + 2001-07-06 Robert Graham Merkel * doc/sgml/C/xacc-balancreport.sgml: minor updates diff --git a/src/doc/TODO-schedxactions b/src/doc/TODO-schedxactions index 306e3b0539..7f35be255c 100644 --- a/src/doc/TODO-schedxactions +++ b/src/doc/TODO-schedxactions @@ -3,66 +3,160 @@ Author: jsled@asynchronous.org Main Scheduled Transaction todo list ------------------------------------ -. Engine ...Init() functions should be private. -. FreqSpec.c - . xaccFreqSpecGetFreqStr [display] needs to go away [?] +################################################## +### Done +################################################## X add the ...GetFreqStr() code for the complex composite FreqSpecs X fix the ...GetNextInstance() code X XMLv2 I/O +X need policy for start-dates in GNCFrequency +X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs + X also needs to deal with >28-mday values WRT last-occur date + multipliers + +################################################## +### To-Do +################################################## + +. Engine ...Init() functions should be private. + +. FreqSpec.c + . xaccFreqSpecGetFreqStr [display] needs to go away [?] + X create a template register X store account and amount data in kvp_frames. . find a way to list multiple registers for template transaction purposes. . this is a "normal" general ledger + a "stock" general ledger . this is going to be: a tabbed notebook in which the tabs contain the number of transactions the GL they hold contain. -X need policy for start-dates in GNCFrequency -X fix GetNextInstance and GetInstanceAfter, mostly for composite FreqSpecs - X also needs to deal with >28-mday values WRT last-occur date + multipliers -. add a big calendar [gnome-pim? evo?] SXaction List code +. Hook into 'book data changed' save-on-exit decision. + +. add a big calendar [gnome-pim? evo?] to SXaction List/overview + . match existing transactions for long-time users . based off template-transaction data, some big existing-transaction scanning code. + . need "since-last-run" UI for instanatiation. X/O create transactions X numeric . formula . need variable fill-in UI... . re-use gnome-sheet code for a variable-binding table? -. need way to expire/purge scheduled transactions which have no chance of - being created [outside their end date; once-scheduled and past]. -. need 'reminders' of upcoming scheduled transactions during since-last-run -. need some configuration for constantly-running GnuCash users of when to pop - up the 'new scheduled transactions' dialog [option, time-of-day] + . need way to expire/purge scheduled transactions which have no chance of + being created [outside their end date; once-scheduled and past]. + . need 'reminders' of upcoming scheduled transactions during since-last-run + . Is it sufficient to look at the next instance of ea. transaction only? + I think not... we probably want to look out until the transaction is + outside the reminder range. + . need some configuration for constantly-running GnuCash users of when to + pop up the 'new scheduled transactions' dialog [option, time-of-day] + . Should deal with "nothing-to-do" better [not even show up]. + . register mods . to see upcoming xactions, modifying future balance - . to instantiate xactions. . to note which are "recurring" . the mozilla "reload" glyph is kinda neat... -. would like "don't even tell me you instantiated it, just fscking do + . Differently-colored "not-yet-created" entries for a configurable + window. + . Context menus/sensitive toolbar button/menu item for creation of + not-yet-created transactions. + . The ability to turn a non-recurring transaction into a recurring one... + +X would like "don't even tell me you instantiated it, just fscking do it!" option for non-manual-conf SXes + + . deal better with formulas in template transactions [real FormulaCell] . recognize purely numeric template transactions and balance at template-creation time. + . GNCFrequency . initial-settings synchronization [start date, optionmenus] . only a couple left; which ones? + . backend support . PostgreSQL . others? -Bugs: +. SX Creation... + . Creation occurs due to a variety of circumstances: + . GnuCash starts and hasn't been run in some length of time; the + transactions which have "come due" since the last run are available for + creation. + . A user opens a register with future transactions in it; they manually + force the creation of the [perhaps not immediately next [though this + seems a bit weird]] one. + . A user is reminded of something which hasn't come due, but will w/in a + configurable amount of time, and thus they pay/create it. + +. Configuration options... + . Overall + . Size of template register window + . color of future register entries + . conrad's desires + . policy + . create for N days in advance + . show for N days in advance, create when come-due + . defaults + . create/show for 'N' days in advance + . remind me 'M' days in advance + . just create + . notify when created + . Per-SX + . just create/notify + . create/show + . lead-time + . reminder + . lead-time + +. Changes + . Create-into-future vs. create-normal + . into-future -> normal : no change; the last_occur date will be + appropriate, and will catch up eventually [unless the have-been-created + transactions should go away] + . normal -> into-future : should create immed, or wait for user? + . into-future [t_0] -> into_future [t_1] + . frequency + . in presence of create-into-future? + . transaction + . in presence of create-into-future? + + +################################################## +### Bugs +################################################## + +. General + . Date l10n. + . GNCFreqency - . Can't click-out of the register . transitioning to a new tab doesn't correctly setup the agreement between the startdate and the page elements. + . Example calendar month change isn't handled correctly/doesn't refresh the + marks. + . "Inappropriate FreqSpec type" on new-SX editing. + . "new; weekly: click on day, click off day: GLib-CRITICAL **: file gdate.c: line 1236 (g_date_to_struct_tm): assertion `g_date_valid (d)' failed." + . Scheduled Transaction Editor + . Can't click-out of the register . auto-shrink on window create [the register is too wide, leading to too much whitespace on the two top panels] + . Size/space issues. + . Un-selecting "End Date" leaves calendar widget sensitive + . Scheduled Transaction List -Enhancements: +. Since-last-run + . always goes one date past the instantiation date. + X credit and debit seem reversed at instantiation time... + . this is fixed, but is the fix correct? + +################################################## +### Enhancements +################################################## + . SX name should be default value for template transaction description . loan/repayment SX's . integrate "Financial Calculator" @@ -70,6 +164,11 @@ Enhancements: account amount. . SX since-last-run should be able to sort by Date [conditional on the dialog staying around]. +. There probably wants to be a multi-month "example" View which the + GNCFrequency can work with. + . jalapeno[ben] has some thoughts on this... +. Evolution calendar integ. +. Evolution To-Do list integ. [SX reminders] ======================================== @@ -161,14 +260,15 @@ normal people, or a sexp for Schemers. ================================================= -Instantiation -------------- +Instantiation Notes +------------------- Wilddev, conrad: Something that came out of Aaron's mail [see my reply to -devel] that I'd like your comment on: How do you intend to use scheduled transactions? Do you intend to use it to create things have should be in there since you last ran GnuCash? Or, do you intend to use it to create future transactions [perhaps a weeks worth] before they occur? Or, just primarily the former, but use the fact that the future transaction will be in the register to remind you to pay things, &c.? + Personally, I'd be looking at future transactions as a reminder thing. But then, I run gnucash every day. conrad: Do you re-invoke it every day, or leave it running? I can see other people wanting case 1 though. @@ -178,7 +278,6 @@ Instantiation I think a further configurable sub-option should be "redisplay on change of day" (possibly with an "at time option?)") without that option, it will not do what I'm counting on it to do - remind my I'm supposed to pay my bills. Yup yup. -* jsled takes notes this. Summary... @@ -195,7 +294,6 @@ being created ATM. and second as an actual transaction that goes into the register on a future date, ie I know that this money leaves my account in 2 days, so I want it to go in automatically on that day. If I leave gnucash running all the time, it'll wait until that day then enter the transaction as you can see the purpose of each is quite different - Wilddev WildWEnd Wilddev: Indeed... For the first, you're saying that reminders should start some number of days before the transaction is usually due/paid... and that there are two acknowledgements of that... 'remind me later' or 'here's the amount/create'. For the second, you're looking at ad-hoc once-scheduled transactions... which should go away immediately afterwards. @@ -205,7 +303,6 @@ being created ATM. Okay... so this brings up something that isn't presently in the scheme at all: reminders. I think it's as simple as a "[ ] Remind me __ days in advance" element in the SXEditor, and the appropriate logic in the since-last-run code... how often is the last run code 'run'? - Wilddev WildWEnd Wilddev: On startup, or when the timer [a-la conrad's requirement] goes off. yes that would work So the "since-last-run" dialog has three panes: 1) auto-created, notification requested. 2) To-create. 3) To-create-soon + reminders. diff --git a/src/engine/SchedXaction.c b/src/engine/SchedXaction.c index 9a86f7b170..9082efc289 100644 --- a/src/engine/SchedXaction.c +++ b/src/engine/SchedXaction.c @@ -44,7 +44,7 @@ static short module = MOD_SX; /** Local data defs *****/ -void transactionListMapDelete( gpointer data, gpointer user_data ); +void _transactionListMapDelete( gpointer data, gpointer user_data ); /** Local Prototypes *****/ @@ -75,7 +75,10 @@ xaccSchedXactionInit( SchedXaction *sx, GNCBook *book ) sx->num_occurances_total = -1; sx->kvp_data = kvp_frame_new(); - sx->manual = FALSE; + sx->autoCreateOption = FALSE; + sx->autoCreateNotify = FALSE; + sx->advanceCreateDays = 0; + sx->advanceRemindDays = 0; sx->templateSplits = NULL; /* create a new template account for our splits */ @@ -102,7 +105,7 @@ xaccSchedXactionFree( SchedXaction *sx ) xaccRemoveEntity( &sx->guid ); g_list_foreach( sx->templateSplits, - transactionListMapDelete, + _transactionListMapDelete, NULL ); g_list_free( sx->templateSplits ); if ( sx->name ) @@ -113,7 +116,7 @@ xaccSchedXactionFree( SchedXaction *sx ) } void -transactionListMapDelete( gpointer data, gpointer user_data ) +_transactionListMapDelete( gpointer data, gpointer user_data ) { Transaction *t = (Transaction*)data; xaccTransBeginEdit( t ); @@ -265,15 +268,45 @@ xaccSchedXactionSetGUID( SchedXaction *sx, GUID g ) } void -xaccSchedXactionSetManual( SchedXaction *sx, gboolean newManual ) +xaccSchedXactionGetAutoCreate( SchedXaction *sx, + gboolean *outAutoCreate, + gboolean *outNotify ) { - sx->manual = newManual; + *outAutoCreate = sx->autoCreateOption; + *outNotify = sx->autoCreateNotify; } -int -xaccSchedXactionGetManual( SchedXaction *sx ) +void +xaccSchedXactionSetAutoCreate( SchedXaction *sx, + gboolean newAutoCreate, + gboolean newNotify ) +{ + sx->autoCreateOption = newAutoCreate; + sx->autoCreateNotify = newNotify; +} + +gint +xaccSchedXactionGetAdvanceCreation( SchedXaction *sx ) +{ + return sx->advanceCreateDays; +} + +void +xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays ) +{ + sx->advanceCreateDays = createDays; +} + +gint +xaccSchedXactionGetAdvanceReminder( SchedXaction *sx ) +{ + return sx->advanceRemindDays; +} + +void +xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays ) { - return sx->manual; + sx->advanceRemindDays = reminderDays; } GDate @@ -300,6 +333,7 @@ xaccSchedXactionGetNextInstance( SchedXaction *sx ) } } +#if 0 if ( g_date_valid( &last_occur ) ) { g_date_set_time( &tmpDate, time(NULL) ); last_occur = @@ -309,6 +343,7 @@ xaccSchedXactionGetNextInstance( SchedXaction *sx ) } else { g_date_set_time( &last_occur, time(NULL) ); } +#endif // 0 if ( g_date_valid( &sx->start_date ) && ! g_date_valid( &sx->last_date ) ) { diff --git a/src/engine/SchedXaction.h b/src/engine/SchedXaction.h index bc98a733cc..98fdb4082f 100644 --- a/src/engine/SchedXaction.h +++ b/src/engine/SchedXaction.h @@ -56,29 +56,29 @@ * of the internal ledger] for this editing. **/ typedef struct gncp_SchedXaction { - gchar *name; + gchar *name; FreqSpec *freq; - GDate last_date; + GDate last_date; - GDate start_date; + GDate start_date; /* if end_date is invalid, then no end. */ - GDate end_date; + GDate end_date; /* if num_occurances_total == 0, then no limit */ - gint num_occurances_total; + gint num_occurances_total; /* reminaing occurances are as-of the 'last_date'. */ - gint num_occurances_remain; + gint num_occurances_remain; - /* If true, confirmation is required. - If false, then this can be created when due without - intervention. */ - gboolean manual; + gboolean autoCreateOption; + gboolean autoCreateNotify; + gint advanceCreateDays; + gint advanceRemindDays; - GList *templateSplits; + GList *templateSplits; - GUID guid; + GUID guid; kvp_frame *kvp_data; } SchedXaction; @@ -136,8 +136,14 @@ void xaccSchedXactionSetRemOccur( SchedXaction *sx, gint numRemain ); GList *xaccSchedXactionGetSplits( SchedXaction *sx ); void xaccSchedXactionSetSplits( SchedXaction *sx, GList *newSplits ); -gboolean xaccSchedXactionGetManual( SchedXaction *sx ); -void xaccSchedXactionSetManual( SchedXaction *sx, gboolean newManual ); +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 ); + +gint xaccSchedXactionGetAdvanceReminder( SchedXaction *sx ); +void xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays ); #if 0 #error vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv diff --git a/src/engine/gnc-schedxaction-xml-v2.c b/src/engine/gnc-schedxaction-xml-v2.c index bbd8560433..326b9d53e1 100644 --- a/src/engine/gnc-schedxaction-xml-v2.c +++ b/src/engine/gnc-schedxaction-xml-v2.c @@ -52,7 +52,10 @@ * * ... * Rent - * f + * y + * n + * 0 + * 5 * * 2001-02-28 * @@ -118,13 +121,21 @@ gnc_schedXaction_dom_tree_create(SchedXaction *sx) xmlNewTextChild( ret, NULL, "sx:name", xaccSchedXactionGetName(sx) ); - xmlNewTextChild( ret, NULL, "sx:manual-conf", - (xaccSchedXactionGetManual(sx) == 1 ? "t" : "f") ); + //xmlNewTextChild( ret, NULL, "sx:manual-conf", + //(xaccSchedXactionGetManual(sx) == 1 ? "t" : "f") ); + + xmlNewTextChild( ret, NULL, "sx:autoCreate", + ( sx->autoCreateOption ? "y" : "n" ) ); + xmlNewTextChild( ret, NULL, "sx:autoCreateNotify", + ( sx->autoCreateNotify ? "y" : "n" ) ); + xml_add_gint32( ret, "sx:advanceCreateDays", sx->advanceCreateDays ); + xml_add_gint32( ret, "sx:advanceRemindDays", sx->advanceRemindDays ); + xmlAddChild( ret, gdate_to_dom_tree( "sx:start", xaccSchedXactionGetStartDate(sx) ) ); - date = xaccSchedXactionGetLastOccurDate(sx); + date = xaccSchedXactionGetLastOccurDate(sx); if ( g_date_valid( date ) ) { xmlAddChild( ret, gdate_to_dom_tree( "sx:last", date ) ); } @@ -176,13 +187,55 @@ static gboolean sx_name_handler( xmlNodePtr node, gpointer sx ) { - gchar *tmp = dom_tree_to_text( node ); + gchar *tmp = dom_tree_to_text( node ); g_return_val_if_fail( tmp, FALSE ); xaccSchedXactionSetName( (SchedXaction*)sx, tmp ); g_free( tmp ); return TRUE; } +static gboolean +sx_autoCreate_handler( xmlNodePtr node, gpointer sx ) +{ + gchar *tmp = dom_tree_to_text( node ); + ((SchedXaction*)sx)->autoCreateOption = (safe_strcmp( tmp, "y" ) == 0 ? TRUE : FALSE ); + return TRUE; +} + +static gboolean +sx_notify_handler( xmlNodePtr node, gpointer sx ) +{ + gchar *tmp = dom_tree_to_text( node ); + ((SchedXaction*)sx)->autoCreateNotify = (safe_strcmp( tmp, "y" ) == 0 ? TRUE : FALSE ); + return TRUE; +} + +static gboolean +sx_advCreate_handler( xmlNodePtr node, gpointer sx ) +{ + gint64 advCreate; + + if ( ! dom_tree_to_integer( node, &advCreate ) ) { + return FALSE; + } + + xaccSchedXactionSetAdvanceCreation( (SchedXaction*)sx, advCreate ); + return TRUE; +} + +static gboolean +sx_advRemind_handler( xmlNodePtr node, gpointer sx ) +{ + gint64 advRemind; + + if ( ! dom_tree_to_integer( node, &advRemind ) ) { + return FALSE; + } + + xaccSchedXactionSetAdvanceReminder( (SchedXaction*)sx, advRemind ); + return TRUE; +} + static gboolean sx_set_date( xmlNodePtr node, SchedXaction *sx, @@ -236,6 +289,7 @@ sx_freqspec_handler( xmlNodePtr node, gpointer sx ) return TRUE; } +#if 0 static gboolean sx_manualConf_handler( xmlNodePtr node, gpointer sx ) @@ -251,6 +305,7 @@ sx_manualConf_handler( xmlNodePtr node, gpointer sx ) g_free(tmp); return TRUE; } +#endif //0 static gboolean @@ -291,16 +346,19 @@ sx_slots_handler( xmlNodePtr node, gpointer sx ) } struct dom_tree_handler sx_dom_handlers[] = { - { "sx:id", sx_id_handler, 1, 0 }, - { "sx:name", sx_name_handler, 1, 0 }, - { "sx:start", sx_start_handler, 1, 0 }, - { "sx:last", sx_last_handler, 0, 0 }, - { "sx:manual-conf", sx_manualConf_handler, 1, 0 }, - { "sx:num-occur", sx_numOccur_handler, 0, 0 }, - { "sx:rem-occur", sx_remOccur_handler, 0, 0 }, - { "sx:end", sx_end_handler, 0, 0 }, - { "sx:freqspec", sx_freqspec_handler, 1, 0 }, - { "sx:slots", sx_slots_handler, 0, 0 }, + { "sx:id", sx_id_handler, 1, 0 }, + { "sx:name", sx_name_handler, 1, 0 }, + { "sx:autoCreate", sx_autoCreate_handler, 1, 0 }, + { "sx:autoCreateNotify", sx_notify_handler, 1, 0 }, + { "sx:advanceCreateDays", sx_advCreate_handler, 1, 0 }, + { "sx:advanceRemindDays", sx_advRemind_handler, 1, 0 }, + { "sx:start", sx_start_handler, 1, 0 }, + { "sx:last", sx_last_handler, 0, 0 }, + { "sx:num-occur", sx_numOccur_handler, 0, 0 }, + { "sx:rem-occur", sx_remOccur_handler, 0, 0 }, + { "sx:end", sx_end_handler, 0, 0 }, + { "sx:freqspec", sx_freqspec_handler, 1, 0 }, + { "sx:slots", sx_slots_handler, 0, 0 }, }; static gboolean diff --git a/src/gnome/Makefile.am b/src/gnome/Makefile.am index 42f718af3b..9b9553e68a 100644 --- a/src/gnome/Makefile.am +++ b/src/gnome/Makefile.am @@ -59,7 +59,8 @@ libgncgnome_a_SOURCES = \ window-reconcile.c \ window-register.c \ window-report.c \ - dialog-nextrun.c + dialog-nextrun.c \ + dialog-sxsincelast.c gnomeappdir = ${datadir}/gnome/apps/Applications @@ -119,7 +120,8 @@ noinst_HEADERS = \ window-reconcile.h \ window-register.h \ window-report.h \ - dialog-nextrun.h + dialog-nextrun.h \ + dialog-sxsincelast.h EXTRA_DIST = \ .cvsignore \ diff --git a/src/gnome/dialog-nextrun.c b/src/gnome/dialog-nextrun.c index d97570dba0..0554f6238e 100644 --- a/src/gnome/dialog-nextrun.c +++ b/src/gnome/dialog-nextrun.c @@ -44,16 +44,16 @@ static short module = MOD_SX; typedef struct _toCreateTransaction { - SchedXaction *sx; - GDate *date; + SchedXaction *sx; + GDate *date; - gint clistRow; + gint clistRow; } toCreateTransaction; typedef struct _sxSinceLastData { - GtkWidget *nextrunDlg; - GladeXML *gxml; - GList /* */ *transList; + GtkWidget *nextrunDlg; + GladeXML *gxml; + GList /* */ *transList; } sxSinceLastData; static void nextrun_init( sxSinceLastData *sxsld ); @@ -69,6 +69,12 @@ static void slr_create_transactions( SchedXaction *sx, GDate *gd ); /* int parse_vars_from_formula( const char *formula, GHashTable *varHash ); */ +void +gnc_ui_nextrun_guile_wrapper( char *foo ) +{ + gnc_ui_nextrun_dialog_create(); +} + void gnc_ui_nextrun_dialog_create(void) { @@ -200,6 +206,7 @@ nr_next_clicked( GtkButton *b, gpointer ud ) return; } + /* FIXME: This is actually a non-changeable date. */ endDate = g_date_new(); g_date_set_time( endDate, gdeDate ); @@ -207,46 +214,37 @@ nr_next_clicked( GtkButton *b, gpointer ud ) cl = GTK_CLIST(o); gtk_clist_clear( cl ); - gd = *g_date_new(); + g_date_clear( &gd, 1 ); row = 0; do { sx = (SchedXaction*)sxList->data; + /* this is really "last-run-date", right? */ g_date_set_time( &gd, time(NULL) ); - do { + + gd = xaccSchedXactionGetNextInstance( sx ); + while ( g_date_compare( &gd, endDate ) <= 0 + && g_date_valid( &gd ) ) { + + g_date_strftime( buf, 1023, "%a, %b %e, %Y", &gd ); + /* add to clist [ahem... register... ahem] */ + rowText[0] = xaccSchedXactionGetName( sx ); + rowText[1] = malloc( sizeof(char) * 256 ); /* FIXME */ + g_date_strftime( rowText[1], 255, "%a, %b %e, %Y", &gd ); + + tct = g_new0( toCreateTransaction, 1 ); + tct->sx = sx; + tct->date = g_date_new(); + *tct->date = gd; + tct->clistRow = row; + sxsld->transList = g_list_append( sxsld->transList, tct ); + + gtk_clist_insert( cl, row, rowText ); + row += 1; gd = xaccSchedXactionGetInstanceAfter( sx, &gd ); - if ( g_date_valid( &gd ) ) { - - g_date_strftime( buf, 1023, "%c", &gd ); - /* add to clist [ahem... register... ahem] */ - rowText[0] = xaccSchedXactionGetName( sx ); - rowText[1] = malloc( sizeof(char) * 256 ); /* FIXME */ - g_date_strftime( rowText[1], 255, "%c", &gd ); - - tct = g_new0( toCreateTransaction, 1 ); - tct->sx = sx; - tct->date = g_date_new(); - *tct->date = gd; - tct->clistRow = row; - sxsld->transList = g_list_append( sxsld->transList, tct ); - - gtk_clist_insert( cl, row, rowText ); - row += 1; - } - } while ( g_date_compare( &gd, endDate ) <= 0 - && g_date_valid( &gd ) ); + } } while ( (sxList = sxList->next) ); -#if 0 - sxList = sxsld->transList; - do { - char buf[128]; - g_date_strftime( buf, 127, "%c", - ((toCreateTransaction*)sxList->data)->date ); - DEBUG( "List contains sx \"%s\" on date \"%s\"\n", - xaccSchedXactionGetName( ((toCreateTransaction*)sxList->data)->sx ), - buf ); - } while ( (sxList = sxList->next) ); -#endif /* 0 */ + g_date_free( endDate ); } static void @@ -304,10 +302,9 @@ create_each_transaction( Transaction *t, void *d ) } do { split = (Split*)sList->data; - /* Ick. This assumes that the split lists will be - ordered identically. :( I think it's fair to say - they will, but I'd rather not have to count on - it. --jsled */ + /* FIXME: Ick. This assumes that the split lists will be + ordered identically. :( I think it's fair to say they + will, but I'd rather not have to count on it. --jsled */ split_kvpf = xaccSplitGetSlots( (Split*)osList->data ); DEBUG( "\tProcessing Split \"%s\"\n", @@ -374,8 +371,7 @@ create_each_transaction( Transaction *t, void *d ) str, gnc_numeric_to_string( debit_num ) ); } - final = gnc_numeric_sub_fixed( debit_num, - credit_num ); + final = gnc_numeric_sub_fixed( credit_num, debit_num ); gncn_error = gnc_numeric_check( final ); if ( gncn_error != GNC_ERROR_OK ) { @@ -383,8 +379,8 @@ create_each_transaction( Transaction *t, void *d ) errFlag = TRUE; break; } - printf( "gnc_numeric::final: \"%s\"\n", - gnc_numeric_to_string( final ) ); + DEBUG( "gnc_numeric::final: \"%s\"\n", + gnc_numeric_to_string( final ) ); xaccSplitSetValue( split, final ); } #if 0 @@ -394,7 +390,7 @@ create_each_transaction( Transaction *t, void *d ) } while ( (sList = sList->next) && (osList = osList->next) ); if ( errFlag ) { - printf( "Some error in newT creation\n" ); + PERR( "Some error in new transaction creation...\n" ); xaccTransRollbackEdit( newT ); } else { xaccTransCommitEdit( newT ); @@ -415,8 +411,8 @@ slr_create_transactions( SchedXaction *sx, GDate *gd ) ag = gnc_book_get_template_group( gncGetCurrentBook() ); id = guid_to_string( xaccSchedXactionGetGUID(sx) ); acct = xaccGetAccountFromName( ag, id ); - printf( "Got account \"%s\"\n", - xaccAccountGetName( acct ) ); + DEBUG( "Got account \"%s\"\n", + xaccAccountGetName( acct ) ); g_free( id ); xaccAccountForEachTransaction( acct, @@ -447,17 +443,17 @@ parse_vars_from_formula( const char *formula, GHashTable *varHash ) gnc_exp_parser_init(); if ( ! gnc_exp_parser_parse( formula, &num_foo, &foo ) ) { - printf( "Error parsing at \"%s\": %s\n", + PERR( "Error parsing at \"%s\": %s\n", foo, gnc_exp_parser_error_string() ); } - printf( "Successful parse...\n" ); + PINFO( "Successful parse...\n" ); list = gnc_exp_parser_get_variable_names(); if ( list == NULL ) { - printf( "NULL variable list\n" ); + PINFO( "NULL variable list\n" ); } else { do { - printf( "Variable \"%s\"\n", - list->data ); + PINFO( "Variable \"%s\"\n", + list->data ); } while ( (list = list->next) ); } diff --git a/src/gnome/dialog-nextrun.h b/src/gnome/dialog-nextrun.h index b6d2f602f8..ce524f3c75 100644 --- a/src/gnome/dialog-nextrun.h +++ b/src/gnome/dialog-nextrun.h @@ -24,5 +24,6 @@ #define DIALOG_NEXTRUN_H void gnc_ui_nextrun_dialog_create( void ); +void gnc_ui_nextrun_guile_wrapper( char* ); #endif diff --git a/src/gnome/dialog-scheduledxaction.c b/src/gnome/dialog-scheduledxaction.c index a4925f592e..4958fbb22d 100644 --- a/src/gnome/dialog-scheduledxaction.c +++ b/src/gnome/dialog-scheduledxaction.c @@ -1,6 +1,6 @@ /********************************************************************\ * dialog-scheduledxaction.c : dialog for scheduled transaction * - * editor * + * list and editor * * Copyright (C) 2001 Joshua Sled * * * * This program is free software; you can redistribute it and/or * @@ -107,11 +107,12 @@ static void schedXact_editor_populate( SchedXactionEditorDialog * ); static void new_button_clicked( GtkButton *b, gpointer d ); static void edit_button_clicked( GtkButton *b, gpointer d ); static void delete_button_clicked( GtkButton *b, gpointer d ); -static void ok_button_clicked( GtkButton *b, gpointer d ); -static void cancel_button_clicked( GtkButton *b, gpointer d ); +static void close_button_clicked( GtkButton *b, gpointer d ); static void endgroup_rb_toggled( GtkButton *b, gpointer d ); static void set_endgroup_toggle_states( SchedXactionEditorDialog *sxed, EndType t ); +static void advance_toggle( GtkButton *b, SchedXactionEditorDialog *sxed ); + /* ledger standard-handlers */ static void sxe_ledger_destroy( xaccLedgerDisplay *ld ); @@ -156,19 +157,11 @@ sxed_close_handler ( gpointer user_data ) static void -ok_button_clicked( GtkButton *b, gpointer d ) +close_button_clicked( GtkButton *b, gpointer d ) { sxd_close_handler( d ); } -static -void -cancel_button_clicked( GtkButton *b, gpointer d ) -{ - /* FIXME. */ - gnc_close_gui_component_by_data( DIALOG_SCHEDXACTION_CM_CLASS, d ); -} - static void editor_close_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed ) @@ -181,13 +174,13 @@ static void editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed ) { - GNCBook *book; - GtkWidget *o, *o2, *o3; - GList *sxList; - FreqSpec *fs; - gint row; - time_t tmpDate; - GDate *gdate; + GNCBook *book; + GtkWidget *o, *o2, *o3; + GList *sxList; + FreqSpec *fs; + gint row; + time_t tmpDate; + GDate *gdate; gdate = g_date_new(); @@ -220,10 +213,43 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed ) } else { PERR( "No valid end specified\n" ); } - /* manual conf */ - o = glade_xml_get_widget( sxed->gxml, "manual_conf" ); - xaccSchedXactionSetManual( sxed->sx, - gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ); + + { + gboolean autocreateState, notifyState; + + o = glade_xml_get_widget( sxed->gxml, "autocreate_opt" ); + autocreateState = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ); + o = glade_xml_get_widget( sxed->gxml, "notify_opt" ); + notifyState = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ); + + /* "Notify" only makes sense if AutoCreate is actived; + enforce that here. */ + xaccSchedXactionSetAutoCreate( sxed->sx, + autocreateState, + (autocreateState & notifyState) ); + } + + { + int daysInAdvance; + + daysInAdvance = 0; + o = glade_xml_get_widget( sxed->gxml, "advance_opt" ); + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ) { + o = glade_xml_get_widget( sxed->gxml, "advance_days" ); + daysInAdvance = + gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(o) ); + } + xaccSchedXactionSetAdvanceCreation( sxed->sx, daysInAdvance ); + + daysInAdvance = 0; + o = glade_xml_get_widget( sxed->gxml, "remind_opt" ); + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ) { + o = glade_xml_get_widget( sxed->gxml, "remind_days" ); + daysInAdvance = + gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON(o) ); + } + xaccSchedXactionSetAdvanceReminder( sxed->sx, daysInAdvance ); + } /* get the frequency spec data */ fs = xaccSchedXactionGetFreqSpec( sxed->sx ); @@ -249,6 +275,32 @@ editor_ok_button_clicked( GtkButton *b, SchedXactionEditorDialog *sxed ) sxed_close_handler( (gpointer)sxed ); } +static void +autocreate_toggled( GtkObject *o, SchedXactionEditorDialog *sxed ) +{ + GtkWidget *notifyCheck; + + notifyCheck = glade_xml_get_widget( sxed->gxml, "notify_opt" ); + gtk_widget_set_sensitive( notifyCheck, + gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ); +} + +static void +advance_toggle( GtkButton *o, SchedXactionEditorDialog *sxed ) +{ + gchar *spinName; + GtkWidget *spin; + + spinName = (gchar*)gtk_object_get_data( GTK_OBJECT(o), "whichOneAmI" ); + spin = glade_xml_get_widget( sxed->gxml, spinName ); + if ( !spin ) { + PERR( "Error getting widget with name \"%s\"", spinName ); + return; + } + gtk_widget_set_sensitive( spin, + gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(o) ) ); +} + /* Local destruction of dialog */ static void scheduledxaction_dialog_destroy(GtkObject *object, gpointer data) @@ -326,17 +378,10 @@ gnc_ui_scheduled_xaction_dialog_create(void) button = glade_xml_get_widget( sxd->gxml, "delete_button" ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(delete_button_clicked), sxd ); - button = glade_xml_get_widget( sxd->gxml, "ok_button" ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(ok_button_clicked), sxd ); - button = glade_xml_get_widget( sxd->gxml, "cancel_button" ); + button = glade_xml_get_widget( sxd->gxml, "close_button" ); gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(cancel_button_clicked), sxd ); - /* turn off the cancel button, for now, as we have no way to cancel. */ - gtk_widget_set_sensitive( GTK_WIDGET(button), FALSE ); + GTK_SIGNAL_FUNC(close_button_clicked), sxd ); - /* Set the clist columns to auto-resize. */ - schedXact_populate( sxd ); gtk_widget_show(sxd->dialog); @@ -416,8 +461,30 @@ SchedXactionEditorDialog * gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd, SchedXaction *sx ) { - SchedXactionEditorDialog *sxed; - GtkWidget *button; + SchedXactionEditorDialog *sxed; + GtkWidget *button; + int i; + + static struct widgetSignalCallback { + char *name; + char *signal; + void (*fn)(); + gpointer objectData; + } widgets[] = { + { "ok_button", "clicked", editor_ok_button_clicked, NULL }, + { "cancel_button", "clicked", editor_close_button_clicked, NULL }, + + { "rb_enddate", "toggled", endgroup_rb_toggled, (gpointer)END_OPTION }, + { "rb_num_occur", "toggled", endgroup_rb_toggled, (gpointer)NUM_OCCUR_OPTION }, + + { "autocreate_opt", "toggled", autocreate_toggled, NULL }, + { "advance_opt", "toggled", advance_toggle, (gpointer)"advance_days" }, + { "remind_opt", "toggled", advance_toggle, (gpointer)"remind_days" }, + + { "rec_button", "clicked", sxed_reg_recordCB, NULL }, + + { NULL, NULL, NULL, NULL } + }; sxed = g_new0( SchedXactionEditorDialog, 1 ); @@ -441,30 +508,26 @@ gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd, sxed); /* FIXME: want delete-event, too. */ - button = glade_xml_get_widget( sxed->gxml, "ok_button" ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(editor_ok_button_clicked), sxed); - - button = glade_xml_get_widget( sxed->gxml, "cancel_button" ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(editor_close_button_clicked), sxed); + for ( i=0; widgets[i].name != NULL; i++ ) { + button = glade_xml_get_widget( sxed->gxml, widgets[i].name ); + if ( widgets[i].objectData != NULL ) { + gtk_object_set_data( GTK_OBJECT(button), + "whichOneAmI", + widgets[i].objectData ); + } + gtk_signal_connect( GTK_OBJECT(button), + widgets[i].signal, + GTK_SIGNAL_FUNC( widgets[i].fn ), sxed ); + } - button = glade_xml_get_widget( sxed->gxml, "ok_button" ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(editor_close_button_clicked), sxed ); - - button = glade_xml_get_widget( sxed->gxml, "rb_enddate" ); - gtk_object_set_data( GTK_OBJECT(button), "whichOneAmI", (gpointer)END_OPTION ); - gtk_signal_connect( GTK_OBJECT(button), "toggled", - GTK_SIGNAL_FUNC(endgroup_rb_toggled), sxed ); - button = glade_xml_get_widget( sxed->gxml, "rb_num_occur" ); - gtk_object_set_data( GTK_OBJECT(button), "whichOneAmI", (gpointer)NUM_OCCUR_OPTION ); - gtk_signal_connect( GTK_OBJECT(button), "toggled", - GTK_SIGNAL_FUNC(endgroup_rb_toggled), sxed ); - - button = glade_xml_get_widget( sxed->gxml, "rec_button" ); - gtk_signal_connect( GTK_OBJECT(button), "clicked", - GTK_SIGNAL_FUNC(sxed_reg_recordCB), sxed ); + /* FIXME: For some reason the Glade-specified sensitivity settings + are not being honored. */ + button = glade_xml_get_widget( sxed->gxml, "notify_opt" ); + gtk_widget_set_sensitive( button, FALSE ); + button = glade_xml_get_widget( sxed->gxml, "advance_days" ); + gtk_widget_set_sensitive( button, FALSE ); + button = glade_xml_get_widget( sxed->gxml, "remind_days" ); + gtk_widget_set_sensitive( button, FALSE ); /* create the frequency-selection macrowidget */ schedXact_editor_create_freq_sel( sxed ); @@ -619,7 +682,7 @@ schedXact_editor_create_ledger( SchedXactionEditorDialog *sxed ) gnc_table_init_gui( regWidget, splitreg ); gtk_container_add( GTK_CONTAINER(glade_xml_get_widget( sxed->gxml, - "vbox124" )), + "register_vbox" )), regWidget ); sxed->reg = GNUCASH_REGISTER(regWidget); @@ -660,7 +723,7 @@ schedXact_editor_populate( SchedXactionEditorDialog *sxed ) GnomeDateEdit *gde; SplitRegister *splitReg; GList *splitList; - GtkWidget *o; + GtkWidget *w; GString *tmpgStr; struct tm *tmpTm; GDate *gd; @@ -672,35 +735,65 @@ schedXact_editor_populate( SchedXactionEditorDialog *sxed ) } gd = xaccSchedXactionGetEndDate( sxed->sx ); if ( g_date_valid( gd ) ) { - o = glade_xml_get_widget( sxed->gxml, "rb_enddate" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(o), TRUE ); + w = glade_xml_get_widget( sxed->gxml, "rb_enddate" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), TRUE ); /* fill in date data. */ - o = glade_xml_get_widget( sxed->gxml, "sxe_end_date" ); + w = glade_xml_get_widget( sxed->gxml, "sxe_end_date" ); tmpTm = g_new0( struct tm, 1 ); g_date_to_struct_tm( gd, tmpTm ); tmpDate = mktime( tmpTm ); g_free( tmpTm ); - gnome_date_edit_set_time( GNOME_DATE_EDIT(o), tmpDate ); + gnome_date_edit_set_time( GNOME_DATE_EDIT(w), tmpDate ); set_endgroup_toggle_states( sxed, END_DATE ); } else if ( xaccSchedXactionGetNumOccur( sxed->sx ) != -1 ) { - o = glade_xml_get_widget( sxed->gxml, "rb_num_occur" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(o), TRUE ); - o = glade_xml_get_widget( sxed->gxml, "end_nentry" ); - o = gnome_number_entry_gtk_entry( GNOME_NUMBER_ENTRY(o) ); + w = glade_xml_get_widget( sxed->gxml, "rb_num_occur" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), TRUE ); + w = glade_xml_get_widget( sxed->gxml, "end_nentry" ); + w = gnome_number_entry_gtk_entry( GNOME_NUMBER_ENTRY(w) ); tmpgStr = g_string_sized_new(5); g_string_sprintf( tmpgStr, "%d", xaccSchedXactionGetNumOccur( sxed->sx ) ); - gtk_entry_set_text( GTK_ENTRY(o), tmpgStr->str ); + gtk_entry_set_text( GTK_ENTRY(w), tmpgStr->str ); g_string_free( tmpgStr, TRUE ); set_endgroup_toggle_states( sxed, END_OCCUR ); } else { - o = glade_xml_get_widget( sxed->gxml, "rb_noend" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(o), TRUE ); + w = glade_xml_get_widget( sxed->gxml, "rb_noend" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), TRUE ); set_endgroup_toggle_states( sxed, END_NONE ); } - o = glade_xml_get_widget( sxed->gxml, "manual_conf" ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(o), - xaccSchedXactionGetManual( sxed->sx ) ); + { + gboolean autoCreateState, notifyState; + + xaccSchedXactionGetAutoCreate( sxed->sx, &autoCreateState, ¬ifyState ); + w = glade_xml_get_widget( sxed->gxml, "autocreate_opt" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), autoCreateState ); + w = glade_xml_get_widget( sxed->gxml, "notify_opt" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), notifyState ); + } + { + gint daysInAdvance; + + daysInAdvance = + xaccSchedXactionGetAdvanceCreation( sxed->sx ); + if ( daysInAdvance != 0 ) { + w = glade_xml_get_widget( sxed->gxml, "advance_opt" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), TRUE ); + w = glade_xml_get_widget( sxed->gxml, "advance_days" ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), + (gfloat)daysInAdvance ); + } + + daysInAdvance = + xaccSchedXactionGetAdvanceReminder( sxed->sx ); + if ( daysInAdvance != 0 ) { + w = glade_xml_get_widget( sxed->gxml, "remind_opt" ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(w), TRUE ); + w= glade_xml_get_widget( sxed->gxml, "remind_days" ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), + (gfloat)daysInAdvance ); + } + + } /* populate the ledger */ { diff --git a/src/gnome/dialog-scheduledxaction.h b/src/gnome/dialog-scheduledxaction.h index 53d554cc98..f0410f6789 100644 --- a/src/gnome/dialog-scheduledxaction.h +++ b/src/gnome/dialog-scheduledxaction.h @@ -1,5 +1,5 @@ /********************************************************************\ - * dialog-scheduledxaction.h : dialogs for a scheduled transactions * + * dialog-scheduledxaction.h : dialogs for scheduled transactions * * Copyright (C) 2001 Joshua Sled * * * * This program is free software; you can redistribute it and/or * diff --git a/src/gnome/dialog-sxsincelast.c b/src/gnome/dialog-sxsincelast.c new file mode 100644 index 0000000000..5ee4ff7e12 --- /dev/null +++ b/src/gnome/dialog-sxsincelast.c @@ -0,0 +1,766 @@ +/********************************************************************\ + * dialog-sxsincelast.c - "since last run" dialog. * + * Copyright (c) 2001 Joshua Sled * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +#include "config.h" + +#include +#include + +#include "gnc-engine-util.h" +#include "FileDialog.h" +#include "gnc-book.h" +#include "Transaction.h" +#include "Group.h" +#include "gnc-numeric.h" +#include "SchedXaction.h" +#include "gnc-component-manager.h" +#include "SplitLedger.h" +#include "gnc-ui-util.h" +#include "gnc-exp-parser.h" +#include "dialog-utils.h" + +#include "dialog-sxsincelast.h" + +#define DIALOG_SXSINCELAST_CM_CLASS "dialog-sxsincelast" + +static short module = MOD_SX; + +typedef struct _toCreateTransaction { + SchedXaction *sx; + GDate *date; + + gint clistRow; +} toCreateTransaction; + +typedef struct _sxSinceLastData { + GtkWidget *sxsincelastDlg; + GladeXML *gxml; + GList /* */ *transList; +} sxSinceLastData; + +typedef struct _reminderTuple { + GDate *endDate; + GDate *occurDate; +} reminderTuple; + +static void sxsincelast_init( sxSinceLastData *sxsld ); +static void sxsincelast_populate( sxSinceLastData *sxsld ); +static void sxsincelast_close_handler( gpointer ud ); +static void sxsincelast_ok_clicked( GtkButton *b, gpointer ud ); +static void sxsincelast_cancel_clicked( GtkButton *b, gpointer ud ); + +static void sxsincelast_destroy( GtkObject *o, gpointer ud ); + +static void _create_transactions_on( SchedXaction *sx, GDate *gd ); + +static void processAutoCreateList( GList *, sxSinceLastData *sxsld, SchedXaction * ); +static void processToCreateList( GList *, sxSinceLastData *sxsld, SchedXaction * ); +static void processReminderList( GList *, sxSinceLastData *sxsld, SchedXaction * ); + +/* int parse_vars_from_formula( const char *formula, GHashTable *varHash ); */ + +void +gnc_ui_sxsincelast_guile_wrapper( char *foo ) +{ + gnc_ui_sxsincelast_dialog_create(); +} + +void +gnc_ui_sxsincelast_dialog_create(void) +{ + sxSinceLastData *sxsld = g_new0( sxSinceLastData, 1 ); + sxsld->gxml = gnc_glade_xml_new( "sched-xact.glade", "Real Since-Last-Run Dialog" ); + sxsld->sxsincelastDlg = glade_xml_get_widget( sxsld->gxml, "Real Since-Last-Run Dialog" ); + + sxsincelast_init( sxsld ); +} + +static void +sxsincelast_init( sxSinceLastData *sxsld ) +{ + GtkWidget *o; + int i; + struct widgetSignalHandlerTuple { + char *name; + char *signal; + void (*handlerFn)(); + } widgets[] = { + { "ok_button", "clicked", sxsincelast_ok_clicked }, + { "cancel_button", "clicked", sxsincelast_cancel_clicked }, + { NULL, NULL, NULL } + }; + + gnc_register_gui_component( DIALOG_SXSINCELAST_CM_CLASS, + NULL, + sxsincelast_close_handler, + sxsld->sxsincelastDlg ); + + gtk_signal_connect( GTK_OBJECT(sxsld->sxsincelastDlg), "destroy", + GTK_SIGNAL_FUNC( sxsincelast_destroy ), sxsld ); + + for ( i=0; widgets[i].name != NULL ; i++ ) { + o = glade_xml_get_widget( sxsld->gxml, widgets[i].name ); + gtk_signal_connect( GTK_OBJECT(o), widgets[i].signal, + GTK_SIGNAL_FUNC(widgets[i].handlerFn), + sxsld ); + + } + + sxsincelast_populate( sxsld ); + + gtk_widget_show_all( sxsld->sxsincelastDlg ); +} + +static void +_generate_instances( SchedXaction *sx, + GDate *end, + GList **instanceList ) +{ + GDate gd, *gdToReturn; + char tmpBuf[26]; + + gd = xaccSchedXactionGetNextInstance( sx ); + while ( g_date_valid(&gd) + && g_date_compare( &gd, end ) <= 0 ) { + + g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", &gd ); + DEBUG( "Adding instance %s", tmpBuf ); + + gdToReturn = g_date_new(); + *gdToReturn = gd; + *instanceList = g_list_append( *instanceList, gdToReturn ); + + gd = xaccSchedXactionGetInstanceAfter( sx, &gd ); + } + if ( ! g_date_valid( &gd ) ) { + PERR( "Should be added to dead-list..." ); + } +} + +static void +_free_gdate_list_elts( gpointer data, gpointer user_data ) +{ + g_date_free( (GDate*)data ); +} + +static void +_free_reminderTuple_list_elts( gpointer data, gpointer user_data ) +{ + g_date_free( ((reminderTuple*)data)->occurDate ); + g_free( (reminderTuple*)data ); +} + +static void +processAutoCreateList( GList *autoCreateList, sxSinceLastData *sxsld, SchedXaction *sx ) +{ + char tmpBuf[26]; + int row; + GtkCList *cl; + gboolean autoCreateState, notifyState; + char *rowText[2]; + + row = 0; + + /* + get the "automagically created and notification requested" + register, and create the entires. + For now, this is a clist... + */ + cl = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "auto_create_clist" ) ); + gtk_clist_freeze( cl ); + while ( autoCreateList ) { + g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", + (GDate*)autoCreateList->data ); + xaccSchedXactionGetAutoCreate( sx, &autoCreateState, ¬ifyState ); + + _create_transactions_on( sx, (GDate*)autoCreateList->data ); + + if ( notifyState ) { + rowText[0] = xaccSchedXactionGetName( sx ); + rowText[1] = malloc( sizeof(gchar) * 26 ); /* FIXME */ + g_date_strftime( rowText[1], 25, "%a, %b %e, %Y", + (GDate*)autoCreateList->data ); + gtk_clist_insert( cl, row++, rowText ); + } + + autoCreateList = autoCreateList->next; + } + gtk_clist_thaw( cl ); + +} + +static void +processToCreateList( GList *toCreateList, sxSinceLastData *sxsld, SchedXaction *sx ) +{ + GtkCList *clist; + int row; + char *rowText[2]; + + row = 0; + if ( toCreateList == NULL ) + return; + + clist = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "to_create_clist" ) ); + do { + /* add to clist [ahem... register... ahem] */ + rowText[0] = xaccSchedXactionGetName( sx ); + rowText[1] = malloc( sizeof(char) * 25 ); /* FIXME */ + g_date_strftime( rowText[1], 25, "%a, %b %e, %Y", (GDate*)toCreateList->data ); + gtk_clist_insert( clist, row++, rowText ); + } while ( (toCreateList = toCreateList->next) ); +} + +static void +processReminderList( GList *reminderList, sxSinceLastData *sxsld, SchedXaction *sx ) +{ + GtkCList *clist; + int row; + char *rowText[3]; + reminderTuple *rt; + + /* . need + . orig end date + . this instance date + . sx + */ + + row = 0; + + if ( reminderList == NULL ) + return; + + clist = GTK_CLIST( glade_xml_get_widget( sxsld->gxml, "reminders_clist" ) ); + + do { + rt = (reminderTuple*)reminderList->data; + /* add to clist [ahem... register... ahem] */ + rowText[0] = xaccSchedXactionGetName( sx ); + rowText[1] = malloc( sizeof(gchar) * 25 ); /* FIXME */ + g_date_strftime( rowText[1], 25, "%a, %b %e, %Y", rt->occurDate ); + rowText[2] = malloc( sizeof(gchar) * 5 ); /* FIXME */ + sprintf( rowText[2], "%d", + (g_date_julian(rt->occurDate) - g_date_julian(rt->endDate)) ); + + gtk_clist_insert( clist, row++, rowText ); + } while ( (reminderList = reminderList->next) ); +} + + +static void +sxsincelast_populate( sxSinceLastData *sxsld ) +{ + + GList *sxList, *instanceList; + GList *autoCreateList, *toCreateList, *reminderList; + SchedXaction *sx; + GDate end, endPlusReminders; + GDate *instDate; + gint daysInAdvance; + gboolean autocreateState, notifyState; + gchar *rowText[3]; + GtkWidget *w; + gint autoCreateRow, toCreateRow, remindersRow; + reminderTuple *rt; + + autoCreateList = toCreateList = reminderList = NULL; + autoCreateRow = toCreateRow = remindersRow = 0; + + sxList = gnc_book_get_schedxactions( gncGetCurrentBook() ); + + if ( sxList == NULL ) { + DEBUG( "No scheduled transactions to populate." ); + } + + do { + sx = (SchedXaction*)sxList->data; + g_date_set_time( &end, time(NULL) ); + daysInAdvance = xaccSchedXactionGetAdvanceCreation( sx ); + g_date_add_days( &end, daysInAdvance ); + + endPlusReminders = end; + daysInAdvance = xaccSchedXactionGetAdvanceReminder( sx ); + g_date_add_days( &endPlusReminders, daysInAdvance ); + + + if (0) { + char tmpBuf[26]; + + g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", &end ); + DEBUG( "We'll generate the appropriate instances, now for " + "SX \"%s\" with end time %s...", + xaccSchedXactionGetName(sx), + tmpBuf ); + } + instanceList = NULL; + _generate_instances( sx, &endPlusReminders, &instanceList ); + + if ( instanceList == NULL ) + continue; + + xaccSchedXactionGetAutoCreate( sx, &autocreateState, ¬ifyState ); + do { + instDate = (GDate*)instanceList->data; + if ( 0 ) { + char tmpBuf[26]; + g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", instDate ); + DEBUG( "SX \"%s\" instance on %s", + xaccSchedXactionGetName(sx), tmpBuf ); + } + + if ( (g_date_compare( &end, &endPlusReminders ) != 0) + && (g_date_compare( &end, instDate ) <= 0) ) { + /* DEBUG( "\tIs a reminder" ); */ + rt = g_new0( reminderTuple, 1 ); + rt->endDate = &end; + rt->occurDate = instDate; + reminderList = g_list_append( reminderList, rt ); + } else { + if ( autocreateState ) { + /* DEBUG( "\tauto-create" ); */ + autoCreateList = g_list_append( autoCreateList, + instDate ); + } else { + /* DEBUG( "\tAdding to create list" ); */ + toCreateList = g_list_append( toCreateList, + instDate ); + } + } + } while ( (instanceList = instanceList->next) ); + + /* process the lists */ + processAutoCreateList( autoCreateList, sxsld, sx ); + processToCreateList ( toCreateList, sxsld, sx ); + processReminderList ( reminderList, sxsld, sx ); + + g_list_foreach( autoCreateList, _free_gdate_list_elts, NULL ); + g_list_free( autoCreateList ); + + g_list_foreach( reminderList, _free_reminderTuple_list_elts, NULL ); + g_list_free( reminderList ); + + /* FIXME: freeup the toCreate list at a more appropriate + time. */ + + } while ( (sxList = sxList->next) ); +} + +static void +sxsincelast_close_handler( gpointer ud ) +{ + gnome_dialog_close( GNOME_DIALOG( ((sxSinceLastData*)ud)->sxsincelastDlg ) ); +} + +static void +free_elts( gpointer data, gpointer user_data ) +{ + g_free( data ); +} + +static void +sxsincelast_ok_clicked( GtkButton *b, gpointer ud ) +{ + sxSinceLastData *sxsld; + GtkWidget *dlg; + GtkWidget *o; + GtkCList *cl; + time_t gdeDate; + GList *sxList; + GNCBook *book; + SchedXaction *sx; + GDate gd, *endDate; + gchar buf[1024]; + gint row; + char *rowText[2]; + toCreateTransaction *tct; + + + sxsld = (sxSinceLastData*)ud; + + sxsincelast_close_handler( sxsld ); + /* FIXME: the SX/date list already has been generated; we should use that. */ +#if 0 + o = glade_xml_get_widget( sxsld->gxml, "next_date" ); + gdeDate = gnome_date_edit_get_date( GNOME_DATE_EDIT(o) ); + + DEBUG( "Okay... I should run with a date of: %s", ctime(&gdeDate) ); + + /* destroy the previous transactions + destroy all the toCreateTransactions */ + if ( sxsld->transList != NULL ) { + g_list_foreach( sxsld->transList, free_elts, NULL ); + g_list_free( sxsld->transList ); + sxsld->transList = NULL; + } + + book = gncGetCurrentBook(); + sxList = gnc_book_get_schedxactions( book ); + if ( sxList == NULL ) { + PERR( "No scheduled transactions to play with\n" ); + return; + } + + endDate = g_date_new(); + g_date_set_time( endDate, gdeDate ); + + o = glade_xml_get_widget( sxsld->gxml, "replace_with_register" ); + cl = GTK_CLIST(o); + gtk_clist_clear( cl ); + + g_date_clear( &gd, 1 ); + row = 0; + do { + sx = (SchedXaction*)sxList->data; + // this is really "last-run-date", right? + g_date_set_time( &gd, time(NULL) ); + + gd = xaccSchedXactionGetInstanceAfter( sx, &gd ); + while ( g_date_compare( &gd, endDate ) <= 0 + && g_date_valid( &gd ) ) { + + g_date_strftime( buf, 1023, "%a, %b %e, %Y", &gd ); + /* add to clist [ahem... register... ahem] */ + rowText[0] = xaccSchedXactionGetName( sx ); + rowText[1] = malloc( sizeof(char) * 256 ); /* FIXME */ + g_date_strftime( rowText[1], 255, "%a, %b %e, %Y", &gd ); + + tct = g_new0( toCreateTransaction, 1 ); + tct->sx = sx; + tct->date = g_date_new(); + *tct->date = gd; + tct->clistRow = row; + sxsld->transList = g_list_append( sxsld->transList, tct ); + + gtk_clist_insert( cl, row, rowText ); + row += 1; + gd = xaccSchedXactionGetInstanceAfter( sx, &gd ); + } + } while ( (sxList = sxList->next) ); + + g_date_free( endDate ); +#endif +} + +static void +sxsincelast_cancel_clicked( GtkButton *o, gpointer ud ) +{ + sxsincelast_close_handler( ud ); +} + +static void +sxsincelast_destroy( GtkObject *o, gpointer ud ) +{ + DEBUG( "nuttin' doin...\n" ); +} + +static gboolean +_create_each_transaction( Transaction *t, void *d ) +{ + Transaction *newT; + GDate *gd; + GList *sList; + GList *osList; + Split *split; + kvp_frame *split_kvpf; + kvp_value *kvp_val; + gboolean errFlag; + + errFlag = FALSE; + + DEBUG( "I'm seeing Transaction \"%s\"", + xaccTransGetDescription( t ) ); + + gd = (GDate*)d; + + newT = xaccMallocTransaction(); + xaccTransBeginEdit( newT ); + /* the action and description/memo are in the template */ + gnc_copy_trans_onto_trans( t, newT, FALSE, FALSE ); + + /* the date is new [gd] */ + xaccTransSetDate( newT, + g_date_day( gd ), + g_date_month( gd ), + g_date_year( gd ) ); + + /* the accounts and amounts are in the kvp_frames of the splits. */ + osList = xaccTransGetSplitList( t ); + sList = xaccTransGetSplitList( newT ); + if ( (osList == NULL) || (sList == NULL) ) { + PERR( "\tseen transaction w/o splits. :(" ); + return FALSE; + } + do { + split = (Split*)sList->data; + /* FIXME: Ick. This assumes that the split lists will be + ordered identically. :( I think it's fair to say they + will, but I'd rather not have to count on it. --jsled */ + split_kvpf = xaccSplitGetSlots( (Split*)osList->data ); + + DEBUG( "\tProcessing Split \"%s\"", + xaccSplitGetMemo( split ) ); + + DEBUG( "\tkvp_frame: %s\n", + kvp_frame_to_string( split_kvpf ) ); + + + /* from-transaction of splits */ + { + GUID *acct_guid; + Account *acct; + /* contains the guid of the split's actual account. */ + kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/xfrm" ); + if ( kvp_val == NULL ) { + PERR( "Null kvp_val for xfrm" ); + } + acct_guid = kvp_value_get_guid( kvp_val ); + acct = xaccAccountLookup( acct_guid ); + DEBUG( "Got account with name \"%s\"", + xaccAccountGetName( acct ) ); + /* xaccSplitSetAccount( split, acct ); */ + xaccAccountInsertSplit( acct, split ); + } + /* credit/debit formulas */ + { + char *str; + gnc_numeric credit_num; + gnc_numeric debit_num; + gnc_numeric final; + int gncn_error; + + kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/credit_formula" ); + str = kvp_value_get_string( kvp_val ); + credit_num = gnc_numeric_create( 0, 1 ); + if ( str != NULL ) { + /* parse_vars_from_formula( str, NULL ); */ + + xaccParseAmount( str, TRUE, &credit_num, NULL ); + /* string_to_gnc_numeric( str, &credit_num ); */ + DEBUG( "gnc_numeric::credit: \"%s\" -> \"%s\"", + str, gnc_numeric_to_string( credit_num ) ); + } + + kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/debit_formula" ); + str = kvp_value_get_string( kvp_val ); + + debit_num = gnc_numeric_create( 0, 1 ); + if ( str != NULL ) { + /* parse_vars_from_formula( str, NULL ); */ + + xaccParseAmount( str, TRUE, &debit_num, NULL ); + /* string_to_gnc_numeric( str, &debit_num ); */ + DEBUG( "gnc_numeric::debit: \"%s\" -> \"%s\"", + str, gnc_numeric_to_string( debit_num ) ); + } + + final = gnc_numeric_sub_fixed( credit_num, debit_num ); + + gncn_error = gnc_numeric_check( final ); + if ( gncn_error != GNC_ERROR_OK ) { + PERR( "Error %d in final gnc_numeric value", gncn_error ); + errFlag = TRUE; + break; + } + DEBUG( "gnc_numeric::final: \"%s\"", + gnc_numeric_to_string( final ) ); + xaccSplitSetValue( split, final ); + } +#if 0 + kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/shares" ); + kvp_val = kvp_frame_get_slot( split_kvpf, "sched-xaction/amnt" ); +#endif /* 0 */ + } while ( (sList = sList->next) && (osList = osList->next) ); + + if ( errFlag ) { + PERR( "Some error in new transaction creation..." ); + xaccTransRollbackEdit( newT ); + } else { + xaccTransCommitEdit( newT ); + } + + return TRUE; + +} + +static void +_create_transactions_on( SchedXaction *sx, GDate *gd ) +{ + AccountGroup *ag; + Account *acct; + char *id; + char tmpBuf[26]; + + { + g_date_strftime( tmpBuf, 25, "%a, %b %e, %Y", gd ); + DEBUG( "Creating transactions on %s for %s", + tmpBuf, xaccSchedXactionGetName( sx ) ); + } + + ag = gnc_book_get_template_group( gncGetCurrentBook() ); + id = guid_to_string( xaccSchedXactionGetGUID(sx) ); + acct = xaccGetAccountFromName( ag, id ); + DEBUG( "Got account \"%s\"\n", + xaccAccountGetName( acct ) ); + g_free( id ); + + xaccAccountForEachTransaction( acct, + _create_each_transaction, + gd ); + xaccSchedXactionSetLastOccurDate( sx, gd ); + +} + +#if 0 + +/** + * Parses in-fix mathematical formulas using the standard operators + * [+-/%*], and '(', ')' grouping. + * + * Any strings are placed in the GHashTable as variables. The value of + * each key in the hash-table is a struct of the form: + * { const char *varStr; + * gint idx; + * gint len; }; + * + **/ +int +parse_vars_from_formula( const char *formula, GHashTable *varHash ) +{ + gnc_numeric num_foo; + char *foo; + GList *list; + + gnc_exp_parser_init(); + if ( ! gnc_exp_parser_parse( formula, &num_foo, &foo ) ) { + PERR( "Error parsing at \"%s\": %s\n", + foo, gnc_exp_parser_error_string() ); + } + PINFO( "Successful parse...\n" ); + list = gnc_exp_parser_get_variable_names(); + if ( list == NULL ) { + PINFO( "NULL variable list\n" ); + } else { + do { + PINFO( "Variable \"%s\"\n", + list->data ); + } while ( (list = list->next) ); + } + + gnc_exp_parser_shutdown(); +} +#endif /* 0 */ + +#if 0 + GScanner *varScanner; + GTokenType tok; + + varScanner = g_scanner_new( NULL ); + g_scanner_set_scope( varScanner, 0 ); + g_scanner_freeze_symbol_table( varScanner ); + g_scanner_scope_add_symbol( varScanner, 0, "(", (gpointer)"left-paren" ); + g_scanner_scope_add_symbol( varScanner, 0, ")", (gpointer)"right-paren" ); + g_scanner_scope_add_symbol( varScanner, 0, "+", (gpointer)"plus" ); + g_scanner_scope_add_symbol( varScanner, 0, "-", (gpointer)"minus" ); + g_scanner_scope_add_symbol( varScanner, 0, "/", (gpointer)"div" ); + g_scanner_scope_add_symbol( varScanner, 0, "*", (gpointer)"mult" ); + g_scanner_thaw_symbol_table( varScanner ); + + g_scanner_input_text( varScanner, formula, strlen( formula ) ); + + do { + tok = g_scanner_get_next_token( varScanner ); + printf( "tok: " ); + switch ( varScanner->token ) { + case G_TOKEN_EOF: + printf( "EOF" ); break; + case G_TOKEN_LEFT_PAREN: + printf( "(" ); break; + case G_TOKEN_RIGHT_PAREN: + printf( ")" ); break; + case G_TOKEN_LEFT_CURLY: + printf( "{" ); break; + case G_TOKEN_RIGHT_CURLY: + printf( "}" ); break; + case G_TOKEN_LEFT_BRACE: + printf( "[" ); break; + case G_TOKEN_RIGHT_BRACE: + printf( "]" ); break; + case G_TOKEN_EQUAL_SIGN: + printf( "=" ); break; + case G_TOKEN_COMMA: + printf( "," ); break; + case G_TOKEN_NONE: + printf( "NONE" ); break; + case G_TOKEN_ERROR: + printf( "ERROR(%d)", varScanner->value.v_error ); break; + case G_TOKEN_CHAR: + printf( "CHAR(%c)", varScanner->value.v_char ); break; + case G_TOKEN_BINARY: + printf( "BINARY" ); break; + case G_TOKEN_OCTAL: + printf( "OCTAL(%ul)", varScanner->value.v_octal ); break; + case G_TOKEN_INT: + printf( "INT(%ul)", varScanner->value.v_int ); break; + case G_TOKEN_HEX: + printf( "HEX(%ul)", varScanner->value.v_hex ); break; + case G_TOKEN_FLOAT: + printf( "FLOAT(%f)", varScanner->value.v_float ); break; + case G_TOKEN_STRING: + printf( "STRING(%s)", varScanner->value.v_string ); break; + case G_TOKEN_SYMBOL: + printf( "SYMBOL(%s)", (gchar*)varScanner->value.v_symbol ); break; + case G_TOKEN_IDENTIFIER: + printf( "IDENT(%s)", varScanner->value.v_identifier ); break; + case G_TOKEN_IDENTIFIER_NULL: + printf( "NULL_IDENT" ); break; + case G_TOKEN_COMMENT_SINGLE: + case G_TOKEN_COMMENT_MULTI: + printf( "COMMENT(%s)", varScanner->value.v_comment ); break; + case G_TOKEN_LAST: + printf( "END" ); break; + default: + printf( "UNK" ); break; + }; + printf( "\n" ); + } while ( (varScanner->token != G_TOKEN_LAST) && + (varScanner->token != G_TOKEN_EOF) && + (varScanner->token != G_TOKEN_NONE) ); + return 1; + /* +"0.33 * ( base + ld ) + (0.25 * internet)": + +tok: FLOAT(0.330000) +tok: UNK +tok: ) +tok: IDENT(base) +tok: UNK +tok: IDENT(ld) +tok: ( +tok: UNK +tok: ) +tok: FLOAT(0.250000) +tok: UNK +tok: IDENT(internet) +tok: ( +tok: EOF + */ + +#endif /* 0 */ diff --git a/src/gnome/dialog-sxsincelast.h b/src/gnome/dialog-sxsincelast.h new file mode 100644 index 0000000000..ec70bb1dee --- /dev/null +++ b/src/gnome/dialog-sxsincelast.h @@ -0,0 +1,29 @@ +/********************************************************************\ + * dialog-sxsincelast.h - SchedXaction "Since-Last-Run" dialog * + * Copyright (c) 2001 Joshua Sled * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +#ifndef DIALOG_SXSINCELAST_H +#define DIALOG_SXSINCELAST_H + +void gnc_ui_sxsincelast_dialog_create( void ); +void gnc_ui_sxsincelast_guile_wrapper( char* ); + +#endif // !defined(DIALOG_SXSINCELAST_H) diff --git a/src/gnome/glade/sched-xact.glade b/src/gnome/glade/sched-xact.glade index 415102ef1f..2e757bc6dc 100644 --- a/src/gnome/glade/sched-xact.glade +++ b/src/gnome/glade/sched-xact.glade @@ -157,9 +157,9 @@ GtkFrame - frame66 + frame73 - 0.05 + 0.1 GTK_SHADOW_ETCHED_IN 0 @@ -169,41 +169,130 @@ GtkVBox - vbox127 + vbox133 False 0 GtkCheckButton - manual_conf + autocreate_opt + Conditional on splits not having variables True - + False True - 2 + 0 False False + + GtkAlignment + alignment2 + 1 + 0.5 + 0.66 + 1 + + 0 + False + False + + + + GtkCheckButton + notify_opt + False + True + + False + True + + + GtkCheckButton - auto_create_notify + advance_opt True - False True - 2 + 0 False False + + + GtkHBox + hbox150 + False + 0 + + + GtkLabel + label847807 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkSpinButton + advance_days + False + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + True + False + 0 + 0 + 100 + 1 + 10 + 10 + + 0 + False + False + + + + + GtkLabel + label847808 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + GtkCheckButton - checkbutton1 + remind_opt True False True @@ -215,14 +304,14 @@ GtkHBox - hbox144 + hbox151 False 0 GtkLabel - label847789 - + label847809 + GTK_JUSTIFY_CENTER False 0.5 @@ -238,15 +327,16 @@ GtkSpinButton - spinbutton1 + remind_days + False True 1 0 True GTK_UPDATE_ALWAYS True - True - 1 + False + 0 0 100 1 @@ -255,14 +345,14 @@ 0 False - True + False GtkLabel - label847790 - + label847810 + GTK_JUSTIFY_CENTER False 0.5 @@ -315,52 +405,65 @@ - GtkHBox - hbox98 - False - 0 + GtkRadioButton + rb_enddate + True + False + True + sx_end_opt 2 - True - True + False + False - GtkRadioButton - rb_enddate - True - - False - True - sx_end_opt - - 0 - False - False - - + GtkHBox + hbox152 + False + 0 - - GnomeDateEdit - sxe_end_date - False - True - False - 7 - 19 - - 2 - False - False - + + GtkLabel + label847812 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GnomeDateEdit + sxe_end_date + False + True + False + 7 + 19 + + 0 + False + False + + - GtkHBox - hbox99 - False - 0 + GtkRadioButton + rb_num_occur + True + False + True + sx_end_opt 2 False @@ -368,39 +471,48 @@ - GtkRadioButton - rb_num_occur - True - - False - True - sx_end_opt - - 0 - False - False - - + GtkVBox + vbox134 + False + 0 - - GnomeNumberEntry - end_nentry - 10 - - 2 - False - False - + + GtkLabel + label847811 + + GTK_JUSTIFY_LEFT + False + 7.45058e-09 + 0.5 + 0 + 0 + + 0 + False + False + + - GtkEntry - GnomeEntry:entry - combo-entry1 - True - True - True - 0 - + GnomeNumberEntry + end_nentry + 10 + + 0 + False + False + + + + GtkEntry + GnomeEntry:entry + combo-entry1 + True + True + True + 0 + + @@ -413,11 +525,11 @@ recur_frame 4 - 0.05 + 0.1 GTK_SHADOW_ETCHED_IN 2 - True + False False @@ -447,13 +559,13 @@ GTK_SHADOW_ETCHED_IN 0 - True - True + False + False GtkVBox - vbox124 + register_vbox False 0 @@ -495,7 +607,7 @@ 0 True - True + False @@ -661,8 +773,8 @@ Yearly False 0 - True - True + False + False @@ -829,7 +941,7 @@ Yearly True True True - True + False False False @@ -943,7 +1055,7 @@ Yearly True True True - True + False False False @@ -1212,7 +1324,7 @@ Yearly True True True - True + False False False @@ -1523,9 +1635,9 @@ Yearly semimonthly_cal False True - False + True True - True + False False False @@ -2443,18 +2555,10 @@ December GtkButton - ok_button + close_button True True - GNOME_STOCK_BUTTON_OK - - - - GtkButton - cancel_button - True - True - GNOME_STOCK_BUTTON_CANCEL + GNOME_STOCK_BUTTON_CLOSE @@ -2866,11 +2970,13 @@ December GnomeDialog - real since-last-run dialog + Real Since-Last-Run Dialog Since Last Run... GTK_WINDOW_TOPLEVEL GTK_WIN_POS_CENTER False + 550 + 500 True True True @@ -2908,7 +3014,7 @@ December GtkButton - button1 + ok_button True True GNOME_STOCK_BUTTON_OK @@ -2916,15 +3022,7 @@ December GtkButton - button2 - True - True - GNOME_STOCK_BUTTON_APPLY - - - - GtkButton - button3 + cancel_button True True GNOME_STOCK_BUTTON_CANCEL @@ -2954,9 +3052,97 @@ December True + + GtkVBox + vbox135 + False + 0 + + + GtkLabel + label847814 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkScrolledWindow + scrolledwindow7 + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkCList + auto_create_clist + True + 2 + 207,80 + GTK_SELECTION_SINGLE + True + GTK_SHADOW_IN + + + GtkLabel + CList:title + label847815 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label847816 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + + + + + GtkFrame + frame68 + + 0.1 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + GtkScrolledWindow - scrolledwindow4 + scrolledwindow6 GTK_POLICY_ALWAYS GTK_POLICY_ALWAYS GTK_UPDATE_CONTINUOUS @@ -2964,10 +3150,10 @@ December GtkCList - clist1 + to_create_clist True - 3 - 80,80,80 + 2 + 210,80 GTK_SELECTION_SINGLE True GTK_SHADOW_IN @@ -2975,21 +3161,8 @@ December GtkLabel CList:title - label847791 - - GTK_JUSTIFY_CENTER - False - 0.5 - 0.5 - 0 - 0 - - - - GtkLabel - CList:title - label847792 - + label847802 + GTK_JUSTIFY_CENTER False 0.5 @@ -3001,8 +3174,8 @@ December GtkLabel CList:title - label847793 - + label847803 + GTK_JUSTIFY_CENTER False 0.5 @@ -3014,23 +3187,6 @@ December - - GtkFrame - frame68 - - 0.1 - GTK_SHADOW_ETCHED_IN - - 0 - True - True - - - - Placeholder - - - GtkFrame frame69 @@ -3044,7 +3200,63 @@ December - Placeholder + GtkScrolledWindow + scrolledwindow5 + 3 + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + + GtkCList + reminders_clist + True + 3 + 147,198,80 + GTK_SELECTION_SINGLE + True + GTK_SHADOW_IN + + + GtkLabel + CList:title + label847795 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label847796 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label847797 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + diff --git a/src/gnome/glade/sched-xact_strings.c b/src/gnome/glade/sched-xact_strings.c index 5eb6b421df..aa53f03459 100644 --- a/src/gnome/glade/sched-xact_strings.c +++ b/src/gnome/glade/sched-xact_strings.c @@ -7,13 +7,16 @@ gchar *s = N_("Edit Scheduled Transaction"); gchar *s = N_("Name:"); gchar *s = N_("Creation Options"); -gchar *s = N_(". Create automatically."); -gchar *s = N_(". Notify me when created."); -gchar *s = N_(". Remind me "); -gchar *s = N_(" days in advance."); +gchar *s = N_("Conditional on splits not having variables"); +gchar *s = N_("Create Automatically"); +gchar *s = N_("Notify me when created"); +gchar *s = N_("Create "); +gchar *s = N_(" days in advance"); +gchar *s = N_("Remind me "); +gchar *s = N_(" days in advance"); gchar *s = N_("End"); gchar *s = N_("No End"); -gchar *s = N_("End Date:"); +gchar *s = N_("End Date: "); gchar *s = N_("Number of Occurances:"); gchar *s = N_("Recurrance Frequency"); gchar *s = N_("Template Transaction"); @@ -351,8 +354,13 @@ gchar *s = N_("Value"); gchar *s = N_("What should this be?"); gchar *s = N_("Since Last Run..."); gchar *s = N_("Auto-created, notification requested..."); -gchar *s = N_("label847791"); -gchar *s = N_("label847792"); -gchar *s = N_("label847793"); +gchar *s = N_("...Replace with GL..."); +gchar *s = N_("Name"); +gchar *s = N_("Date"); gchar *s = N_("To-create..."); +gchar *s = N_("Name"); +gchar *s = N_("Date"); gchar *s = N_("Reminders"); +gchar *s = N_("Name"); +gchar *s = N_("Next Date"); +gchar *s = N_("Days"); diff --git a/src/gnome/window-main.c b/src/gnome/window-main.c index 163695583e..14bb0d307a 100644 --- a/src/gnome/window-main.c +++ b/src/gnome/window-main.c @@ -53,6 +53,7 @@ #include "dialog-utils.h" #include "dialog-scheduledxaction.h" #include "dialog-nextrun.h" +#include "dialog-sxsincelast.h" #include "window-help.h" #include "window-main.h" @@ -917,6 +918,16 @@ gnc_main_window_find_transactions_cb (GtkWidget *widget, gpointer data) { gnc_ui_find_transactions_dialog_create(NULL); } +static void +gnc_main_window_sched_xaction_cb (GtkWidget *widget, gpointer data) { + gnc_ui_scheduled_xaction_dialog_create(); +} + +static void +gnc_main_window_sched_xaction_slr_cb (GtkWidget *widget, gpointer data) { + gnc_ui_sxsincelast_dialog_create(); +} + static void gnc_main_window_about_cb (GtkWidget *widget, gpointer data) { @@ -1082,6 +1093,20 @@ gnc_main_window_create_menus(GNCMainInfo * maininfo) { GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL }, + { GNOME_APP_UI_ITEM, + N_("Scheduled Transactions List"), + N_("A 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_("Scheduled Transactions 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, + 0, 0, NULL + }, GNOMEUIINFO_END }; diff --git a/src/scm/extensions.scm b/src/scm/extensions.scm index 4e78911d8d..3fc96254cc 100644 --- a/src/scm/extensions.scm +++ b/src/scm/extensions.scm @@ -73,13 +73,17 @@ (list "Extensions" "") (lambda () (gnc:sx-editor))) ) - (define schedxact-slr-item - (gnc:make-menu-item (N_ "SchedXact: Since Last Run") + (define schedxact-old-slr-item + (gnc:make-menu-item (N_ "SchedXact: [Old] Since Last Run") (N_ "since last run dialog") (list "Extensions" "") (lambda () (gnc:sx-since-last-run))) ) - + (define schedxact-slr-item + (gnc:make-menu-item (N_ "SchedXact: [New] Since Last Run") + (N_ "since last run dialog") + (list "Extensions" "" ) + (lambda () (gnc:sx-sincelast-create )))) (define progress-item (gnc:make-menu-item (N_ "Test progress dialog") (N_ "Test progress dialog") @@ -110,6 +114,7 @@ ;; appear in the menu [prepending to some list]... (gnc:add-extension progress-item) + (gnc:add-extension schedxact-old-slr-item) (gnc:add-extension schedxact-slr-item) (gnc:add-extension schedxact-editor-item) ) diff --git a/src/scm/main-window.scm b/src/scm/main-window.scm index 1d6292c84c..662186f78b 100644 --- a/src/scm/main-window.scm +++ b/src/scm/main-window.scm @@ -189,3 +189,12 @@ the account instead of opening a register.") #f)) (gnc:hook-add-dangler gnc:*book-closed-hook* gnc:main-window-book-close-handler) + +(gnc:hook-add-dangler gnc:*book-opened-hook* + (lambda (file) + (if ((gnc:option-getter + (gnc:lookup-global-option + (N_ "Scheduled Transactions") + (N_ "Run on GnuCash Start" )))) + (gnc:sx-since-last-run-wrapper file))) ) + diff --git a/src/scm/prefs.scm b/src/scm/prefs.scm index 3014791d04..7c3d61ece4 100644 --- a/src/scm/prefs.scm +++ b/src/scm/prefs.scm @@ -77,8 +77,7 @@ ;; hook should probably revert back to just save-global-options. (define (gnc:save-all-options) (gnc:save-global-options) -; (gnc:save-report-options) -; (gnc:save-acct-tree-options) +; (gnc:save-report-options); (gnc:save-acct-tree-options) (gnc:save-style-sheet-options)) (define (gnc:save-global-options) @@ -531,6 +530,66 @@ without one.") "d" (N_ "Host to connect to for user registration and support services") "www.gnumatic.com")) + +;; Scheduled|Recurring Transactions + +(gnc:register-configuration-option + (gnc:make-simple-boolean-option + (N_ "Scheduled Transactions") + (N_ "Run on GnuCash Start") + "a" (N_ "Should the Since-Last-Run window appear on GnuCash startup?") + #f )) + +(gnc:register-configuration-option + (gnc:make-simple-boolean-option + (N_ "Scheduled Transactions") + (N_ "Default: Auto-Create new Scheduled Transactions?") + "b" (N_ "Should new SchedXactions have the 'AutoCreate' flag set by default?") + #f )) + +(gnc:register-configuration-option + (gnc:make-simple-boolean-option + (N_ "Scheduled Transactions") + (N_ "Default: Notify on new, auto-created scheduled transactions") + "c" (N_ "Should new SchedXactions with the 'AutoCreate' flag set also be set to notify?") + #t )) + +(gnc:register-configuration-option + (gnc:make-number-range-option + (N_ "Scheduled Transactions") + (N_ "Default create-in-advance days") + "d" (N_ "Default number of days-in-advance to create new SXes") + 0 ; default + 0 ; min + 99999999 ; max + 0 ; num decimals + 1 ; step size + )) + +(gnc:register-configuration-option + (gnc:make-number-range-option + (N_ "Scheduled Transactions") + (N_ "Default remind-in-advance days") + "e" (N_ "Default number of days-in-advance to remind on new SXes") + 0 ; default + 0 ; min + 99999 ; max + 0 ; num-decimals + 1 ; step size + )) + +(gnc:register-configuration-option + (gnc:make-number-range-option + (N_ "Scheduled Transactions") + (N_ "Template Register Lines") + "f" (N_ "How many lines in the template register?") + 4 ; default + 1 ; min + 50 ; max + 0 ; num-decimals + 1 ; step size + )) + ;;; Configuation variables (define gnc:*arg-show-version*