mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
2001-06-17 Joshua Sled <jsled@asynchronous.org>
* src/engine/gnc-account-xml-v2.c (dom_tree_to_account): Added.
* src/engine/gnc-transaction-xml-v2.c (dom_tree_to_transaction):
Added.
* src/FileDialog.c: Added support for copying
scheduled-transaction-related GNCBook fields.
src/engine/
* src/engine/FreqSpec.{h,c}: Added.
* src/engine/SchedXaction.{h,c}: Added.
* src/engine/gnc-{freqspec,schedxaction}-xml-v2.c: Added
* src/engine/gnc-book.c: Added the template group [template
transaction belong to the template group] and the Scheduled
Trasnaction list.
* src/gnome/glade/sched_xact.glade: Added.
* src/gnome/dialog-nextrun.{h,c}: Added.
* src/gnome/dialog-scheduledxaction.{h,c}: Added.
* src/gnome/gnc-frequency.{h,c}: Added.
* src/SplitLedger.c, src/MultiLedger.c: Added support for a
Template Ledger.
* src/guile/gnc.gwp: Added wrapping for
dialog-{scheduledxactions,nextrun}-creation functions.
* src/register/splitreg.c: Added formula credit and debit cells,
and flags for template-register support.
* src/register/formulacell.h: Added.
* src/gnome/gnc-dateedit.h: Added explanatory comment from dave_p
in IRC.
* src/gnome/query-user.h: Added prototype of
gnc_verify_dialog_parented(...), so I could use it the SX UI
stuff.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4725 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
3
AUTHORS
3
AUTHORS
@@ -66,6 +66,9 @@ Christian Stimming <stimming@tuhh.de> is a report-generating
|
|||||||
monster. He's been on of the largest contributors to the current report
|
monster. He's been on of the largest contributors to the current report
|
||||||
infrastructure, creating many of the important reports.
|
infrastructure, creating many of the important reports.
|
||||||
|
|
||||||
|
Joshua Sled <jsled@asynchronous.org> works on scheduled transactions
|
||||||
|
and budgeting.
|
||||||
|
|
||||||
|
|
||||||
Other Contributors:
|
Other Contributors:
|
||||||
----------------
|
----------------
|
||||||
|
|||||||
49
ChangeLog
49
ChangeLog
@@ -1,3 +1,50 @@
|
|||||||
|
2001-06-17 Joshua Sled <jsled@asynchronous.org>
|
||||||
|
|
||||||
|
* src/engine/gnc-account-xml-v2.c (dom_tree_to_account): Added.
|
||||||
|
|
||||||
|
* src/engine/gnc-transaction-xml-v2.c (dom_tree_to_transaction):
|
||||||
|
Added.
|
||||||
|
|
||||||
|
* src/FileDialog.c: Added support for copying
|
||||||
|
scheduled-transaction-related GNCBook fields.
|
||||||
|
src/engine/
|
||||||
|
|
||||||
|
* src/engine/FreqSpec.{h,c}: Added.
|
||||||
|
|
||||||
|
* src/engine/SchedXaction.{h,c}: Added.
|
||||||
|
|
||||||
|
* src/engine/gnc-{freqspec,schedxaction}-xml-v2.c: Added
|
||||||
|
|
||||||
|
* src/engine/gnc-book.c: Added the template group [template
|
||||||
|
transaction belong to the template group] and the Scheduled
|
||||||
|
Trasnaction list.
|
||||||
|
|
||||||
|
* src/gnome/glade/sched_xact.glade: Added.
|
||||||
|
|
||||||
|
* src/gnome/dialog-nextrun.{h,c}: Added.
|
||||||
|
|
||||||
|
* src/gnome/dialog-scheduledxaction.{h,c}: Added.
|
||||||
|
|
||||||
|
* src/gnome/gnc-frequency.{h,c}: Added.
|
||||||
|
|
||||||
|
* src/SplitLedger.c, src/MultiLedger.c: Added support for a
|
||||||
|
Template Ledger.
|
||||||
|
|
||||||
|
* src/guile/gnc.gwp: Added wrapping for
|
||||||
|
dialog-{scheduledxactions,nextrun}-creation functions.
|
||||||
|
|
||||||
|
* src/register/splitreg.c: Added formula credit and debit cells,
|
||||||
|
and flags for template-register support.
|
||||||
|
|
||||||
|
* src/register/formulacell.h: Added.
|
||||||
|
|
||||||
|
* src/gnome/gnc-dateedit.h: Added explanatory comment from dave_p
|
||||||
|
in IRC.
|
||||||
|
|
||||||
|
* src/gnome/query-user.h: Added prototype of
|
||||||
|
gnc_verify_dialog_parented(...), so I could use it the SX UI
|
||||||
|
stuff.
|
||||||
|
|
||||||
2001-06-17 Kevin Finn <kevinfinn@mediaone.net>
|
2001-06-17 Kevin Finn <kevinfinn@mediaone.net>
|
||||||
|
|
||||||
* src/gnome/window-reconcile.c: Implemented automatic interest
|
* src/gnome/window-reconcile.c: Implemented automatic interest
|
||||||
@@ -75,7 +122,7 @@
|
|||||||
creation druid code. Rename api calls to reflect the more
|
creation druid code. Rename api calls to reflect the more
|
||||||
general use of the druid.
|
general use of the druid.
|
||||||
|
|
||||||
2001-06-16 Robert Graham Merkel <rgmerk@mira.net
|
2001-06-16 Robert Graham Merkel <rgmerk@mira.net>
|
||||||
|
|
||||||
* po/POTFILES.in : remove references to deleted files.
|
* po/POTFILES.in : remove references to deleted files.
|
||||||
|
|
||||||
|
|||||||
@@ -565,6 +565,8 @@ gncFileSaveAs (void)
|
|||||||
{
|
{
|
||||||
AccountGroup *group;
|
AccountGroup *group;
|
||||||
GNCPriceDB *pdb;
|
GNCPriceDB *pdb;
|
||||||
|
GList *sxList;
|
||||||
|
AccountGroup *templateGroup;
|
||||||
GNCBook *new_book;
|
GNCBook *new_book;
|
||||||
GNCBook *book;
|
GNCBook *book;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
@@ -596,8 +598,14 @@ gncFileSaveAs (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -- this session code is NOT identical in FileOpen and FileSaveAs -- */
|
/* -- this session code is NOT identical in FileOpen and FileSaveAs -- */
|
||||||
|
|
||||||
|
// FIXME: this might want to be a function of the GNCBook, since it
|
||||||
|
// needs to sync with changes to the internals/structure of
|
||||||
|
// GNCBook... --jsled
|
||||||
group = gnc_book_get_group(book);
|
group = gnc_book_get_group(book);
|
||||||
pdb = gnc_book_get_pricedb(book);
|
pdb = gnc_book_get_pricedb(book);
|
||||||
|
sxList = gnc_book_get_schedxactions(book);
|
||||||
|
templateGroup = gnc_book_get_template_group(book);
|
||||||
|
|
||||||
new_book = gnc_book_new ();
|
new_book = gnc_book_new ();
|
||||||
gnc_book_begin (new_book, newfile, FALSE, FALSE);
|
gnc_book_begin (new_book, newfile, FALSE, FALSE);
|
||||||
@@ -671,6 +679,8 @@ gncFileSaveAs (void)
|
|||||||
/* OK, save the data to the file ... */
|
/* OK, save the data to the file ... */
|
||||||
gnc_book_set_group(new_book, group);
|
gnc_book_set_group(new_book, group);
|
||||||
gnc_book_set_pricedb(new_book, pdb);
|
gnc_book_set_pricedb(new_book, pdb);
|
||||||
|
gnc_book_set_schedxactions(new_book, sxList);
|
||||||
|
gnc_book_set_template_group(new_book, templateGroup);
|
||||||
gncFileSave ();
|
gncFileSave ();
|
||||||
|
|
||||||
g_free (newfile);
|
g_free (newfile);
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ void gncFileQuit (void);
|
|||||||
|
|
||||||
AccountGroup *gncGetCurrentGroup (void);
|
AccountGroup *gncGetCurrentGroup (void);
|
||||||
|
|
||||||
|
Account *gncGetTemplateAccount(void);
|
||||||
|
|
||||||
GNCBook *gncGetCurrentBook (void);
|
GNCBook *gncGetCurrentBook (void);
|
||||||
|
|
||||||
#endif /* __GNC_FILE_DIALOG_H__ */
|
#endif /* __GNC_FILE_DIALOG_H__ */
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#define REGISTER_SINGLE_CM_CLASS "register-single"
|
#define REGISTER_SINGLE_CM_CLASS "register-single"
|
||||||
#define REGISTER_SUBACCOUNT_CM_CLASS "register-subaccount"
|
#define REGISTER_SUBACCOUNT_CM_CLASS "register-subaccount"
|
||||||
#define REGISTER_GL_CM_CLASS "register-gl"
|
#define REGISTER_GL_CM_CLASS "register-gl"
|
||||||
|
#define REGISTER_TEMPLATE_CM_CLASS "register-template"
|
||||||
|
|
||||||
|
|
||||||
struct _xaccLedgerDisplay
|
struct _xaccLedgerDisplay
|
||||||
@@ -74,7 +75,8 @@ static xaccLedgerDisplay *
|
|||||||
xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
||||||
LedgerDisplayType ld_type,
|
LedgerDisplayType ld_type,
|
||||||
SplitRegisterType reg_type,
|
SplitRegisterType reg_type,
|
||||||
SplitRegisterStyle style);
|
SplitRegisterStyle style,
|
||||||
|
gboolean templateMode );
|
||||||
static void xaccLedgerDisplayRefreshInternal (xaccLedgerDisplay *ld,
|
static void xaccLedgerDisplayRefreshInternal (xaccLedgerDisplay *ld,
|
||||||
GList *splits);
|
GList *splits);
|
||||||
|
|
||||||
@@ -358,7 +360,7 @@ xaccLedgerDisplaySimple (Account *account)
|
|||||||
reg_type = get_reg_type (account, LD_SINGLE);
|
reg_type = get_reg_type (account, LD_SINGLE);
|
||||||
|
|
||||||
return xaccLedgerDisplayInternal (account, NULL, LD_SINGLE, reg_type,
|
return xaccLedgerDisplayInternal (account, NULL, LD_SINGLE, reg_type,
|
||||||
gnc_get_default_register_style ());
|
gnc_get_default_register_style (), FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@@ -378,9 +380,11 @@ xaccLedgerDisplayAccGroup (Account *account)
|
|||||||
reg_type = get_reg_type (account, LD_SUBACCOUNT);
|
reg_type = get_reg_type (account, LD_SUBACCOUNT);
|
||||||
|
|
||||||
return xaccLedgerDisplayInternal (account, NULL, LD_SUBACCOUNT,
|
return xaccLedgerDisplayInternal (account, NULL, LD_SUBACCOUNT,
|
||||||
reg_type, REG_STYLE_JOURNAL);
|
reg_type, REG_STYLE_JOURNAL, FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* xaccLedgerDisplayGL *
|
* xaccLedgerDisplayGL *
|
||||||
* opens up a general ledger window *
|
* opens up a general ledger window *
|
||||||
@@ -390,7 +394,7 @@ xaccLedgerDisplayAccGroup (Account *account)
|
|||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
xaccLedgerDisplay *
|
xaccLedgerDisplay *
|
||||||
xaccLedgerDisplayGL (void)
|
xaccLedgerDisplayGL ()
|
||||||
{
|
{
|
||||||
Query *query;
|
Query *query;
|
||||||
time_t start;
|
time_t start;
|
||||||
@@ -423,7 +427,48 @@ xaccLedgerDisplayGL (void)
|
|||||||
|
|
||||||
return xaccLedgerDisplayInternal (NULL, query, LD_GL,
|
return xaccLedgerDisplayInternal (NULL, query, LD_GL,
|
||||||
GENERAL_LEDGER,
|
GENERAL_LEDGER,
|
||||||
REG_STYLE_JOURNAL);
|
REG_STYLE_JOURNAL, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id is some identifier that can be:
|
||||||
|
* . used in a query to look for the transaction which belong to this
|
||||||
|
* template ledger
|
||||||
|
* . set in a specific key value for new transactions which belong to
|
||||||
|
* this template ledger.
|
||||||
|
**/
|
||||||
|
xaccLedgerDisplay *
|
||||||
|
xaccLedgerDisplayTemplateGL( char *id )
|
||||||
|
{
|
||||||
|
GNCBook *book;
|
||||||
|
Query *q;
|
||||||
|
time_t start;
|
||||||
|
struct tm *tm;
|
||||||
|
xaccLedgerDisplay *ld;
|
||||||
|
SplitRegister *sr;
|
||||||
|
AccountGroup *ag;
|
||||||
|
Account *acct;
|
||||||
|
|
||||||
|
q = xaccMallocQuery();
|
||||||
|
|
||||||
|
ag = gnc_book_get_template_group( gncGetCurrentBook() );
|
||||||
|
acct = xaccGetAccountFromName( ag, id );
|
||||||
|
if ( acct == NULL ) {
|
||||||
|
// FIXME
|
||||||
|
printf( "can't get template account for id \"%s\"\n", id );
|
||||||
|
}
|
||||||
|
xaccQueryAddSingleAccountMatch( q, acct, QUERY_AND );
|
||||||
|
book = gncGetCurrentBook();
|
||||||
|
xaccQuerySetGroup( q, gnc_book_get_template_group(book) );
|
||||||
|
|
||||||
|
ld = xaccLedgerDisplayInternal( NULL, q, LD_GL,
|
||||||
|
GENERAL_LEDGER,
|
||||||
|
REG_STYLE_JOURNAL,
|
||||||
|
TRUE ); // template mode? TRUE.
|
||||||
|
|
||||||
|
sr = xaccLedgerDisplayGetSR( ld );
|
||||||
|
sr->templateAcct = acct;
|
||||||
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gncUIWidget
|
static gncUIWidget
|
||||||
@@ -541,8 +586,6 @@ refresh_handler (GHashTable *changes, gpointer user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xaccQuerySetGroup (ld->query, gncGetCurrentGroup ());
|
|
||||||
|
|
||||||
splits = xaccQueryGetSplits (ld->query);
|
splits = xaccQueryGetSplits (ld->query);
|
||||||
|
|
||||||
ledger_set_watches (ld, splits);
|
ledger_set_watches (ld, splits);
|
||||||
@@ -590,6 +633,7 @@ make_ledger_query (xaccLedgerDisplay *ld,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case LD_GL:
|
case LD_GL:
|
||||||
|
case LD_TEMPLATE:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -637,14 +681,15 @@ xaccLedgerDisplay *
|
|||||||
xaccLedgerDisplayQuery (Query *query, SplitRegisterType type,
|
xaccLedgerDisplayQuery (Query *query, SplitRegisterType type,
|
||||||
SplitRegisterStyle style)
|
SplitRegisterStyle style)
|
||||||
{
|
{
|
||||||
return xaccLedgerDisplayInternal (NULL, query, LD_GL, type, style);
|
return xaccLedgerDisplayInternal (NULL, query, LD_GL, type, style, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static xaccLedgerDisplay *
|
static xaccLedgerDisplay *
|
||||||
xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
||||||
LedgerDisplayType ld_type,
|
LedgerDisplayType ld_type,
|
||||||
SplitRegisterType reg_type,
|
SplitRegisterType reg_type,
|
||||||
SplitRegisterStyle style)
|
SplitRegisterStyle style,
|
||||||
|
gboolean templateMode )
|
||||||
{
|
{
|
||||||
xaccLedgerDisplay *ld;
|
xaccLedgerDisplay *ld;
|
||||||
gboolean show_all;
|
gboolean show_all;
|
||||||
@@ -712,9 +757,16 @@ xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LD_TEMPLATE:
|
||||||
|
class = REGISTER_TEMPLATE_CM_CLASS;
|
||||||
|
// FIXME: sanity checks?
|
||||||
|
// Check for kvp-frame data?
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PERR ("bad ledger type: %d", ld_type);
|
PERR ("bad ledger type: %d", ld_type);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ld = g_new (xaccLedgerDisplay, 1);
|
ld = g_new (xaccLedgerDisplay, 1);
|
||||||
@@ -748,24 +800,33 @@ xaccLedgerDisplayInternal (Account *lead_account, Query *q,
|
|||||||
|
|
||||||
/* xaccMallocSplitRegister will malloc & initialize the register,
|
/* xaccMallocSplitRegister will malloc & initialize the register,
|
||||||
* but will not do the gui init */
|
* but will not do the gui init */
|
||||||
view.entry_handler = xaccSRGetEntryHandler;
|
|
||||||
view.label_handler = xaccSRGetLabelHandler;
|
view.label_handler = xaccSRGetLabelHandler;
|
||||||
view.io_flag_handler = xaccSRGetIOFlagsHandler;
|
|
||||||
view.fg_color_handler = xaccSRGetFGColorHandler;
|
view.fg_color_handler = xaccSRGetFGColorHandler;
|
||||||
view.bg_color_handler = xaccSRGetBGColorHandler;
|
view.bg_color_handler = xaccSRGetBGColorHandler;
|
||||||
view.cell_border_handler = xaccSRGetCellBorderHandler;
|
view.cell_border_handler = xaccSRGetCellBorderHandler;
|
||||||
view.confirm_handler = xaccSRConfirmHandler;
|
|
||||||
view.handler_user_data = NULL;
|
view.handler_user_data = NULL;
|
||||||
|
// The following handlers are changed in template mode.
|
||||||
|
if ( templateMode ) {
|
||||||
|
view.entry_handler = xaccSRTemplateGetEntryHandler;
|
||||||
|
view.io_flag_handler = xaccSRTemplateGetIOFlagsHandler;
|
||||||
|
view.confirm_handler = xaccSRTemplateConfirmHandler;
|
||||||
|
} else {
|
||||||
|
view.entry_handler = xaccSRGetEntryHandler;
|
||||||
|
view.io_flag_handler = xaccSRGetIOFlagsHandler;
|
||||||
|
view.confirm_handler = xaccSRConfirmHandler;
|
||||||
|
}
|
||||||
|
|
||||||
ld->reg = xaccMallocSplitRegister (reg_type, style, FALSE, &view,
|
ld->reg = xaccMallocSplitRegister (reg_type, style, FALSE, &view,
|
||||||
xaccMLGUIDMalloc,
|
xaccMLGUIDMalloc,
|
||||||
xaccMLGUIDFree,
|
xaccMLGUIDFree,
|
||||||
xaccMLGUIDCopy);
|
xaccMLGUIDCopy,
|
||||||
|
templateMode);
|
||||||
xaccSRSetData (ld->reg, ld,
|
xaccSRSetData (ld->reg, ld,
|
||||||
xaccLedgerDisplayParent,
|
xaccLedgerDisplayParent,
|
||||||
xaccLedgerDisplaySetHelp);
|
xaccLedgerDisplaySetHelp);
|
||||||
|
|
||||||
|
ld->reg->template = templateMode;
|
||||||
|
|
||||||
splits = xaccQueryGetSplits (ld->query);
|
splits = xaccQueryGetSplits (ld->query);
|
||||||
|
|
||||||
ledger_set_watches (ld, splits);
|
ledger_set_watches (ld, splits);
|
||||||
@@ -825,6 +886,8 @@ xaccLedgerDisplayRefresh (xaccLedgerDisplay *ld)
|
|||||||
if (!ld || ld->loading)
|
if (!ld || ld->loading)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//xaccQueryPrint( ld->query );
|
||||||
|
|
||||||
xaccLedgerDisplayRefreshInternal (ld, xaccQueryGetSplits (ld->query));
|
xaccLedgerDisplayRefreshInternal (ld, xaccQueryGetSplits (ld->query));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,6 +922,13 @@ xaccLedgerDisplayRefreshByReg (SplitRegister *reg)
|
|||||||
xaccLedgerDisplayRefresh (ld);
|
xaccLedgerDisplayRefresh (ld);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ld = gnc_find_first_gui_component (REGISTER_TEMPLATE_CM_CLASS,
|
||||||
|
find_by_reg, reg );
|
||||||
|
if (ld)
|
||||||
|
{
|
||||||
|
xaccLedgerDisplayRefresh (ld);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@@ -892,6 +962,8 @@ xaccDestroyLedgerDisplay (Account *account)
|
|||||||
xaccDestroyLedgerDisplayClass (account, REGISTER_SINGLE_CM_CLASS);
|
xaccDestroyLedgerDisplayClass (account, REGISTER_SINGLE_CM_CLASS);
|
||||||
xaccDestroyLedgerDisplayClass (account, REGISTER_SUBACCOUNT_CM_CLASS);
|
xaccDestroyLedgerDisplayClass (account, REGISTER_SUBACCOUNT_CM_CLASS);
|
||||||
xaccDestroyLedgerDisplayClass (account, REGISTER_GL_CM_CLASS);
|
xaccDestroyLedgerDisplayClass (account, REGISTER_GL_CM_CLASS);
|
||||||
|
// no TEMPLATE_CM_CLASS, because it doesn't correspond to any account
|
||||||
|
// FIXME: but there probably should be an analagous method
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "Query.h"
|
#include "Query.h"
|
||||||
#include "splitreg.h"
|
#include "splitreg.h"
|
||||||
#include "SplitLedger.h"
|
#include "SplitLedger.h"
|
||||||
|
#include "SchedXaction.h"
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +51,8 @@ typedef enum
|
|||||||
{
|
{
|
||||||
LD_SINGLE,
|
LD_SINGLE,
|
||||||
LD_SUBACCOUNT,
|
LD_SUBACCOUNT,
|
||||||
LD_GL
|
LD_GL,
|
||||||
|
LD_TEMPLATE,
|
||||||
} LedgerDisplayType;
|
} LedgerDisplayType;
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +84,16 @@ xaccLedgerDisplay * xaccLedgerDisplaySimple (Account *account);
|
|||||||
xaccLedgerDisplay * xaccLedgerDisplayAccGroup (Account *account);
|
xaccLedgerDisplay * xaccLedgerDisplayAccGroup (Account *account);
|
||||||
|
|
||||||
xaccLedgerDisplay * xaccLedgerDisplayGL (void);
|
xaccLedgerDisplay * xaccLedgerDisplayGL (void);
|
||||||
|
xaccLedgerDisplay * xaccLedgerDisplayGLTemplate( char *id );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a template ledger.
|
||||||
|
* This lists template Splits from the given ScheduledTransaction.
|
||||||
|
*
|
||||||
|
* Really, requires a GList of scheduled transactions and kvp-frame
|
||||||
|
* data.
|
||||||
|
**/
|
||||||
|
xaccLedgerDisplay * xaccLedgerDisplayTemplateGL( );
|
||||||
|
|
||||||
/* display a general ledger for an arbitrary query */
|
/* display a general ledger for an arbitrary query */
|
||||||
xaccLedgerDisplay * xaccLedgerDisplayQuery (Query *query,
|
xaccLedgerDisplay * xaccLedgerDisplayQuery (Query *query,
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ struct _SRInfo
|
|||||||
|
|
||||||
/* hook to set help string */
|
/* hook to set help string */
|
||||||
SRSetHelpCallback set_help;
|
SRSetHelpCallback set_help;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -230,8 +231,13 @@ static Transaction * xaccSRGetTrans (SplitRegister *reg,
|
|||||||
VirtualCellLocation vcell_loc);
|
VirtualCellLocation vcell_loc);
|
||||||
static Split * xaccSRGetCurrentTransSplit (SplitRegister *reg,
|
static Split * xaccSRGetCurrentTransSplit (SplitRegister *reg,
|
||||||
VirtualCellLocation *vcell_loc);
|
VirtualCellLocation *vcell_loc);
|
||||||
|
static void xaccSRActuallySaveChangedCells (SplitRegister *reg, Transaction *trans,
|
||||||
|
Split *split, guint32 changed );
|
||||||
static void xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans,
|
static void xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans,
|
||||||
Split *split);
|
Split *split);
|
||||||
|
static void xaccSRSaveChangedTemplateCells (SplitRegister *reg,
|
||||||
|
Transaction *trans,
|
||||||
|
Split *split);
|
||||||
static gboolean xaccSRFindSplit (SplitRegister *reg,
|
static gboolean xaccSRFindSplit (SplitRegister *reg,
|
||||||
Transaction *trans, Split *trans_split,
|
Transaction *trans, Split *trans_split,
|
||||||
Split *split, CursorClass cursor_class,
|
Split *split, CursorClass cursor_class,
|
||||||
@@ -393,7 +399,7 @@ gnc_copy_split_onto_split(Split *from, Split *to, gboolean use_cut_semantics)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Uses the scheme transaction copying routines */
|
/* Uses the scheme transaction copying routines */
|
||||||
static void
|
void
|
||||||
gnc_copy_trans_onto_trans(Transaction *from, Transaction *to,
|
gnc_copy_trans_onto_trans(Transaction *from, Transaction *to,
|
||||||
gboolean use_cut_semantics,
|
gboolean use_cut_semantics,
|
||||||
gboolean do_commit)
|
gboolean do_commit)
|
||||||
@@ -1272,7 +1278,11 @@ LedgerAutoCompletion(SplitRegister *reg, gncTableTraversalDir dir,
|
|||||||
|
|
||||||
info->blank_split_edited = TRUE;
|
info->blank_split_edited = TRUE;
|
||||||
|
|
||||||
xaccSRSaveChangedCells(reg, trans, blank_split);
|
if ( reg->template ) {
|
||||||
|
xaccSRSaveChangedTemplateCells( reg, trans, blank_split );
|
||||||
|
} else {
|
||||||
|
xaccSRSaveChangedCells(reg, trans, blank_split);
|
||||||
|
}
|
||||||
|
|
||||||
gnc_resume_gui_refresh ();
|
gnc_resume_gui_refresh ();
|
||||||
|
|
||||||
@@ -2673,6 +2683,8 @@ xaccSRRedrawReg (SplitRegister *reg)
|
|||||||
/* Copy from the register object to scheme. This needs to be
|
/* Copy from the register object to scheme. This needs to be
|
||||||
* in sync with xaccSRSaveRegEntry and xaccSRSaveChangedCells. */
|
* in sync with xaccSRSaveRegEntry and xaccSRSaveChangedCells. */
|
||||||
|
|
||||||
|
|
||||||
|
// jsled: This will need to be modified, as well.
|
||||||
static gboolean
|
static gboolean
|
||||||
xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm,
|
xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm,
|
||||||
gboolean use_cut_semantics)
|
gboolean use_cut_semantics)
|
||||||
@@ -2815,7 +2827,9 @@ xaccSRSaveRegEntryToSCM (SplitRegister *reg, SCM trans_scm, SCM split_scm,
|
|||||||
|
|
||||||
/* ======================================================== */
|
/* ======================================================== */
|
||||||
/* Copy from the register object to the engine */
|
/* Copy from the register object to the engine */
|
||||||
|
// jsled: okay... the fun.
|
||||||
|
// actually, not really the fun, but scan this to see if anything
|
||||||
|
// jumps out; the
|
||||||
gboolean
|
gboolean
|
||||||
xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit)
|
xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit)
|
||||||
{
|
{
|
||||||
@@ -2829,6 +2843,8 @@ xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit)
|
|||||||
const char *memo;
|
const char *memo;
|
||||||
const char *desc;
|
const char *desc;
|
||||||
|
|
||||||
|
//DEBUG( "=== In xaccSRSaveRegEntry\n" );
|
||||||
|
|
||||||
/* get the handle to the current split and transaction */
|
/* get the handle to the current split and transaction */
|
||||||
split = xaccSRGetCurrentSplit (reg);
|
split = xaccSRGetCurrentSplit (reg);
|
||||||
trans = xaccSRGetCurrentTrans (reg);
|
trans = xaccSRGetCurrentTrans (reg);
|
||||||
@@ -2922,13 +2938,16 @@ xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit)
|
|||||||
|
|
||||||
DEBUG ("updating trans addr=%p\n", trans);
|
DEBUG ("updating trans addr=%p\n", trans);
|
||||||
|
|
||||||
xaccSRSaveChangedCells (reg, trans, split);
|
if ( reg->template ) {
|
||||||
|
xaccSRSaveChangedTemplateCells( reg, trans, split );
|
||||||
|
} else {
|
||||||
|
xaccSRSaveChangedCells (reg, trans, split);
|
||||||
|
}
|
||||||
|
|
||||||
memo = xaccSplitGetMemo (split);
|
memo = xaccSplitGetMemo (split);
|
||||||
memo = memo ? memo : "(null)";
|
memo = memo ? memo : "(null)";
|
||||||
desc = xaccTransGetDescription (trans);
|
desc = xaccTransGetDescription (trans);
|
||||||
desc = desc ? desc : "(null)";
|
desc = desc ? desc : "(null)";
|
||||||
|
|
||||||
PINFO ("finished saving split %s of trans %s \n", memo, desc);
|
PINFO ("finished saving split %s of trans %s \n", memo, desc);
|
||||||
|
|
||||||
/* If the modified split is the "blank split", then it is now an
|
/* If the modified split is the "blank split", then it is now an
|
||||||
@@ -3122,7 +3141,6 @@ sr_split_auto_calc (SplitRegister *reg, Split *split, guint32 changed)
|
|||||||
message,
|
message,
|
||||||
default_value,
|
default_value,
|
||||||
radio_list);
|
radio_list);
|
||||||
|
|
||||||
for (node = radio_list; node; node = node->next)
|
for (node = radio_list; node; node = node->next)
|
||||||
g_free (node->data);
|
g_free (node->data);
|
||||||
|
|
||||||
@@ -3190,14 +3208,149 @@ sr_split_auto_calc (SplitRegister *reg, Split *split, guint32 changed)
|
|||||||
/* ======================================================== */
|
/* ======================================================== */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
xaccSRSaveChangedTemplateCells( SplitRegister *reg,
|
||||||
|
Transaction *trans,
|
||||||
|
Split *split )
|
||||||
|
{
|
||||||
|
SRInfo *info = xaccSRGetInfo( reg );
|
||||||
|
Split *other_split = NULL;
|
||||||
|
guint32 changed;
|
||||||
|
kvp_frame *kvpf;
|
||||||
|
AccountGroup *template_ag;
|
||||||
|
Account *template_acc;
|
||||||
|
kvp_value *tag_val;
|
||||||
|
|
||||||
|
DEBUG( "=== In xaccSRSaveChangedTemplateCells\n" );
|
||||||
|
|
||||||
|
//template_acc = gncGetTemplateAccount();
|
||||||
|
//template_ag = gnc_book_get_template_group( gncGetCurrentBook() );
|
||||||
|
template_acc = reg->templateAcct;
|
||||||
|
|
||||||
|
changed = xaccSplitRegisterGetChangeFlag( reg );
|
||||||
|
changed |= xaccSplitRegisterGetConditionalChangeFlag( reg );
|
||||||
|
if ( (MOD_DATE & changed) ||
|
||||||
|
(MOD_NUM & changed) ||
|
||||||
|
(MOD_RECN & changed) )
|
||||||
|
{
|
||||||
|
PERR( "unexpected changed field in a template register: %32x\n", changed );
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll be using the Split's KVP frame a lot...
|
||||||
|
kvpf = xaccSplitGetSlots( split );
|
||||||
|
|
||||||
|
if ( MOD_XFRM & changed )
|
||||||
|
{
|
||||||
|
// FIXME: This should probably do the same checks as
|
||||||
|
// xaccSRSaveChangedCells regarding account types
|
||||||
|
// [between different currency accounts, mainly]
|
||||||
|
char *new_name;
|
||||||
|
Account *acct;
|
||||||
|
AccountGroup *acctGrp;
|
||||||
|
GUID *acctGUID;
|
||||||
|
|
||||||
|
// save the account GUID into the kvp_data.
|
||||||
|
new_name = reg->xfrmCell->cell.value;
|
||||||
|
acctGrp = gnc_book_get_group( gncGetCurrentBook() );
|
||||||
|
acct = xaccGetAccountFromFullName( acctGrp, new_name,
|
||||||
|
gnc_get_account_separator() );
|
||||||
|
if ( acct == NULL ) {
|
||||||
|
PERR( "unknown group \"%s\"\n", new_name );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
acctGUID = (const GUID *)xaccAccountGetGUID( acct );
|
||||||
|
kvp_frame_set_slot( kvpf, "sched-xaction/xfrm",
|
||||||
|
kvp_value_new_guid( acctGUID ) );
|
||||||
|
kvpf = xaccSplitGetSlots( split );
|
||||||
|
changed ^= MOD_XFRM;
|
||||||
|
// +DEBUG
|
||||||
|
if ( 0 ) {
|
||||||
|
GList *foo = xaccAccountGetSplitList( template_acc );
|
||||||
|
if ( foo ) {
|
||||||
|
printf( "Splits:\n" );
|
||||||
|
do {
|
||||||
|
printf ("\tsplit: \"%s\"\n", xaccSplitGetMemo( (Split*)foo->data ) );
|
||||||
|
} while ( (foo = foo->next) );
|
||||||
|
} else {
|
||||||
|
printf( "No Splits.\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -DEBUG
|
||||||
|
|
||||||
|
// set the actual account to the fake account for
|
||||||
|
// these templates...
|
||||||
|
xaccAccountInsertSplit (template_acc, split);
|
||||||
|
|
||||||
|
// +DEBUG
|
||||||
|
if ( 0 ) {
|
||||||
|
GList *foo = xaccAccountGetSplitList( template_acc );
|
||||||
|
if ( foo ) {
|
||||||
|
printf( "Splits:\n" );
|
||||||
|
do {
|
||||||
|
printf ("\tsplit: \"%s\"\n", xaccSplitGetMemo( (Split*)foo->data ) );
|
||||||
|
} while ( (foo = foo->next) );
|
||||||
|
} else {
|
||||||
|
printf( "No Splits.\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// -DEBUG
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( MOD_MXFRM & changed )
|
||||||
|
{
|
||||||
|
// DTRT
|
||||||
|
DEBUG( "Template: Got MOD_MXFRM changed\n" );
|
||||||
|
changed ^= MOD_MXFRM;
|
||||||
|
}
|
||||||
|
if ( MOD_AMNT & changed )
|
||||||
|
{
|
||||||
|
char *amountStr = "x + y/42";
|
||||||
|
gnc_numeric new_amount;
|
||||||
|
gnc_numeric credit;
|
||||||
|
gnc_numeric debit;
|
||||||
|
|
||||||
|
//credit = xaccGetPriceCellValue(reg->creditCell);
|
||||||
|
//debit = xaccGetPriceCellValue(reg->debitCell);
|
||||||
|
//new_amount = gnc_numeric_sub_fixed (debit, credit);
|
||||||
|
|
||||||
|
// FIXME: the credit/debit cells are limited to
|
||||||
|
// numeric values by definition [and code]. Blegh.
|
||||||
|
DEBUG( "kvp_frame before: %s\n", kvp_frame_to_string( kvpf ) );
|
||||||
|
//amountStr = gnc_numeric_to_string( new_amount );
|
||||||
|
kvp_frame_set_slot( kvpf, "sched-xaction/credit_formula",
|
||||||
|
kvp_value_new_string( reg->formCreditCell->cell.value ) );
|
||||||
|
kvp_frame_set_slot( kvpf, "sched-xaction/debit_formula",
|
||||||
|
kvp_value_new_string( reg->formDebitCell->cell.value ) );
|
||||||
|
DEBUG( "kvp_frame after: %s\n", kvp_frame_to_string( kvpf ) );
|
||||||
|
changed ^= MOD_AMNT;
|
||||||
|
// set the amount to an innocuous value
|
||||||
|
xaccSplitSetValue (split, gnc_numeric_create(0, 1) );
|
||||||
|
}
|
||||||
|
if ( MOD_SHRS & changed )
|
||||||
|
{
|
||||||
|
char *sharesStr = "(x + y)/42";
|
||||||
|
|
||||||
|
// FIXME: shares cells are numeric by definition.
|
||||||
|
DEBUG( "kvp_frame before: %s\n", kvp_frame_to_string( kvpf ) );
|
||||||
|
|
||||||
|
//sharesStr = gnc_numeric_to_string( sharesStr );
|
||||||
|
kvp_frame_set_slot( kvpf, "sched-xaction/shares",
|
||||||
|
kvp_value_new_string( sharesStr ) );
|
||||||
|
DEBUG( "kvp_frame after: %s\n", kvp_frame_to_string( kvpf ) );
|
||||||
|
// set the shares to an innocuous value
|
||||||
|
xaccSplitSetSharePriceAndAmount (split,
|
||||||
|
gnc_numeric_create(0, 1),
|
||||||
|
gnc_numeric_create(0, 1) );
|
||||||
|
changed ^= MOD_SHRS;
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccSRActuallySaveChangedCells( reg, trans, split, changed );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xaccSRActuallySaveChangedCells( SplitRegister *reg, Transaction *trans, Split *split, guint32 changed )
|
||||||
{
|
{
|
||||||
SRInfo *info = xaccSRGetInfo (reg);
|
SRInfo *info = xaccSRGetInfo (reg);
|
||||||
Split *other_split = NULL;
|
Split *other_split = NULL;
|
||||||
guint32 changed;
|
|
||||||
|
|
||||||
changed = xaccSplitRegisterGetChangeFlag (reg);
|
|
||||||
changed |= xaccSplitRegisterGetConditionalChangeFlag (reg);
|
|
||||||
|
|
||||||
/* copy the contents from the cursor to the split */
|
/* copy the contents from the cursor to the split */
|
||||||
if (MOD_DATE & changed)
|
if (MOD_DATE & changed)
|
||||||
@@ -3214,7 +3367,6 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
|||||||
|
|
||||||
xaccTransSetDateTS (trans, &ts);
|
xaccTransSetDateTS (trans, &ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MOD_NUM & changed)
|
if (MOD_NUM & changed)
|
||||||
{
|
{
|
||||||
DEBUG ("MOD_NUM: %s\n",
|
DEBUG ("MOD_NUM: %s\n",
|
||||||
@@ -3273,6 +3425,10 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
|||||||
* a two-line display, we want to reparent the "other" split, but
|
* a two-line display, we want to reparent the "other" split, but
|
||||||
* only if there is one. XFRM is the straight split, MXFRM is the
|
* only if there is one. XFRM is the straight split, MXFRM is the
|
||||||
* mirrored split. */
|
* mirrored split. */
|
||||||
|
|
||||||
|
// jsled: this is where it starts to get fun. in the template
|
||||||
|
// register, we save the XFRM account in the kvp frame.
|
||||||
|
// also, when loading, we load from the kvp data.
|
||||||
if (MOD_XFRM & changed)
|
if (MOD_XFRM & changed)
|
||||||
{
|
{
|
||||||
Account *old_acc;
|
Account *old_acc;
|
||||||
@@ -3377,13 +3533,13 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
|||||||
|
|
||||||
currency = xaccAccountGetCurrency(new_acc);
|
currency = xaccAccountGetCurrency(new_acc);
|
||||||
currency = xaccTransIsCommonExclSCurrency(trans,
|
currency = xaccTransIsCommonExclSCurrency(trans,
|
||||||
currency, other_split);
|
currency, other_split);
|
||||||
|
|
||||||
if (currency == NULL)
|
if (currency == NULL)
|
||||||
{
|
{
|
||||||
security = xaccAccountGetSecurity(new_acc);
|
security = xaccAccountGetSecurity(new_acc);
|
||||||
security = xaccTransIsCommonExclSCurrency(trans,
|
security = xaccTransIsCommonExclSCurrency(trans,
|
||||||
security, other_split);
|
security, other_split);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((currency != NULL) || (security != NULL))
|
if ((currency != NULL) || (security != NULL))
|
||||||
@@ -3473,6 +3629,22 @@ xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
|||||||
xaccSplitScrub (other_split);
|
xaccSplitScrub (other_split);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xaccSRSaveChangedCells (SplitRegister *reg, Transaction *trans, Split *split)
|
||||||
|
{
|
||||||
|
SRInfo *info = xaccSRGetInfo (reg);
|
||||||
|
Split *other_split = NULL;
|
||||||
|
guint32 changed;
|
||||||
|
|
||||||
|
changed = xaccSplitRegisterGetChangeFlag (reg);
|
||||||
|
changed |= xaccSplitRegisterGetConditionalChangeFlag (reg);
|
||||||
|
|
||||||
|
// all the code in xaccSRActuallySaveChangedCells was right here,
|
||||||
|
// before. -- jsled
|
||||||
|
xaccSRActuallySaveChangedCells( reg, trans, split, changed );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======================================================== */
|
/* ======================================================== */
|
||||||
@@ -3632,6 +3804,125 @@ use_security_cells (SplitRegister *reg, VirtualLocation virt_loc)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
xaccSRTemplateGetEntryHandler( VirtualLocation virt_loc,
|
||||||
|
gboolean translate,
|
||||||
|
gboolean *conditionally_changed,
|
||||||
|
gpointer user_data )
|
||||||
|
{
|
||||||
|
SplitRegister *reg = user_data;
|
||||||
|
const char *value = "";
|
||||||
|
CellType cell_type;
|
||||||
|
Transaction *trans;
|
||||||
|
Split *split;
|
||||||
|
kvp_frame *kvpf;
|
||||||
|
GUID *tmpguid;
|
||||||
|
|
||||||
|
//DEBUG( "In xaccSRTemplateGetEntryHandler\n" );
|
||||||
|
|
||||||
|
cell_type = xaccSplitRegisterGetCellType (reg, virt_loc);
|
||||||
|
|
||||||
|
split = sr_get_split (reg, virt_loc.vcell_loc);
|
||||||
|
if (split == NULL)
|
||||||
|
{
|
||||||
|
return xaccSRGetEntryHandler( virt_loc, translate,
|
||||||
|
conditionally_changed, user_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trans = xaccSplitGetParent (split);
|
||||||
|
kvpf = xaccSplitGetSlots( split );
|
||||||
|
|
||||||
|
switch (cell_type) {
|
||||||
|
case XFRM_CELL:
|
||||||
|
{
|
||||||
|
static char *name = NULL;
|
||||||
|
char account_separator;
|
||||||
|
|
||||||
|
if ( kvpf != NULL ) {
|
||||||
|
DEBUG( "kvp_frame: %s\n", kvp_frame_to_string( kvpf ) );
|
||||||
|
tmpguid = kvp_value_get_guid( kvp_frame_get_slot( kvpf,
|
||||||
|
"sched-xaction/xfrm" ) );
|
||||||
|
DEBUG( "Got the guid \"%s\"\n", guid_to_string( tmpguid ) );
|
||||||
|
account_separator = gnc_get_account_separator();
|
||||||
|
DEBUG( "foo\n" );
|
||||||
|
name = xaccAccountGetFullName (xaccAccountLookup( tmpguid ),
|
||||||
|
account_separator);
|
||||||
|
DEBUG( "bar\n" );
|
||||||
|
|
||||||
|
DEBUG( "Got the full name: %s\n", name );
|
||||||
|
} else {
|
||||||
|
name = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CRED_CELL:
|
||||||
|
case DEBT_CELL:
|
||||||
|
{
|
||||||
|
char *amtStr;
|
||||||
|
gnc_numeric amount;
|
||||||
|
|
||||||
|
if ( kvpf != NULL ) {
|
||||||
|
amtStr = kvp_value_get_string( kvp_frame_get_slot( kvpf,
|
||||||
|
"sched-xaction/amnt" ) );
|
||||||
|
amount = gnc_numeric_create( 0, 1 );
|
||||||
|
string_to_gnc_numeric( amtStr, &amount );
|
||||||
|
|
||||||
|
if (gnc_numeric_zero_p (amount))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (gnc_numeric_negative_p (amount) && (cell_type == DEBT_CELL))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (gnc_numeric_positive_p (amount) && (cell_type == CRED_CELL))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
amount = gnc_numeric_abs (amount);
|
||||||
|
|
||||||
|
//return xaccPrintAmount (amount,
|
||||||
|
//gnc_split_value_print_info (split, FALSE));
|
||||||
|
|
||||||
|
// jsled_FIXME: This should be fixed
|
||||||
|
// to be correct for the "fake" account.
|
||||||
|
return xaccPrintAmount( amount,
|
||||||
|
gnc_default_print_info( FALSE ) );
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FCRED_CELL:
|
||||||
|
{
|
||||||
|
char *formulaStr;
|
||||||
|
if ( kvpf != NULL ) {
|
||||||
|
return kvp_value_get_string( kvp_frame_get_slot( kvpf,
|
||||||
|
"sched-xaction/credit_formula" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FDEBT_CELL:
|
||||||
|
{
|
||||||
|
char *formulaStr;
|
||||||
|
if ( kvpf != NULL ) {
|
||||||
|
return kvp_value_get_string( kvp_frame_get_slot( kvpf,
|
||||||
|
"sched-xaction/debit_formula" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MXFRM_CELL:
|
||||||
|
{
|
||||||
|
return "FIXME:MXFRM";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} // end switch
|
||||||
|
return xaccSRGetEntryHandler( virt_loc,
|
||||||
|
translate,
|
||||||
|
conditionally_changed,
|
||||||
|
user_data );
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
xaccSRGetEntryHandler (VirtualLocation virt_loc, gboolean translate,
|
xaccSRGetEntryHandler (VirtualLocation virt_loc, gboolean translate,
|
||||||
gboolean *conditionally_changed, gpointer user_data)
|
gboolean *conditionally_changed, gpointer user_data)
|
||||||
@@ -3796,8 +4087,6 @@ xaccSRGetEntryHandler (VirtualLocation virt_loc, gboolean translate,
|
|||||||
{
|
{
|
||||||
static char *name = NULL;
|
static char *name = NULL;
|
||||||
|
|
||||||
g_free (name);
|
|
||||||
|
|
||||||
name = xaccAccountGetFullName (xaccSplitGetAccount (split),
|
name = xaccAccountGetFullName (xaccSplitGetAccount (split),
|
||||||
account_separator);
|
account_separator);
|
||||||
|
|
||||||
@@ -3868,8 +4157,6 @@ xaccSRGetEntryHandler (VirtualLocation virt_loc, gboolean translate,
|
|||||||
Split *s = xaccSplitGetOtherSplit (split);
|
Split *s = xaccSplitGetOtherSplit (split);
|
||||||
static char *name = NULL;
|
static char *name = NULL;
|
||||||
|
|
||||||
g_free (name);
|
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
name = xaccAccountGetFullName (xaccSplitGetAccount (s),
|
name = xaccAccountGetFullName (xaccSplitGetAccount (s),
|
||||||
account_separator);
|
account_separator);
|
||||||
@@ -4108,6 +4395,11 @@ xaccSRGetLabelHandler (VirtualLocation virt_loc, gpointer user_data)
|
|||||||
case NOTES_CELL:
|
case NOTES_CELL:
|
||||||
return _("Notes");
|
return _("Notes");
|
||||||
|
|
||||||
|
case FCRED_CELL:
|
||||||
|
return _("Credit Formula");
|
||||||
|
case FDEBT_CELL:
|
||||||
|
return _("Debit Formula");
|
||||||
|
|
||||||
case NO_CELL:
|
case NO_CELL:
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@@ -4120,6 +4412,15 @@ xaccSRGetLabelHandler (VirtualLocation virt_loc, gpointer user_data)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CellIOFlags
|
||||||
|
xaccSRTemplateGetIOFlagsHandler( VirtualLocation virt_loc,
|
||||||
|
gpointer user_data )
|
||||||
|
{
|
||||||
|
//printf( "In xaccSRTemplateGetIOFlagsHandler\n" );
|
||||||
|
return xaccSRGetIOFlagsHandler( virt_loc,
|
||||||
|
user_data );
|
||||||
|
}
|
||||||
|
|
||||||
CellIOFlags
|
CellIOFlags
|
||||||
xaccSRGetIOFlagsHandler (VirtualLocation virt_loc, gpointer user_data)
|
xaccSRGetIOFlagsHandler (VirtualLocation virt_loc, gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -4139,6 +4440,8 @@ xaccSRGetIOFlagsHandler (VirtualLocation virt_loc, gpointer user_data)
|
|||||||
case MEMO_CELL:
|
case MEMO_CELL:
|
||||||
case MXFRM_CELL:
|
case MXFRM_CELL:
|
||||||
case NOTES_CELL:
|
case NOTES_CELL:
|
||||||
|
case FCRED_CELL:
|
||||||
|
case FDEBT_CELL:
|
||||||
return XACC_CELL_ALLOW_ALL;
|
return XACC_CELL_ALLOW_ALL;
|
||||||
|
|
||||||
case CRED_CELL:
|
case CRED_CELL:
|
||||||
@@ -4356,7 +4659,9 @@ xaccSRGetBGColorHandler (VirtualLocation virt_loc,
|
|||||||
if ((cell_type != DEBT_CELL) &&
|
if ((cell_type != DEBT_CELL) &&
|
||||||
(cell_type != CRED_CELL) &&
|
(cell_type != CRED_CELL) &&
|
||||||
(cell_type != TDEBT_CELL) &&
|
(cell_type != TDEBT_CELL) &&
|
||||||
(cell_type != TCRED_CELL))
|
(cell_type != TCRED_CELL) &&
|
||||||
|
(cell_type != FCRED_CELL) &&
|
||||||
|
(cell_type != FDEBT_CELL) )
|
||||||
*hatching = FALSE;
|
*hatching = FALSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4439,6 +4744,14 @@ xaccSRGetBGColorHandler (VirtualLocation virt_loc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
xaccSRTemplateConfirmHandler( VirtualLocation virt_loc,
|
||||||
|
gpointer user_data )
|
||||||
|
{
|
||||||
|
//DEBUG( "In xaccSRConfirmHandler\n" );
|
||||||
|
return xaccSRConfirmHandler( virt_loc, user_data );
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
xaccSRConfirmHandler (VirtualLocation virt_loc,
|
xaccSRConfirmHandler (VirtualLocation virt_loc,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
|
|||||||
@@ -166,6 +166,8 @@ void xaccSRLoadRegister (SplitRegister *reg, GList * slist,
|
|||||||
* a refresh will result in a new blank transaction.
|
* a refresh will result in a new blank transaction.
|
||||||
* The method returns TRUE if something was changed. */
|
* The method returns TRUE if something was changed. */
|
||||||
gboolean xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit);
|
gboolean xaccSRSaveRegEntry (SplitRegister *reg, gboolean do_commit);
|
||||||
|
gboolean xaccSRTemplateSaveRegEntry (SplitRegister *reg,
|
||||||
|
gboolean do_commit);
|
||||||
|
|
||||||
/* The xaccSRRedrawReg() method should be called soon
|
/* The xaccSRRedrawReg() method should be called soon
|
||||||
* after the xaccSRSaveRegEntry() method. It checks the
|
* after the xaccSRSaveRegEntry() method. It checks the
|
||||||
@@ -209,10 +211,16 @@ const char * xaccSRGetEntryHandler (VirtualLocation virt_loc,
|
|||||||
gboolean translate,
|
gboolean translate,
|
||||||
gboolean *changed,
|
gboolean *changed,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
const char * xaccSRTemplateGetEntryHandler (VirtualLocation virt_loc,
|
||||||
|
gboolean translate,
|
||||||
|
gboolean *changed,
|
||||||
|
gpointer user_data);
|
||||||
const char * xaccSRGetLabelHandler (VirtualLocation virt_loc,
|
const char * xaccSRGetLabelHandler (VirtualLocation virt_loc,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
CellIOFlags xaccSRGetIOFlagsHandler (VirtualLocation virt_loc,
|
CellIOFlags xaccSRGetIOFlagsHandler (VirtualLocation virt_loc,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
CellIOFlags xaccSRTemplateGetIOFlagsHandler (VirtualLocation virt_loc,
|
||||||
|
gpointer user_data);
|
||||||
guint32 xaccSRGetFGColorHandler (VirtualLocation virt_loc,
|
guint32 xaccSRGetFGColorHandler (VirtualLocation virt_loc,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
guint32 xaccSRGetBGColorHandler (VirtualLocation virt_loc,
|
guint32 xaccSRGetBGColorHandler (VirtualLocation virt_loc,
|
||||||
@@ -223,5 +231,14 @@ void xaccSRGetCellBorderHandler (VirtualLocation virt_loc,
|
|||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
gboolean xaccSRConfirmHandler (VirtualLocation virt_loc,
|
gboolean xaccSRConfirmHandler (VirtualLocation virt_loc,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
gboolean xaccSRTemplateConfirmHandler (VirtualLocation virt_loc,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
// jsled-added 2001.05.19 for export to dialog-nextrun.c [which will
|
||||||
|
// change its name at some point]
|
||||||
|
void gnc_copy_trans_onto_trans(Transaction *from, Transaction *to,
|
||||||
|
gboolean use_cut_semantics,
|
||||||
|
gboolean do_commit);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __XACC_SPLIT_LEDGER_H__ */
|
#endif /* __XACC_SPLIT_LEDGER_H__ */
|
||||||
|
|||||||
144
src/doc/TODO-schedxactions
Normal file
144
src/doc/TODO-schedxactions
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
Author: jsled@asynchronous.org
|
||||||
|
|
||||||
|
Main Scheduled Transaction todo list
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
. Engine ...Init() functions should be private.
|
||||||
|
. FreqSpec.c
|
||||||
|
. xaccFreqSpecGetFreqStr [display] needs to go away
|
||||||
|
|
||||||
|
. finish the GNCFrequency widget
|
||||||
|
. finish/recreate restoring UI state from FreqSpec.
|
||||||
|
X add the ...GetFreqStr() code for the complex composite FreqSpecs
|
||||||
|
X fix the ...GetNextInstance() code
|
||||||
|
X XMLv2 I/O
|
||||||
|
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
|
||||||
|
. 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.
|
||||||
|
. create transactions
|
||||||
|
X numeric
|
||||||
|
. formula
|
||||||
|
. need variable fill-in UI...
|
||||||
|
. re-use gnome-sheet code for a variable-binding table?
|
||||||
|
. 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
|
||||||
|
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
|
||||||
|
. weekly options
|
||||||
|
. restoring FreqSpec into GNCFrequency UI
|
||||||
|
. initial-settings synchronization [start date, optionmenus]
|
||||||
|
. backend support
|
||||||
|
. PostgreSQL
|
||||||
|
. others?
|
||||||
|
|
||||||
|
|
||||||
|
Enhancements:
|
||||||
|
. SX name should be default value for template transaction description
|
||||||
|
. loan/repayment SX's
|
||||||
|
. integrate "Financial Calculator"
|
||||||
|
. auto-determine number of occurances/end condition from liability
|
||||||
|
account amount.
|
||||||
|
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Template Registers/Transactions
|
||||||
|
|
||||||
|
Template-option registers are used for users to enter the template
|
||||||
|
transaction to be created when the scheduled transaction comes due.
|
||||||
|
Most fields will be copied directly, but certain fields will need to
|
||||||
|
be modified upon instantiation, and the template version of these
|
||||||
|
transactions will need to contain the information necessary to do that
|
||||||
|
instiantion. For some fields, this will be a derivable quantity, and
|
||||||
|
for others the user will need to be prompted. This will show up
|
||||||
|
mostly for the amount of variable-amount transactions; perhaps the
|
||||||
|
amount is then derivable from some external source. These amounts
|
||||||
|
will then be represented by a variable, a function, or a formula
|
||||||
|
including both.
|
||||||
|
|
||||||
|
Examples...
|
||||||
|
|
||||||
|
Verizon bill: "108.83 +- x"
|
||||||
|
. x: tax amounts [user-input]
|
||||||
|
Power: "seasonal_util_gas( 'OAK_CA', '100 therms' ) + seasonal_util_elec( 'OAK_CA', '220 kwhrs' )"
|
||||||
|
. seasonal_util_gas( loc, amt ): regional/seasonal power price
|
||||||
|
. seasonal_util_elec( loc, amt ): regional/seasonal electricity price
|
||||||
|
Rent: 1900
|
||||||
|
Phone: "26"
|
||||||
|
Internet: "80 - 40 - 10" [3 splits]
|
||||||
|
Daily: "4 + 6 (+ 26)"
|
||||||
|
. 4: cigarettes
|
||||||
|
. 6: avg lunch
|
||||||
|
. (opt) 20: wine
|
||||||
|
Gas: "regional_auto_gas( 'BERK_CA', 'premium', 14 gal +- 2 )"
|
||||||
|
. regional_gas( loc, type, formula )
|
||||||
|
. loc: location
|
||||||
|
. type: subclass of gasoline
|
||||||
|
. formula: formula to use for user-query
|
||||||
|
TROA: "220.14"
|
||||||
|
|
||||||
|
User-input
|
||||||
|
|
||||||
|
When user input is required for scheduled transaction instantiation,
|
||||||
|
we should have some sort of simple, spreadsheet-like UI for the entry
|
||||||
|
and verification of values. This would allow the entry of all values
|
||||||
|
necessary for the formula to be calculated.
|
||||||
|
|
||||||
|
We also need a way to defer instantiation of a scheduled transaction
|
||||||
|
until the information can be obtained.
|
||||||
|
|
||||||
|
Example...
|
||||||
|
|
||||||
|
type | date | formula | variable | value | total
|
||||||
|
+---------------------------------------------------------------------------+
|
||||||
|
| PG&E | 2001.04.12 | lookup(x) + lookup| | | 184 |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | x | 142 | |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | y | 42 | |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| gas | 2001.03.01 | cost/gal * gal | | | |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | cost/gal | 1.949 | 14.27 |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | gal | 12.32 | |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| gas | 2001.03.12 | cost/gal * gal | | | |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | cost/gal | 1.959 | 15.39 |
|
||||||
|
|---------------------------------------------------------------------------|
|
||||||
|
| | | | gal | 13.43 | |
|
||||||
|
+---------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
I believe this means we can use the existing gnc-sheet/register-style
|
||||||
|
thingy.
|
||||||
|
|
||||||
|
We probably want to defer the lookup-based stuff until
|
||||||
|
1.8/2.0/gnumatic-provided network backing for this.
|
||||||
|
|
||||||
|
Stocks/recurring share purchases can make use of this, as well. The
|
||||||
|
idea is then, probably, that the user will have a fixed amount with
|
||||||
|
which to buy as many shares as possible; the num-shares, then, is a
|
||||||
|
formula based on a lookup at the given time [the share price],
|
||||||
|
involving the function FLOOR.
|
||||||
|
|
||||||
|
It'd be nice if this formula could be either a simple infix syntax for
|
||||||
|
normal people, or a sexp for Schemers.
|
||||||
812
src/engine/FreqSpec.c
Normal file
812
src/engine/FreqSpec.c
Normal file
@@ -0,0 +1,812 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* FreqSpec.c -- Frequency specifier implementation. *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au> *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
* *
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
Current status
|
||||||
|
All kinds of repeats work, including composites. This is tested -
|
||||||
|
although composites need some more test cases to be put into the test
|
||||||
|
suite - ../test/test-freq-spec.c
|
||||||
|
FreqSpec objects are currently 'set' to give them the information
|
||||||
|
they need. Separate methods for modifying currently existing FreqSpec
|
||||||
|
objects are not provided. In the case of composites, you may add FreqSpec
|
||||||
|
objects to a composite, and you may access a list of the FreqSpec objects
|
||||||
|
which form the composite. This interface allows you to do damage...
|
||||||
|
|
||||||
|
TODO list
|
||||||
|
Ben Stanley 2001-04-02
|
||||||
|
* Write xaccFreqSpecGetFreqStr (I wonder how this will be
|
||||||
|
internationalised... I suspect that this code will need to be
|
||||||
|
re-written for each language, because the code will have to
|
||||||
|
generate grammar... It's more than just translating strings.)
|
||||||
|
However, the first priority is to write one that works for
|
||||||
|
English.
|
||||||
|
* Write a function to allow you to query whether a given
|
||||||
|
date forms part of the recurrence.
|
||||||
|
* Write a method to get the previous recurrence
|
||||||
|
* provide XML Load/Save functionality for this object.
|
||||||
|
* Figure out xaccFreqSpecIsValidDate - I suspect that this is the
|
||||||
|
'query whether a given date forms part of the recurrence'
|
||||||
|
above.
|
||||||
|
* FIGURE OUT WHAT'S GOING ON WITH xaccFreqSpecGetUIType AND
|
||||||
|
xaccFreqSpecSetUIType.
|
||||||
|
* Try to reduce the size of the data structure. There are quite a few
|
||||||
|
32 bit fields which could be stored in about 8 bits.
|
||||||
|
* Add public methods to allow for recurrences with an interval
|
||||||
|
of 1 to be set without reference to an initial 'date' - monthly
|
||||||
|
things in particular. Try to reduce the dependence on an initial
|
||||||
|
date for the input to set up the recurrence.
|
||||||
|
|
||||||
|
Questions:
|
||||||
|
Is it best that the public interface stay as GDate, or should it
|
||||||
|
really be a timespec? I have no problem with converting GDates to
|
||||||
|
timespecs for load/save if that makes life easier.
|
||||||
|
|
||||||
|
However, I chose to use GDate internally because I have used a *lot*
|
||||||
|
of the date calculating ability of GDate in the internal implementation.
|
||||||
|
GDate has simplified this work enormously compared to using struct tm
|
||||||
|
and time_t. The engine's timespec object doesn't appear to have the
|
||||||
|
required functionality either, so I would need to write the required
|
||||||
|
functions for timespec (perhaps by implementing in terms of GDate?).
|
||||||
|
|
||||||
|
Hopefully it's not too painful to leave GDate in the public interface
|
||||||
|
and change other code to use it.
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
/* #include <time.h> // should be config'd */
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "FreqSpecP.h"
|
||||||
|
#include "GNCIdP.h"
|
||||||
|
/*#include "Transaction.h"*/
|
||||||
|
/*#include "TransactionP.h"*/
|
||||||
|
#include "date.h"
|
||||||
|
#include "gnc-engine-util.h"
|
||||||
|
#include "gnc-event-p.h"
|
||||||
|
#include "messages.h"
|
||||||
|
|
||||||
|
/* I have done this to prevent compiler warnings...
|
||||||
|
* This is used to convert a const GDate* to a GDate* for passing
|
||||||
|
* to the glib g_date_xxx functions which don't use const...
|
||||||
|
* Strangely, most of the rest of glib does use const, so
|
||||||
|
* perhaps this will change? When it does, just define this macro to
|
||||||
|
* nothing and the compiler will check the constness of each pointer....
|
||||||
|
*/
|
||||||
|
#define CONST_HACK (GDate*)
|
||||||
|
|
||||||
|
static short module = MOD_SX;
|
||||||
|
|
||||||
|
/** PROTOTYPES ******************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys all sub-FreqSpecs in a composite FreqSpec.
|
||||||
|
* Assertion error if it's not a COMPOSITE FreqSpec.
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecCompositesClear( FreqSpec *fs );
|
||||||
|
|
||||||
|
void subSpecsListMapDelete( gpointer data, gpointer user_data );
|
||||||
|
|
||||||
|
/** Local data defs *****/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of days in each month.
|
||||||
|
**/
|
||||||
|
struct monthDesc {
|
||||||
|
char *dshort;
|
||||||
|
char *dlong;
|
||||||
|
gint numDays;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This stuff is going to need i18n.
|
||||||
|
* wouldn't it be simpler to use the system
|
||||||
|
* date conversion functions?
|
||||||
|
* glib already knows about this. */
|
||||||
|
static char *weekDayNames[] = {
|
||||||
|
"Sunday",
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* hmmm... glib already knows all about this. */
|
||||||
|
struct monthDesc monthInfo[] = {
|
||||||
|
#define M_JAN 0
|
||||||
|
{ "Jan", "January", 31 },
|
||||||
|
#define M_FEB 1
|
||||||
|
{ "Feb", "February", 28 },
|
||||||
|
#define M_MAR 2
|
||||||
|
{ "Mar", "March", 31 },
|
||||||
|
#define M_APR 3
|
||||||
|
{ "Apr", "April", 30 },
|
||||||
|
#define M_MAY 4
|
||||||
|
{ "May", "May", 31 },
|
||||||
|
#define M_JUN 5
|
||||||
|
{ "Jun", "June", 30 },
|
||||||
|
#define M_JUL 6
|
||||||
|
{ "Jul", "July", 31 },
|
||||||
|
#define M_AUG 7
|
||||||
|
{ "Aug", "August", 31 },
|
||||||
|
#define M_SEP 8
|
||||||
|
{ "Sep", "September", 30 },
|
||||||
|
#define M_OCT 9
|
||||||
|
{ "Oct", "October", 31 },
|
||||||
|
#define M_NOV 10
|
||||||
|
{ "Nov", "November", 30 },
|
||||||
|
#define M_DEC 11
|
||||||
|
{ "Dec", "December", 31 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Local Prototypes *****/
|
||||||
|
|
||||||
|
FreqSpec*
|
||||||
|
xaccFreqSpecMalloc()
|
||||||
|
{
|
||||||
|
FreqSpec *fs = g_new0(FreqSpec, 1);
|
||||||
|
xaccFreqSpecInit( fs );
|
||||||
|
// FIXME:event
|
||||||
|
gnc_engine_generate_event( &fs->guid, GNC_EVENT_CREATE );
|
||||||
|
return fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecInit( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
xaccGUIDNew( &fs->guid );
|
||||||
|
xaccStoreEntity( fs, &fs->guid, GNC_ID_FREQSPEC );
|
||||||
|
fs->type = INVALID;
|
||||||
|
fs->uift = UIFREQ_ONCE;
|
||||||
|
memset( &(fs->s), 0, sizeof(fs->s) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecCleanUp( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
switch ( fs->type ) {
|
||||||
|
case INVALID:
|
||||||
|
case ONCE:
|
||||||
|
case DAILY:
|
||||||
|
case WEEKLY:
|
||||||
|
case MONTHLY:
|
||||||
|
case MONTH_RELATIVE:
|
||||||
|
break;
|
||||||
|
case COMPOSITE:
|
||||||
|
xaccFreqSpecCompositesClear( fs );
|
||||||
|
g_list_free( fs->s.composites.subSpecs );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_return_if_fail(FALSE);
|
||||||
|
}
|
||||||
|
fs->type = INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecFree( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
if ( fs == NULL ) return;
|
||||||
|
gnc_engine_generate_event( &fs->guid, GNC_EVENT_DESTROY );
|
||||||
|
xaccRemoveEntity( &fs->guid );
|
||||||
|
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
|
||||||
|
g_free( fs );
|
||||||
|
}
|
||||||
|
|
||||||
|
FreqType
|
||||||
|
xaccFreqSpecGetType( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_val_if_fail( fs, INVALID );
|
||||||
|
/* Is this really a fail? */
|
||||||
|
g_return_val_if_fail( fs->type != INVALID, INVALID );
|
||||||
|
return fs->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UIFreqType
|
||||||
|
xaccFreqSpecGetUIType( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_val_if_fail( fs, INVALID );
|
||||||
|
return fs->uift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetUIType( FreqSpec *fs, UIFreqType newUIFreqType )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
fs->uift = newUIFreqType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetTypes( FreqSpec *fs, FreqType newFT, UIFreqType newUIFT )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
xaccFreqSpecSetType( fs, newFT );
|
||||||
|
xaccFreqSpecSetUIType( fs, newUIFT );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline guint32 min( guint32 a, guint32 b )
|
||||||
|
{
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecGetNextInstance(
|
||||||
|
FreqSpec *fs,
|
||||||
|
const GDate* in_date,
|
||||||
|
GDate* out_date )
|
||||||
|
{
|
||||||
|
GList *list, *blist;
|
||||||
|
int mon;
|
||||||
|
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
switch( fs->type ) {
|
||||||
|
case INVALID:
|
||||||
|
g_return_if_fail(FALSE);
|
||||||
|
|
||||||
|
case ONCE:
|
||||||
|
if ( g_date_compare( &(fs->s.once.date), CONST_HACK in_date ) > 0 ) {
|
||||||
|
*out_date = fs->s.once.date;
|
||||||
|
} else {
|
||||||
|
/* Date is past due. Return an invalid date. */
|
||||||
|
g_date_clear( out_date, 1 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DAILY: {
|
||||||
|
guint32 julian_in_date, julian_next_repeat, complete_intervals;
|
||||||
|
julian_in_date = g_date_julian( CONST_HACK in_date );
|
||||||
|
complete_intervals =
|
||||||
|
(julian_in_date - fs->s.daily.offset_from_epoch) /
|
||||||
|
fs->s.daily.interval_days;
|
||||||
|
julian_next_repeat =
|
||||||
|
fs->s.daily.offset_from_epoch +
|
||||||
|
(complete_intervals + 1) * fs->s.daily.interval_days;
|
||||||
|
g_date_set_julian( out_date, julian_next_repeat );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WEEKLY: {
|
||||||
|
/* This implementation stores the offset from epoch as the number
|
||||||
|
* of days, not week epoch offset and day in week offset.
|
||||||
|
* It is very similar to the daily repeat representation. */
|
||||||
|
guint32 julian_in_date, julian_next_repeat, complete_intervals;
|
||||||
|
julian_in_date = g_date_julian( CONST_HACK in_date );
|
||||||
|
complete_intervals =
|
||||||
|
(julian_in_date - fs->s.weekly.offset_from_epoch) /
|
||||||
|
(fs->s.weekly.interval_weeks * 7);
|
||||||
|
julian_next_repeat =
|
||||||
|
fs->s.weekly.offset_from_epoch +
|
||||||
|
(complete_intervals + 1) * fs->s.weekly.interval_weeks * 7;
|
||||||
|
g_date_set_julian( out_date, julian_next_repeat );
|
||||||
|
|
||||||
|
/* This code passes the test, but it seems large and complicated...
|
||||||
|
* it uses a separate week offset from epoch and day in week offset. */
|
||||||
|
/* guint32 julian_in_date, julian_next_repeat, complete_intervals,
|
||||||
|
in_weeks_from_epoch, after_repeat_in_week_interval;
|
||||||
|
julian_in_date = g_date_julian( CONST_HACK in_date );
|
||||||
|
in_weeks_from_epoch = (julian_in_date-1) / 7;
|
||||||
|
complete_intervals =
|
||||||
|
(in_weeks_from_epoch -
|
||||||
|
fs->s.weekly.offset_from_epoch) /
|
||||||
|
fs->s.weekly.interval_weeks;
|
||||||
|
after_repeat_in_week_interval =
|
||||||
|
((julian_in_date-1) % 7 >= fs->s.weekly.day_of_week ||
|
||||||
|
(in_weeks_from_epoch - fs->s.weekly.offset_from_epoch) %
|
||||||
|
fs->s.weekly.interval_weeks > 0 ) ? 1 : 0;
|
||||||
|
julian_next_repeat =
|
||||||
|
(fs->s.weekly.offset_from_epoch +
|
||||||
|
(complete_intervals + after_repeat_in_week_interval) *
|
||||||
|
fs->s.weekly.interval_weeks) * 7 +
|
||||||
|
fs->s.weekly.day_of_week + 1;
|
||||||
|
g_date_set_julian( out_date, julian_next_repeat );
|
||||||
|
*/
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MONTHLY: {
|
||||||
|
guint32 in_months_from_epoch, after_repeat_in_month_interval,
|
||||||
|
complete_intervals, next_repeat_months_from_epoch, month, year;
|
||||||
|
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
|
||||||
|
g_date_month( CONST_HACK in_date ) - 1;
|
||||||
|
complete_intervals =
|
||||||
|
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) /
|
||||||
|
fs->s.monthly.interval_months;
|
||||||
|
after_repeat_in_month_interval =
|
||||||
|
(g_date_day( CONST_HACK in_date ) >= fs->s.monthly.day_of_month ||
|
||||||
|
(in_months_from_epoch - fs->s.monthly.offset_from_epoch) %
|
||||||
|
fs->s.monthly.interval_months > 0 ||
|
||||||
|
g_date_day( CONST_HACK in_date ) >=
|
||||||
|
g_date_days_in_month( g_date_month( CONST_HACK in_date ),
|
||||||
|
g_date_year( CONST_HACK in_date ) ) ) ? 1 : 0;
|
||||||
|
next_repeat_months_from_epoch =
|
||||||
|
fs->s.monthly.offset_from_epoch +
|
||||||
|
(complete_intervals + after_repeat_in_month_interval) *
|
||||||
|
fs->s.monthly.interval_months;
|
||||||
|
/* Hmmm... what happens if the day of the month is greater than the
|
||||||
|
* number of days in this month?
|
||||||
|
* Here I have constrained the day of the month by the number
|
||||||
|
* of days in the month. This is compensated for above by checking if
|
||||||
|
* the input day is the last day of that month, in which case it will
|
||||||
|
* move to the next month interval.
|
||||||
|
*/
|
||||||
|
month = next_repeat_months_from_epoch % 12 + 1;
|
||||||
|
year = next_repeat_months_from_epoch / 12 + 1;
|
||||||
|
g_date_set_dmy( out_date,
|
||||||
|
min( fs->s.monthly.day_of_month,
|
||||||
|
g_date_days_in_month( month, year ) ),
|
||||||
|
month,
|
||||||
|
year );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MONTH_RELATIVE: {
|
||||||
|
guint32 in_months_from_epoch, after_repeat_in_month_interval,
|
||||||
|
complete_intervals, next_repeat_months_from_epoch, month, year,
|
||||||
|
wday_of_1st, day_of_repeat;
|
||||||
|
GDate date1;
|
||||||
|
in_months_from_epoch = (g_date_year( CONST_HACK in_date )-1) * 12 +
|
||||||
|
g_date_month( CONST_HACK in_date ) - 1;
|
||||||
|
complete_intervals =
|
||||||
|
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) /
|
||||||
|
fs->s.month_relative.interval_months;
|
||||||
|
month = g_date_month( CONST_HACK in_date );
|
||||||
|
year = g_date_year( CONST_HACK in_date );
|
||||||
|
g_date_set_dmy( &date1, 1, month, year );
|
||||||
|
wday_of_1st = g_date_weekday( &date1 );
|
||||||
|
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
|
||||||
|
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
|
||||||
|
after_repeat_in_month_interval =
|
||||||
|
(g_date_day( CONST_HACK in_date ) >= day_of_repeat ||
|
||||||
|
day_of_repeat > g_date_days_in_month( month, year ) ||
|
||||||
|
(in_months_from_epoch - fs->s.month_relative.offset_from_epoch) %
|
||||||
|
fs->s.month_relative.interval_months > 0 ) ? 1 : 0;
|
||||||
|
next_repeat_months_from_epoch =
|
||||||
|
fs->s.month_relative.offset_from_epoch +
|
||||||
|
(complete_intervals + after_repeat_in_month_interval) *
|
||||||
|
fs->s.month_relative.interval_months;
|
||||||
|
month = next_repeat_months_from_epoch % 12 + 1;
|
||||||
|
year = next_repeat_months_from_epoch / 12 + 1;
|
||||||
|
g_date_set_dmy( &date1, 1, month, year );
|
||||||
|
wday_of_1st = g_date_weekday( &date1 );
|
||||||
|
/* This calculates the day of the month in the month which forms
|
||||||
|
* the next month in the cycle after the given input date.
|
||||||
|
* However, this day may be larger than the number of days in that month... */
|
||||||
|
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
|
||||||
|
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
|
||||||
|
while( day_of_repeat > g_date_days_in_month( month, year ) ) {
|
||||||
|
/* If the repeat occurs after the end of the month, then
|
||||||
|
* find the next month containing a day which satisfies the request.
|
||||||
|
* Each candiate month separated by interval_months is considered
|
||||||
|
* by this loop.*/
|
||||||
|
++complete_intervals;
|
||||||
|
next_repeat_months_from_epoch =
|
||||||
|
fs->s.month_relative.offset_from_epoch +
|
||||||
|
complete_intervals * fs->s.month_relative.interval_months;
|
||||||
|
month = next_repeat_months_from_epoch % 12 + 1;
|
||||||
|
year = next_repeat_months_from_epoch / 12 + 1;
|
||||||
|
g_date_set_dmy( &date1, 1, month, year );
|
||||||
|
wday_of_1st = g_date_weekday( &date1 );
|
||||||
|
day_of_repeat = (fs->s.month_relative.occurrence-1)*7 +
|
||||||
|
((fs->s.month_relative.weekday + 7 - wday_of_1st)%7 + 1);
|
||||||
|
/* Hmmm... It would be nice to know that this loop is
|
||||||
|
* guaranteed to terminate... CHECK ME! */
|
||||||
|
}
|
||||||
|
g_date_set_dmy( out_date, day_of_repeat, month, year );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case COMPOSITE:
|
||||||
|
list = fs->s.composites.subSpecs;
|
||||||
|
if ( !list ) {
|
||||||
|
/* sets date to be invalid */
|
||||||
|
g_date_clear( out_date, 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
/* This implements || composites. */
|
||||||
|
guint32 min_julian = 0xFFFFFFFF; /* the biggest unsigned 32 bit number */
|
||||||
|
guint32 this_julian;
|
||||||
|
do {
|
||||||
|
GDate next_repeat;
|
||||||
|
xaccFreqSpecGetNextInstance(
|
||||||
|
(FreqSpec*) list->data,
|
||||||
|
in_date,
|
||||||
|
&next_repeat );
|
||||||
|
this_julian = g_date_julian( &next_repeat );
|
||||||
|
|
||||||
|
min_julian = min( min_julian, this_julian );
|
||||||
|
|
||||||
|
} while ( (list = g_list_next(list)) );
|
||||||
|
g_date_set_julian( out_date, min_julian );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_date_clear( out_date, 1 );
|
||||||
|
g_return_if_fail(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
char*
|
||||||
|
xaccFreqSpecIsValidDateRelaxed( FreqSpec *fs, time_t query )
|
||||||
|
{
|
||||||
|
return "FIXME: not implemented yet!";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetOnceDate( FreqSpec *fs, const GDate* when )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( when );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
fs->type = ONCE;
|
||||||
|
fs->s.once.date = *when;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetDaily( FreqSpec *fs,
|
||||||
|
const GDate* initial_date,
|
||||||
|
guint interval_days )
|
||||||
|
{
|
||||||
|
guint32 julian_days_since_epoch;
|
||||||
|
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_days > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
fs->type = DAILY;
|
||||||
|
fs->s.daily.interval_days = interval_days;
|
||||||
|
|
||||||
|
julian_days_since_epoch = g_date_julian( CONST_HACK initial_date );
|
||||||
|
fs->s.daily.offset_from_epoch = julian_days_since_epoch % interval_days;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetWeekly( FreqSpec *fs,
|
||||||
|
const GDate* initial_date,
|
||||||
|
guint interval_weeks )
|
||||||
|
{
|
||||||
|
/* pick one... make sure that the code in next matches this,
|
||||||
|
* and that the fields in the
|
||||||
|
* weekly struct match too.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
/* *
|
||||||
|
* This implements weekly by using the fact that 1 week = 7 days.
|
||||||
|
* Weeks start at epoch in this representation, not necesarily Monday,
|
||||||
|
* so there is not really any difference...
|
||||||
|
* The weekly tests pass.
|
||||||
|
*/
|
||||||
|
guint32 julian_days_since_epoch;
|
||||||
|
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_weeks > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
|
||||||
|
fs->type = DAILY;
|
||||||
|
fs->s.daily.interval_days = 7 * interval_weeks;
|
||||||
|
|
||||||
|
julian_days_since_epoch = g_date_julian( CONST_HACK initial_date );
|
||||||
|
fs->s.daily.offset_from_epoch = julian_days_since_epoch % (7*interval_weeks);
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
|
/* simplest solution */
|
||||||
|
guint32 julian_days_since_epoch;
|
||||||
|
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_weeks > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
|
||||||
|
fs->type = WEEKLY;
|
||||||
|
fs->s.weekly.interval_weeks = interval_weeks;
|
||||||
|
|
||||||
|
julian_days_since_epoch = g_date_julian( CONST_HACK initial_date );
|
||||||
|
fs->s.weekly.offset_from_epoch = julian_days_since_epoch % (7*interval_weeks);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* Use the weekly implementation, which seems to be more complicated...
|
||||||
|
* uses separate weekly and day in week offsets.
|
||||||
|
* works.
|
||||||
|
*/
|
||||||
|
guint32 julian_day_initial, weeks_since_epoch;
|
||||||
|
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_weeks > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
|
||||||
|
fs->type = WEEKLY;
|
||||||
|
fs->s.weekly.interval_weeks = interval_weeks;
|
||||||
|
|
||||||
|
julian_day_initial = g_date_julian( CONST_HACK initial_date );
|
||||||
|
weeks_since_epoch = (julian_day_initial-1) / 7;
|
||||||
|
fs->s.weekly.day_of_week = (julian_day_initial-1) % 7;
|
||||||
|
fs->s.weekly.offset_from_epoch = weeks_since_epoch % interval_weeks;
|
||||||
|
|
||||||
|
g_return_if_fail( 0 <= fs->s.weekly.day_of_week );
|
||||||
|
g_return_if_fail( fs->s.weekly.day_of_week < 7 );
|
||||||
|
g_return_if_fail( fs->s.weekly.offset_from_epoch < interval_weeks );
|
||||||
|
g_return_if_fail( 0 <= fs->s.weekly.offset_from_epoch );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetMonthly( FreqSpec *fs,
|
||||||
|
const GDate* initial_date,
|
||||||
|
guint interval_months )
|
||||||
|
{
|
||||||
|
guint months_since_epoch;
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_months > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
fs->type = MONTHLY;
|
||||||
|
fs->s.monthly.interval_months = interval_months;
|
||||||
|
|
||||||
|
months_since_epoch = (g_date_year( CONST_HACK initial_date )-1) * 12 +
|
||||||
|
g_date_month( CONST_HACK initial_date ) - 1;
|
||||||
|
fs->s.monthly.offset_from_epoch = months_since_epoch % interval_months;
|
||||||
|
fs->s.monthly.day_of_month = g_date_day( CONST_HACK initial_date );
|
||||||
|
|
||||||
|
g_return_if_fail( fs->s.monthly.offset_from_epoch <
|
||||||
|
fs->s.monthly.interval_months );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetMonthRelative( FreqSpec *fs,
|
||||||
|
const GDate* initial_date,
|
||||||
|
guint interval_months )
|
||||||
|
{
|
||||||
|
guint months_since_epoch;
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( interval_months > 0 );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
fs->type = MONTH_RELATIVE;
|
||||||
|
fs->s.month_relative.interval_months = interval_months;
|
||||||
|
|
||||||
|
months_since_epoch = (g_date_year( CONST_HACK initial_date )-1) * 12 +
|
||||||
|
g_date_month( CONST_HACK initial_date ) - 1;
|
||||||
|
fs->s.month_relative.offset_from_epoch = months_since_epoch % interval_months;
|
||||||
|
|
||||||
|
fs->s.month_relative.weekday = g_date_weekday( CONST_HACK initial_date );
|
||||||
|
fs->s.month_relative.occurrence = (g_date_day( CONST_HACK initial_date )-1) / 7 + 1;
|
||||||
|
|
||||||
|
g_return_if_fail( fs->s.month_relative.weekday > 0 );
|
||||||
|
g_return_if_fail( fs->s.month_relative.weekday <= 7 );
|
||||||
|
g_return_if_fail( fs->s.month_relative.occurrence > 0 );
|
||||||
|
g_return_if_fail( fs->s.month_relative.occurrence <= 5 );
|
||||||
|
g_return_if_fail( fs->s.month_relative.offset_from_epoch <
|
||||||
|
fs->s.month_relative.interval_months );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecSetComposite( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
xaccFreqSpecCleanUp( fs );
|
||||||
|
fs->type = COMPOSITE;
|
||||||
|
fs->s.composites.subSpecs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
xaccFreqSpecCompositeGet( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_val_if_fail( fs, NULL );
|
||||||
|
g_return_val_if_fail( fs->type == COMPOSITE, NULL );
|
||||||
|
return fs->s.composites.subSpecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecCompositeAdd( FreqSpec *fs, FreqSpec *fsToAdd )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
g_return_if_fail( fs->type == COMPOSITE );
|
||||||
|
fs->s.composites.subSpecs =
|
||||||
|
g_list_append( fs->s.composites.subSpecs, fsToAdd );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
subSpecsListMapDelete( gpointer data, gpointer user_data )
|
||||||
|
{
|
||||||
|
xaccFreqSpecFree( (FreqSpec*)data );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecCompositesClear( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs->type == COMPOSITE );
|
||||||
|
g_list_foreach( fs->s.composites.subSpecs,
|
||||||
|
subSpecsListMapDelete, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str )
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
FreqSpec *tmpFS;
|
||||||
|
int tmpInt;
|
||||||
|
char *tmpStr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// FIXME: fill in.
|
||||||
|
switch( xaccFreqSpecGetUIType( fs ) ) {
|
||||||
|
case UIFREQ_ONCE:
|
||||||
|
tmpStr = g_new0( char, 25 );
|
||||||
|
// this is now a GDate.
|
||||||
|
g_date_strftime( tmpStr, 25,
|
||||||
|
"%a, %b %e, %Y",
|
||||||
|
&fs->s.once.date );
|
||||||
|
g_string_sprintf( str, "Once: %s", tmpStr );
|
||||||
|
g_free( tmpStr );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_DAILY:
|
||||||
|
g_string_sprintf( str, "Daily" );
|
||||||
|
if ( fs->s.daily.interval_days > 1 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.daily.interval_days );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_DAILY_MF:
|
||||||
|
g_string_sprintf( str, "Daily [M-F]" );
|
||||||
|
if ( fs->s.weekly.interval_weeks > 1 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.weekly.interval_weeks );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_WEEKLY:
|
||||||
|
g_string_sprintf( str, "Weekly" );
|
||||||
|
tmpInt = -1;
|
||||||
|
tmpStr = g_new0( char, 8 );
|
||||||
|
for ( i=0; i<7; i++ ) {
|
||||||
|
tmpStr[i] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
list = xaccFreqSpecCompositeGet( fs );
|
||||||
|
do {
|
||||||
|
tmpFS = (FreqSpec*)list->data;
|
||||||
|
if ( xaccFreqSpecGetType(tmpFS) != WEEKLY ) {
|
||||||
|
g_string_sprintf( str,
|
||||||
|
"error: UIFREQ_WEEKLY doesn't contain weekly children" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( tmpInt == -1 ) {
|
||||||
|
tmpInt = tmpFS->s.weekly.interval_weeks;
|
||||||
|
}
|
||||||
|
// put the first letter of the weekday name in
|
||||||
|
// the appropriate position.
|
||||||
|
|
||||||
|
// FIXME: need the offset from the day-of-week
|
||||||
|
// of the Julian epoch
|
||||||
|
/*
|
||||||
|
tmpStr[tmpFS->specData.dateAnchor[1]] =
|
||||||
|
weekDayNames[tmpFS->specData.dateAnchor[1]][0];
|
||||||
|
*/
|
||||||
|
} while ( (list = g_list_next(list)) );
|
||||||
|
|
||||||
|
if ( tmpInt > 1 ) {
|
||||||
|
g_string_sprintfa( str, " (x%d)", tmpInt );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %s", tmpStr );
|
||||||
|
g_free( tmpStr );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_SEMI_MONTHLY:
|
||||||
|
g_string_sprintf( str, "Semi-Monthly" );
|
||||||
|
list = xaccFreqSpecCompositeGet( fs );
|
||||||
|
tmpFS = (FreqSpec*)(g_list_nth( list, 0 )->data);
|
||||||
|
if ( tmpFS->s.monthly.interval_months > 1 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)", tmpFS->s.monthly.interval_months );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": " );
|
||||||
|
if ( tmpFS->s.monthly.day_of_month > 31 ) {
|
||||||
|
g_string_sprintfa( str, "%s", "last day" );
|
||||||
|
} else {
|
||||||
|
g_string_sprintfa( str, "%u", tmpFS->s.monthly.day_of_month );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ", " );
|
||||||
|
tmpFS = (FreqSpec*)(g_list_nth( list, 1 )->data);
|
||||||
|
if ( tmpFS->s.monthly.day_of_month > 31 ) {
|
||||||
|
g_string_sprintfa( str, "%s", "last day" );
|
||||||
|
} else {
|
||||||
|
g_string_sprintfa( str, "%u", tmpFS->s.monthly.day_of_month );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_MONTHLY:
|
||||||
|
g_string_sprintf( str, "Monthly" );
|
||||||
|
if ( fs->s.monthly.interval_months > 1 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.monthly.interval_months );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %u",
|
||||||
|
fs->s.monthly.day_of_month );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_QUARTERLY:
|
||||||
|
g_string_sprintf( str, "Quarterly" );
|
||||||
|
if ( fs->s.monthly.interval_months != 3 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.monthly.interval_months/3 );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %u",
|
||||||
|
fs->s.monthly.day_of_month );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_TRI_ANUALLY:
|
||||||
|
g_string_sprintf( str, "Tri-Anually" );
|
||||||
|
if ( fs->s.monthly.interval_months != 4 ) {
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.monthly.interval_months/4 );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %u",
|
||||||
|
fs->s.monthly.day_of_month );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_SEMI_YEARLY:
|
||||||
|
g_string_sprintf( str, "Semi-Yearly" );
|
||||||
|
if ( fs->s.monthly.interval_months != 6 ) {
|
||||||
|
if ( (fs->s.monthly.interval_months % 6) != 0 ) {
|
||||||
|
// FIXME:error
|
||||||
|
printf( "ERROR: FreqSpec Semi-Yearly month-interval "
|
||||||
|
"is not a multiple of 6 [%d]",
|
||||||
|
fs->s.monthly.interval_months );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.monthly.interval_months/6 );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %u",
|
||||||
|
fs->s.monthly.day_of_month );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UIFREQ_YEARLY:
|
||||||
|
g_string_sprintf( str, "Yearly" );
|
||||||
|
if ( fs->s.monthly.interval_months != 12 ) {
|
||||||
|
if ( (fs->s.monthly.interval_months % 12) != 0 ) {
|
||||||
|
// FIXME:error
|
||||||
|
printf( "ERROR: \"Yearly\" FreqSpec month-interval "
|
||||||
|
"is not a multiple of 12 [%d]",
|
||||||
|
fs->s.monthly.interval_months );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, " (x%u)",
|
||||||
|
fs->s.monthly.interval_months/12 );
|
||||||
|
}
|
||||||
|
g_string_sprintfa( str, ": %s/%u",
|
||||||
|
// FIXME: need the year-of-month value.
|
||||||
|
monthInfo[/*fs->specData.dateAnchor[2]*/ 0].dshort,
|
||||||
|
fs->s.monthly.day_of_month );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_string_sprintf( str, "Unknown" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
242
src/engine/FreqSpec.h
Normal file
242
src/engine/FreqSpec.h
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* FreqSpec.h -- Frequency Specification *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au> *
|
||||||
|
* *
|
||||||
|
* 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 XACC_FREQSPEC_H
|
||||||
|
#define XACC_FREQSPEC_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "GNCId.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frequency specification.
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
typedef enum gncp_FreqType {
|
||||||
|
INVALID,
|
||||||
|
ONCE,
|
||||||
|
DAILY,
|
||||||
|
WEEKLY, /* Hmmm... This is sort of DAILY[7]... */
|
||||||
|
// BI_WEEKLY: weekly[2]
|
||||||
|
// SEMI_MONTHLY: use composite
|
||||||
|
MONTHLY,
|
||||||
|
MONTH_RELATIVE,
|
||||||
|
// YEARLY: monthly[12]
|
||||||
|
COMPOSITE,
|
||||||
|
} FreqType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user's conception of the frequency. It is expected that this
|
||||||
|
* list will grow, while the former [FreqType] will not.
|
||||||
|
*
|
||||||
|
* Ideally this is not here, but what can you do?
|
||||||
|
**/
|
||||||
|
typedef enum gncp_UIFreqType {
|
||||||
|
UIFREQ_NONE,
|
||||||
|
UIFREQ_ONCE,
|
||||||
|
UIFREQ_DAILY,
|
||||||
|
UIFREQ_DAILY_MF,
|
||||||
|
UIFREQ_WEEKLY,
|
||||||
|
UIFREQ_BI_WEEKLY,
|
||||||
|
UIFREQ_SEMI_MONTHLY,
|
||||||
|
UIFREQ_MONTHLY,
|
||||||
|
UIFREQ_QUARTERLY,
|
||||||
|
UIFREQ_TRI_ANUALLY,
|
||||||
|
UIFREQ_SEMI_YEARLY,
|
||||||
|
UIFREQ_YEARLY,
|
||||||
|
UIFREQ_NUM_UI_FREQSPECS
|
||||||
|
} UIFreqType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward declaration of FreqSpec type for storing
|
||||||
|
* date repetition information. This is an opaque type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct gncp_freq_spec;
|
||||||
|
typedef struct gncp_freq_spec FreqSpec;
|
||||||
|
|
||||||
|
|
||||||
|
/** PROTOTYPES ******************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates memory for a FreqSpec.
|
||||||
|
* Calls xaccFreqSpecInit() to initialise.
|
||||||
|
**/
|
||||||
|
FreqSpec* xaccFreqSpecMalloc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a FreqSpec by setting it's to type INVALID.
|
||||||
|
* Use this to initialise a stack object.
|
||||||
|
* FreqSpec objects must be initalised before being used by
|
||||||
|
* any other method.
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecInit( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroys any private data belonging to the FreqSpec.
|
||||||
|
* Use this for a stack object.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecCleanUp( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a heap allocated FreqSpec.
|
||||||
|
* This is the opposite of xaccFreqSpecMalloc().
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecFree( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of a FreqSpec.
|
||||||
|
**/
|
||||||
|
FreqType xaccFreqSpecGetType( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type of a FreqSpec.
|
||||||
|
* Setting the type re-initializes any spec-data; this means
|
||||||
|
* destroying any sub-types in the case of COMPOSITE.
|
||||||
|
* THESE FUNCTIONS HAVE NOT BEEN MAINTAINED THROUGH BEN'S CHANGES.
|
||||||
|
* They need to be checked.
|
||||||
|
**/
|
||||||
|
/* void xaccFreqSpecSetType( FreqSpec *fs, FreqType newType ); */
|
||||||
|
|
||||||
|
UIFreqType xaccFreqSpecGetUIType( FreqSpec *fs );
|
||||||
|
void xaccFreqSpecSetUIType( FreqSpec *fs, UIFreqType newUIFreqType );
|
||||||
|
|
||||||
|
/* Convenience function; calls the two above. */
|
||||||
|
/* void xaccFreqSpecSetTypes( FreqSpec *fs, FreqType newType, UIFreqType newUIType ); */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to once-off, and initialises the
|
||||||
|
* date it occurs on.
|
||||||
|
* Disposes of any previous data.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetOnceDate( FreqSpec *fs,
|
||||||
|
const GDate* when );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to DAILY. Disposes of any previous data.
|
||||||
|
* Uses the start date to figure
|
||||||
|
* out how many days after epoch (1/1/1900) this repeat would
|
||||||
|
* have first occurred on if it had been running back then.
|
||||||
|
* This is used later to figure out absolute repeat dates.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetDaily( FreqSpec *fs,
|
||||||
|
const GDate* initial_date,
|
||||||
|
guint interval_days );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to WEEKLY. Disposes of any previous data.
|
||||||
|
* Uses the inital date to figure out the day of the week to use.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetWeekly( FreqSpec *fs,
|
||||||
|
const GDate* inital_date,
|
||||||
|
guint interval_weeks );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to MONTHLY. Disposes of any previous data.
|
||||||
|
* Uses the inital date to figure out the day of the month to use.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetMonthly( FreqSpec *fs,
|
||||||
|
const GDate* inital_date,
|
||||||
|
guint interval_months );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to MONTH_RELATIVE. Disposes of any previous data.
|
||||||
|
* Uses the inital date to figure out the day of the month to use.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetMonthRelative( FreqSpec *fs,
|
||||||
|
const GDate* inital_date,
|
||||||
|
guint interval_months );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type to COMPOSITE. Disposes of any previous data.
|
||||||
|
* You must Add some repeats to the composite before using
|
||||||
|
* it for repeating.
|
||||||
|
*/
|
||||||
|
void xaccFreqSpecSetComposite( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a human-readable string of the Frequency. This uses
|
||||||
|
* UIFreqType to unroll the internal structure. It is an assertion
|
||||||
|
* failure if the FreqSpec data doesn't match the UIFreqType.
|
||||||
|
* Caller allocates the GString [natch].
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecGetFreqStr( FreqSpec *fs, GString *str );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of FreqSpecs in a COMPOSITE FreqSpec.
|
||||||
|
* It is an error to use this if the type is not COMPOSITE.
|
||||||
|
* The caller should not modify this list;
|
||||||
|
* only add/remove composites and use this fn to get
|
||||||
|
* the perhaps-changed list head.
|
||||||
|
**/
|
||||||
|
GList* xaccFreqSpecCompositeGet( FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a FreqSpec to the list in a COMPOSITE FreqSpec; if the
|
||||||
|
* FreqSpec is not COMPOSITE, this is an assertion failure.
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecCompositeAdd( FreqSpec *fs, FreqSpec *fsToAdd );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next date which the FreqSpec specifies given the
|
||||||
|
* previous occurance. Like the relaxed validity check, this doesn't
|
||||||
|
* take multipliers into account; it just returns the next possible
|
||||||
|
* occurance after the given day.
|
||||||
|
* bstanley I think this should be private.
|
||||||
|
**/
|
||||||
|
/*
|
||||||
|
time_t xaccFreqSpecGetInstanceAfter( FreqSpec *fs, time_t after );
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next instance of the FreqSpec after a given input date.
|
||||||
|
* Note that if the given date happens to be a repeat date,
|
||||||
|
* then the next repeat date will be returned.
|
||||||
|
**/
|
||||||
|
void xaccFreqSpecGetNextInstance( FreqSpec *fs,
|
||||||
|
const GDate* in_date,
|
||||||
|
GDate* out_date );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns either NULL [valid] or a descriptive string [reason not
|
||||||
|
* valid] for the given query date. This is "relaxed", in that it
|
||||||
|
* doesn't care about the frequency multiplier [e.g., For
|
||||||
|
* WEEKLY[2]:Wed, all Wednesdays are valid; for MONTHLY[12]:16, the
|
||||||
|
* 16th day of every month is valid.
|
||||||
|
**/
|
||||||
|
/*
|
||||||
|
char* xaccFreqSpecIsValidDateRelaxed( FreqSpec *fs, time_t query );
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A strict validity check. Given a previous and query date, returns
|
||||||
|
* NULL if the query date is valid, or a text reason if not.
|
||||||
|
**/
|
||||||
|
/*
|
||||||
|
char* xaccFreqSpecIsValidDate( FreqSpec *fs, time_t previous, time_t query );
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* XACC_FREQSPEC_H */
|
||||||
128
src/engine/FreqSpecP.h
Normal file
128
src/engine/FreqSpecP.h
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* FreqSpec.h -- Frequency Specification *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au> *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
* *
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
This file contains private definitions and should not be used by
|
||||||
|
other parts of the engine. This is private data and is subject to
|
||||||
|
change.
|
||||||
|
Currently the only files which include this file are:
|
||||||
|
FreqSpec.c
|
||||||
|
gnc-freqspec-xml-v2.c
|
||||||
|
\********************************************************************/
|
||||||
|
#ifndef XACC_FREQSPECP_H
|
||||||
|
#define XACC_FREQSPECP_H
|
||||||
|
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scheduled transactions have a frequency defined by a frequency
|
||||||
|
* specifier. This specifier, given a start date, end date [present
|
||||||
|
* in the scheduled transaction] and last occurance date [possibly not
|
||||||
|
* present] can be used to determine that a s.transaction should be
|
||||||
|
* instantiated on a given date [the given query date].
|
||||||
|
*
|
||||||
|
* There is a split between the UIFreqType and the 'internal' FreqType
|
||||||
|
* to reduce the complexity of some of the code involved.
|
||||||
|
*
|
||||||
|
* Hmmm... having this in the private header file actually prevents
|
||||||
|
* client code from allocating this 'class' on the stack.
|
||||||
|
* Is that a problem?
|
||||||
|
*
|
||||||
|
* This still needs to deal with:
|
||||||
|
* . exceptions
|
||||||
|
* . yearly 360/365?
|
||||||
|
* . re-based frequencies [based around a non-standard [read:
|
||||||
|
* not-Jan-1-based/fiscal] year]
|
||||||
|
* . "business days" -- m-f sans holidays [per-user list thereof]
|
||||||
|
**/
|
||||||
|
struct gncp_freq_spec {
|
||||||
|
FreqType type;
|
||||||
|
UIFreqType uift;
|
||||||
|
union u {
|
||||||
|
struct {
|
||||||
|
GDate date; /** The date on which the single event occurs. */
|
||||||
|
} once;
|
||||||
|
struct {
|
||||||
|
guint interval_days; /** number of days from one repeat to the next. */
|
||||||
|
guint offset_from_epoch; /** epoch is defined by glib to be 1/1/1. Offset measured in days. 0 <= offset < interval */
|
||||||
|
} daily;
|
||||||
|
struct {
|
||||||
|
/* A week here is measured as 7 days. The first week starts at epoch.
|
||||||
|
* 1/1/1 was a ?. */
|
||||||
|
guint interval_weeks; /** number of weeks from one repeat to the next. */
|
||||||
|
guint offset_from_epoch; /* offset measured in days.
|
||||||
|
* This combines the week
|
||||||
|
* offset and the day of the
|
||||||
|
* week offset. */
|
||||||
|
/* guint offset_from_epoch;*/ /* offset measured in weeks, 0 <= offset < interval */
|
||||||
|
/* guint day_of_week;*/ /* I'm not sure what days each value represents, but it's not important. */
|
||||||
|
} weekly;
|
||||||
|
struct {
|
||||||
|
guint interval_months; /** number of months from one repeat to the next. */
|
||||||
|
guint offset_from_epoch; /* offset measured in months */
|
||||||
|
guint day_of_month; /* Which day of the month it occurs on. */
|
||||||
|
} monthly;
|
||||||
|
struct {
|
||||||
|
guint interval_months; /** Number of months from one repeat to the next. */
|
||||||
|
guint offset_from_epoch; /* offset measured in months */
|
||||||
|
guint weekday; /* stores a value equivalent to a GDateWeekday. */
|
||||||
|
guint occurrence; /* the 1st occurrence to the 5th occurrence. */
|
||||||
|
} month_relative;
|
||||||
|
struct {
|
||||||
|
/** A list of specs for a composite freq. */
|
||||||
|
GList *subSpecs;
|
||||||
|
} composites;
|
||||||
|
/**
|
||||||
|
* The dateAnchor anchors the spec to determinable days.
|
||||||
|
*
|
||||||
|
* ONCE:
|
||||||
|
* dA[0] contains time_t
|
||||||
|
* DAILY:
|
||||||
|
* dA[0] contains day multiplier
|
||||||
|
* dA[1] contains offset from epoch.
|
||||||
|
* WEEKLY:
|
||||||
|
* dA[0] contains week multiplier
|
||||||
|
* dA[1] contains 0..6 [sun-based]
|
||||||
|
* SEMI_MONTHLY: bstanley disused...
|
||||||
|
* dA[0] contains month multiplier
|
||||||
|
* dA[1] contains the first date-of-month,
|
||||||
|
* dA[2] the second.
|
||||||
|
* MONTHLY:
|
||||||
|
* dA[0] contains month multiplier
|
||||||
|
* dA[1] contains the date-of-month
|
||||||
|
* MONTH_RELATIVE:
|
||||||
|
* dA[0] continas month multiplier
|
||||||
|
* dA[1] contains week number [1..5, 6=="last"]
|
||||||
|
* [1..5 is really 1..4.428 [31/7], but it's a UI issue]
|
||||||
|
* dA[2] contains 0..6 [sun-based day of week]
|
||||||
|
* COMPOSITE:
|
||||||
|
* ... list ...
|
||||||
|
* RELATIVE:
|
||||||
|
* ... don't know yet ...
|
||||||
|
**/
|
||||||
|
} s;
|
||||||
|
GUID guid;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* XACC_FREQSPECP_H */
|
||||||
@@ -53,7 +53,9 @@ typedef enum
|
|||||||
GNC_ID_TRANS,
|
GNC_ID_TRANS,
|
||||||
GNC_ID_SPLIT,
|
GNC_ID_SPLIT,
|
||||||
GNC_ID_PRICE,
|
GNC_ID_PRICE,
|
||||||
LAST_GNC_ID = GNC_ID_PRICE
|
GNC_ID_SCHEDXACTION,
|
||||||
|
GNC_ID_FREQSPEC,
|
||||||
|
LAST_GNC_ID = GNC_ID_FREQSPEC
|
||||||
} GNCIdType;
|
} GNCIdType;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,11 @@ libgncengine_la_SOURCES = \
|
|||||||
sixtp-to-dom-parser.c \
|
sixtp-to-dom-parser.c \
|
||||||
sixtp-utils.c \
|
sixtp-utils.c \
|
||||||
sixtp-xml-write-utils.c \
|
sixtp-xml-write-utils.c \
|
||||||
sixtp.c
|
sixtp.c \
|
||||||
|
FreqSpec.c \
|
||||||
|
SchedXaction.c \
|
||||||
|
gnc-freqspec-xml-v2.c \
|
||||||
|
gnc-schedxaction-xml-v2.c
|
||||||
|
|
||||||
libgncengine_la_LDFLAGS = -version-info 2:3:1
|
libgncengine_la_LDFLAGS = -version-info 2:3:1
|
||||||
|
|
||||||
@@ -107,7 +111,9 @@ noinst_HEADERS = \
|
|||||||
sixtp-utils.h \
|
sixtp-utils.h \
|
||||||
sixtp-writers.h \
|
sixtp-writers.h \
|
||||||
sixtp-xml-write-utils.h \
|
sixtp-xml-write-utils.h \
|
||||||
sixtp.h
|
sixtp.h \
|
||||||
|
FreqSpec.h \
|
||||||
|
SchedXaction.h
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.cvsignore \
|
.cvsignore \
|
||||||
|
|||||||
316
src/engine/SchedXaction.c
Normal file
316
src/engine/SchedXaction.c
Normal file
@@ -0,0 +1,316 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* SchedXaction.c -- Scheduled Transaction implementation. *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
#include "GNCIdP.h"
|
||||||
|
#include "Transaction.h"
|
||||||
|
#include "TransactionP.h"
|
||||||
|
#include "date.h"
|
||||||
|
#include "gnc-engine-util.h"
|
||||||
|
#include "gnc-event-p.h"
|
||||||
|
#include "messages.h"
|
||||||
|
#include "Account.h"
|
||||||
|
#include "Group.h"
|
||||||
|
#include "guid.h"
|
||||||
|
#include "gnc-book.h"
|
||||||
|
#include "FileDialog.h"
|
||||||
|
|
||||||
|
static short module = MOD_SX;
|
||||||
|
|
||||||
|
/** Local data defs *****/
|
||||||
|
void transactionListMapDelete( gpointer data, gpointer user_data );
|
||||||
|
|
||||||
|
/** Local Prototypes *****/
|
||||||
|
|
||||||
|
SchedXaction*
|
||||||
|
xaccSchedXactionMalloc( GNCBook *book )
|
||||||
|
{
|
||||||
|
SchedXaction *sx;
|
||||||
|
sx = g_new0( SchedXaction, 1 );
|
||||||
|
xaccSchedXactionInit( sx, book );
|
||||||
|
gnc_engine_generate_event( &sx->guid, GNC_EVENT_CREATE );
|
||||||
|
return sx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionInit( SchedXaction *sx, GNCBook *book )
|
||||||
|
{
|
||||||
|
Account *acct;
|
||||||
|
AccountGroup *ag;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
sx->freq = xaccFreqSpecMalloc();
|
||||||
|
|
||||||
|
xaccGUIDNew( &sx->guid );
|
||||||
|
xaccStoreEntity( sx, &sx->guid, GNC_ID_SCHEDXACTION );
|
||||||
|
g_date_clear( &sx->last_date, 1 );
|
||||||
|
g_date_clear( &sx->start_date, 1 );
|
||||||
|
g_date_clear( &sx->end_date, 1 );
|
||||||
|
|
||||||
|
sx->num_occurances_total = -1;
|
||||||
|
sx->kvp_data = kvp_frame_new();
|
||||||
|
sx->manual = FALSE;
|
||||||
|
|
||||||
|
sx->templateSplits = NULL;
|
||||||
|
// create a new template account for our splits...
|
||||||
|
acct = xaccMallocAccount();
|
||||||
|
name = guid_to_string( &sx->guid );
|
||||||
|
xaccAccountSetName( acct, name );
|
||||||
|
xaccAccountSetCurrency( acct,
|
||||||
|
gnc_commodity_new( "template", "template", "template", "template", 1 ) );
|
||||||
|
// FIXME: g_free?
|
||||||
|
// FIXME: leaks
|
||||||
|
// g_free( name );
|
||||||
|
xaccAccountSetType( acct, BANK );
|
||||||
|
ag = gnc_book_get_template_group( book );
|
||||||
|
xaccGroupInsertAccount( ag, acct );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionFree( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
if ( sx == NULL ) return;
|
||||||
|
|
||||||
|
xaccFreqSpecFree( sx->freq );
|
||||||
|
gnc_engine_generate_event( &sx->guid, GNC_EVENT_DESTROY );
|
||||||
|
xaccRemoveEntity( &sx->guid );
|
||||||
|
|
||||||
|
g_list_foreach( sx->templateSplits,
|
||||||
|
transactionListMapDelete,
|
||||||
|
NULL );
|
||||||
|
g_list_free( sx->templateSplits );
|
||||||
|
if ( sx->name )
|
||||||
|
g_free( sx->name );
|
||||||
|
g_free( sx );
|
||||||
|
|
||||||
|
// FIXME: clean up our template account...
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transactionListMapDelete( gpointer data, gpointer user_data )
|
||||||
|
{
|
||||||
|
Transaction *t = (Transaction*)data;
|
||||||
|
xaccTransBeginEdit( t );
|
||||||
|
xaccTransDestroy( t );
|
||||||
|
xaccTransCommitEdit( t );
|
||||||
|
}
|
||||||
|
|
||||||
|
FreqSpec *
|
||||||
|
xaccSchedXactionGetFreqSpec( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
|
||||||
|
{
|
||||||
|
g_return_if_fail( fs );
|
||||||
|
|
||||||
|
xaccFreqSpecFree( sx->freq );
|
||||||
|
sx->freq = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
xaccSchedXactionGetName( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName )
|
||||||
|
{
|
||||||
|
GString *gstr;
|
||||||
|
g_return_if_fail( newName != NULL );
|
||||||
|
if ( sx->name != NULL ) {
|
||||||
|
g_free( sx->name );
|
||||||
|
}
|
||||||
|
gstr = g_string_new( newName );
|
||||||
|
sx->name = gstr->str;
|
||||||
|
g_string_free( gstr, FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
GDate*
|
||||||
|
xaccSchedXactionGetStartDate( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return &sx->start_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart )
|
||||||
|
{
|
||||||
|
sx->start_date = *newStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
xaccSchedXactionHasEndDate( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return g_date_valid( &sx->end_date );
|
||||||
|
}
|
||||||
|
|
||||||
|
GDate*
|
||||||
|
xaccSchedXactionGetEndDate( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return &sx->end_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd )
|
||||||
|
{
|
||||||
|
if ( g_date_valid( newEnd ) ) {
|
||||||
|
if ( g_date_compare( newEnd, &sx->start_date ) < 0 ) {
|
||||||
|
// FIXME:error
|
||||||
|
// error( "New end date before start date" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sx->end_date = *newEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDate*
|
||||||
|
xaccSchedXactionGetLastOccurDate( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return &sx->last_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur )
|
||||||
|
{
|
||||||
|
sx->last_date = *newLastOccur;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
xaccSchedXactionHasOccurDef( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return ( xaccSchedXactionGetNumOccur( sx ) != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
xaccSchedXactionGetNumOccur( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->num_occurances_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetNumOccur( SchedXaction *sx, gint newNum )
|
||||||
|
{
|
||||||
|
sx->num_occurances_remain = sx->num_occurances_total = newNum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
xaccSchedXactionGetRemOccur( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->num_occurances_remain;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetRemOccur( SchedXaction *sx,
|
||||||
|
gint numRemain )
|
||||||
|
{
|
||||||
|
/* FIXME This condition can be tightened up */
|
||||||
|
if ( numRemain > sx->num_occurances_total ) {
|
||||||
|
// FIXME:error
|
||||||
|
// error( "more remaining occurances than total" );
|
||||||
|
}
|
||||||
|
sx->num_occurances_remain = numRemain;
|
||||||
|
}
|
||||||
|
|
||||||
|
kvp_frame*
|
||||||
|
xaccSchedXactionGetSlots( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->kvp_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetSlots( SchedXaction *sx, kvp_frame *frm )
|
||||||
|
{
|
||||||
|
sx->kvp_data = frm;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GUID*
|
||||||
|
xaccSchedXactionGetGUID( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return &sx->guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetGUID( SchedXaction *sx, GUID g )
|
||||||
|
{
|
||||||
|
sx->guid = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetManual( SchedXaction *sx, gboolean newManual )
|
||||||
|
{
|
||||||
|
sx->manual = newManual;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xaccSchedXactionGetManual( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
return sx->manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDate
|
||||||
|
xaccSchedXactionGetNextInstance( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
GDate last_occur, next_occur;
|
||||||
|
|
||||||
|
if ( g_date_valid( &sx->last_date ) ) {
|
||||||
|
last_occur = sx->last_date;
|
||||||
|
} else {
|
||||||
|
if ( g_date_valid( &sx->start_date ) ) {
|
||||||
|
last_occur = sx->start_date;
|
||||||
|
} else {
|
||||||
|
g_date_set_time( &last_occur, time(NULL) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
|
||||||
|
return next_occur;
|
||||||
|
}
|
||||||
|
|
||||||
|
GDate xaccSchedXactionGetInstanceAfter( SchedXaction *sx, GDate *date )
|
||||||
|
{
|
||||||
|
GDate next_occur;
|
||||||
|
xaccFreqSpecGetNextInstance( sx->freq, date, &next_occur );
|
||||||
|
return next_occur;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
xaccSchedXactionGetSplits( SchedXaction *sx )
|
||||||
|
{
|
||||||
|
g_return_val_if_fail( sx, NULL );
|
||||||
|
return sx->templateSplits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSchedXactionSetSplits( SchedXaction *sx, GList *newSplits )
|
||||||
|
{
|
||||||
|
g_return_if_fail( sx );
|
||||||
|
sx->templateSplits = newSplits;
|
||||||
|
}
|
||||||
170
src/engine/SchedXaction.h
Normal file
170
src/engine/SchedXaction.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* SchedXaction.h -- Scheduled Transaction *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 XACC_SCHEDXACTION_H
|
||||||
|
#define XACC_SCHEDXACTION_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include "GNCId.h"
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
#include "date.h"
|
||||||
|
#include "kvp_frame.h"
|
||||||
|
#include "gnc-book.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single scheduled transaction.
|
||||||
|
*
|
||||||
|
* Scheduled transactions have a list of transactions, and a frequency
|
||||||
|
* [and associated date anchors] with which they are scheduled.
|
||||||
|
*
|
||||||
|
* Things that make sense to have in a template transaction:
|
||||||
|
* [not] Date [though eventually some/multiple template transactions
|
||||||
|
* might have relative dates].
|
||||||
|
* Memo
|
||||||
|
* Account
|
||||||
|
* Funds In/Out... or an expr involving 'amt' [A, x, y, a?] for
|
||||||
|
* variable expenses.
|
||||||
|
*
|
||||||
|
* Template transactions are instantiated by:
|
||||||
|
* . copying the fields of the template
|
||||||
|
* . setting the date to the calculated "due" date.
|
||||||
|
*
|
||||||
|
* We should be able to use the GeneralLedger [or, yet-another-subtype
|
||||||
|
* of the internal ledger] for this editing.
|
||||||
|
**/
|
||||||
|
typedef struct gncp_SchedXaction {
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
FreqSpec *freq;
|
||||||
|
|
||||||
|
GDate last_date;
|
||||||
|
|
||||||
|
GDate start_date;
|
||||||
|
// if end_date is invalid, then no end.
|
||||||
|
GDate end_date;
|
||||||
|
|
||||||
|
// if num_occurances_total == 0, then no limit
|
||||||
|
gint num_occurances_total;
|
||||||
|
// reminaing occurances are as-of the 'last_date'.
|
||||||
|
gint num_occurances_remain;
|
||||||
|
|
||||||
|
// If true, confirmation is required.
|
||||||
|
// If false, then this can be created when due without
|
||||||
|
// intervention.
|
||||||
|
gboolean manual;
|
||||||
|
|
||||||
|
GList *templateSplits;
|
||||||
|
|
||||||
|
GUID guid;
|
||||||
|
kvp_frame *kvp_data;
|
||||||
|
} SchedXaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and initializes a scheduled transaction.
|
||||||
|
**/
|
||||||
|
SchedXaction *xaccSchedXactionMalloc( GNCBook *book );
|
||||||
|
/**
|
||||||
|
* Initially created with a null name, the default frequency, a
|
||||||
|
* start-date of today, no end date, no counted occurances, no
|
||||||
|
* templates transactions, and null kvp data.
|
||||||
|
**/
|
||||||
|
void xaccSchedXactionInit( SchedXaction *sx, GNCBook *book );
|
||||||
|
/**
|
||||||
|
* Cleans up and frees a SchedXaction and it's associated data.
|
||||||
|
**/
|
||||||
|
void xaccSchedXactionFree( SchedXaction *sx );
|
||||||
|
|
||||||
|
FreqSpec *xaccSchedXactionGetFreqSpec( SchedXaction *sx );
|
||||||
|
/**
|
||||||
|
* The FreqSpec is given to the SchedXaction for mem mgmt; it should
|
||||||
|
* not be freed by the external code.
|
||||||
|
**/
|
||||||
|
void xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs );
|
||||||
|
|
||||||
|
gchar *xaccSchedXactionGetName( SchedXaction *sx );
|
||||||
|
/**
|
||||||
|
* A copy of the name is made.
|
||||||
|
**/
|
||||||
|
void xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName );
|
||||||
|
|
||||||
|
GDate* xaccSchedXactionGetStartDate( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart );
|
||||||
|
|
||||||
|
int xaccSchedXactionHasEndDate( SchedXaction *sx );
|
||||||
|
/**
|
||||||
|
* Returns invalid date when there is no end-date specified.
|
||||||
|
**/
|
||||||
|
GDate* xaccSchedXactionGetEndDate( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionSetEndDate( SchedXaction *sx, GDate* newEnd );
|
||||||
|
|
||||||
|
GDate* xaccSchedXactionGetLastOccurDate( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the scheduled transaction has a defined number of
|
||||||
|
* occurances, false if not.
|
||||||
|
**/
|
||||||
|
gboolean xaccSchedXactionHasOccurDef( SchedXaction *sx );
|
||||||
|
gint xaccSchedXactionGetNumOccur( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionSetNumOccur( SchedXaction *sx, gint numNum );
|
||||||
|
gint xaccSchedXactionGetRemOccur( SchedXaction *sx );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#error vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||||
|
GList *xaccSchedXactionGetXactions( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionClearXactions( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionAddXaction( SchedXaction *sx,
|
||||||
|
Transaction *t );
|
||||||
|
#error ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
kvp_frame *xaccSchedXactionGetSlots( SchedXaction *sx );
|
||||||
|
/**
|
||||||
|
* Sets the SX kvp data to the given kvp_frame.
|
||||||
|
* NOTE: This is not copied, but set directly.
|
||||||
|
**/
|
||||||
|
void xaccSchedXactionSetSlots( SchedXaction *sx,
|
||||||
|
kvp_frame *frm );
|
||||||
|
|
||||||
|
const GUID *xaccSchedXactionGetGUID( SchedXaction *sx );
|
||||||
|
void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next occurance of a scheduled transaction. If the
|
||||||
|
* transaction hasn't occured, then it's based off the start date.
|
||||||
|
* Otherwise, it's based off the last-occurance date.
|
||||||
|
**/
|
||||||
|
GDate xaccSchedXactionGetNextInstance( SchedXaction *sx );
|
||||||
|
GDate xaccSchedXactionGetInstanceAfter( SchedXaction *sx, GDate *date );
|
||||||
|
|
||||||
|
#endif /* XACC_SCHEDXACTION_H */
|
||||||
@@ -689,5 +689,13 @@ gnc_timezone (struct tm *tm)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
timespecFromTime_t( Timespec *ts, time_t t )
|
||||||
|
{
|
||||||
|
ts->tv_sec = t;
|
||||||
|
ts->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/********************** END OF FILE *********************************\
|
/********************** END OF FILE *********************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|||||||
@@ -122,6 +122,11 @@ void printDateSecs (char * buff, time_t secs);
|
|||||||
char * xaccPrintDateSecs (time_t secs);
|
char * xaccPrintDateSecs (time_t secs);
|
||||||
const char * gnc_print_date(Timespec ts);
|
const char * gnc_print_date(Timespec ts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a time_t into a Timespec
|
||||||
|
**/
|
||||||
|
void timespecFromTime_t( Timespec *ts, time_t t );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scanDate
|
* scanDate
|
||||||
* Convert a string into day / month / year integers according to
|
* Convert a string into day / month / year integers according to
|
||||||
|
|||||||
@@ -326,6 +326,25 @@ gnc_account_end_handler(gpointer data_for_children,
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Account*
|
||||||
|
dom_tree_to_account( xmlNodePtr node )
|
||||||
|
{
|
||||||
|
Account *accToRet;
|
||||||
|
gboolean successful;
|
||||||
|
|
||||||
|
accToRet = xaccMallocAccount();
|
||||||
|
successful = dom_tree_generic_parse( node, account_handlers_v2, accToRet );
|
||||||
|
xaccAccountCommitEdit( accToRet );
|
||||||
|
|
||||||
|
if ( !successful ) {
|
||||||
|
xaccFreeAccount( accToRet );
|
||||||
|
accToRet = NULL;
|
||||||
|
}
|
||||||
|
// jsled_FIXME? See note above.
|
||||||
|
xaccAccountBeginEdit( accToRet );
|
||||||
|
return accToRet;
|
||||||
|
}
|
||||||
|
|
||||||
sixtp*
|
sixtp*
|
||||||
gnc_account_sixtp_parser_create(void)
|
gnc_account_sixtp_parser_create(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ struct _gnc_book
|
|||||||
{
|
{
|
||||||
AccountGroup *topgroup;
|
AccountGroup *topgroup;
|
||||||
GNCPriceDB *pricedb;
|
GNCPriceDB *pricedb;
|
||||||
|
GList *sched_xactions;
|
||||||
|
AccountGroup *template_group;
|
||||||
|
|
||||||
/* the requested book id, in the form or a URI, such as
|
/* the requested book id, in the form or a URI, such as
|
||||||
* file:/some/where, or sql:server.host.com:555
|
* file:/some/where, or sql:server.host.com:555
|
||||||
@@ -157,13 +159,21 @@ gnc_book_pop_error (GNCBook * book)
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
const char *TEMPLATE_ACCOUNT_NAME = "__account for template transactions__";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gnc_book_init (GNCBook *book)
|
gnc_book_init (GNCBook *book)
|
||||||
{
|
{
|
||||||
|
Account *template_acct;
|
||||||
|
|
||||||
if(!book) return;
|
if(!book) return;
|
||||||
|
|
||||||
book->topgroup = xaccMallocAccountGroup();
|
book->topgroup = xaccMallocAccountGroup();
|
||||||
book->pricedb = gnc_pricedb_create();
|
book->pricedb = gnc_pricedb_create();
|
||||||
|
|
||||||
|
book->sched_xactions = NULL;
|
||||||
|
book->template_group = xaccMallocAccountGroup();
|
||||||
|
|
||||||
book->book_id = NULL;
|
book->book_id = NULL;
|
||||||
gnc_book_clear_error (book);
|
gnc_book_clear_error (book);
|
||||||
book->fullpath = NULL;
|
book->fullpath = NULL;
|
||||||
@@ -241,6 +251,34 @@ gnc_book_set_pricedb(GNCBook *book, GNCPriceDB *db)
|
|||||||
book->pricedb = db;
|
book->pricedb = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
gnc_book_get_schedxactions( GNCBook *book )
|
||||||
|
{
|
||||||
|
if ( book == NULL ) return NULL;
|
||||||
|
return book->sched_xactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gnc_book_set_schedxactions( GNCBook *book, GList *newList )
|
||||||
|
{
|
||||||
|
if ( book == NULL ) return;
|
||||||
|
book->sched_xactions = newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountGroup *
|
||||||
|
gnc_book_get_template_group( GNCBook *book )
|
||||||
|
{
|
||||||
|
if ( book == NULL ) return NULL;
|
||||||
|
return book->template_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gnc_book_set_template_group( GNCBook *book, AccountGroup *templateGroup )
|
||||||
|
{
|
||||||
|
if ( book == NULL ) return;
|
||||||
|
book->template_group = templateGroup;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
Backend *
|
Backend *
|
||||||
@@ -967,7 +1005,7 @@ gnc_book_load (GNCBook *book)
|
|||||||
else if ((strncmp(book->book_id, "http://", 7) == 0) ||
|
else if ((strncmp(book->book_id, "http://", 7) == 0) ||
|
||||||
(strncmp(book->book_id, "https://", 8) == 0) ||
|
(strncmp(book->book_id, "https://", 8) == 0) ||
|
||||||
(strncmp(book->book_id, "postgres://", 11) == 0) ||
|
(strncmp(book->book_id, "postgres://", 11) == 0) ||
|
||||||
(strncmp(book->book_id, "rpc://", 6)) == 0)
|
(strncmp(book->book_id, "rpc://", 6)) == 0)
|
||||||
{
|
{
|
||||||
/* This code should be sufficient to initialize *any* backend,
|
/* This code should be sufficient to initialize *any* backend,
|
||||||
* whether http, postgres, or anything else that might come along.
|
* whether http, postgres, or anything else that might come along.
|
||||||
|
|||||||
@@ -132,6 +132,15 @@ guint gnc_book_count_transactions(GNCBook *book);
|
|||||||
*/
|
*/
|
||||||
gnc_commodity_table* gnc_book_get_commodity_table(GNCBook *book);
|
gnc_commodity_table* gnc_book_get_commodity_table(GNCBook *book);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of scheduled transactions.
|
||||||
|
**/
|
||||||
|
GList * gnc_book_get_schedxactions( GNCBook *book );
|
||||||
|
void gnc_book_set_schedxactions( GNCBook *book, GList *newList );
|
||||||
|
|
||||||
|
AccountGroup *gnc_book_get_template_group( GNCBook *book );
|
||||||
|
void gnc_book_set_template_group( GNCBook *book, AccountGroup *templateGroup );
|
||||||
|
|
||||||
/* The gnc_book_get_file_path() routine returns the fully-qualified file
|
/* The gnc_book_get_file_path() routine returns the fully-qualified file
|
||||||
* path for the book. That is, if a relative or partial filename
|
* path for the book. That is, if a relative or partial filename
|
||||||
* was for the book, then it had to have been fully resolved to
|
* was for the book, then it had to have been fully resolved to
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ typedef enum
|
|||||||
MOD_EVENT = 13,
|
MOD_EVENT = 13,
|
||||||
MOD_TXN = 14,
|
MOD_TXN = 14,
|
||||||
MOD_KVP = 15,
|
MOD_KVP = 15,
|
||||||
MOD_LAST = 15
|
MOD_SX = 16,
|
||||||
|
MOD_LAST = 16
|
||||||
} gncModuleType;
|
} gncModuleType;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
|||||||
589
src/engine/gnc-freqspec-xml-v2.c
Normal file
589
src/engine/gnc-freqspec-xml-v2.c
Normal file
@@ -0,0 +1,589 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* gnc-freqspec-xml-v2.c -- xml routines for FreqSpecs *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* Copyright (C) 2001 Ben Stanley <bds02@uow.edu.au> *
|
||||||
|
* *
|
||||||
|
* 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 <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gnc-xml-helper.h"
|
||||||
|
#include "gnc-engine-util.h"
|
||||||
|
|
||||||
|
#include "sixtp.h"
|
||||||
|
#include "sixtp-utils.h"
|
||||||
|
#include "sixtp-parsers.h"
|
||||||
|
#include "sixtp-utils.h"
|
||||||
|
#include "sixtp-xml-write-utils.h"
|
||||||
|
#include "sixtp-dom-parsers.h"
|
||||||
|
#include "sixtp-dom-generators.h"
|
||||||
|
|
||||||
|
#include "gnc-xml.h"
|
||||||
|
|
||||||
|
#include "io-gncxml-v2.h"
|
||||||
|
|
||||||
|
#include "sixtp-dom-parsers.h"
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
#include "FreqSpecP.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XML output should look something like:
|
||||||
|
* <freqspec>
|
||||||
|
* <fs:monthly>
|
||||||
|
* <fs:interval>2</fs:interval>
|
||||||
|
* <fs:offset>1</fs:offset>
|
||||||
|
* <fs:day>21</fs:day>
|
||||||
|
* </fs:monthly>
|
||||||
|
* <fs:id>...</fs:id>
|
||||||
|
* </freqspec>
|
||||||
|
*
|
||||||
|
* <freqspec>
|
||||||
|
*
|
||||||
|
* <fs:composite>
|
||||||
|
* <freqspec>
|
||||||
|
* <fs:weekly>
|
||||||
|
* <fs:interval>2</fs:interval>
|
||||||
|
* <fs:offset>3</fs:offset>
|
||||||
|
* </fs:weekly>
|
||||||
|
* </freqspec>
|
||||||
|
* <freqspec>
|
||||||
|
* <fs:weekly>
|
||||||
|
* <fs:interval>2</fs:interval>
|
||||||
|
* <fs:offset>12</fs:offset>
|
||||||
|
* </fs:weekly>
|
||||||
|
* </freqspec>
|
||||||
|
* </fs:composite>
|
||||||
|
* <fs:id>...</fs:id>
|
||||||
|
* </freqspec>
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
const gchar *freqspec_version_string = "1.0.0";
|
||||||
|
|
||||||
|
struct freqTypeTuple {
|
||||||
|
char *str;
|
||||||
|
FreqType ft;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct freqTypeTuple freqTypeStrs[] = {
|
||||||
|
{ "once", ONCE },
|
||||||
|
{ "daily", DAILY },
|
||||||
|
{ "weekly", WEEKLY },
|
||||||
|
{ "monthly", MONTHLY },
|
||||||
|
{ "month_relative", MONTH_RELATIVE },
|
||||||
|
{ "composite", COMPOSITE },
|
||||||
|
{ NULL, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uiFreqTypeTuple {
|
||||||
|
char *str;
|
||||||
|
UIFreqType uift;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uiFreqTypeTuple uiFreqTypeStrs[] = {
|
||||||
|
{ "none", UIFREQ_NONE },
|
||||||
|
{ "once", UIFREQ_ONCE },
|
||||||
|
{ "daily", UIFREQ_DAILY },
|
||||||
|
{ "daily_mf", UIFREQ_DAILY_MF },
|
||||||
|
{ "weekly", UIFREQ_WEEKLY },
|
||||||
|
{ "bi_weekly", UIFREQ_BI_WEEKLY },
|
||||||
|
{ "semi_monthly", UIFREQ_SEMI_MONTHLY },
|
||||||
|
{ "monthly", UIFREQ_MONTHLY },
|
||||||
|
{ "quarterly", UIFREQ_QUARTERLY },
|
||||||
|
{ "tri_anually", UIFREQ_TRI_ANUALLY },
|
||||||
|
{ "semi_yearly", UIFREQ_SEMI_YEARLY },
|
||||||
|
{ "yearly", UIFREQ_YEARLY },
|
||||||
|
{ NULL, -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct passed around as user-data when parsing the FreqSpec.
|
||||||
|
**/
|
||||||
|
typedef struct _freqSpecParseData {
|
||||||
|
FreqSpec *fs; // FreqSpec we're parsing into.
|
||||||
|
// fields used in the union of unions... :)
|
||||||
|
GDate once_day; // once
|
||||||
|
gint64 interval; // all [except once]
|
||||||
|
gint64 offset; // all [except once]
|
||||||
|
gint64 day; // monthly or month-relative
|
||||||
|
gint64 occurrence; // month-relative
|
||||||
|
GList *list; // composite
|
||||||
|
} fsParseData;
|
||||||
|
|
||||||
|
void
|
||||||
|
_fspd_init( fsParseData *fspd )
|
||||||
|
{
|
||||||
|
fspd->fs = NULL;
|
||||||
|
fspd->list = NULL;
|
||||||
|
fspd->interval
|
||||||
|
= fspd->offset
|
||||||
|
= fspd->day
|
||||||
|
= fspd->occurrence
|
||||||
|
= 0;
|
||||||
|
g_date_clear( &fspd->once_day, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
FreqSpec *dom_tree_to_freqSpec(xmlNodePtr node);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
gnc_freqSpec_dom_tree_create( FreqSpec *fs )
|
||||||
|
{
|
||||||
|
xmlNodePtr ret;
|
||||||
|
xmlNodePtr dateAnchorTmp;
|
||||||
|
xmlNodePtr xmlSub;
|
||||||
|
GString *tmpStr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ret = xmlNewNode( NULL, "gnc:freqspec" );
|
||||||
|
xmlSetProp( ret, "version", freqspec_version_string );
|
||||||
|
|
||||||
|
xmlAddChild( ret, guid_to_dom_tree( "fs:id", &fs->guid ) );
|
||||||
|
|
||||||
|
xmlSub = text_to_dom_tree( "fs:ui_type",
|
||||||
|
uiFreqTypeStrs[ xaccFreqSpecGetUIType(fs) ].str );
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
|
||||||
|
switch( fs->type ) {
|
||||||
|
case ONCE: {
|
||||||
|
xmlSub = xmlNewNode( NULL, "fs:once" );
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
gdate_to_dom_tree( "fs:date",
|
||||||
|
&fs->s.once.date ) );
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DAILY: {
|
||||||
|
xmlSub = xmlNewNode( NULL, "fs:daily" );
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:interval",
|
||||||
|
fs->s.daily.interval_days )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:offset",
|
||||||
|
fs->s.daily.offset_from_epoch )
|
||||||
|
);
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WEEKLY: {
|
||||||
|
xmlSub = xmlNewNode( NULL, "fs:weekly" );
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:interval",
|
||||||
|
fs->s.weekly.interval_weeks )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:offset",
|
||||||
|
fs->s.weekly.offset_from_epoch )
|
||||||
|
);
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MONTHLY: {
|
||||||
|
xmlSub = xmlNewNode( NULL, "fs:monthly" );
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:interval",
|
||||||
|
fs->s.monthly.interval_months )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:offset",
|
||||||
|
fs->s.monthly.offset_from_epoch )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:day",
|
||||||
|
fs->s.monthly.day_of_month )
|
||||||
|
);
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case MONTH_RELATIVE: {
|
||||||
|
xmlSub = xmlNewNode( NULL, "fs:month_relative" );
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:interval",
|
||||||
|
fs->s.month_relative.interval_months )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:offset",
|
||||||
|
fs->s.month_relative.offset_from_epoch )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:weekday",
|
||||||
|
fs->s.month_relative.weekday )
|
||||||
|
);
|
||||||
|
xmlAddChild( xmlSub,
|
||||||
|
guint_to_dom_tree(
|
||||||
|
"fs:occurrence",
|
||||||
|
fs->s.month_relative.occurrence )
|
||||||
|
);
|
||||||
|
xmlAddChild( ret, xmlSub );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case COMPOSITE: {
|
||||||
|
GList *subelts;
|
||||||
|
xmlNodePtr xmlComposites;
|
||||||
|
xmlComposites = xmlNewNode( NULL, "fs:composite" );
|
||||||
|
subelts = fs->s.composites.subSpecs;
|
||||||
|
while( subelts ) {
|
||||||
|
xmlAddChild( xmlComposites,
|
||||||
|
gnc_freqSpec_dom_tree_create(
|
||||||
|
subelts->data ) );
|
||||||
|
subelts = subelts->next;
|
||||||
|
}
|
||||||
|
xmlAddChild( ret, xmlComposites );
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case INVALID:
|
||||||
|
default:
|
||||||
|
g_return_val_if_fail( FALSE, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
gnc_fs_handler( xmlNodePtr node, gpointer d )
|
||||||
|
{
|
||||||
|
// we ignore the wrapper... we were just called at the wrong
|
||||||
|
// level.
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_uift_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *nodeTxt;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
nodeTxt = dom_tree_to_text( node );
|
||||||
|
|
||||||
|
g_return_val_if_fail( nodeTxt, FALSE );
|
||||||
|
for ( i=0; (tmp = uiFreqTypeStrs[i].str) != NULL; i++ ) {
|
||||||
|
if ( safe_strcmp( nodeTxt, tmp ) == 0 ) {
|
||||||
|
xaccFreqSpecSetUIType( fspd->fs, uiFreqTypeStrs[i].uift );
|
||||||
|
g_free( nodeTxt );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free( nodeTxt );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_date_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
GDate *foo;
|
||||||
|
foo = dom_tree_to_gdate( node );
|
||||||
|
if ( foo == NULL )
|
||||||
|
return FALSE;
|
||||||
|
fspd->once_day = *foo;
|
||||||
|
g_date_free( foo );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_interval_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
gint64 foo;
|
||||||
|
|
||||||
|
ret = dom_tree_to_integer( node, &foo );
|
||||||
|
if ( ! ret ) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
fspd->interval = foo;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_offset_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
gint64 foo;
|
||||||
|
|
||||||
|
ret = dom_tree_to_integer( node, &foo );
|
||||||
|
if ( ! ret )
|
||||||
|
return ret;
|
||||||
|
fspd->offset = foo;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_day_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
gint64 foo;
|
||||||
|
|
||||||
|
ret = dom_tree_to_integer( node, &foo );
|
||||||
|
if ( ! ret )
|
||||||
|
return ret;
|
||||||
|
fspd->day = foo;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_weekday_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
gint64 foo;
|
||||||
|
ret = dom_tree_to_integer( node, &foo );
|
||||||
|
if ( !ret )
|
||||||
|
return ret;
|
||||||
|
fspd->day = foo;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_occurrence_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
gint64 foo;
|
||||||
|
ret = dom_tree_to_integer( node, &foo );
|
||||||
|
if ( !ret )
|
||||||
|
return ret;
|
||||||
|
fspd->occurrence = foo;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_subelement_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
FreqSpec *fs;
|
||||||
|
gboolean successful;
|
||||||
|
fs = dom_tree_to_freqSpec( node );
|
||||||
|
if ( fs == NULL )
|
||||||
|
return FALSE;
|
||||||
|
fspd->list = g_list_append( fspd->list, fs );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dom_tree_handler fs_union_dom_handlers[] = {
|
||||||
|
{ "fs:date", fs_date_handler, 0, 0 },
|
||||||
|
{ "fs:interval", fs_interval_handler, 0, 0 },
|
||||||
|
{ "fs:offset", fs_offset_handler, 0, 0 },
|
||||||
|
{ "fs:day", fs_day_handler, 0, 0 },
|
||||||
|
{ "fs:weekday", fs_weekday_handler, 0, 0 },
|
||||||
|
{ "fs:occurrence", fs_occurrence_handler, 0, 0 },
|
||||||
|
{ "gnc:freqspec", fs_subelement_handler, 0, 0 },
|
||||||
|
{ NULL, NULL, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_once_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = ONCE;
|
||||||
|
fspd->fs->s.once.date = fspd->once_day;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_daily_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = DAILY;
|
||||||
|
fspd->fs->s.daily.interval_days = fspd->interval;
|
||||||
|
fspd->fs->s.daily.offset_from_epoch = fspd->offset;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_weekly_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = WEEKLY;
|
||||||
|
fspd->fs->s.weekly.interval_weeks = fspd->interval;
|
||||||
|
fspd->fs->s.weekly.offset_from_epoch = fspd->offset;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_monthly_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = MONTHLY;
|
||||||
|
fspd->fs->s.monthly.interval_months = fspd->interval;
|
||||||
|
fspd->fs->s.monthly.offset_from_epoch = fspd->offset;
|
||||||
|
fspd->fs->s.monthly.day_of_month = fspd->day;
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_month_relative_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = MONTH_RELATIVE;
|
||||||
|
fspd->fs->s.month_relative.interval_months = fspd->interval;
|
||||||
|
fspd->fs->s.month_relative.offset_from_epoch = fspd->offset;
|
||||||
|
fspd->fs->s.month_relative.weekday = fspd->day;
|
||||||
|
fspd->fs->s.month_relative.occurrence = fspd->occurrence;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_guid_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
GUID *guid;
|
||||||
|
guid = dom_tree_to_guid( node );
|
||||||
|
fspd->fs->guid = *guid;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
fs_composite_handler( xmlNodePtr node, fsParseData *fspd )
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
successful = dom_tree_generic_parse( node,
|
||||||
|
fs_union_dom_handlers,
|
||||||
|
fspd );
|
||||||
|
if ( !successful )
|
||||||
|
return FALSE;
|
||||||
|
fspd->fs->type = COMPOSITE;
|
||||||
|
fspd->fs->s.composites.subSpecs = fspd->list;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dom_tree_handler fs_dom_handlers[] = {
|
||||||
|
{ "gnc:freqspec", gnc_fs_handler, 0, 0 },
|
||||||
|
{ "fs:ui_type", fs_uift_handler, 1, 0 },
|
||||||
|
{ "fs:id", fs_guid_handler, 1, 0 },
|
||||||
|
{ "fs:once", fs_once_handler, 0, 0 },
|
||||||
|
{ "fs:daily", fs_daily_handler, 0, 0 },
|
||||||
|
{ "fs:weekly", fs_weekly_handler, 0, 0 },
|
||||||
|
{ "fs:monthly", fs_monthly_handler, 0, 0 },
|
||||||
|
{ "fs:month_relative", fs_month_relative_handler, 0, 0 },
|
||||||
|
{ "fs:composite", fs_composite_handler, 0, 0 },
|
||||||
|
{ NULL, NULL, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
gnc_freqSpec_end_handler(gpointer data_for_children,
|
||||||
|
GSList* data_from_children, GSList* sibling_data,
|
||||||
|
gpointer parent_data, gpointer global_data,
|
||||||
|
gpointer *result, const gchar *tag)
|
||||||
|
{
|
||||||
|
fsParseData fspd;
|
||||||
|
gboolean successful = FALSE;
|
||||||
|
xmlNodePtr aChild;
|
||||||
|
xmlNodePtr tree = (xmlNodePtr)data_for_children;
|
||||||
|
sixtp_gdv2 *globaldata = (sixtp_gdv2*)global_data;
|
||||||
|
|
||||||
|
_fspd_init( &fspd );
|
||||||
|
|
||||||
|
// this won't actually get invoked [FreqSpecs aren't top-level
|
||||||
|
// elements]; see dom_tree_to_freqSpec(), below.
|
||||||
|
if ( parent_data )
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if ( !tag )
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
g_return_val_if_fail( tree, FALSE );
|
||||||
|
|
||||||
|
fspd.fs = xaccFreqSpecMalloc();
|
||||||
|
successful = dom_tree_generic_parse( tree, fs_dom_handlers, &fspd );
|
||||||
|
if (!successful) {
|
||||||
|
xmlElemDump( stdout, NULL, tree );
|
||||||
|
xaccFreqSpecFree( fspd.fs );
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFreeNode(tree);
|
||||||
|
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
sixtp*
|
||||||
|
gnc_freqSpec_sixtp_parser_create(void)
|
||||||
|
{
|
||||||
|
return sixtp_dom_parser_new( gnc_freqSpec_end_handler, NULL, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
FreqSpec*
|
||||||
|
dom_tree_to_freqSpec(xmlNodePtr node)
|
||||||
|
{
|
||||||
|
gboolean successful;
|
||||||
|
fsParseData fspd;
|
||||||
|
|
||||||
|
_fspd_init( &fspd );
|
||||||
|
|
||||||
|
fspd.fs = xaccFreqSpecMalloc();
|
||||||
|
successful = dom_tree_generic_parse( node, fs_dom_handlers, &fspd );
|
||||||
|
if ( !successful ) {
|
||||||
|
xaccFreqSpecFree( fspd.fs );
|
||||||
|
fspd.fs = NULL;
|
||||||
|
}
|
||||||
|
return fspd.fs;
|
||||||
|
}
|
||||||
443
src/engine/gnc-schedxaction-xml-v2.c
Normal file
443
src/engine/gnc-schedxaction-xml-v2.c
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* gnc-schedxactions-xml-v2.c -- xml routines for transactions *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 <glib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "gnc-xml-helper.h"
|
||||||
|
#include "gnc-engine-util.h"
|
||||||
|
|
||||||
|
#include "sixtp.h"
|
||||||
|
#include "sixtp-utils.h"
|
||||||
|
#include "sixtp-xml-write-utils.h"
|
||||||
|
#include "sixtp-parsers.h"
|
||||||
|
#include "sixtp-utils.h"
|
||||||
|
#include "sixtp-dom-parsers.h"
|
||||||
|
#include "sixtp-dom-generators.h"
|
||||||
|
|
||||||
|
#include "gnc-xml.h"
|
||||||
|
|
||||||
|
#include "io-gncxml-v2.h"
|
||||||
|
#include "io-gncxml-gen.h"
|
||||||
|
|
||||||
|
#include "sixtp-dom-parsers.h"
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XML output should look something like:
|
||||||
|
* <gnc:count-data cd:type="schedXaction">XXX</gnc:count-data>
|
||||||
|
* ...
|
||||||
|
* <gnc:schedxaction version="1.0.0">
|
||||||
|
* <sx:id type="guid">...</sx:id>
|
||||||
|
* <sx:name>Rent</sx:name>
|
||||||
|
* <sx:manual-conf>f</sx:manual-conf>
|
||||||
|
* <sx:lastOccur>
|
||||||
|
* <gdate>2001-02-28</gdate>
|
||||||
|
* </sx:lastOccur>
|
||||||
|
* <sx:start>
|
||||||
|
* <gdate>2000-12-31</gdate>
|
||||||
|
* </sx:start>
|
||||||
|
* <!-- no end -->
|
||||||
|
* <sx:freq>
|
||||||
|
* <!-- freq spec tree -->
|
||||||
|
* </sx:freq>
|
||||||
|
* </gnc:schedxaction>
|
||||||
|
* <gnc:schedxaction version="1.0.0">
|
||||||
|
* <sx:id type="guid">...</sx:id>
|
||||||
|
* <sx:name>Loan 1</sx:name>
|
||||||
|
* <sx:manual-conf>f</sx:manual-conf>
|
||||||
|
* <sx:start>
|
||||||
|
* <gdate>2000-12-31</gdate>
|
||||||
|
* </sx:start>
|
||||||
|
* <sx:end type="date">
|
||||||
|
* <gdate>2004-03-20</gdate>
|
||||||
|
* </sx:end>
|
||||||
|
* <sx:freq>
|
||||||
|
* <!-- freqspec tree -->
|
||||||
|
* </sx:freq>
|
||||||
|
* </gnc:schedxaction>
|
||||||
|
* <gnc:schedxaction version="1.0.0">
|
||||||
|
* <sx:id type="guid">...</sx:id>
|
||||||
|
* <sx:name>Loan 2</sx:name>
|
||||||
|
* <sx:manual-conf>f</sx:manual-conf>
|
||||||
|
* <sx:start>
|
||||||
|
* <gdate>2000-12-31</gdate>
|
||||||
|
* </sx:start>
|
||||||
|
* <sx:end type="num_occur">
|
||||||
|
* <sx:num>42</sx:num>
|
||||||
|
* </sx:end>
|
||||||
|
* <sx:freq>
|
||||||
|
* <!-- freqspec tree -->
|
||||||
|
* </sx:freq>
|
||||||
|
* </gnc:schedxaction>
|
||||||
|
*
|
||||||
|
* et-cetera...
|
||||||
|
* bleh.
|
||||||
|
**/
|
||||||
|
|
||||||
|
const gchar *schedxaction_version_string = "1.0.0";
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
gnc_schedXaction_dom_tree_create(SchedXaction *sx)
|
||||||
|
{
|
||||||
|
xmlNodePtr ret;
|
||||||
|
xmlNodePtr fsNode;
|
||||||
|
Timespec ts;
|
||||||
|
GDate *date;
|
||||||
|
|
||||||
|
// FIXME: this should be the same as the def in io-gncxml-v2.c...
|
||||||
|
ret = xmlNewNode( NULL, "gnc:schedxaction" );
|
||||||
|
|
||||||
|
xmlSetProp( ret, "version", schedxaction_version_string );
|
||||||
|
|
||||||
|
xmlAddChild( ret,
|
||||||
|
guid_to_dom_tree("sx:id",
|
||||||
|
xaccSchedXactionGetGUID(sx)) );
|
||||||
|
|
||||||
|
xmlNewTextChild( ret, NULL, "sx:name", xaccSchedXactionGetName(sx) );
|
||||||
|
|
||||||
|
xmlNewTextChild( ret, NULL, "sx:manual-conf",
|
||||||
|
(xaccSchedXactionGetManual(sx) == 1 ? "t" : "f") );
|
||||||
|
xmlAddChild( ret,
|
||||||
|
gdate_to_dom_tree( "sx:start",
|
||||||
|
xaccSchedXactionGetStartDate(sx) ) );
|
||||||
|
date = xaccSchedXactionGetLastOccurDate(sx);
|
||||||
|
|
||||||
|
if ( g_date_valid( date ) ) {
|
||||||
|
xmlAddChild( ret, gdate_to_dom_tree( "sx:last", date ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xaccSchedXactionHasOccurDef(sx) ) {
|
||||||
|
xml_add_gint32( ret, "sx:num-occur",
|
||||||
|
(gint32)xaccSchedXactionGetNumOccur(sx) );
|
||||||
|
xml_add_gint32( ret, "sx:rem-occur",
|
||||||
|
(gint32)xaccSchedXactionGetRemOccur(sx) );
|
||||||
|
} else if ( xaccSchedXactionHasEndDate(sx) ) {
|
||||||
|
xmlAddChild( ret,
|
||||||
|
gdate_to_dom_tree( "sx:end",
|
||||||
|
xaccSchedXactionGetEndDate(sx) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// output freq spec
|
||||||
|
fsNode = xmlNewNode(NULL, "sx:freqspec");
|
||||||
|
xmlAddChild( fsNode,
|
||||||
|
gnc_freqSpec_dom_tree_create(
|
||||||
|
xaccSchedXactionGetFreqSpec(sx)) );
|
||||||
|
xmlAddChild( ret, fsNode );
|
||||||
|
|
||||||
|
// output kvp_frame
|
||||||
|
{
|
||||||
|
xmlNodePtr kvpnode =
|
||||||
|
kvp_frame_to_dom_tree( "sx:slots",
|
||||||
|
xaccSchedXactionGetSlots(sx) );
|
||||||
|
if ( kvpnode )
|
||||||
|
{
|
||||||
|
xmlAddChild(ret, kvpnode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_id_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
GUID *tmp = dom_tree_to_guid( node );
|
||||||
|
g_return_val_if_fail( tmp, FALSE );
|
||||||
|
xaccSchedXactionSetGUID( (SchedXaction*)sx, *tmp );
|
||||||
|
g_free( tmp );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_name_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
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_set_date( xmlNodePtr node, SchedXaction *sx,
|
||||||
|
void (*settor)( SchedXaction *sx, GDate *d ) )
|
||||||
|
{
|
||||||
|
GDate *date;
|
||||||
|
date = dom_tree_to_gdate( node );
|
||||||
|
g_return_val_if_fail( date, FALSE );
|
||||||
|
(*settor)( sx, date );
|
||||||
|
g_date_free( date );
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_start_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
return sx_set_date( node, (SchedXaction*)sx,
|
||||||
|
xaccSchedXactionSetStartDate );
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_last_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
return sx_set_date( node, (SchedXaction*)sx,
|
||||||
|
xaccSchedXactionSetLastOccurDate );
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_end_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
return sx_set_date( node, (SchedXaction*)sx,
|
||||||
|
xaccSchedXactionSetEndDate );
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_freqspec_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
xmlNodePtr mark;
|
||||||
|
FreqSpec *fs;
|
||||||
|
|
||||||
|
g_return_val_if_fail( node, FALSE );
|
||||||
|
|
||||||
|
fs = dom_tree_to_freqSpec( xmlGetLastChild( node ) );
|
||||||
|
xaccSchedXactionSetFreqSpec( (SchedXaction*)sx, fs );
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_manualConf_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
gchar *tmp;
|
||||||
|
|
||||||
|
tmp = dom_tree_to_text( node );
|
||||||
|
g_return_val_if_fail( tmp, FALSE );
|
||||||
|
|
||||||
|
xaccSchedXactionSetManual( (SchedXaction*)sx,
|
||||||
|
safe_strcmp(tmp, "t") == 0 );
|
||||||
|
|
||||||
|
g_free(tmp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_numOccur_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
gint64 numOccur;
|
||||||
|
|
||||||
|
if ( ! dom_tree_to_integer( node, &numOccur ) ) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccSchedXactionSetNumOccur( (SchedXaction*)sx, numOccur );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_remOccur_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
gint64 remOccur;
|
||||||
|
|
||||||
|
if ( ! dom_tree_to_integer( node, &remOccur ) ) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccSchedXactionSetRemOccur( (SchedXaction*)sx, remOccur );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
sx_slots_handler( xmlNodePtr node, gpointer sx )
|
||||||
|
{
|
||||||
|
kvp_frame *frm;
|
||||||
|
frm = dom_tree_to_kvp_frame( node );
|
||||||
|
xaccSchedXactionSetSlots( (SchedXaction*)sx, frm );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gnc_schedXaction_end_handler(gpointer data_for_children,
|
||||||
|
GSList* data_from_children, GSList* sibling_data,
|
||||||
|
gpointer parent_data, gpointer global_data,
|
||||||
|
gpointer *result, const gchar *tag)
|
||||||
|
{
|
||||||
|
SchedXaction *sx;
|
||||||
|
gboolean successful = FALSE;
|
||||||
|
xmlNodePtr achild;
|
||||||
|
xmlNodePtr tree = (xmlNodePtr)data_for_children;
|
||||||
|
gxpf_data *gdata = (gxpf_data*)global_data;
|
||||||
|
|
||||||
|
if ( parent_data ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !tag ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail( tree, FALSE );
|
||||||
|
|
||||||
|
sx = xaccSchedXactionMalloc( NULL );
|
||||||
|
|
||||||
|
successful = dom_tree_generic_parse( tree, sx_dom_handlers, sx );
|
||||||
|
|
||||||
|
if ( successful ) {
|
||||||
|
gdata->cb( tag, gdata->data, sx );
|
||||||
|
} else {
|
||||||
|
xmlElemDump( stdout, NULL, tree );
|
||||||
|
xaccSchedXactionFree( sx );
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFreeNode( tree );
|
||||||
|
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
sixtp*
|
||||||
|
gnc_schedXaction_sixtp_parser_create(void)
|
||||||
|
{
|
||||||
|
return sixtp_dom_parser_new( gnc_schedXaction_end_handler, NULL, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
tt_act_handler( xmlNodePtr node, gnc_template_xaction_data *txd )
|
||||||
|
{
|
||||||
|
Account *acc;
|
||||||
|
acc = dom_tree_to_account( node );
|
||||||
|
if ( acc == NULL ) {
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
txd->accts = g_list_append( txd->accts, acc );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
tt_trn_handler( xmlNodePtr node, gnc_template_xaction_data *txd )
|
||||||
|
{
|
||||||
|
Transaction *trn;
|
||||||
|
trn = dom_tree_to_transaction( node );
|
||||||
|
if ( trn == NULL ) {
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
txd->transactions = g_list_append( txd->transactions, trn );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dom_tree_handler tt_dom_handlers[] = {
|
||||||
|
{ "gnc:account", tt_act_handler, 0, 0 },
|
||||||
|
{ "gnc:transaction", tt_trn_handler, 0, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gnc_template_transaction_end_handler(gpointer data_for_children,
|
||||||
|
GSList* data_from_children, GSList* sibling_data,
|
||||||
|
gpointer parent_data, gpointer global_data,
|
||||||
|
gpointer *result, const gchar *tag)
|
||||||
|
{
|
||||||
|
gboolean successful = FALSE;
|
||||||
|
xmlNodePtr achild;
|
||||||
|
xmlNodePtr tree = (xmlNodePtr)data_for_children;
|
||||||
|
gxpf_data *gdata = (gxpf_data*)global_data;
|
||||||
|
GList *n;
|
||||||
|
gnc_template_xaction_data *txd =
|
||||||
|
g_new0( gnc_template_xaction_data, 1 );
|
||||||
|
|
||||||
|
// the DOM tree will have an account tree [the template group
|
||||||
|
// and account] and a list of transactions [which will be
|
||||||
|
// members of the template account].
|
||||||
|
|
||||||
|
|
||||||
|
// we want to parse through the dom trees for each, placing
|
||||||
|
// the null-parent account in the book's template-group slot,
|
||||||
|
// the others under it, and the transactions as normal.
|
||||||
|
|
||||||
|
if ( parent_data ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !tag ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail( tree, FALSE );
|
||||||
|
|
||||||
|
successful = dom_tree_generic_parse( tree, tt_dom_handlers, txd );
|
||||||
|
|
||||||
|
if ( successful ) {
|
||||||
|
gdata->cb( tag, gdata->data, txd );
|
||||||
|
} else {
|
||||||
|
xmlElemDump( stdout, NULL, tree );
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
for ( n = txd->accts; n; n = n->next ) {
|
||||||
|
n->data = NULL;
|
||||||
|
}
|
||||||
|
for ( n = txd->transactions; n; n = n->next ) {
|
||||||
|
n->data = NULL;
|
||||||
|
}
|
||||||
|
g_list_free( txd->accts );
|
||||||
|
g_list_free( txd->transactions );
|
||||||
|
g_free( txd );
|
||||||
|
xmlFreeNode( tree );
|
||||||
|
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
|
||||||
|
sixtp*
|
||||||
|
gnc_template_transaction_sixtp_parser_create( void )
|
||||||
|
{
|
||||||
|
return sixtp_dom_parser_new( gnc_template_transaction_end_handler, NULL, NULL );
|
||||||
|
}
|
||||||
@@ -510,6 +510,34 @@ gnc_transaction_end_handler(gpointer data_for_children,
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transaction *
|
||||||
|
dom_tree_to_transaction( xmlNodePtr node )
|
||||||
|
{
|
||||||
|
Transaction *trn;
|
||||||
|
gboolean successful;
|
||||||
|
|
||||||
|
g_return_val_if_fail(node, FALSE);
|
||||||
|
|
||||||
|
trn = xaccMallocTransaction();
|
||||||
|
g_return_val_if_fail(trn, FALSE);
|
||||||
|
xaccTransBeginEdit(trn);
|
||||||
|
|
||||||
|
successful = dom_tree_generic_parse(node, trn_dom_handlers, trn);
|
||||||
|
|
||||||
|
xaccTransCommitEdit(trn);
|
||||||
|
|
||||||
|
if ( !successful )
|
||||||
|
{
|
||||||
|
xmlElemDump(stdout, NULL, node);
|
||||||
|
xaccTransBeginEdit(trn);
|
||||||
|
xaccTransDestroy(trn);
|
||||||
|
xaccTransCommitEdit(trn);
|
||||||
|
trn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//xmlFreeNode(tree);
|
||||||
|
return trn;
|
||||||
|
}
|
||||||
|
|
||||||
sixtp*
|
sixtp*
|
||||||
gnc_transaction_sixtp_parser_create(void)
|
gnc_transaction_sixtp_parser_create(void)
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
#include "sixtp.h"
|
#include "sixtp.h"
|
||||||
#include "gnc-pricedb.h"
|
#include "gnc-pricedb.h"
|
||||||
|
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
|
||||||
xmlNodePtr gnc_account_dom_tree_create(Account *act);
|
xmlNodePtr gnc_account_dom_tree_create(Account *act);
|
||||||
sixtp* gnc_account_sixtp_parser_create(void);
|
sixtp* gnc_account_sixtp_parser_create(void);
|
||||||
|
|
||||||
@@ -50,5 +53,12 @@ Split* dom_tree_to_split(xmlNodePtr node);
|
|||||||
xmlNodePtr gnc_pricedb_dom_tree_create(GNCPriceDB *db);
|
xmlNodePtr gnc_pricedb_dom_tree_create(GNCPriceDB *db);
|
||||||
sixtp* gnc_pricedb_sixtp_parser_create(void);
|
sixtp* gnc_pricedb_sixtp_parser_create(void);
|
||||||
|
|
||||||
|
xmlNodePtr gnc_schedXaction_dom_tree_create( SchedXaction *sx );
|
||||||
|
sixtp* gnc_schedXaction_sixtp_parser_create(void);
|
||||||
|
|
||||||
|
xmlNodePtr gnc_freqSpec_dom_tree_create( FreqSpec *fs );
|
||||||
|
sixtp* gnc_freqSpec_sixtp_parser_create(void);
|
||||||
|
|
||||||
|
sixtp* gnc_template_transaction_sixtp_parser_create(void);
|
||||||
|
|
||||||
#endif /* __GNC_XML_H__ */
|
#endif /* __GNC_XML_H__ */
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
|
|
||||||
#include "Group.h"
|
#include "Group.h"
|
||||||
|
|
||||||
|
#include "Transaction.h"
|
||||||
|
|
||||||
#define GNC_V2_STRING "gnc-v2"
|
#define GNC_V2_STRING "gnc-v2"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -120,10 +122,61 @@ add_transaction_local(sixtp_gdv2 *data, Transaction *trn)
|
|||||||
|
|
||||||
data->counter.transactions_loaded++;
|
data->counter.transactions_loaded++;
|
||||||
run_callback(data, "transaction");
|
run_callback(data, "transaction");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
add_schedXaction_local(sixtp_gdv2 *data, SchedXaction *sx)
|
||||||
|
{
|
||||||
|
GList *list;
|
||||||
|
list = gnc_book_get_schedxactions( data->book );
|
||||||
|
list = g_list_append( list, sx );
|
||||||
|
gnc_book_set_schedxactions( data->book, list );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
gboolean
|
||||||
|
add_template_transaction_local( sixtp_gdv2 *data,
|
||||||
|
gnc_template_xaction_data *txd )
|
||||||
|
{
|
||||||
|
GList *n;
|
||||||
|
Account *tmpAcct;
|
||||||
|
AccountGroup *acctGroup;
|
||||||
|
|
||||||
|
// expect a struct of:
|
||||||
|
// . template accounts.
|
||||||
|
// . transactions in those accounts.
|
||||||
|
for ( n = txd->accts; n; n = n->next ) {
|
||||||
|
if ( xaccAccountGetParent( (Account*)n->data ) == NULL ) {
|
||||||
|
// remove the gnc_book_init-created account of
|
||||||
|
// the same name
|
||||||
|
acctGroup =
|
||||||
|
gnc_book_get_template_group( data->book );
|
||||||
|
tmpAcct =
|
||||||
|
xaccGetAccountFromName( acctGroup,
|
||||||
|
xaccAccountGetName( (Account*)n->data ) );
|
||||||
|
if ( tmpAcct != NULL ) {
|
||||||
|
xaccGroupRemoveAccount( acctGroup, tmpAcct );
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccGroupInsertAccount( acctGroup, (Account*)n->data );
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't care about the "AccountCommitEdit-at-end"
|
||||||
|
// paradigm of the normal accounts/transactions so much,
|
||||||
|
// because there's only one template Account.
|
||||||
|
xaccAccountCommitEdit( (Account*)n->data );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( n = txd->transactions; n; n = n->next ) {
|
||||||
|
// insert transactions into accounts
|
||||||
|
add_transaction_local( data, (Transaction*)n->data );
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
add_pricedb_local(sixtp_gdv2 *data, GNCPriceDB *db)
|
add_pricedb_local(sixtp_gdv2 *data, GNCPriceDB *db)
|
||||||
{
|
{
|
||||||
@@ -189,6 +242,10 @@ gnc_counter_end_handler(gpointer data_for_children,
|
|||||||
{
|
{
|
||||||
sixdata->counter.commodities_total = val;
|
sixdata->counter.commodities_total = val;
|
||||||
}
|
}
|
||||||
|
else if(safe_strcmp(type, "schedxaction") == 0)
|
||||||
|
{
|
||||||
|
sixdata->counter.schedXactions_total = val;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_warning("Unknown type: %s",
|
g_warning("Unknown type: %s",
|
||||||
@@ -218,6 +275,8 @@ print_counter_data(load_counter data)
|
|||||||
data.accounts_total, data.accounts_loaded);
|
data.accounts_total, data.accounts_loaded);
|
||||||
printf("Commodities: Total: %d, Loaded: %d\n",
|
printf("Commodities: Total: %d, Loaded: %d\n",
|
||||||
data.commodities_total, data.commodities_loaded);
|
data.commodities_total, data.commodities_loaded);
|
||||||
|
printf("Scheduled Tansactions: Total: %d, Loaded: %d\n",
|
||||||
|
data.schedXactions_total, data.schedXactions_loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *ACCOUNT_TAG = "gnc:account";
|
static const char *ACCOUNT_TAG = "gnc:account";
|
||||||
@@ -225,6 +284,8 @@ static const char *PRICEDB_TAG = "gnc:pricedb";
|
|||||||
static const char *COMMODITY_TAG = "gnc:commodity";
|
static const char *COMMODITY_TAG = "gnc:commodity";
|
||||||
static const char *COUNT_DATA_TAG = "gnc:count-data";
|
static const char *COUNT_DATA_TAG = "gnc:count-data";
|
||||||
static const char *TRANSACTION_TAG = "gnc:transaction";
|
static const char *TRANSACTION_TAG = "gnc:transaction";
|
||||||
|
static const char *SCHEDXACTION_TAG = "gnc:schedxaction";
|
||||||
|
static const char *TEMPLATE_TRANSACTION_TAG = "gnc:template-transactions";
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
generic_callback(const char *tag, gpointer globaldata, gpointer data)
|
generic_callback(const char *tag, gpointer globaldata, gpointer data)
|
||||||
@@ -247,6 +308,14 @@ generic_callback(const char *tag, gpointer globaldata, gpointer data)
|
|||||||
{
|
{
|
||||||
add_transaction_local(gd, (Transaction*)data);
|
add_transaction_local(gd, (Transaction*)data);
|
||||||
}
|
}
|
||||||
|
else if(safe_strcmp(tag, SCHEDXACTION_TAG) == 0)
|
||||||
|
{
|
||||||
|
add_schedXaction_local(gd, (SchedXaction*)data);
|
||||||
|
}
|
||||||
|
else if(safe_strcmp(tag, TEMPLATE_TRANSACTION_TAG ) == 0 )
|
||||||
|
{
|
||||||
|
add_template_transaction_local( gd, (gnc_template_xaction_data*)data );
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +339,8 @@ gnc_book_load_from_xml_file_v2(
|
|||||||
gd->counter.transactions_total = 0;
|
gd->counter.transactions_total = 0;
|
||||||
gd->counter.prices_loaded = 0;
|
gd->counter.prices_loaded = 0;
|
||||||
gd->counter.prices_total = 0;
|
gd->counter.prices_total = 0;
|
||||||
|
gd->counter.schedXactions_loaded = 0;
|
||||||
|
gd->counter.schedXactions_total = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
AccountGroup *g = gnc_book_get_group(book);
|
AccountGroup *g = gnc_book_get_group(book);
|
||||||
@@ -297,6 +368,8 @@ gnc_book_load_from_xml_file_v2(
|
|||||||
COMMODITY_TAG, gnc_commodity_sixtp_parser_create(),
|
COMMODITY_TAG, gnc_commodity_sixtp_parser_create(),
|
||||||
ACCOUNT_TAG, gnc_account_sixtp_parser_create(),
|
ACCOUNT_TAG, gnc_account_sixtp_parser_create(),
|
||||||
TRANSACTION_TAG, gnc_transaction_sixtp_parser_create(),
|
TRANSACTION_TAG, gnc_transaction_sixtp_parser_create(),
|
||||||
|
SCHEDXACTION_TAG, gnc_schedXaction_sixtp_parser_create(),
|
||||||
|
TEMPLATE_TRANSACTION_TAG, gnc_template_transaction_sixtp_parser_create(),
|
||||||
NULL, NULL))
|
NULL, NULL))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -483,9 +556,42 @@ xml_add_trn_data(Transaction *t, gpointer data) {
|
|||||||
static void
|
static void
|
||||||
write_transactions(FILE *out, GNCBook *book)
|
write_transactions(FILE *out, GNCBook *book)
|
||||||
{
|
{
|
||||||
xaccGroupForEachTransaction(gnc_book_get_group(book),
|
xaccGroupForEachTransaction(gnc_book_get_group(book),
|
||||||
xml_add_trn_data,
|
xml_add_trn_data,
|
||||||
(gpointer) out);
|
(gpointer) out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_template_transaction_data( FILE *out, GNCBook *book )
|
||||||
|
{
|
||||||
|
fprintf( out, "<%s>\n", TEMPLATE_TRANSACTION_TAG );
|
||||||
|
write_account_group( out, gnc_book_get_template_group(book) );
|
||||||
|
xaccGroupForEachTransaction( gnc_book_get_template_group(book),
|
||||||
|
xml_add_trn_data,
|
||||||
|
(gpointer)out );
|
||||||
|
fprintf( out, "</%s>\n", TEMPLATE_TRANSACTION_TAG );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_schedXactions( FILE *out, GNCBook *book )
|
||||||
|
{
|
||||||
|
GList *schedXactions;
|
||||||
|
SchedXaction *tmpSX;
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
// get list of scheduled transactions from GNCBook
|
||||||
|
schedXactions = gnc_book_get_schedxactions( book );
|
||||||
|
|
||||||
|
if ( schedXactions == NULL )
|
||||||
|
return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
tmpSX = schedXactions->data;
|
||||||
|
node = gnc_schedXaction_dom_tree_create( tmpSX );
|
||||||
|
xmlElemDump( out, NULL, node );
|
||||||
|
fprintf( out, "\n" );
|
||||||
|
xmlFreeNode( node );
|
||||||
|
} while ( (schedXactions = schedXactions->next) );
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@@ -506,6 +612,8 @@ gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename)
|
|||||||
xaccGroupGetNumSubAccounts(gnc_book_get_group(book)),
|
xaccGroupGetNumSubAccounts(gnc_book_get_group(book)),
|
||||||
"transaction",
|
"transaction",
|
||||||
gnc_book_count_transactions(book),
|
gnc_book_count_transactions(book),
|
||||||
|
"schedxaction",
|
||||||
|
g_list_length( gnc_book_get_schedxactions(book) ),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
write_commodities(out, book);
|
write_commodities(out, book);
|
||||||
@@ -516,6 +624,10 @@ gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename)
|
|||||||
|
|
||||||
write_transactions(out, book);
|
write_transactions(out, book);
|
||||||
|
|
||||||
|
write_template_transaction_data(out, book);
|
||||||
|
|
||||||
|
write_schedXactions(out, book);
|
||||||
|
|
||||||
fprintf(out, "</" GNC_V2_STRING ">\n\n");
|
fprintf(out, "</" GNC_V2_STRING ">\n\n");
|
||||||
write_emacs_trailer(out);
|
write_emacs_trailer(out);
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
#include "gnc-commodity.h"
|
#include "gnc-commodity.h"
|
||||||
#include "gnc-pricedb.h"
|
#include "gnc-pricedb.h"
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
|
||||||
struct _load_counter_struct
|
struct _load_counter_struct
|
||||||
{
|
{
|
||||||
@@ -52,6 +53,9 @@ struct _load_counter_struct
|
|||||||
|
|
||||||
int prices_total;
|
int prices_total;
|
||||||
int prices_loaded;
|
int prices_loaded;
|
||||||
|
|
||||||
|
int schedXactions_total;
|
||||||
|
int schedXactions_loaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _load_counter_struct load_counter;
|
typedef struct _load_counter_struct load_counter;
|
||||||
@@ -63,6 +67,18 @@ struct sixtp_global_data_v2_struct
|
|||||||
void (*countCallback)(const char *type, load_counter counter);
|
void (*countCallback)(const char *type, load_counter counter);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct used to pass the account group/accounts and trasnactions in
|
||||||
|
* the <gnc:template-transactions> section between the parser in
|
||||||
|
* gnc-schedxactions-xml-v2.c and the add-to-book callback in
|
||||||
|
* io-gncxml-v2.c.
|
||||||
|
**/
|
||||||
|
typedef struct _gnc_template_xaction_data
|
||||||
|
{
|
||||||
|
GList *accts;
|
||||||
|
GList *transactions;
|
||||||
|
} gnc_template_xaction_data;
|
||||||
|
|
||||||
typedef struct sixtp_global_data_v2_struct sixtp_gdv2;
|
typedef struct sixtp_global_data_v2_struct sixtp_gdv2;
|
||||||
|
|
||||||
/* read in an account group from a file */
|
/* read in an account group from a file */
|
||||||
@@ -78,5 +94,4 @@ gboolean gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename);
|
|||||||
*/
|
*/
|
||||||
gboolean gnc_is_xml_data_file_v2(const gchar *name);
|
gboolean gnc_is_xml_data_file_v2(const gchar *name);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __IO_GNCXML_V2_H__ */
|
#endif /* __IO_GNCXML_V2_H__ */
|
||||||
|
|||||||
@@ -121,9 +121,27 @@ Type: gint64
|
|||||||
Entities: Account
|
Entities: Account
|
||||||
Use: A boolean flag indicated whether the Account is tax-related.
|
Use: A boolean flag indicated whether the Account is tax-related.
|
||||||
|
|
||||||
|
Name: sched-xaction
|
||||||
|
Type: frame
|
||||||
|
Entities: Split in a SchedXaction
|
||||||
|
Use: Storage for the various fields of a scheduled transaction's
|
||||||
|
template Splits.
|
||||||
|
|
||||||
|
Name: sched-xaction/xfrm
|
||||||
|
Type: GUID
|
||||||
|
Entities: Split
|
||||||
|
Use: The GUID of this Split's xfrm account.
|
||||||
|
|
||||||
|
Name: sched-xaction/amnt
|
||||||
|
Type: string
|
||||||
|
Entities: Split in a SchedXaction
|
||||||
|
Use: The amount field of a SchedXaction might be a formula, which we
|
||||||
|
store here.
|
||||||
|
|
||||||
Name: user-keys
|
Name: user-keys
|
||||||
Type: frame
|
Type: frame
|
||||||
Entities: All
|
Entities: All
|
||||||
Use: This frame is used to store keys which are editable directly by
|
Use: This frame is used to store keys which are editable directly by
|
||||||
the user. The program should not attach any semantics to keys
|
the user. The program should not attach any semantics to keys
|
||||||
under this frame.
|
under this frame.
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,9 @@ gint double_compare(double v1, double v2);
|
|||||||
|
|
||||||
void kvp_value_delete(kvp_value * value);
|
void kvp_value_delete(kvp_value * value);
|
||||||
kvp_value * kvp_value_copy(const kvp_value * value);
|
kvp_value * kvp_value_copy(const kvp_value * value);
|
||||||
|
/**
|
||||||
|
* Similar returns as strcmp.
|
||||||
|
**/
|
||||||
gint kvp_value_compare(const kvp_value *va, const kvp_value *vb);
|
gint kvp_value_compare(const kvp_value *va, const kvp_value *vb);
|
||||||
|
|
||||||
/* list convenience funcs. */
|
/* list convenience funcs. */
|
||||||
|
|||||||
@@ -127,39 +127,55 @@ timespec_nsec_to_string(const Timespec *ts)
|
|||||||
xmlNodePtr
|
xmlNodePtr
|
||||||
timespec_to_dom_tree(const char *tag, const Timespec *spec)
|
timespec_to_dom_tree(const char *tag, const Timespec *spec)
|
||||||
{
|
{
|
||||||
xmlNodePtr ret;
|
xmlNodePtr ret;
|
||||||
gchar *date_str = NULL;
|
gchar *date_str = NULL;
|
||||||
gchar *ns_str = NULL;
|
gchar *ns_str = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail(spec, NULL);
|
g_return_val_if_fail(spec, NULL);
|
||||||
|
|
||||||
date_str = timespec_sec_to_string(spec);
|
date_str = timespec_sec_to_string(spec);
|
||||||
|
|
||||||
if(!date_str)
|
if(!date_str) {
|
||||||
{
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ret = xmlNewNode(NULL, tag);
|
ret = xmlNewNode(NULL, tag);
|
||||||
|
|
||||||
xmlNewTextChild(ret, NULL, "ts:date", date_str);
|
xmlNewTextChild(ret, NULL, "ts:date", date_str);
|
||||||
|
|
||||||
if(spec->tv_nsec > 0)
|
if(spec->tv_nsec > 0){
|
||||||
{
|
ns_str = timespec_nsec_to_string(spec);
|
||||||
ns_str = timespec_nsec_to_string(spec);
|
if(ns_str){
|
||||||
if(ns_str)
|
xmlNewTextChild(ret, NULL, "ts:ns", ns_str);
|
||||||
{
|
}
|
||||||
xmlNewTextChild(ret, NULL, "ts:ns", ns_str);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(date_str);
|
g_free(date_str);
|
||||||
if(ns_str)
|
if(ns_str){
|
||||||
{
|
g_free(ns_str);
|
||||||
g_free(ns_str);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
gdate_to_dom_tree(const char *tag, GDate *date)
|
||||||
|
{
|
||||||
|
xmlNodePtr ret;
|
||||||
|
gchar *date_str = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail(date, NULL);
|
||||||
|
date_str = g_new( gchar, 512 );
|
||||||
|
|
||||||
|
g_date_strftime( date_str, 512, "%Y-%m-%d", date );
|
||||||
|
|
||||||
|
ret = xmlNewNode(NULL, tag);
|
||||||
|
|
||||||
|
xmlNewTextChild(ret, NULL, "gdate", date_str);
|
||||||
|
|
||||||
|
g_free(date_str);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlNodePtr
|
xmlNodePtr
|
||||||
@@ -331,3 +347,20 @@ kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlNodePtr guint_to_dom_tree(const char *tag, guint an_int)
|
||||||
|
{
|
||||||
|
xmlNodePtr ret;
|
||||||
|
gchar *numstr;
|
||||||
|
|
||||||
|
numstr = g_strdup_printf( "%u", an_int );
|
||||||
|
g_return_val_if_fail(numstr, NULL);
|
||||||
|
|
||||||
|
ret = xmlNewNode(NULL, tag);
|
||||||
|
|
||||||
|
xmlNodeAddContent(ret, numstr);
|
||||||
|
|
||||||
|
g_free(numstr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,10 @@ xmlNodePtr commodity_ref_to_dom_tree(const char *tag, const gnc_commodity *c);
|
|||||||
xmlNodePtr timespec_to_dom_tree(const char *tag, const Timespec *spec);
|
xmlNodePtr timespec_to_dom_tree(const char *tag, const Timespec *spec);
|
||||||
gchar * timespec_nsec_to_string(const Timespec *ts);
|
gchar * timespec_nsec_to_string(const Timespec *ts);
|
||||||
gchar * timespec_sec_to_string(const Timespec *ts);
|
gchar * timespec_sec_to_string(const Timespec *ts);
|
||||||
|
xmlNodePtr gdate_to_dom_tree(const char *tag, GDate *spec);
|
||||||
xmlNodePtr gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num);
|
xmlNodePtr gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num);
|
||||||
xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame);
|
xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame);
|
||||||
|
xmlNodePtr guint_to_dom_tree(const char *tag, guint an_int);
|
||||||
|
|
||||||
gchar* double_to_string(double value);
|
gchar* double_to_string(double value);
|
||||||
|
|
||||||
|
|||||||
@@ -419,6 +419,7 @@ dom_tree_to_text(xmlNodePtr tree)
|
|||||||
return g_strdup("");
|
return g_strdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result = g_strdup("");
|
result = g_strdup("");
|
||||||
|
|
||||||
for(current = tree->xmlChildrenNode; current; current = current->next) {
|
for(current = tree->xmlChildrenNode; current; current = current->next) {
|
||||||
@@ -570,6 +571,71 @@ dom_tree_to_timespec(xmlNodePtr node)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GDate*
|
||||||
|
dom_tree_to_gdate(xmlNodePtr node)
|
||||||
|
{
|
||||||
|
/* Turn something like this
|
||||||
|
|
||||||
|
<sx:startdate>
|
||||||
|
<gdate>2001-04-03</gdate>
|
||||||
|
</sx:startdate>
|
||||||
|
|
||||||
|
into a GDate. If the xml is invalid, returns NULL. */
|
||||||
|
|
||||||
|
GDate *ret;
|
||||||
|
gboolean seen_date = FALSE;
|
||||||
|
xmlNodePtr n;
|
||||||
|
|
||||||
|
/* creates an invalid date */
|
||||||
|
ret = g_date_new();
|
||||||
|
|
||||||
|
for(n = node->xmlChildrenNode; n; n = n->next) {
|
||||||
|
switch(n->type) {
|
||||||
|
case XML_COMMENT_NODE:
|
||||||
|
break;
|
||||||
|
case XML_ELEMENT_NODE:
|
||||||
|
if(safe_strcmp("gdate", n->name) == 0) {
|
||||||
|
if(seen_date) {
|
||||||
|
goto failure;
|
||||||
|
} else {
|
||||||
|
gchar *content = dom_tree_to_text(n);
|
||||||
|
gint year, month, day;
|
||||||
|
if(!content) {
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sscanf(content, "%d-%d-%d", &year, &month, &day ) != 3) {
|
||||||
|
g_free(content);
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
g_free(content);
|
||||||
|
seen_date = TRUE;
|
||||||
|
g_date_set_dmy( ret, day, month, year );
|
||||||
|
if( !g_date_valid( ret ) ) {
|
||||||
|
g_warning("dom_tree_to_gdate: invalid date");
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PERR("dom_tree_to_gdate: unexpected sub-node.");
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!seen_date) {
|
||||||
|
g_warning("dom_tree_to_gdate: no gdate node found.");
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
failure:
|
||||||
|
g_date_free( ret );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gnc_commodity *
|
gnc_commodity *
|
||||||
dom_tree_to_commodity_ref_no_engine(xmlNodePtr node)
|
dom_tree_to_commodity_ref_no_engine(xmlNodePtr node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
#include "GNCId.h"
|
#include "GNCId.h"
|
||||||
|
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
#include "Account.h"
|
||||||
|
#include "Transaction.h"
|
||||||
|
|
||||||
GUID* dom_tree_to_guid(xmlNodePtr node);
|
GUID* dom_tree_to_guid(xmlNodePtr node);
|
||||||
|
|
||||||
gnc_commodity* dom_tree_to_commodity_ref(xmlNodePtr node);
|
gnc_commodity* dom_tree_to_commodity_ref(xmlNodePtr node);
|
||||||
@@ -44,7 +48,10 @@ gnc_commodity* associate_commodity_ref_with_engine_commodity(
|
|||||||
gnc_commodity *com);
|
gnc_commodity *com);
|
||||||
gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node);
|
gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node);
|
||||||
|
|
||||||
|
FreqSpec* dom_tree_to_freqSpec( xmlNodePtr node );
|
||||||
|
|
||||||
Timespec* dom_tree_to_timespec(xmlNodePtr node);
|
Timespec* dom_tree_to_timespec(xmlNodePtr node);
|
||||||
|
GDate* dom_tree_to_gdate(xmlNodePtr node);
|
||||||
gnc_numeric* dom_tree_to_gnc_numeric(xmlNodePtr node);
|
gnc_numeric* dom_tree_to_gnc_numeric(xmlNodePtr node);
|
||||||
gchar * dom_tree_to_text(xmlNodePtr tree);
|
gchar * dom_tree_to_text(xmlNodePtr tree);
|
||||||
gboolean string_to_binary(const gchar *str, void **v, guint64 *data_len);
|
gboolean string_to_binary(const gchar *str, void **v, guint64 *data_len);
|
||||||
@@ -62,6 +69,9 @@ kvp_value* dom_tree_to_frame_kvp_value(xmlNodePtr node);
|
|||||||
|
|
||||||
gboolean dom_tree_to_integer(xmlNodePtr node, gint64 *daint);
|
gboolean dom_tree_to_integer(xmlNodePtr node, gint64 *daint);
|
||||||
|
|
||||||
|
// jsled-added...
|
||||||
|
Account* dom_tree_to_account( xmlNodePtr node );
|
||||||
|
Transaction* dom_tree_to_transaction( xmlNodePtr node );
|
||||||
|
|
||||||
struct dom_tree_handler
|
struct dom_tree_handler
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -258,6 +258,11 @@ gnc_cm_event_handler (GUID *entity,
|
|||||||
case GNC_ID_NONE:
|
case GNC_ID_NONE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GNC_ID_SCHEDXACTION:
|
||||||
|
case GNC_ID_FREQSPEC:
|
||||||
|
DEBUG( "FIXME for GNC_ID %d", id_type );
|
||||||
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
char guid_str[GUID_ENCODING_LENGTH+1];
|
char guid_str[GUID_ENCODING_LENGTH+1];
|
||||||
guid_to_string_buff (entity, guid_str);
|
guid_to_string_buff (entity, guid_str);
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ libgncgnome_a_SOURCES = \
|
|||||||
dialog-transfer.c \
|
dialog-transfer.c \
|
||||||
dialog-userpass.c \
|
dialog-userpass.c \
|
||||||
dialog-utils.c \
|
dialog-utils.c \
|
||||||
|
dialog-scheduledxaction.c \
|
||||||
druid-commodity.c \
|
druid-commodity.c \
|
||||||
druid-hierarchy.c \
|
druid-hierarchy.c \
|
||||||
druid-qif-import.c \
|
druid-qif-import.c \
|
||||||
@@ -38,6 +39,7 @@ libgncgnome_a_SOURCES = \
|
|||||||
gnc-datedelta.c \
|
gnc-datedelta.c \
|
||||||
gnc-dateedit.c \
|
gnc-dateedit.c \
|
||||||
gnc-gpg.c \
|
gnc-gpg.c \
|
||||||
|
gnc-frequency.c \
|
||||||
gnc-html-history.c \
|
gnc-html-history.c \
|
||||||
gnc-html-guppi.c \
|
gnc-html-guppi.c \
|
||||||
gnc-html.c \
|
gnc-html.c \
|
||||||
@@ -56,7 +58,8 @@ libgncgnome_a_SOURCES = \
|
|||||||
window-main-summarybar.c \
|
window-main-summarybar.c \
|
||||||
window-reconcile.c \
|
window-reconcile.c \
|
||||||
window-register.c \
|
window-register.c \
|
||||||
window-report.c
|
window-report.c \
|
||||||
|
dialog-nextrun.c
|
||||||
|
|
||||||
gnomeappdir = ${datadir}/gnome/apps/Applications
|
gnomeappdir = ${datadir}/gnome/apps/Applications
|
||||||
|
|
||||||
@@ -83,6 +86,7 @@ noinst_HEADERS = \
|
|||||||
dialog-totd.h \
|
dialog-totd.h \
|
||||||
dialog-transfer.h \
|
dialog-transfer.h \
|
||||||
dialog-utils.h \
|
dialog-utils.h \
|
||||||
|
dialog-scheduledxaction.h \
|
||||||
druid-commodity.h \
|
druid-commodity.h \
|
||||||
druid-hierarchy.h \
|
druid-hierarchy.h \
|
||||||
druid-qif-import.h \
|
druid-qif-import.h \
|
||||||
@@ -95,6 +99,7 @@ noinst_HEADERS = \
|
|||||||
gnc-dateedit.h \
|
gnc-dateedit.h \
|
||||||
gnc-dir.h \
|
gnc-dir.h \
|
||||||
gnc-gpg.h \
|
gnc-gpg.h \
|
||||||
|
gnc-frequency.h \
|
||||||
gnc-html-history.h \
|
gnc-html-history.h \
|
||||||
gnc-html-guppi.h \
|
gnc-html-guppi.h \
|
||||||
gnc-html.h \
|
gnc-html.h \
|
||||||
@@ -113,7 +118,8 @@ noinst_HEADERS = \
|
|||||||
window-main-summarybar.h \
|
window-main-summarybar.h \
|
||||||
window-reconcile.h \
|
window-reconcile.h \
|
||||||
window-register.h \
|
window-register.h \
|
||||||
window-report.h
|
window-report.h \
|
||||||
|
dialog-nextrun.h
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
.cvsignore \
|
.cvsignore \
|
||||||
|
|||||||
560
src/gnome/dialog-nextrun.c
Normal file
560
src/gnome/dialog-nextrun.c
Normal file
@@ -0,0 +1,560 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* dialog-nextrun.c - "since last run" dialog. *
|
||||||
|
* Copyright (c) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 <gnome.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#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 "dialog-nextrun.h"
|
||||||
|
#include "SplitLedger.h"
|
||||||
|
#include "gnc-ui-util.h"
|
||||||
|
#include "gnc-exp-parser.h"
|
||||||
|
#include "dialog-utils.h"
|
||||||
|
|
||||||
|
#define DIALOG_NEXTRUN_CM_CLASS "dialog-nextrun"
|
||||||
|
|
||||||
|
static short module = MOD_SX;
|
||||||
|
|
||||||
|
typedef struct _toCreateTransaction {
|
||||||
|
SchedXaction *sx;
|
||||||
|
GDate *date;
|
||||||
|
|
||||||
|
gint clistRow;
|
||||||
|
} toCreateTransaction;
|
||||||
|
|
||||||
|
typedef struct _sxSinceLastData {
|
||||||
|
GtkWidget *nextrunDlg;
|
||||||
|
GladeXML *gxml;
|
||||||
|
GList /* <toCreateTransaction*> */ *transList;
|
||||||
|
} sxSinceLastData;
|
||||||
|
|
||||||
|
static void nextrun_init( sxSinceLastData *sxsld );
|
||||||
|
static void nextrun_close_handler( gpointer ud );
|
||||||
|
static void nr_ok_clicked( GtkButton *b, gpointer ud );
|
||||||
|
static void nr_next_clicked( GtkButton *b, gpointer ud );
|
||||||
|
static void nr_prev_xaction_clicked( GtkButton *b, gpointer ud );
|
||||||
|
static void nr_next_xaction_clicked( GtkButton *b, gpointer ud );
|
||||||
|
|
||||||
|
static void nextrun_destroy( GtkObject *o, gpointer ud );
|
||||||
|
|
||||||
|
static void slr_create_transactions( SchedXaction *sx, GDate *gd );
|
||||||
|
|
||||||
|
//int parse_vars_from_formula( const char *formula, GHashTable *varHash );
|
||||||
|
|
||||||
|
void
|
||||||
|
gnc_ui_nextrun_dialog_create(void)
|
||||||
|
{
|
||||||
|
sxSinceLastData *sxsld = g_new0( sxSinceLastData, 1 );
|
||||||
|
sxsld->gxml = gnc_glade_xml_new( "sched-xact.glade", "Since-Last-Run Instantiation" );
|
||||||
|
sxsld->nextrunDlg = glade_xml_get_widget( sxsld->gxml, "Since-Last-Run Instantiation" );
|
||||||
|
|
||||||
|
nextrun_init( sxsld );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nextrun_init( sxSinceLastData *sxsld )
|
||||||
|
{
|
||||||
|
GtkObject *o;
|
||||||
|
int i;
|
||||||
|
struct widgetNameSignalHandlerTuple {
|
||||||
|
char *name;
|
||||||
|
char *signal;
|
||||||
|
void (*handlerFn)();
|
||||||
|
} widgets[] = {
|
||||||
|
{ "ok", "clicked", nr_ok_clicked },
|
||||||
|
{ "next", "clicked", nr_next_clicked },
|
||||||
|
{ "prev_xaction", "clicked", nr_prev_xaction_clicked },
|
||||||
|
{ "next_xaction", "clicked", nr_next_xaction_clicked },
|
||||||
|
{ NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
gnc_register_gui_component( DIALOG_NEXTRUN_CM_CLASS,
|
||||||
|
NULL,
|
||||||
|
nextrun_close_handler,
|
||||||
|
sxsld->nextrunDlg );
|
||||||
|
|
||||||
|
gtk_signal_connect( GTK_OBJECT(sxsld->nextrunDlg), "destroy",
|
||||||
|
GTK_SIGNAL_FUNC( nextrun_destroy ), sxsld );
|
||||||
|
|
||||||
|
for ( i=0; widgets[i].name != NULL ; i++ ) {
|
||||||
|
o = glade_xml_get_widget( sxsld->gxml, widgets[i].name );
|
||||||
|
gtk_signal_connect( o, widgets[i].signal,
|
||||||
|
GTK_SIGNAL_FUNC(widgets[i].handlerFn),
|
||||||
|
sxsld );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
o = glade_xml_get_widget( sxsld->gxml, "next" );
|
||||||
|
gtk_signal_connect( o, "clicked",
|
||||||
|
GTK_SIGNAL_FUNC(nr_next_clicked),
|
||||||
|
sxsld );
|
||||||
|
|
||||||
|
o = glade_xml_get_widget( sxsld->gxml, "prev_xaction" );
|
||||||
|
gtk_signal_connect( o, "clicked",
|
||||||
|
GTK_SIGNAL_FUNC(nr_prev_xaction_clicked),
|
||||||
|
sxsld );
|
||||||
|
o = glade_xml_get_widget( sxsld->gxml, "next_xaction" );
|
||||||
|
gtk_signal_connect( o, "clicked",
|
||||||
|
GTK_SIGNAL_FUNC(nr_next_xaction_clicked),
|
||||||
|
sxsld );
|
||||||
|
|
||||||
|
gtk_widget_show_all( sxsld->nextrunDlg );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nextrun_close_handler( gpointer ud )
|
||||||
|
{
|
||||||
|
gnome_dialog_close( GNOME_DIALOG( ((sxSinceLastData*)ud)->nextrunDlg ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nr_ok_clicked( GtkButton *b, gpointer ud )
|
||||||
|
{
|
||||||
|
sxSinceLastData *sxsld;
|
||||||
|
GList *tctList;
|
||||||
|
toCreateTransaction *tct;
|
||||||
|
|
||||||
|
sxsld = (sxSinceLastData*)ud;
|
||||||
|
|
||||||
|
tctList = sxsld->transList;
|
||||||
|
if ( tctList == NULL ) {
|
||||||
|
PERR( "no transactions to create\n" );
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
tct = (toCreateTransaction*)tctList->data;
|
||||||
|
slr_create_transactions( tct->sx, tct->date );
|
||||||
|
} while ( (tctList = tctList->next) );
|
||||||
|
|
||||||
|
nextrun_close_handler( ud );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_elts( gpointer data, gpointer user_data )
|
||||||
|
{
|
||||||
|
g_free( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nr_next_clicked( GtkButton *b, gpointer ud )
|
||||||
|
{
|
||||||
|
sxSinceLastData *sxsld;
|
||||||
|
GtkWidget *dlg;
|
||||||
|
GtkObject *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;
|
||||||
|
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 );
|
||||||
|
|
||||||
|
gd = *g_date_new();
|
||||||
|
row = 0;
|
||||||
|
do {
|
||||||
|
sx = (SchedXaction*)sxList->data;
|
||||||
|
g_date_set_time( &gd, time(NULL) );
|
||||||
|
while ( g_date_compare( &gd, endDate ) <= 0 ) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
gd = xaccSchedXactionGetInstanceAfter( sx, &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
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nextrun_destroy( GtkObject *o, gpointer ud )
|
||||||
|
{
|
||||||
|
DEBUG( "nuttin' doin...\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nr_prev_xaction_clicked( GtkButton *b, gpointer ud )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nr_next_xaction_clicked( GtkButton *b, gpointer ud )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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\"\n",
|
||||||
|
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. :(\n" );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
split_kvpf = xaccSplitGetSlots( (Split*)osList->data );
|
||||||
|
|
||||||
|
DEBUG( "\tProcessing Split \"%s\"\n",
|
||||||
|
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\n" );
|
||||||
|
}
|
||||||
|
acct_guid = kvp_value_get_guid( kvp_val );
|
||||||
|
acct = xaccAccountLookup( acct_guid );
|
||||||
|
DEBUG( "Got account with name \"%s\"\n",
|
||||||
|
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 ) {
|
||||||
|
|
||||||
|
printf( "---------------\n" );
|
||||||
|
printf( "Parsing formula:\n" );
|
||||||
|
//parse_vars_from_formula( str, NULL );
|
||||||
|
printf( "---------------\n" );
|
||||||
|
|
||||||
|
xaccParseAmount( str, TRUE, &credit_num, NULL );
|
||||||
|
//string_to_gnc_numeric( str, &credit_num );
|
||||||
|
printf( "gnc_numeric::credit: \"%s\" -> \"%s\"\n",
|
||||||
|
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 ) {
|
||||||
|
|
||||||
|
printf( "---------------\n" );
|
||||||
|
printf( "Parsing formula:\n" );
|
||||||
|
//parse_vars_from_formula( str, NULL );
|
||||||
|
printf( "---------------\n" );
|
||||||
|
|
||||||
|
xaccParseAmount( str, TRUE, &debit_num, NULL );
|
||||||
|
//string_to_gnc_numeric( str, &debit_num );
|
||||||
|
printf( "gnc_numeric::debit: \"%s\" -> \"%s\"\n",
|
||||||
|
str, gnc_numeric_to_string( debit_num ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
final = gnc_numeric_sub_fixed( debit_num,
|
||||||
|
credit_num );
|
||||||
|
|
||||||
|
gncn_error = gnc_numeric_check( final );
|
||||||
|
if ( gncn_error != GNC_ERROR_OK ) {
|
||||||
|
printf( "Error %d in final gnc_numeric value\n", gncn_error );
|
||||||
|
errFlag = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf( "gnc_numeric::final: \"%s\"\n",
|
||||||
|
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 ) {
|
||||||
|
printf( "Some error in newT creation\n" );
|
||||||
|
xaccTransRollbackEdit( newT );
|
||||||
|
} else {
|
||||||
|
xaccTransCommitEdit( newT );
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
slr_create_transactions( SchedXaction *sx, GDate *gd )
|
||||||
|
{
|
||||||
|
AccountGroup *ag;
|
||||||
|
Account *acct;
|
||||||
|
char *id;
|
||||||
|
|
||||||
|
// get template account group
|
||||||
|
ag = gnc_book_get_template_group( gncGetCurrentBook() );
|
||||||
|
id = guid_to_string( xaccSchedXactionGetGUID(sx) );
|
||||||
|
acct = xaccGetAccountFromName( ag, id );
|
||||||
|
printf( "Got account \"%s\"\n",
|
||||||
|
xaccAccountGetName( acct ) );
|
||||||
|
g_free( id );
|
||||||
|
|
||||||
|
xaccAccountForEachTransaction( acct,
|
||||||
|
create_each_transaction,
|
||||||
|
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 ) ) {
|
||||||
|
printf( "Error parsing at \"%s\": %s\n",
|
||||||
|
foo, gnc_exp_parser_error_string() );
|
||||||
|
}
|
||||||
|
printf( "Successful parse...\n" );
|
||||||
|
list = gnc_exp_parser_get_variable_names();
|
||||||
|
if ( list == NULL ) {
|
||||||
|
printf( "NULL variable list\n" );
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
printf( "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
|
||||||
23
src/gnome/dialog-nextrun.h
Normal file
23
src/gnome/dialog-nextrun.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* dialog-nextrun.h - Beginnings of "since last run" dialog. *
|
||||||
|
* Copyright (c) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
void gnc_ui_nextrun_dialog_create( void );
|
||||||
1303
src/gnome/dialog-scheduledxaction.c
Normal file
1303
src/gnome/dialog-scheduledxaction.c
Normal file
File diff suppressed because it is too large
Load Diff
51
src/gnome/dialog-scheduledxaction.h
Normal file
51
src/gnome/dialog-scheduledxaction.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* dialog-scheduledxaction.h : dialogs for a scheduled transactions *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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_SCHEDULEDXACTION_H_
|
||||||
|
#define __DIALOG_SCHEDULEDXACTION_H_
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <gnome.h>
|
||||||
|
#include "SchedXaction.h"
|
||||||
|
|
||||||
|
struct _SchedXactionDialog;
|
||||||
|
struct _SchedXactionEditorDialog;
|
||||||
|
|
||||||
|
typedef struct _SchedXactionDialog SchedXactionDialog;
|
||||||
|
typedef struct _SchedXactionEditorDialog SchedXactionEditorDialog;
|
||||||
|
|
||||||
|
SchedXactionDialog * gnc_ui_scheduled_xaction_dialog_create(void);
|
||||||
|
void gnc_ui_scheduled_xaction_dialog_destroy(SchedXactionDialog *sxd);
|
||||||
|
void row_select_handler( GtkCList *clist, gint row, gint col, GdkEventButton *event, gpointer d );
|
||||||
|
|
||||||
|
SchedXactionEditorDialog *
|
||||||
|
gnc_ui_scheduled_xaction_editor_dialog_create( SchedXactionDialog *sxd,
|
||||||
|
SchedXaction *sx );
|
||||||
|
void gnc_ui_scheduled_xaction_editor_dialog_destroy(SchedXactionEditorDialog *sxd);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO:
|
||||||
|
* . date-entries should back-stop each other?
|
||||||
|
* . modify gtkentry to prohibit fracation num-occurance values.
|
||||||
|
**/
|
||||||
@@ -15,7 +15,8 @@ glade_DATA = \
|
|||||||
stocks.glade \
|
stocks.glade \
|
||||||
tax.glade \
|
tax.glade \
|
||||||
transfer.glade \
|
transfer.glade \
|
||||||
userpass.glade
|
userpass.glade \
|
||||||
|
sched-xact.glade
|
||||||
|
|
||||||
STRING_FILES = \
|
STRING_FILES = \
|
||||||
account_strings.c \
|
account_strings.c \
|
||||||
@@ -33,6 +34,7 @@ STRING_FILES = \
|
|||||||
stocks_strings.c \
|
stocks_strings.c \
|
||||||
tax_strings.c \
|
tax_strings.c \
|
||||||
transfer_strings.c \
|
transfer_strings.c \
|
||||||
userpass_strings.c
|
userpass_strings.c \
|
||||||
|
sched-xact_strings.c
|
||||||
|
|
||||||
EXTRA_DIST = $(glade_DATA) $(STRING_FILES)
|
EXTRA_DIST = $(glade_DATA) $(STRING_FILES)
|
||||||
|
|||||||
2790
src/gnome/glade/sched-xact.glade
Normal file
2790
src/gnome/glade/sched-xact.glade
Normal file
File diff suppressed because it is too large
Load Diff
349
src/gnome/glade/sched-xact_strings.c
Normal file
349
src/gnome/glade/sched-xact_strings.c
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
/*
|
||||||
|
* Translatable strings file generated by Glade.
|
||||||
|
* Add this file to your project's POTFILES.in.
|
||||||
|
* DO NOT compile it as part of your application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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_("End");
|
||||||
|
gchar *s = N_("No End");
|
||||||
|
gchar *s = N_("End Date:");
|
||||||
|
gchar *s = N_("Number of Occurances:");
|
||||||
|
gchar *s = N_("Recurrance Frequency");
|
||||||
|
gchar *s = N_("Template Transaction");
|
||||||
|
gchar *s = N_("Record");
|
||||||
|
gchar *s = N_("REPLACEME with the Register control box...");
|
||||||
|
gchar *s = N_("This window should never be realized.");
|
||||||
|
gchar *s = N_("Frequency:");
|
||||||
|
gchar *s = N_("None");
|
||||||
|
gchar *s = N_("Once");
|
||||||
|
gchar *s = N_("Daily");
|
||||||
|
gchar *s = N_("Daily [M-F]");
|
||||||
|
gchar *s = N_("Weekly");
|
||||||
|
gchar *s = N_("Bi-Weekly");
|
||||||
|
gchar *s = N_("Semi-Monthly");
|
||||||
|
gchar *s = N_("Monthly");
|
||||||
|
gchar *s = N_("Quarterly");
|
||||||
|
gchar *s = N_("Tri-Anually");
|
||||||
|
gchar *s = N_("Semi-Yearly");
|
||||||
|
gchar *s = N_("Yearly");
|
||||||
|
gchar *s = N_("Start Date:");
|
||||||
|
gchar *s = N_("Not scheduled");
|
||||||
|
gchar *s = N_("None");
|
||||||
|
gchar *s = N_("Select occurrence date above.");
|
||||||
|
gchar *s = N_("Once");
|
||||||
|
gchar *s = N_("Every ");
|
||||||
|
gchar *s = N_("days.");
|
||||||
|
gchar *s = N_("Example");
|
||||||
|
gchar *s = N_("Daily");
|
||||||
|
gchar *s = N_("Every ");
|
||||||
|
gchar *s = N_("weeks.");
|
||||||
|
gchar *s = N_("Example");
|
||||||
|
gchar *s = N_("Daily [M-F]");
|
||||||
|
gchar *s = N_("Every");
|
||||||
|
gchar *s = N_("weeks.");
|
||||||
|
gchar *s = N_("Days");
|
||||||
|
gchar *s = N_("Sunday");
|
||||||
|
gchar *s = N_("Monday");
|
||||||
|
gchar *s = N_("Tuesday");
|
||||||
|
gchar *s = N_("Wednesday");
|
||||||
|
gchar *s = N_("Thursday");
|
||||||
|
gchar *s = N_("Friday");
|
||||||
|
gchar *s = N_("Saturday");
|
||||||
|
gchar *s = N_("Example");
|
||||||
|
gchar *s = N_("Weekly");
|
||||||
|
gchar *s = N_("Select initial date, above.");
|
||||||
|
gchar *s = N_("Bi-Weekly");
|
||||||
|
gchar *s = N_("Every");
|
||||||
|
gchar *s = N_("months.");
|
||||||
|
gchar *s = N_("First on the:");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("then on the:");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Example");
|
||||||
|
gchar *s = N_("Semi-Monthly");
|
||||||
|
gchar *s = N_("Every ");
|
||||||
|
gchar *s = N_("months.");
|
||||||
|
gchar *s = N_("On the");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Example");
|
||||||
|
gchar *s = N_("Monthly");
|
||||||
|
gchar *s = N_("Occuring in");
|
||||||
|
gchar *s = N_("Jan, Apr, Jul, Oct");
|
||||||
|
gchar *s = N_("Feb, May, Aug, Nov");
|
||||||
|
gchar *s = N_("Mar, Jun, Sep, Dec");
|
||||||
|
gchar *s = N_("On the");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Quarterly");
|
||||||
|
gchar *s = N_("Occuring in");
|
||||||
|
gchar *s = N_("Jan, May, Sep");
|
||||||
|
gchar *s = N_("Feb, Apr, Oct");
|
||||||
|
gchar *s = N_("Mar, Jun, Nov");
|
||||||
|
gchar *s = N_("Apr, Jul, Dec");
|
||||||
|
gchar *s = N_("On the");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Tri-Yearly");
|
||||||
|
gchar *s = N_("Occuring in");
|
||||||
|
gchar *s = N_("Jan, Jul");
|
||||||
|
gchar *s = N_("Feb, Aug");
|
||||||
|
gchar *s = N_("Mar, Sep");
|
||||||
|
gchar *s = N_("Apr, Oct");
|
||||||
|
gchar *s = N_("May, Nov");
|
||||||
|
gchar *s = N_("Jun, Dec");
|
||||||
|
gchar *s = N_("On the");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Semi-Yearly");
|
||||||
|
gchar *s = N_("Every");
|
||||||
|
gchar *s = N_("year(s).");
|
||||||
|
gchar *s = N_("Month");
|
||||||
|
gchar *s = N_("January");
|
||||||
|
gchar *s = N_("February");
|
||||||
|
gchar *s = N_("March");
|
||||||
|
gchar *s = N_("April");
|
||||||
|
gchar *s = N_("May");
|
||||||
|
gchar *s = N_("June");
|
||||||
|
gchar *s = N_("July");
|
||||||
|
gchar *s = N_("August");
|
||||||
|
gchar *s = N_("September");
|
||||||
|
gchar *s = N_("October");
|
||||||
|
gchar *s = N_("November");
|
||||||
|
gchar *s = N_("December");
|
||||||
|
gchar *s = N_("Day");
|
||||||
|
gchar *s = N_("1st");
|
||||||
|
gchar *s = N_("2nd");
|
||||||
|
gchar *s = N_("3rd");
|
||||||
|
gchar *s = N_("4th");
|
||||||
|
gchar *s = N_("5th");
|
||||||
|
gchar *s = N_("6th");
|
||||||
|
gchar *s = N_("7th");
|
||||||
|
gchar *s = N_("8th");
|
||||||
|
gchar *s = N_("9th");
|
||||||
|
gchar *s = N_("10th");
|
||||||
|
gchar *s = N_("11th");
|
||||||
|
gchar *s = N_("12th");
|
||||||
|
gchar *s = N_("13th");
|
||||||
|
gchar *s = N_("14th");
|
||||||
|
gchar *s = N_("15th");
|
||||||
|
gchar *s = N_("16th");
|
||||||
|
gchar *s = N_("17th");
|
||||||
|
gchar *s = N_("18th");
|
||||||
|
gchar *s = N_("19th");
|
||||||
|
gchar *s = N_("20th");
|
||||||
|
gchar *s = N_("21st");
|
||||||
|
gchar *s = N_("22nd");
|
||||||
|
gchar *s = N_("23rd");
|
||||||
|
gchar *s = N_("24th");
|
||||||
|
gchar *s = N_("25th");
|
||||||
|
gchar *s = N_("26th");
|
||||||
|
gchar *s = N_("27th");
|
||||||
|
gchar *s = N_("28th");
|
||||||
|
gchar *s = N_("[29th]");
|
||||||
|
gchar *s = N_("[30th]");
|
||||||
|
gchar *s = N_("[31st]");
|
||||||
|
gchar *s = N_("[last day]");
|
||||||
|
gchar *s = N_("Yearly");
|
||||||
|
gchar *s = N_("Scheduled Transactions");
|
||||||
|
gchar *s = N_("Name");
|
||||||
|
gchar *s = N_("Frequency");
|
||||||
|
gchar *s = N_("Next");
|
||||||
|
gchar *s = N_("New");
|
||||||
|
gchar *s = N_("Edit");
|
||||||
|
gchar *s = N_("Delete");
|
||||||
|
gchar *s = N_("Since Last Run...");
|
||||||
|
gchar *s = N_("Next run date...");
|
||||||
|
gchar *s = N_("To-create...");
|
||||||
|
gchar *s = N_("Name");
|
||||||
|
gchar *s = N_("Date");
|
||||||
|
gchar *s = N_("Variable");
|
||||||
|
gchar *s = N_("Value");
|
||||||
|
gchar *s = N_("What should this be?");
|
||||||
@@ -7,6 +7,12 @@
|
|||||||
* This file was part of the Gnome Library. It was modifed by
|
* This file was part of the Gnome Library. It was modifed by
|
||||||
* Dave Peticolas <peticola@cs.ucdavis.edu> for use in GnuCash.
|
* Dave Peticolas <peticola@cs.ucdavis.edu> for use in GnuCash.
|
||||||
*
|
*
|
||||||
|
* 2001.05.13T1647 [PDT], #gnucash:
|
||||||
|
* <jsled> dave_p: So the header for gnc-dateedit.h is a bit light
|
||||||
|
* on _why_ such a thing was done... any help?
|
||||||
|
* <dave_p> jsled: gnome date edit isn't i18n'd properly. also, we
|
||||||
|
* added the register date hotkeys.
|
||||||
|
*
|
||||||
* GnuCash is free software; you can redistribute it and/or modify
|
* GnuCash is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU Library General Public License as
|
* it under the terms of the GNU Library General Public License as
|
||||||
* published by the Free Software Foundation; either version 2 of
|
* published by the Free Software Foundation; either version 2 of
|
||||||
@@ -23,8 +29,7 @@
|
|||||||
* Free Software Foundation Voice: +1-617-542-5942
|
* Free Software Foundation Voice: +1-617-542-5942
|
||||||
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652
|
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652
|
||||||
* Boston, MA 02111-1307, USA gnu@gnu.org
|
* Boston, MA 02111-1307, USA gnu@gnu.org
|
||||||
*
|
* */
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
@NOTATION@
|
@NOTATION@
|
||||||
*/
|
*/
|
||||||
|
|||||||
1014
src/gnome/gnc-frequency.c
Normal file
1014
src/gnome/gnc-frequency.c
Normal file
File diff suppressed because it is too large
Load Diff
89
src/gnome/gnc-frequency.h
Normal file
89
src/gnome/gnc-frequency.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* gnc-frequency.h -- GnuCash widget for frequency editing. *
|
||||||
|
* Copyright (C) 2001 Joshua Sled <jsled@asynchronous.org> *
|
||||||
|
* *
|
||||||
|
* 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 GNC_FREQUENCY_H
|
||||||
|
#define GNC_FREQUENCY_H
|
||||||
|
|
||||||
|
#include <gnome.h>
|
||||||
|
#include "FreqSpec.h"
|
||||||
|
#include "dialog-utils.h"
|
||||||
|
|
||||||
|
BEGIN_GNOME_DECLS
|
||||||
|
|
||||||
|
#define GNC_FREQUENCY(obj) GTK_CHECK_CAST(obj, gnc_frequency_get_type(), GNCFrequency)
|
||||||
|
#define GNC_FREQENCY_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, gnc_frequency_get_type(), GNCFrequency)
|
||||||
|
#define GNC_IS_FREQUENCY(obj) GTK_CHECK_TYPE(obj, gnc_frequency_get_type())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GNCFrequency is a VBox containing a scrollable GtkNotebook which
|
||||||
|
* allows the user to specify the frequency [of a scheduled
|
||||||
|
* transaction or budgeting category, for instance], manipulating a
|
||||||
|
* FreqSpec object in the process.
|
||||||
|
**/
|
||||||
|
typedef struct _GNCFrequency {
|
||||||
|
GtkVBox widget;
|
||||||
|
|
||||||
|
GtkVBox *vb;
|
||||||
|
GtkNotebook *nb;
|
||||||
|
GtkOptionMenu *freqOpt;
|
||||||
|
GnomeDateEdit *startDate;
|
||||||
|
GladeXML *gxml;
|
||||||
|
} GNCFrequency;
|
||||||
|
|
||||||
|
typedef struct _GNCFrequencyClass {
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
void (*value_changed) (GNCFrequency *gf);
|
||||||
|
} GNCFrequencyClass;
|
||||||
|
|
||||||
|
struct pageDataTuple {
|
||||||
|
int idx;
|
||||||
|
UIFreqType uiFTVal;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
guint gnc_frequency_get_type( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the default freq spec widget, use 'NULL'.
|
||||||
|
**/
|
||||||
|
GtkWidget * gnc_frequency_new( FreqSpec *fs );
|
||||||
|
void gnc_frequency_init( GNCFrequency *gf );
|
||||||
|
/**
|
||||||
|
* Sets up the given GNCFrequency with the given FreqSpec and
|
||||||
|
* UIFreqSpec. If the FreqSpec is NULL, then the default value is
|
||||||
|
* Daily; if the UIFreqSpec is not NONE, then that value is the
|
||||||
|
* default. If the FreqSpec is non-NULL, then it really should agree
|
||||||
|
* with the UIFreqSpec; this is considered a 'critical' error.
|
||||||
|
**/
|
||||||
|
void gnc_frequency_setup( GNCFrequency *gf, FreqSpec *fs );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the state of the GNCFrequenecy widget into the given FreqSpec
|
||||||
|
* and UIFreqSpec.
|
||||||
|
* Places the start date in outStartDate, if it's not null.
|
||||||
|
**/
|
||||||
|
void gnc_frequency_save_state( GNCFrequency *gf, FreqSpec *fs, GDate *outStartDate );
|
||||||
|
|
||||||
|
END_GNOME_DECLS
|
||||||
|
|
||||||
|
#endif // !defined( GNC_FREQUENCY_H )
|
||||||
@@ -207,7 +207,7 @@ gnc_verify_dialog_parented(gncUIWidget parent, const char *message,
|
|||||||
if (parent != NULL)
|
if (parent != NULL)
|
||||||
gnome_dialog_set_parent(GNOME_DIALOG(verify_box), GTK_WINDOW(parent));
|
gnome_dialog_set_parent(GNOME_DIALOG(verify_box), GTK_WINDOW(parent));
|
||||||
|
|
||||||
gnome_dialog_set_default(GNOME_DIALOG(verify_box), yes_is_default ? 0 : 1);
|
gnome_dialog_set_default(GNOME_DIALOG(verify_box), (yes_is_default ? 0 : 1));
|
||||||
|
|
||||||
return (gnome_dialog_run_and_close(GNOME_DIALOG(verify_box)) == 0);
|
return (gnome_dialog_run_and_close(GNOME_DIALOG(verify_box)) == 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#ifndef __QUERY_USER_H__
|
#ifndef __QUERY_USER_H__
|
||||||
#define __QUERY_USER_H__
|
#define __QUERY_USER_H__
|
||||||
|
|
||||||
|
// +jsled: for line below.
|
||||||
|
#include "gnc-ui.h"
|
||||||
|
|
||||||
void gnc_info_dialog(const char *message);
|
void gnc_info_dialog(const char *message);
|
||||||
void gnc_info_dialog_parented(GtkWindow *parent, const char *message);
|
void gnc_info_dialog_parented(GtkWindow *parent, const char *message);
|
||||||
|
|
||||||
@@ -30,4 +33,7 @@ void gnc_warning_dialog(const char *message);
|
|||||||
|
|
||||||
void gnc_error_dialog_parented(GtkWindow *parent, const char *message);
|
void gnc_error_dialog_parented(GtkWindow *parent, const char *message);
|
||||||
|
|
||||||
|
// +jsled: export so dialog-scheduledxaction can see it...
|
||||||
|
gboolean gnc_verify_dialog_parented(gncUIWidget parent, const char *message, gboolean yes_is_default);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -51,6 +51,8 @@
|
|||||||
#include "dialog-totd.h"
|
#include "dialog-totd.h"
|
||||||
#include "dialog-transfer.h"
|
#include "dialog-transfer.h"
|
||||||
#include "dialog-utils.h"
|
#include "dialog-utils.h"
|
||||||
|
#include "dialog-scheduledxaction.h"
|
||||||
|
#include "dialog-nextrun.h"
|
||||||
|
|
||||||
#include "window-help.h"
|
#include "window-help.h"
|
||||||
#include "window-main.h"
|
#include "window-main.h"
|
||||||
@@ -880,6 +882,18 @@ gnc_main_window_fincalc_cb(GtkWidget *widget, gpointer data) {
|
|||||||
gnc_ui_fincalc_dialog_create();
|
gnc_ui_fincalc_dialog_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gnc_ui_mainWindow_scheduled_xaction_cb(GtkWidget *widget, gpointer data)
|
||||||
|
{
|
||||||
|
gnc_ui_scheduled_xaction_dialog_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gnc_ui_mainWindow_nextrun_cb( GtkWidget *widget, gpointer d )
|
||||||
|
{
|
||||||
|
gnc_ui_nextrun_dialog_create();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gnc_main_window_gl_cb(GtkWidget *widget, gpointer data) {
|
gnc_main_window_gl_cb(GtkWidget *widget, gpointer data) {
|
||||||
xaccLedgerDisplay *ld;
|
xaccLedgerDisplay *ld;
|
||||||
@@ -1100,12 +1114,18 @@ gnc_main_window_create_menus(GNCMainInfo * maininfo) {
|
|||||||
GNOMEUIINFO_END
|
GNOMEUIINFO_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GnomeUIInfo gnc_developer_menu_template[] =
|
||||||
|
{
|
||||||
|
GNOMEUIINFO_END
|
||||||
|
};
|
||||||
|
|
||||||
static GnomeUIInfo gnc_main_menu_template[] =
|
static GnomeUIInfo gnc_main_menu_template[] =
|
||||||
{
|
{
|
||||||
GNOMEUIINFO_MENU_FILE_TREE(gnc_file_menu_template),
|
GNOMEUIINFO_MENU_FILE_TREE(gnc_file_menu_template),
|
||||||
GNOMEUIINFO_SUBTREE(N_("_Tools"), gnc_tools_menu_template),
|
GNOMEUIINFO_SUBTREE(N_("_Tools"), gnc_tools_menu_template),
|
||||||
GNOMEUIINFO_SUBTREE(N_("_Settings"), gnc_settings_menu_template),
|
GNOMEUIINFO_SUBTREE(N_("_Settings"), gnc_settings_menu_template),
|
||||||
GNOMEUIINFO_SUBTREE(N_("_Windows"), gnc_windows_menu_template),
|
GNOMEUIINFO_SUBTREE(N_("_Windows"), gnc_windows_menu_template),
|
||||||
|
// GNOEMUIINFO_SUBTREE(N_("_Developer Options"), gnc_developer_menu_template),
|
||||||
GNOMEUIINFO_MENU_HELP_TREE(gnc_help_menu_template),
|
GNOMEUIINFO_MENU_HELP_TREE(gnc_help_menu_template),
|
||||||
GNOMEUIINFO_END
|
GNOMEUIINFO_END
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1058,7 +1058,6 @@ gnc_register_create_status_bar (RegWindow *regData)
|
|||||||
return statusbar;
|
return statusbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gnc_register_jump_to_blank (RegWindow *regData)
|
gnc_register_jump_to_blank (RegWindow *regData)
|
||||||
{
|
{
|
||||||
|
|||||||
86
src/register/formulacell.h
Normal file
86
src/register/formulacell.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/********************************************************************\
|
||||||
|
* formulacell.h -- Formula entry/handling/display cell *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
* *
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FILE:
|
||||||
|
* formulacell.h
|
||||||
|
*
|
||||||
|
* FUNCTION:
|
||||||
|
*
|
||||||
|
* The FormulaCell object implements a cell which can contain a
|
||||||
|
* mathematical formula involving some number of variables, defined by
|
||||||
|
* the user. Any standard math functions [*, /, +, -, ()] are
|
||||||
|
* supported, and any non-numeric, non-syntactic characters or
|
||||||
|
* character strings are interpreted as variables; these character
|
||||||
|
* strings may be enclosed by square brackets ([...]) if they contain
|
||||||
|
* spaces.
|
||||||
|
*
|
||||||
|
* The FormulaCell will check for formula validity [paren-matching,
|
||||||
|
* mainly].
|
||||||
|
*
|
||||||
|
* The FormulaCell...
|
||||||
|
*
|
||||||
|
* DOES...
|
||||||
|
*
|
||||||
|
* SHOULD DO...
|
||||||
|
* . numeric-value detection
|
||||||
|
* . paren-matching
|
||||||
|
* . quick-fill on variables
|
||||||
|
* . functions [special character strings which reference an external
|
||||||
|
* function
|
||||||
|
* . scheme
|
||||||
|
*
|
||||||
|
* HISTORY:
|
||||||
|
* Copyright (c) 2001 Joshua Sled <jsled@asynchronous.org>
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __FORMULA_CELL_C__
|
||||||
|
#define __FORMULA_CELL_C__
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "basiccell.h"
|
||||||
|
#include "date.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _FormulaCell
|
||||||
|
{
|
||||||
|
BasicCell cell;
|
||||||
|
} FormulaCell;
|
||||||
|
|
||||||
|
/* installs a callback to handle date recording */
|
||||||
|
FormulaCell * xaccMallocFormulaCell (void);
|
||||||
|
void xaccDestroyFormulaCell (FormulaCell *cell);
|
||||||
|
|
||||||
|
/* days are 1-31, mon is 1-12, year 1900 == 1900 */
|
||||||
|
void xaccSetFormulaCellValue (FormulaCell *cell, int day, int mon, int year);
|
||||||
|
void xaccSetFormulaCellValueSecs (FormulaCell *cell, time_t secs);
|
||||||
|
void xaccSetFormulaCellValueSecsL (FormulaCell *cell, long long secs);
|
||||||
|
|
||||||
|
void xaccCommitFormulaCell (FormulaCell *cell);
|
||||||
|
|
||||||
|
void xaccFormulaCellGetDate (FormulaCell *cell, Timespec *ts);
|
||||||
|
|
||||||
|
#endif /* __FORMULA_CELL_C__ */
|
||||||
|
|
||||||
|
/* --------------- end of file ---------------------- */
|
||||||
|
|
||||||
@@ -80,6 +80,8 @@ struct _SplitRegisterBuffer
|
|||||||
CellBuffer sharesCell;
|
CellBuffer sharesCell;
|
||||||
CellBuffer mxfrmCell;
|
CellBuffer mxfrmCell;
|
||||||
CellBuffer notesCell;
|
CellBuffer notesCell;
|
||||||
|
CellBuffer formCreditCell;
|
||||||
|
CellBuffer formDebitCell;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -110,6 +112,8 @@ static sample_string cell_sample_strings[] =
|
|||||||
{ N_("sample:999,999.000"), 7}, /* tshrbaln cell */
|
{ N_("sample:999,999.000"), 7}, /* tshrbaln cell */
|
||||||
{ N_("sample:999,999.000"), 7}, /* tbalance cell */
|
{ N_("sample:999,999.000"), 7}, /* tbalance cell */
|
||||||
{ N_("sample:Notes field sample text string"), 7}, /* notes cell */
|
{ N_("sample:Notes field sample text string"), 7}, /* notes cell */
|
||||||
|
{ N_("sample:(x + 0.33 * y + (x+y) )"), 7 }, /* formula credit cell */
|
||||||
|
{ N_("sample:(x + 0.33 * y + (x+y) )"), 7 }, /* formula debit cell */
|
||||||
};
|
};
|
||||||
|
|
||||||
static CellAlignment cell_alignments[] =
|
static CellAlignment cell_alignments[] =
|
||||||
@@ -134,6 +138,8 @@ static CellAlignment cell_alignments[] =
|
|||||||
CELL_ALIGN_RIGHT, /* tshrbaln cell */
|
CELL_ALIGN_RIGHT, /* tshrbaln cell */
|
||||||
CELL_ALIGN_RIGHT, /* tbalance cell */
|
CELL_ALIGN_RIGHT, /* tbalance cell */
|
||||||
CELL_ALIGN_LEFT, /* notes cell */
|
CELL_ALIGN_LEFT, /* notes cell */
|
||||||
|
CELL_ALIGN_LEFT, /* formula credit cell */
|
||||||
|
CELL_ALIGN_LEFT, /* formula debit cell */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -145,7 +151,8 @@ xaccInitSplitRegister (SplitRegister *reg,
|
|||||||
TableView *view,
|
TableView *view,
|
||||||
VirtCellDataAllocator allocator,
|
VirtCellDataAllocator allocator,
|
||||||
VirtCellDataDeallocator deallocator,
|
VirtCellDataDeallocator deallocator,
|
||||||
VirtCellDataCopy copy);
|
VirtCellDataCopy copy,
|
||||||
|
gboolean templateMode);
|
||||||
|
|
||||||
|
|
||||||
/* ============================================== */
|
/* ============================================== */
|
||||||
@@ -240,6 +247,7 @@ configAction (SplitRegister *reg)
|
|||||||
xaccAddComboCellMenuItem (reg->actionCell, _("Dist"));
|
xaccAddComboCellMenuItem (reg->actionCell, _("Dist"));
|
||||||
xaccAddComboCellMenuItem (reg->actionCell, _("Split"));
|
xaccAddComboCellMenuItem (reg->actionCell, _("Split"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
xaccAddComboCellMenuItem (reg->actionCell, _("Buy"));
|
xaccAddComboCellMenuItem (reg->actionCell, _("Buy"));
|
||||||
xaccAddComboCellMenuItem (reg->actionCell, _("Sell"));
|
xaccAddComboCellMenuItem (reg->actionCell, _("Sell"));
|
||||||
@@ -322,6 +330,8 @@ configLayout (SplitRegister *reg)
|
|||||||
CellBlock *curs;
|
CellBlock *curs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
printf( "configLayout with type %d\n", reg->type );
|
||||||
|
|
||||||
/* fill things up with null cells */
|
/* fill things up with null cells */
|
||||||
for (i = 0; i < reg->cursor_header->num_cols; i++)
|
for (i = 0; i < reg->cursor_header->num_cols; i++)
|
||||||
{
|
{
|
||||||
@@ -369,8 +379,13 @@ configLayout (SplitRegister *reg)
|
|||||||
set_cell (reg, curs, DESC_CELL, 0, 2);
|
set_cell (reg, curs, DESC_CELL, 0, 2);
|
||||||
set_cell (reg, curs, MXFRM_CELL, 0, 3);
|
set_cell (reg, curs, MXFRM_CELL, 0, 3);
|
||||||
set_cell (reg, curs, RECN_CELL, 0, 4);
|
set_cell (reg, curs, RECN_CELL, 0, 4);
|
||||||
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
if ( reg->template ) {
|
||||||
set_cell (reg, curs, CRED_CELL, 0, 6);
|
set_cell( reg, curs, FDEBT_CELL, 0, 5);
|
||||||
|
set_cell( reg, curs, FCRED_CELL, 0, 6);
|
||||||
|
} else {
|
||||||
|
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, CRED_CELL, 0, 6);
|
||||||
|
}
|
||||||
set_cell (reg, curs, BALN_CELL, 0, 7);
|
set_cell (reg, curs, BALN_CELL, 0, 7);
|
||||||
|
|
||||||
curs = reg->cursor_ledger_double;
|
curs = reg->cursor_ledger_double;
|
||||||
@@ -397,8 +412,13 @@ configLayout (SplitRegister *reg)
|
|||||||
set_cell (reg, curs, MEMO_CELL, 0, 2);
|
set_cell (reg, curs, MEMO_CELL, 0, 2);
|
||||||
set_cell (reg, curs, XFRM_CELL, 0, 3);
|
set_cell (reg, curs, XFRM_CELL, 0, 3);
|
||||||
set_cell (reg, curs, RECN_CELL, 0, 4);
|
set_cell (reg, curs, RECN_CELL, 0, 4);
|
||||||
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
if ( reg->template ) {
|
||||||
set_cell (reg, curs, CRED_CELL, 0, 6);
|
set_cell( reg, curs, FDEBT_CELL, 0, 5);
|
||||||
|
set_cell( reg, curs, FCRED_CELL, 0, 6);
|
||||||
|
} else {
|
||||||
|
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, CRED_CELL, 0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -414,8 +434,13 @@ configLayout (SplitRegister *reg)
|
|||||||
set_cell (reg, curs, DESC_CELL, 0, 2);
|
set_cell (reg, curs, DESC_CELL, 0, 2);
|
||||||
set_cell (reg, curs, MXFRM_CELL, 0, 3);
|
set_cell (reg, curs, MXFRM_CELL, 0, 3);
|
||||||
set_cell (reg, curs, RECN_CELL, 0, 4);
|
set_cell (reg, curs, RECN_CELL, 0, 4);
|
||||||
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
if ( reg->template ) {
|
||||||
set_cell (reg, curs, CRED_CELL, 0, 6);
|
set_cell (reg, curs, FDEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, FCRED_CELL, 0, 6);
|
||||||
|
} else {
|
||||||
|
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, CRED_CELL, 0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
curs = reg->cursor_ledger_double;
|
curs = reg->cursor_ledger_double;
|
||||||
copy_cursor_row (reg, curs, reg->cursor_ledger_single, 0);
|
copy_cursor_row (reg, curs, reg->cursor_ledger_single, 0);
|
||||||
@@ -440,8 +465,13 @@ configLayout (SplitRegister *reg)
|
|||||||
set_cell (reg, curs, MEMO_CELL, 0, 2);
|
set_cell (reg, curs, MEMO_CELL, 0, 2);
|
||||||
set_cell (reg, curs, XFRM_CELL, 0, 3);
|
set_cell (reg, curs, XFRM_CELL, 0, 3);
|
||||||
set_cell (reg, curs, RECN_CELL, 0, 4);
|
set_cell (reg, curs, RECN_CELL, 0, 4);
|
||||||
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
if ( reg->template ) {
|
||||||
set_cell (reg, curs, CRED_CELL, 0, 6);
|
set_cell (reg, curs, FDEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, FCRED_CELL, 0, 6);
|
||||||
|
} else {
|
||||||
|
set_cell (reg, curs, DEBT_CELL, 0, 5);
|
||||||
|
set_cell (reg, curs, CRED_CELL, 0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -540,7 +570,6 @@ configLayout (SplitRegister *reg)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------- */
|
/* --------------------------------------------------------- */
|
||||||
default:
|
default:
|
||||||
PERR ("unknown register type %d \n", reg->type);
|
PERR ("unknown register type %d \n", reg->type);
|
||||||
@@ -557,7 +586,8 @@ xaccMallocSplitRegister (SplitRegisterType type,
|
|||||||
TableView *view,
|
TableView *view,
|
||||||
VirtCellDataAllocator allocator,
|
VirtCellDataAllocator allocator,
|
||||||
VirtCellDataDeallocator deallocator,
|
VirtCellDataDeallocator deallocator,
|
||||||
VirtCellDataCopy copy)
|
VirtCellDataCopy copy,
|
||||||
|
gboolean templateMode)
|
||||||
{
|
{
|
||||||
SplitRegister * reg;
|
SplitRegister * reg;
|
||||||
|
|
||||||
@@ -577,7 +607,8 @@ xaccMallocSplitRegister (SplitRegisterType type,
|
|||||||
view,
|
view,
|
||||||
allocator,
|
allocator,
|
||||||
deallocator,
|
deallocator,
|
||||||
copy);
|
copy,
|
||||||
|
templateMode);
|
||||||
|
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
@@ -655,7 +686,8 @@ xaccInitSplitRegister (SplitRegister *reg,
|
|||||||
TableView *view,
|
TableView *view,
|
||||||
VirtCellDataAllocator allocator,
|
VirtCellDataAllocator allocator,
|
||||||
VirtCellDataDeallocator deallocator,
|
VirtCellDataDeallocator deallocator,
|
||||||
VirtCellDataCopy copy)
|
VirtCellDataCopy copy,
|
||||||
|
gboolean templateMode)
|
||||||
{
|
{
|
||||||
Table * table;
|
Table * table;
|
||||||
|
|
||||||
@@ -666,6 +698,7 @@ xaccInitSplitRegister (SplitRegister *reg,
|
|||||||
reg->type = type;
|
reg->type = type;
|
||||||
reg->style = style;
|
reg->style = style;
|
||||||
reg->use_double_line = use_double_line;
|
reg->use_double_line = use_double_line;
|
||||||
|
reg->template = templateMode;
|
||||||
|
|
||||||
/* --------------------------- */
|
/* --------------------------- */
|
||||||
/* define the number of columns in the display, malloc the cursors */
|
/* define the number of columns in the display, malloc the cursors */
|
||||||
@@ -705,6 +738,8 @@ xaccInitSplitRegister (SplitRegister *reg,
|
|||||||
NEW (TSHRBALN, tshrbaln, Price);
|
NEW (TSHRBALN, tshrbaln, Price);
|
||||||
NEW (TBALN, tbalance, Price);
|
NEW (TBALN, tbalance, Price);
|
||||||
NEW (NOTES, notes, QuickFill);
|
NEW (NOTES, notes, QuickFill);
|
||||||
|
NEW (FCRED, formCredit, QuickFill);
|
||||||
|
NEW (FDEBT, formDebit, QuickFill);
|
||||||
|
|
||||||
/* --------------------------- */
|
/* --------------------------- */
|
||||||
|
|
||||||
@@ -761,6 +796,11 @@ xaccInitSplitRegister (SplitRegister *reg,
|
|||||||
/* the notes cell */
|
/* the notes cell */
|
||||||
xaccSetBasicCellBlankHelp (®->notesCell->cell,
|
xaccSetBasicCellBlankHelp (®->notesCell->cell,
|
||||||
_("Enter notes for the transaction"));
|
_("Enter notes for the transaction"));
|
||||||
|
/* the formula cell */
|
||||||
|
xaccSetBasicCellBlankHelp( ®->formCreditCell->cell,
|
||||||
|
_("Enter credit formula for real transaction"));
|
||||||
|
xaccSetBasicCellBlankHelp( ®->formDebitCell->cell,
|
||||||
|
_("Enter debit formula for real transaction"));
|
||||||
|
|
||||||
/* Use 6 decimal places for prices */
|
/* Use 6 decimal places for prices */
|
||||||
xaccSetPriceCellFraction (reg->priceCell, 1000000);
|
xaccSetPriceCellFraction (reg->priceCell, 1000000);
|
||||||
@@ -918,6 +958,8 @@ xaccDestroySplitRegister (SplitRegister *reg)
|
|||||||
xaccDestroyPriceCell (reg->tshrbalnCell);
|
xaccDestroyPriceCell (reg->tshrbalnCell);
|
||||||
xaccDestroyPriceCell (reg->tbalanceCell);
|
xaccDestroyPriceCell (reg->tbalanceCell);
|
||||||
xaccDestroyQuickFillCell (reg->notesCell);
|
xaccDestroyQuickFillCell (reg->notesCell);
|
||||||
|
xaccDestroyQuickFillCell (reg->formCreditCell);
|
||||||
|
xaccDestroyQuickFillCell (reg->formDebitCell);
|
||||||
|
|
||||||
reg->nullCell = NULL;
|
reg->nullCell = NULL;
|
||||||
reg->dateCell = NULL;
|
reg->dateCell = NULL;
|
||||||
@@ -940,6 +982,8 @@ xaccDestroySplitRegister (SplitRegister *reg)
|
|||||||
reg->tshrbalnCell = NULL;
|
reg->tshrbalnCell = NULL;
|
||||||
reg->tbalanceCell = NULL;
|
reg->tbalanceCell = NULL;
|
||||||
reg->notesCell = NULL;
|
reg->notesCell = NULL;
|
||||||
|
reg->formCreditCell = NULL;
|
||||||
|
reg->formDebitCell = NULL;
|
||||||
|
|
||||||
for (i = 0; i < CELL_TYPE_COUNT; i++)
|
for (i = 0; i < CELL_TYPE_COUNT; i++)
|
||||||
{
|
{
|
||||||
@@ -987,6 +1031,9 @@ xaccSplitRegisterGetChangeFlag (SplitRegister *reg)
|
|||||||
changed |= MOD_MXFRM & reg->mxfrmCell->cell.changed;
|
changed |= MOD_MXFRM & reg->mxfrmCell->cell.changed;
|
||||||
changed |= MOD_NOTES & reg->notesCell->cell.changed;
|
changed |= MOD_NOTES & reg->notesCell->cell.changed;
|
||||||
|
|
||||||
|
changed |= MOD_AMNT & reg->formCreditCell->cell.changed;
|
||||||
|
changed |= MOD_AMNT & reg->formDebitCell->cell.changed;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,6 +1056,9 @@ xaccSplitRegisterGetConditionalChangeFlag (SplitRegister *reg)
|
|||||||
changed |= MOD_SHRS & reg->sharesCell->cell.conditionally_changed;
|
changed |= MOD_SHRS & reg->sharesCell->cell.conditionally_changed;
|
||||||
changed |= MOD_MXFRM & reg->mxfrmCell->cell.conditionally_changed;
|
changed |= MOD_MXFRM & reg->mxfrmCell->cell.conditionally_changed;
|
||||||
changed |= MOD_NOTES & reg->notesCell->cell.conditionally_changed;
|
changed |= MOD_NOTES & reg->notesCell->cell.conditionally_changed;
|
||||||
|
|
||||||
|
changed |= MOD_AMNT & reg->formCreditCell->cell.conditionally_changed;
|
||||||
|
changed |= MOD_AMNT & reg->formDebitCell->cell.conditionally_changed;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
@@ -1031,6 +1081,8 @@ xaccSplitRegisterClearChangeFlag (SplitRegister *reg)
|
|||||||
reg->sharesCell->cell.changed = 0;
|
reg->sharesCell->cell.changed = 0;
|
||||||
reg->mxfrmCell->cell.changed = 0;
|
reg->mxfrmCell->cell.changed = 0;
|
||||||
reg->notesCell->cell.changed = 0;
|
reg->notesCell->cell.changed = 0;
|
||||||
|
reg->formDebitCell->cell.changed = 0;
|
||||||
|
reg->formCreditCell->cell.changed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================== */
|
/* ============================================== */
|
||||||
@@ -1309,6 +1361,8 @@ xaccDestroySplitRegisterBuffer (SplitRegisterBuffer *srb)
|
|||||||
destroyCellBuffer(&srb->sharesCell);
|
destroyCellBuffer(&srb->sharesCell);
|
||||||
destroyCellBuffer(&srb->mxfrmCell);
|
destroyCellBuffer(&srb->mxfrmCell);
|
||||||
destroyCellBuffer(&srb->notesCell);
|
destroyCellBuffer(&srb->notesCell);
|
||||||
|
destroyCellBuffer(&srb->formCreditCell);
|
||||||
|
destroyCellBuffer(&srb->formDebitCell);
|
||||||
|
|
||||||
g_free(srb);
|
g_free(srb);
|
||||||
}
|
}
|
||||||
@@ -1349,6 +1403,8 @@ xaccSplitRegisterSaveCursor(SplitRegister *sr, SplitRegisterBuffer *srb)
|
|||||||
saveCell(&sr->sharesCell->cell, &srb->sharesCell);
|
saveCell(&sr->sharesCell->cell, &srb->sharesCell);
|
||||||
saveCell(&sr->mxfrmCell->cell, &srb->mxfrmCell);
|
saveCell(&sr->mxfrmCell->cell, &srb->mxfrmCell);
|
||||||
saveCell(&sr->notesCell->cell, &srb->notesCell);
|
saveCell(&sr->notesCell->cell, &srb->notesCell);
|
||||||
|
saveCell(&sr->formCreditCell->cell, &srb->formCreditCell);
|
||||||
|
saveCell(&sr->formDebitCell->cell, &srb->formDebitCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================== */
|
/* ============================================== */
|
||||||
@@ -1412,6 +1468,8 @@ xaccSplitRegisterRestoreCursorChanged(SplitRegister *sr,
|
|||||||
restoreCellChanged(&sr->sharesCell->cell, &srb->sharesCell, cursor);
|
restoreCellChanged(&sr->sharesCell->cell, &srb->sharesCell, cursor);
|
||||||
restoreCellChanged(&sr->mxfrmCell->cell, &srb->mxfrmCell, cursor);
|
restoreCellChanged(&sr->mxfrmCell->cell, &srb->mxfrmCell, cursor);
|
||||||
restoreCellChanged(&sr->notesCell->cell, &srb->notesCell, cursor);
|
restoreCellChanged(&sr->notesCell->cell, &srb->notesCell, cursor);
|
||||||
|
restoreCellChanged(&sr->formCreditCell->cell, &srb->formCreditCell, cursor);
|
||||||
|
restoreCellChanged(&sr->formDebitCell->cell, &srb->formDebitCell, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* keep in sync with CellType enum */
|
/* keep in sync with CellType enum */
|
||||||
@@ -1435,7 +1493,9 @@ static const char *cell_names[] =
|
|||||||
"trans-debit",
|
"trans-debit",
|
||||||
"trans-share-balance",
|
"trans-share-balance",
|
||||||
"trans-balance",
|
"trans-balance",
|
||||||
"notes"
|
"notes",
|
||||||
|
"credit formula",
|
||||||
|
"debit formula",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ typedef enum
|
|||||||
INCOME_LEDGER,
|
INCOME_LEDGER,
|
||||||
PORTFOLIO_LEDGER,
|
PORTFOLIO_LEDGER,
|
||||||
SEARCH_LEDGER,
|
SEARCH_LEDGER,
|
||||||
|
|
||||||
NUM_REGISTER_TYPES
|
NUM_REGISTER_TYPES
|
||||||
} SplitRegisterType;
|
} SplitRegisterType;
|
||||||
|
|
||||||
@@ -103,7 +104,9 @@ typedef enum
|
|||||||
TSHRBALN_CELL,
|
TSHRBALN_CELL,
|
||||||
TBALN_CELL,
|
TBALN_CELL,
|
||||||
NOTES_CELL,
|
NOTES_CELL,
|
||||||
CELL_TYPE_COUNT
|
FCRED_CELL, // formula credit, used by the template ledger
|
||||||
|
FDEBT_CELL, // formula debit, used by the template ledger
|
||||||
|
CELL_TYPE_COUNT,
|
||||||
} CellType;
|
} CellType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -139,6 +142,8 @@ typedef enum
|
|||||||
MOD_PRIC = 1 << 9,
|
MOD_PRIC = 1 << 9,
|
||||||
MOD_SHRS = 1 << 10,
|
MOD_SHRS = 1 << 10,
|
||||||
MOD_NOTES = 1 << 11,
|
MOD_NOTES = 1 << 11,
|
||||||
|
MOD_FCRED = 1 << 12,
|
||||||
|
MOD_FDEBT = 1 << 13,
|
||||||
MOD_ALL = 0xffff
|
MOD_ALL = 0xffff
|
||||||
} CellModifiedFlags;
|
} CellModifiedFlags;
|
||||||
|
|
||||||
@@ -204,6 +209,9 @@ struct _SplitRegister
|
|||||||
PriceCell * tbalanceCell;
|
PriceCell * tbalanceCell;
|
||||||
QuickFillCell * notesCell;
|
QuickFillCell * notesCell;
|
||||||
|
|
||||||
|
QuickFillCell * formCreditCell;
|
||||||
|
QuickFillCell * formDebitCell;
|
||||||
|
|
||||||
SplitRegisterType type;
|
SplitRegisterType type;
|
||||||
SplitRegisterStyle style;
|
SplitRegisterStyle style;
|
||||||
gboolean use_double_line;
|
gboolean use_double_line;
|
||||||
@@ -213,6 +221,17 @@ struct _SplitRegister
|
|||||||
BasicCell *header_cells[CELL_TYPE_COUNT];
|
BasicCell *header_cells[CELL_TYPE_COUNT];
|
||||||
BasicCell *cells[CELL_TYPE_COUNT];
|
BasicCell *cells[CELL_TYPE_COUNT];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag indicating a "template" register.
|
||||||
|
**/
|
||||||
|
gboolean template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template account which the transactions in a template
|
||||||
|
* splitregister will belong to.
|
||||||
|
**/
|
||||||
|
Account *templateAcct;
|
||||||
|
|
||||||
/* user_data allows users of this object to hang
|
/* user_data allows users of this object to hang
|
||||||
* private data onto it */
|
* private data onto it */
|
||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
@@ -236,7 +255,8 @@ xaccMallocSplitRegister (SplitRegisterType type,
|
|||||||
TableView *view,
|
TableView *view,
|
||||||
VirtCellDataAllocator allocator,
|
VirtCellDataAllocator allocator,
|
||||||
VirtCellDataDeallocator deallocator,
|
VirtCellDataDeallocator deallocator,
|
||||||
VirtCellDataCopy copy);
|
VirtCellDataCopy copy,
|
||||||
|
gboolean templateMode);
|
||||||
|
|
||||||
void xaccConfigSplitRegister (SplitRegister *reg,
|
void xaccConfigSplitRegister (SplitRegister *reg,
|
||||||
SplitRegisterType type,
|
SplitRegisterType type,
|
||||||
|
|||||||
@@ -66,6 +66,20 @@
|
|||||||
; (list "Extensions" "")
|
; (list "Extensions" "")
|
||||||
; (lambda () (gnc:main-win-account-group-write win))))
|
; (lambda () (gnc:main-win-account-group-write win))))
|
||||||
|
|
||||||
|
|
||||||
|
(define schedxact-editor-item
|
||||||
|
(gnc:make-menu-item (N_ "SchedXact: Editor")
|
||||||
|
(N_ "Editor of Scheduled Transactions")
|
||||||
|
(list "Extensions" "")
|
||||||
|
(lambda () (gnc:sx-editor)))
|
||||||
|
)
|
||||||
|
(define schedxact-slr-item
|
||||||
|
(gnc:make-menu-item (N_ "SchedXact: Since Last Run")
|
||||||
|
(N_ "since last run dialog")
|
||||||
|
(list "Extensions" "")
|
||||||
|
(lambda () (gnc:sx-since-last-run)))
|
||||||
|
)
|
||||||
|
|
||||||
(define progress-item
|
(define progress-item
|
||||||
(gnc:make-menu-item (N_ "Test progress dialog")
|
(gnc:make-menu-item (N_ "Test progress dialog")
|
||||||
(N_ "Test progress dialog")
|
(N_ "Test progress dialog")
|
||||||
@@ -91,7 +105,14 @@
|
|||||||
|
|
||||||
(gnc:add-extension menu)
|
(gnc:add-extension menu)
|
||||||
; (gnc:add-extension export-item)
|
; (gnc:add-extension export-item)
|
||||||
(gnc:add-extension progress-item))
|
|
||||||
|
;; NOTE: this is the inverse order from how you may want them to
|
||||||
|
;; appear in the menu [prepending to some list]...
|
||||||
|
|
||||||
|
(gnc:add-extension progress-item)
|
||||||
|
(gnc:add-extension schedxact-slr-item)
|
||||||
|
(gnc:add-extension schedxact-editor-item)
|
||||||
|
)
|
||||||
|
|
||||||
(if (gnc:debugging?)
|
(if (gnc:debugging?)
|
||||||
(gnc:hook-add-dangler gnc:*ui-startup-hook*
|
(gnc:hook-add-dangler gnc:*ui-startup-hook*
|
||||||
|
|||||||
Reference in New Issue
Block a user