mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
2002-08-06 Joshua Sled <jsled@asynchronous.org>
* src/gnome/dialog-scheduledxaction.c (gnc_sxed_check_consistent): The pre-defined variable 'i' no longer blocks transactions from being created "auto-create". * src/calculation/expression_parser.c: Added documentation for function support in the expression parser. * src/gnome/dialog-sxsincelast.c (create_each_transaction_helper): Scrub created splits so they get setup correctly, fixing the "incorrect-running-balance" problem [Bug#89879]. Wrote the oft-procrastinated memory-cleanup code; ensured [most] other dynamic memory allocation is clean. Removed some dead code/debugging. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7144 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
16
ChangeLog
16
ChangeLog
@@ -1,3 +1,19 @@
|
||||
2002-08-06 Joshua Sled <jsled@asynchronous.org>
|
||||
|
||||
* src/gnome/dialog-scheduledxaction.c (gnc_sxed_check_consistent):
|
||||
The pre-defined variable 'i' no longer blocks transactions from
|
||||
being created "auto-create".
|
||||
|
||||
* src/calculation/expression_parser.c: Added documentation for
|
||||
function support in the expression parser.
|
||||
|
||||
* src/gnome/dialog-sxsincelast.c (create_each_transaction_helper):
|
||||
Scrub created splits so they get setup correctly, fixing the
|
||||
"incorrect-running-balance" problem [Bug#89879].
|
||||
Wrote the oft-procrastinated memory-cleanup code; ensured [most]
|
||||
other dynamic memory allocation is clean. Removed some dead
|
||||
code/debugging.
|
||||
|
||||
2002-08-06 David Hampton <hampton@employees.org>
|
||||
|
||||
* doc/sgml/*/Makefile.am: Tweak for newer versions of db2html.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* 6-21-2000
|
||||
*/
|
||||
|
||||
/* Modified to support functions - Summer, 2002 -- jsled@asynchronous.org */
|
||||
|
||||
/* expression parser/evaluator use:
|
||||
*
|
||||
* Before describing the parser per se, I want to describe the
|
||||
@@ -43,6 +45,9 @@
|
||||
* "value" variable points to a user defined structure containing the
|
||||
* numeric value of the variable.
|
||||
*
|
||||
* As well, variables now have a VarStoreType, to distinguish between numeric
|
||||
* and string values, as we want string arguments to functions.
|
||||
*
|
||||
* In designing and writing the parser, I decided early on that the
|
||||
* parser should be an "expression parser/evaluator" and that the
|
||||
* actual arithmetic was the responsibility of the caller/user.
|
||||
@@ -117,6 +122,8 @@
|
||||
* 4: free_numeric - this function is responsible for freeing memory
|
||||
* used by the internal numeric representation.
|
||||
*
|
||||
* 5: func_op - this function is repsonsible for handling function calls.
|
||||
*
|
||||
* I have included the file "numeric_ops.c" containing the above
|
||||
* functions for the usual "double" and "int" representation of
|
||||
* numerics. The functions perform integer or floating point
|
||||
@@ -173,6 +180,12 @@
|
||||
* is responsible for freeing any memory used by the "pre-defined"
|
||||
* variables and their final numeric representation.
|
||||
*
|
||||
* There may also be strings in the expression, by quoting them in '"'
|
||||
* characters. These are intended to be passed literally into functions; the
|
||||
* result of using a string in a numeric operation is undefined. Presently,
|
||||
* the expression-parser code does not check the variable types during
|
||||
* parsing or evaluation.
|
||||
*
|
||||
* A second design goal of the parser was that it should be callable
|
||||
* concurrently by multiple modules independently. That each module
|
||||
* should be capable of using differing "pre-defined" variables and
|
||||
@@ -249,6 +262,14 @@
|
||||
* After parsing the above expressions the variables nni, jk, tyh and
|
||||
* tgh would all be defined.
|
||||
*
|
||||
* Functiosn are invoked with expressions of the format
|
||||
*
|
||||
* [_a-zA-Z]( <argument_0> : <argument_1> : ... : <argument_n> )
|
||||
*
|
||||
* where each argument can itself be a sub-expression [arithmetic operation
|
||||
* or function call].
|
||||
*
|
||||
*
|
||||
* There are six parser functions needed to use the parser/evaluator:
|
||||
*
|
||||
* Note: in the last five functions, in the function paramter (void
|
||||
@@ -265,7 +286,8 @@
|
||||
* void *left_value,
|
||||
* void *right_value),
|
||||
* void *negate_numeric(void *value),
|
||||
* void free_numeric(void *numeric_value));
|
||||
* void free_numeric(void *numeric_value),
|
||||
* void *func_op(const char *fname, int argc, void **argv));
|
||||
*
|
||||
* This function is called by the module/function/whatever to
|
||||
* initialize the parser. The parser returns a pointer to a
|
||||
|
||||
@@ -458,7 +458,7 @@ static
|
||||
gboolean
|
||||
gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
{
|
||||
gboolean ttHasVars;
|
||||
gint ttVarCount;
|
||||
FreqSpec *fs;
|
||||
|
||||
/* FIXMEs...
|
||||
@@ -480,7 +480,7 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
* right... ]
|
||||
*/
|
||||
|
||||
ttHasVars = FALSE;
|
||||
ttVarCount = 0;
|
||||
{
|
||||
static const int NUM_ITERS_WITH_VARS = 5;
|
||||
static const int NUM_ITERS_NO_VARS = 1;
|
||||
@@ -493,6 +493,7 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
Split *s;
|
||||
gnc_numeric creditSum, debitSum, tmp;
|
||||
gboolean unbalanceable;
|
||||
gpointer unusedKey, unusedValue;
|
||||
|
||||
unbalanceable = FALSE; /* innocent until proven guilty */
|
||||
vars = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
@@ -513,8 +514,8 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
/* numeric-formulas-get-balanced determination */
|
||||
sxsl_get_sx_vars( sxed->sx, vars );
|
||||
|
||||
ttHasVars = (g_hash_table_size( vars ) != 0);
|
||||
if ( g_hash_table_size( vars ) != 0 ) {
|
||||
ttVarCount = g_hash_table_size( vars );
|
||||
if ( ttVarCount != 0 ) {
|
||||
/* balance with random variable bindings some number
|
||||
* of times in an attempt to ferret out
|
||||
* un-balanceable transactions.
|
||||
@@ -585,6 +586,13 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
/* Subtract out pre-defined vars */
|
||||
if ( g_hash_table_lookup_extended( vars, "i",
|
||||
&unusedKey, &unusedValue ) ) {
|
||||
ttVarCount -= 1;
|
||||
}
|
||||
|
||||
g_hash_table_foreach( vars, free_var_numeric, (gpointer)vars );
|
||||
g_hash_table_destroy( vars );
|
||||
|
||||
@@ -649,17 +657,17 @@ gnc_sxed_check_consistent( SchedXactionEditorDialog *sxed )
|
||||
{
|
||||
gboolean autocreateState, notifyState;
|
||||
|
||||
autocreateState = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(sxed->autocreateOpt) );
|
||||
notifyState = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(sxed->notifyOpt) );
|
||||
autocreateState =
|
||||
gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(sxed->autocreateOpt) );
|
||||
notifyState =
|
||||
gtk_toggle_button_get_active(
|
||||
GTK_TOGGLE_BUTTON(sxed->notifyOpt) );
|
||||
|
||||
if ( ttHasVars && autocreateState ) {
|
||||
/* FIXME: Wow... that's a mouthful. Reword. */
|
||||
if ( (ttVarCount > 0) && autocreateState ) {
|
||||
gnc_warning_dialog_parented( sxed->dialog,
|
||||
_("You attempted to create a \"Create "
|
||||
"Automatically\" "
|
||||
"Scheduled Transaction which has Variables, "
|
||||
"which is not allowed.\nPlease remove the "
|
||||
"Create Automatically flag and try again.") );
|
||||
_("Scheduled Transactions with variables\n"
|
||||
"cannot be automatically created.") );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,12 @@
|
||||
#include <gnome.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "Account.h"
|
||||
#include "Group.h"
|
||||
#include "Query.h"
|
||||
#include "SchedXaction.h"
|
||||
#include "Transaction.h"
|
||||
#include "Scrub.h"
|
||||
#include "dialog-utils.h"
|
||||
#include "finvar.h"
|
||||
#include "gnc-book.h"
|
||||
@@ -166,8 +168,7 @@ typedef struct _sxSinceLastData {
|
||||
|
||||
/** A HashTable of SX mapped to initial temporal data. */
|
||||
GHashTable /* <SchedXaction*,void*> */ *sxInitStates;
|
||||
/** The list of removed SXes, in case we need to revert/cancel. */
|
||||
GList /* <toDeleteTuple*> */ *removedList;
|
||||
|
||||
/** The list of the GUIDs of _all_ transactions we've created. */
|
||||
GList /* <GUID*> */ *createdTxnGUIDList;
|
||||
|
||||
@@ -226,7 +227,6 @@ typedef struct reminderInstanceTuple_ {
|
||||
typedef struct toDeleteTuple_ {
|
||||
SchedXaction *sx;
|
||||
GDate *endDate;
|
||||
gchar *freq_info;
|
||||
gboolean isSelected;
|
||||
} toDeleteTuple;
|
||||
|
||||
@@ -312,7 +312,11 @@ static void sx_obsolete_unselect_all_clicked( GtkButton *button,
|
||||
gpointer user_data );
|
||||
|
||||
static void gnc_sxsld_free_tci( toCreateInstance *tci );
|
||||
|
||||
static void gnc_sxsld_free_toCreateTuple_list( GList *l );
|
||||
static void gnc_sxsld_free_sxState( gpointer key,
|
||||
gpointer value,
|
||||
gpointer userdata );
|
||||
static void gnc_sxsld_free_entry_numeric( GtkObject *o, gpointer ud );
|
||||
|
||||
/**
|
||||
* Used to wrap for the book-open hook, where the book filename is given.
|
||||
@@ -987,27 +991,19 @@ gnc_sxsld_finish( GnomeDruidPage *druid_page,
|
||||
if ( g_list_length( cl->selection ) > 0 ) {
|
||||
sxList = gnc_book_get_schedxactions( gnc_get_current_book() );
|
||||
|
||||
gnc_suspend_gui_refresh();
|
||||
for ( toDelPtr = cl->selection;
|
||||
toDelPtr;
|
||||
toDelPtr = toDelPtr->next ) {
|
||||
|
||||
row = (gint)toDelPtr->data;
|
||||
tdt = (toDeleteTuple*)gtk_clist_get_row_data( cl, row );
|
||||
{
|
||||
elt = g_list_find( sxList, tdt->sx );
|
||||
sxList = g_list_remove_link( sxList, elt );
|
||||
|
||||
sxsld->removedList = g_list_concat( sxsld->removedList, elt );
|
||||
}
|
||||
{
|
||||
elt = g_list_find( sxsld->toRemoveList, tdt );
|
||||
sxsld->toRemoveList =
|
||||
g_list_remove_link( sxsld->toRemoveList, elt );
|
||||
g_list_free_1(elt);
|
||||
}
|
||||
g_date_free( tdt->endDate );
|
||||
g_free( tdt );
|
||||
elt = g_list_find( sxList, tdt->sx );
|
||||
sxList = g_list_remove_link( sxList, elt );
|
||||
|
||||
xaccSchedXactionFree( (SchedXaction*)elt->data );
|
||||
}
|
||||
gnc_resume_gui_refresh();
|
||||
|
||||
gnc_book_set_schedxactions( gnc_get_current_book(), sxList );
|
||||
}
|
||||
@@ -1043,10 +1039,7 @@ cancel_check( GnomeDruidPage *druid_page,
|
||||
"Are you sure you want to lose all "
|
||||
"Scheduled Transaction changes?" );
|
||||
|
||||
DEBUG( "cancel_check" );
|
||||
|
||||
if ( g_list_length( sxsld->removedList ) == 0
|
||||
&& g_list_length( sxsld->createdTxnGUIDList ) == 0 ) {
|
||||
if ( g_list_length( sxsld->createdTxnGUIDList ) == 0 ) {
|
||||
/* There's nothing to cancel, so just do so... */
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1056,7 +1049,6 @@ cancel_check( GnomeDruidPage *druid_page,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DEBUG( "reverting SX changes...\n" );
|
||||
/* Cancel policy:
|
||||
* . deleted SXes
|
||||
* . reborn
|
||||
@@ -1069,47 +1061,20 @@ cancel_check( GnomeDruidPage *druid_page,
|
||||
* . reminders -> created
|
||||
* . Trans deleted
|
||||
* . SXes reset
|
||||
*
|
||||
* SXes reset:
|
||||
* SXes reset [we use the temporal-state-data to take care of this]
|
||||
* . end_date || num_remain_instances
|
||||
* . last_occur_date
|
||||
*/
|
||||
|
||||
gnc_suspend_gui_refresh();
|
||||
/* rebirth deleted SXes */
|
||||
DEBUG( "There are %d SXes on the 'removedList' to re-birth",
|
||||
g_list_length( sxsld->removedList ) );
|
||||
if ( g_list_length( sxsld->removedList ) > 0 ) {
|
||||
GList *sxList =
|
||||
gnc_book_get_schedxactions( gnc_get_current_book () );
|
||||
for ( l = sxsld->removedList; l; l = l->next ) {
|
||||
DEBUG( "re-birthing SX \"%s\"",
|
||||
xaccSchedXactionGetName( (SchedXaction*)l->data ) );
|
||||
sxList = g_list_append( sxList,
|
||||
(SchedXaction*)l->data );
|
||||
}
|
||||
gnc_book_set_schedxactions( gnc_get_current_book(),
|
||||
sxList );
|
||||
}
|
||||
/* delete created transactions */
|
||||
DEBUG( "length( sxsld->createdTxnGUIDList ): %d",
|
||||
g_list_length( sxsld->createdTxnGUIDList ) );
|
||||
|
||||
/* destroy created transactions */
|
||||
if ( g_list_length( sxsld->createdTxnGUIDList ) > 0 ) {
|
||||
Transaction *t = NULL;
|
||||
for ( l = sxsld->createdTxnGUIDList; l; l = l->next ) {
|
||||
t = xaccTransLookup( (GUID*)l->data,
|
||||
gnc_get_current_book() );
|
||||
if ( t == NULL ) {
|
||||
char *guidStr;
|
||||
guidStr =
|
||||
guid_to_string( (GUID*)l->data );
|
||||
PERR( "We thought we created Transaction "
|
||||
"\"%s\", but can't "
|
||||
"xaccTransLookup(...) it now.",
|
||||
guidStr );
|
||||
free(guidStr);
|
||||
break;
|
||||
}
|
||||
g_assert( t );
|
||||
xaccTransBeginEdit( t );
|
||||
xaccTransDestroy( t );
|
||||
xaccTransCommitEdit( t );
|
||||
@@ -1255,7 +1220,6 @@ generate_instances( SchedXaction *sx,
|
||||
reminderTuple *rt;
|
||||
reminderInstanceTuple *rit;
|
||||
void *seqStateData;
|
||||
char tmpBuf[GNC_D_BUF_WIDTH];
|
||||
|
||||
g_assert( g_date_valid(end) );
|
||||
g_assert( g_date_valid(reminderEnd) );
|
||||
@@ -1322,24 +1286,6 @@ generate_instances( SchedXaction *sx,
|
||||
seqStateData = NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
free_gdate_list_elts( gpointer data, gpointer user_data )
|
||||
{
|
||||
g_date_free( (GDate*)data );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static void
|
||||
_free_reminderTuple_list_elts( gpointer data, gpointer user_data )
|
||||
{
|
||||
/* FIXME: endDate? */
|
||||
g_date_free( ((reminderTuple*)data)->occurDate );
|
||||
g_free( (reminderTuple*)data );
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_free_varBindings_hash_elts( gpointer key, gpointer value, gpointer data )
|
||||
{
|
||||
@@ -1413,8 +1359,9 @@ process_auto_create_list( GList *autoCreateList, sxSinceLastData *sxsld )
|
||||
tci = (toCreateInstance*)instances->data;
|
||||
thisGUID = createdGUIDs = NULL;
|
||||
create_transactions_on( tct->sx,
|
||||
(GDate*)tci->date,
|
||||
NULL, &createdGUIDs );
|
||||
tci->date,
|
||||
tci,
|
||||
&createdGUIDs );
|
||||
|
||||
count++;
|
||||
gtk_progress_set_value( GTK_PROGRESS(sxsld->prog), count );
|
||||
@@ -1449,7 +1396,6 @@ add_to_create_list_to_gui( GList *toCreateList, sxSinceLastData *sxsld )
|
||||
GtkCTreeNode *sxNode;
|
||||
char *rowText[ TO_CREATE_LIST_WIDTH ];
|
||||
GList *insts;
|
||||
gpointer unusedkey, unusedvalue;
|
||||
|
||||
ct = GTK_CTREE( glade_xml_get_widget( sxsld->gxml, TO_CREATE_LIST ) );
|
||||
|
||||
@@ -1532,6 +1478,8 @@ add_reminders_to_gui( GList *reminderList, sxSinceLastData *sxsld )
|
||||
NULL, NULL, NULL, NULL, /* pixmaps */
|
||||
FALSE, /* leafP */
|
||||
TRUE ); /* expandedP */
|
||||
g_string_free( freqSpecStr, TRUE );
|
||||
|
||||
/* The SX node itself isn't selectable; only the
|
||||
* instances. */
|
||||
gtk_ctree_node_set_selectable( ctree, sxNode, FALSE );
|
||||
@@ -1568,7 +1516,6 @@ add_reminders_to_gui( GList *reminderList, sxSinceLastData *sxsld )
|
||||
g_free( rowText[0] );
|
||||
g_free( rowText[2] );
|
||||
}
|
||||
g_string_free( freqSpecStr, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1581,18 +1528,18 @@ add_dead_list_to_gui(GList *removeList, sxSinceLastData *sxsld)
|
||||
GString *tmp_str;
|
||||
toDeleteTuple *tdt;
|
||||
FreqSpec *fs;
|
||||
rowtext[2] = g_new0(gchar, GNC_D_BUF_WIDTH );
|
||||
|
||||
cl = GTK_CLIST( glade_xml_get_widget( sxsld->gxml,
|
||||
SX_OBSOLETE_CLIST ));
|
||||
|
||||
tmp_str = g_string_new(NULL);
|
||||
rowtext[2] = g_new0(gchar, GNC_D_BUF_WIDTH );
|
||||
|
||||
gtk_clist_freeze( cl );
|
||||
gtk_clist_clear( cl );
|
||||
gtk_signal_handler_block_by_func( GTK_OBJECT(cl),
|
||||
sxsld_obsolete_row_toggle,
|
||||
sxsld );
|
||||
|
||||
for ( row = 0; removeList;
|
||||
row++, removeList = removeList->next ) {
|
||||
tdt = (toDeleteTuple*)removeList->data;
|
||||
@@ -1608,6 +1555,7 @@ add_dead_list_to_gui(GList *removeList, sxSinceLastData *sxsld)
|
||||
* last valid one. :( Or, even better, the reason for
|
||||
* obsolesence. */
|
||||
/*g_date_strftime( rowtext[2], GNC_D_WIDTH, GNC_D_FMT, tdt->endDate ); */
|
||||
|
||||
strcpy( rowtext[2], "obsolete" );
|
||||
|
||||
gtk_clist_insert( cl, row, rowtext );
|
||||
@@ -1672,7 +1620,8 @@ processSelectedReminderList( GList *goodList, sxSinceLastData *sxsld )
|
||||
tci = g_new0( toCreateInstance, 1 );
|
||||
tci->dirty = FALSE;
|
||||
tci->parentTCT = tct;
|
||||
tci->date = rit->occurDate;
|
||||
tci->date = g_date_new();
|
||||
*tci->date = *rit->occurDate;
|
||||
tci->varBindings = NULL;
|
||||
tci->instanceNum = rit->instanceNum;
|
||||
tci->node = NULL;
|
||||
@@ -1790,22 +1739,6 @@ sxsincelast_populate( sxSinceLastData *sxsld )
|
||||
return showIt;
|
||||
}
|
||||
|
||||
static void
|
||||
clean_sincelast_dlg( sxSinceLastData *sxsld )
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
/* . clean out to-create clist
|
||||
* . free associated memories.
|
||||
*
|
||||
* FIXME: other dlg stuff to clean?
|
||||
*/
|
||||
clean_variable_table( sxsld );
|
||||
|
||||
w = glade_xml_get_widget( sxsld->gxml, TO_CREATE_LIST );
|
||||
gtk_clist_clear( GTK_CLIST(w) );
|
||||
}
|
||||
|
||||
static void
|
||||
sxsincelast_close_handler( gpointer ud )
|
||||
{
|
||||
@@ -1813,9 +1746,8 @@ sxsincelast_close_handler( gpointer ud )
|
||||
|
||||
gtk_widget_hide( sxsld->sincelast_window );
|
||||
sxsincelast_save_size( sxsld );
|
||||
clean_sincelast_dlg( sxsld );
|
||||
gtk_widget_destroy( sxsld->sincelast_window );
|
||||
clean_sincelast_data( sxsld );
|
||||
/* The data will be cleaned up in the destroy handler. */
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1858,8 +1790,10 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
"gnc_numeric-parseable", entryText );
|
||||
num = NULL;
|
||||
} else {
|
||||
#if 0 /* 0 -- this is fine. */
|
||||
DEBUG( "\"%s\" parses as \"%f\"", entryText,
|
||||
gnc_numeric_to_double( *num ) );
|
||||
#endif /* 0 -- this is fine. */
|
||||
}
|
||||
|
||||
g_hash_table_destroy( dummyVarHash );
|
||||
@@ -1879,9 +1813,8 @@ sxsincelast_entry_changed( GtkEditable *e, gpointer ud )
|
||||
if ( maybeValue ) {
|
||||
g_free( maybeValue );
|
||||
}
|
||||
/* FIXME: Does the maybeKey need to be freed? */
|
||||
}
|
||||
g_hash_table_insert( tci->varBindings, maybeKey, ourNum );
|
||||
g_hash_table_insert( tci->varBindings, varName, ourNum );
|
||||
tci->dirty = TRUE;
|
||||
}
|
||||
|
||||
@@ -1902,18 +1835,21 @@ sxsincelast_destroy( GtkObject *o, gpointer ud )
|
||||
{
|
||||
sxSinceLastData *sxsld = (sxSinceLastData*)ud;
|
||||
|
||||
gnc_unregister_gui_component_by_data( DIALOG_SXSINCELAST_CM_CLASS,
|
||||
sxsld->sincelast_window );
|
||||
|
||||
/* appropriate place to destroy data structures */
|
||||
clean_sincelast_data( sxsld );
|
||||
|
||||
/* FIXME: need more freeing for ledgers? why do these result in
|
||||
* "gnc_close_gui_component: component not found" messages? */
|
||||
|
||||
gnc_ledger_display_close( sxsld->ac_ledger );
|
||||
/* FIXME: need more freeing for ac_ledger? */
|
||||
sxsld->ac_ledger = NULL;
|
||||
|
||||
gnc_ledger_display_close( sxsld->created_ledger );
|
||||
/* FIXME: need more freeing for created_ledger? */
|
||||
sxsld->created_ledger = NULL;
|
||||
|
||||
gnc_unregister_gui_component_by_data( DIALOG_SXSINCELAST_CM_CLASS,
|
||||
sxsld->sincelast_window );
|
||||
|
||||
g_free( sxsld );
|
||||
}
|
||||
|
||||
@@ -1982,24 +1918,9 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
/* FIXME: when we copy the trans_onto_trans, we don't want to copy
|
||||
the Split's kvp_frames... */
|
||||
|
||||
/* FIXME: This should setup the predefined variables 'i' and 'N' */
|
||||
|
||||
createUD = (createData*)d;
|
||||
tci = createUD->tci;
|
||||
|
||||
actualVars = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
if ( tci->varBindings != NULL ) {
|
||||
g_hash_table_foreach( tci->varBindings,
|
||||
gnc_sxsl_copy_ea_hash, actualVars );
|
||||
}
|
||||
varIValue = g_new0( gnc_numeric, 1 );
|
||||
*varIValue = gnc_numeric_create( tci->instanceNum, 1 );
|
||||
|
||||
/* It's really important that we strdup "i" here, so we can
|
||||
* generically cleanup with a simple 'foreach' that blindly frees the
|
||||
* keys, below. */
|
||||
g_hash_table_insert( actualVars, g_strdup("i"), varIValue );
|
||||
|
||||
newT = xaccMallocTransaction(gnc_get_current_book ());
|
||||
xaccTransBeginEdit( newT );
|
||||
/* the action and description/memo are in the template */
|
||||
@@ -2015,26 +1936,41 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
sList = xaccTransGetSplitList( newT );
|
||||
if ( (osList == NULL) || (sList == NULL) ) {
|
||||
PERR( "\tseen transaction w/o splits. :(" );
|
||||
/* FIXME: we've allocated things we need to cleanup... */
|
||||
xaccTransDestroy( newT );
|
||||
xaccTransCommitEdit( newT );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Setup the predefined variables for credit/debit formula
|
||||
* processing. */
|
||||
actualVars = g_hash_table_new( g_str_hash, g_str_equal );
|
||||
if ( tci->varBindings != NULL ) {
|
||||
g_hash_table_foreach( tci->varBindings,
|
||||
gnc_sxsl_copy_ea_hash, actualVars );
|
||||
}
|
||||
varIValue = g_new0( gnc_numeric, 1 );
|
||||
*varIValue = gnc_numeric_create( tci->instanceNum, 1 );
|
||||
/* It's really important that we strdup "i" here, so we can
|
||||
* generically cleanup with a simple 'foreach' that blindly frees the
|
||||
* keys, below. */
|
||||
g_hash_table_insert( actualVars, g_strdup("i"), varIValue );
|
||||
|
||||
for ( ; sList && osList ;
|
||||
sList = sList->next, osList = osList->next ) {
|
||||
split = (Split*)sList->data;
|
||||
|
||||
Account *acct;
|
||||
|
||||
/* FIXME: Ick. This assumes that the split lists will be
|
||||
ordered identically. :( I think it's fair to say they
|
||||
will, but I'd rather not have to count on it. --jsled */
|
||||
split_kvpf = xaccSplitGetSlots( (Split*)osList->data );
|
||||
|
||||
|
||||
/* from-transaction of splits */
|
||||
/* FIXME: is this true? -- seems like it should be the other
|
||||
* way around; perhaps this is the reason for Bug#89879? */
|
||||
/* This needs to be before the value setting [below] so the
|
||||
* balance calculations can work. */
|
||||
{
|
||||
GUID *acct_guid;
|
||||
Account *acct;
|
||||
/* contains the guid of the split's actual account. */
|
||||
kvp_val = kvp_frame_get_slot_path( split_kvpf,
|
||||
GNC_SX_ID,
|
||||
@@ -2060,10 +1996,8 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
commonCommodity = xaccAccountGetCommodity( acct );
|
||||
xaccAccountBeginEdit( acct );
|
||||
xaccAccountInsertSplit( acct, split );
|
||||
xaccAccountCommitEdit( acct );
|
||||
}
|
||||
|
||||
|
||||
/* commonCommodity = xaccTransGetCurrency( t ); */
|
||||
/* credit/debit formulas */
|
||||
{
|
||||
@@ -2133,9 +2067,9 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
#endif /* 0 -- debug */
|
||||
|
||||
xaccSplitSetValue( split, final );
|
||||
xaccSplitScrub( split );
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* NOT [YET] USED */
|
||||
kvp_val = kvp_frame_get_slot_path( split_kvpf,
|
||||
@@ -2149,8 +2083,10 @@ create_each_transaction_helper( Transaction *t, void *d )
|
||||
NULL);
|
||||
#endif /* 0 */
|
||||
|
||||
xaccAccountCommitEdit( acct );
|
||||
}
|
||||
|
||||
|
||||
/* Cleanup actualVars table. */
|
||||
{
|
||||
g_hash_table_foreach( actualVars,
|
||||
@@ -2216,47 +2152,15 @@ create_transactions_on( SchedXaction *sx,
|
||||
toCreateTuple *tct;
|
||||
gboolean createdTCT;
|
||||
|
||||
#if 0
|
||||
{
|
||||
char tmpBuf[GNC_D_WIDTH];
|
||||
g_date_strftime( tmpBuf, GNC_D_WIDTH, GNC_D_FMT, gd );
|
||||
DEBUG( "Creating transactions on %s for %s",
|
||||
tmpBuf, xaccSchedXactionGetName( sx ) );
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
if ( tci != NULL
|
||||
&& g_date_compare( gd, tci->date ) != 0 ) {
|
||||
PERR( "GDate and TCI date aren't equal, "
|
||||
"which isn't a Good Thing." );
|
||||
return;
|
||||
}
|
||||
|
||||
tct = NULL;
|
||||
createdTCT = FALSE;
|
||||
if ( tci == NULL ) {
|
||||
/* Create a faux tct for the creation-helper. */
|
||||
tct = g_new0( toCreateTuple, 1 );
|
||||
tci = g_new0( toCreateInstance, 1 );
|
||||
/* FIXME: add instance num */
|
||||
tct->sx = sx;
|
||||
tct->instanceList =
|
||||
g_list_append( tct->instanceList, tci );
|
||||
tci->dirty = FALSE;
|
||||
tci->date = gd;
|
||||
tci->node = NULL;
|
||||
tci->parentTCT = tct;
|
||||
|
||||
createdTCT = TRUE;
|
||||
if ( tci ) {
|
||||
g_assert( g_date_compare( gd, tci->date ) == 0 );
|
||||
}
|
||||
|
||||
ag = gnc_book_get_template_group( gnc_get_current_book () );
|
||||
id = guid_to_string( xaccSchedXactionGetGUID(sx) );
|
||||
if(ag && id)
|
||||
{
|
||||
if ( ag && id ) {
|
||||
acct = xaccGetAccountFromName( ag, id );
|
||||
if(acct)
|
||||
{
|
||||
if ( acct ) {
|
||||
createUD.tci = tci;
|
||||
createUD.createdGUIDs = createdGUIDs;
|
||||
xaccAccountForEachTransaction( acct,
|
||||
@@ -2265,8 +2169,7 @@ create_transactions_on( SchedXaction *sx,
|
||||
}
|
||||
}
|
||||
|
||||
if (id)
|
||||
{
|
||||
if (id) {
|
||||
g_free( id );
|
||||
}
|
||||
|
||||
@@ -2282,14 +2185,6 @@ create_transactions_on( SchedXaction *sx,
|
||||
xaccSchedXactionSetRemOccur( sx, tmp-1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( createdTCT ) {
|
||||
g_free( tci );
|
||||
g_list_free( tct->instanceList );
|
||||
g_free( tct );
|
||||
tci = NULL;
|
||||
tct = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2393,7 +2288,7 @@ tct_table_entry_key_handle( GtkWidget *widget, GdkEventKey *event, gpointer ud )
|
||||
gtk_entry_set_text( ent, str->str );
|
||||
g_string_free( str, TRUE );
|
||||
|
||||
/* Next, deal with tab-ordering in this page... */
|
||||
/* FIXME: Next, deal with tab-ordering in this page... */
|
||||
|
||||
// if ( entry isn't last in table )
|
||||
// return (normal)FALSE
|
||||
@@ -2514,6 +2409,9 @@ sxsincelast_tc_row_sel( GtkCTree *ct,
|
||||
gtk_signal_connect( GTK_OBJECT(entry), "changed",
|
||||
GTK_SIGNAL_FUNC( sxsincelast_entry_changed ),
|
||||
sxsld );
|
||||
gtk_signal_connect( GTK_OBJECT(entry), "destroy",
|
||||
GTK_SIGNAL_FUNC(gnc_sxsld_free_entry_numeric),
|
||||
sxsld );
|
||||
|
||||
gtk_table_attach( varTable, label,
|
||||
0, 1, tableIdx, tableIdx + 1,
|
||||
@@ -2531,19 +2429,15 @@ static void
|
||||
clean_variable_table( sxSinceLastData *sxsld )
|
||||
{
|
||||
GtkTable *table;
|
||||
GList *children, *toFree;
|
||||
GList *children, *toFree, *l;
|
||||
GtkTableChild *child;
|
||||
|
||||
table = GTK_TABLE( glade_xml_get_widget( sxsld->gxml,
|
||||
VARIABLE_TABLE ) );
|
||||
children = table->children;
|
||||
toFree = NULL;
|
||||
if ( children == NULL ) {
|
||||
PERR( "The variable-binding table should always have at "
|
||||
"least 2 children... something's amiss." );
|
||||
return;
|
||||
}
|
||||
g_assert( children );
|
||||
|
||||
toFree = NULL;
|
||||
for( ; children ; children = children->next ) {
|
||||
/* Destroy all children after the first [label-continaing]
|
||||
row... ie, leave the labels in place. */
|
||||
@@ -2555,9 +2449,8 @@ clean_variable_table( sxSinceLastData *sxsld )
|
||||
|
||||
gtk_table_resize( table, 1, 2 );
|
||||
|
||||
while ( toFree != NULL ) {
|
||||
gtk_widget_destroy( (GtkWidget*)toFree->data );
|
||||
toFree = toFree->next;
|
||||
for ( l = toFree; l; l = l->next ) {
|
||||
gtk_widget_destroy( (GtkWidget*)l->data );
|
||||
}
|
||||
g_list_free( toFree );
|
||||
}
|
||||
@@ -2572,7 +2465,8 @@ sxsincelast_tc_row_unsel( GtkCTree *ct,
|
||||
|
||||
sxsld = (sxSinceLastData*)user_data;
|
||||
clean_variable_table( sxsld );
|
||||
/* FIXME: need to cleanup the gnc_numerics we allocated */
|
||||
/* we cleanup the gnc_numerics we allocated in the "destroy" signal
|
||||
* handler of the entry [where we attached them] */
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2598,6 +2492,7 @@ parse_vars_from_formula( const char *formula,
|
||||
num = g_new0( gnc_numeric, 1 );
|
||||
}
|
||||
|
||||
toRet = 0;
|
||||
if ( ! gnc_exp_parser_parse_separate_vars( formula, num,
|
||||
&errLoc, varHash ) ) {
|
||||
#if 0 /* just too verbose, as "Numeric errors" are acceptable in this
|
||||
@@ -2606,11 +2501,8 @@ parse_vars_from_formula( const char *formula,
|
||||
errLoc, gnc_exp_parser_error_string() );
|
||||
#endif /* 0 */
|
||||
toRet = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
toRet = 0;
|
||||
|
||||
cleanup:
|
||||
if ( !result ) {
|
||||
g_free( num );
|
||||
}
|
||||
@@ -2778,14 +2670,17 @@ gnc_sxsld_revert_reminders( sxSinceLastData *sxsld,
|
||||
xaccSchedXactionGetAutoCreate( rit->parentRT->sx,
|
||||
&autoCreateState,
|
||||
¬ifyState );
|
||||
|
||||
correctList = NULL;
|
||||
if ( autoCreateState ) {
|
||||
correctList = &sxsld->autoCreateList;
|
||||
if ( notifyState ) {
|
||||
correctList = &sxsld->autoCreateList;
|
||||
}
|
||||
} else {
|
||||
correctList = &sxsld->toCreateList;
|
||||
}
|
||||
|
||||
*correctList = g_list_remove( *correctList, tct );
|
||||
if ( correctList )
|
||||
*correctList = g_list_remove( *correctList, tct );
|
||||
}
|
||||
|
||||
/* destroy any created transactions. */
|
||||
@@ -2793,18 +2688,22 @@ gnc_sxsld_revert_reminders( sxSinceLastData *sxsld,
|
||||
for ( m = tci->createdTxnGUIDs; m; m = m->next ) {
|
||||
Transaction *t;
|
||||
|
||||
sxsld->createdTxnGUIDList =
|
||||
g_list_remove( sxsld->createdTxnGUIDList,
|
||||
(GUID*)m->data );
|
||||
t = xaccTransLookup( (GUID*)m->data,
|
||||
gnc_get_current_book() );
|
||||
g_assert( t );
|
||||
xaccTransBeginEdit(t);
|
||||
xaccTransDestroy(t);
|
||||
xaccTransCommitEdit(t);
|
||||
|
||||
}
|
||||
gnc_resume_gui_refresh();
|
||||
|
||||
/* FIXME: Free the now-dead TCI; this is buggy and causing
|
||||
/* Free the now-dead TCI; this is buggy and causing
|
||||
* problems... */
|
||||
//gnc_sxsld_free_tci( tci );
|
||||
gnc_sxsld_free_tci( tci );
|
||||
rit->resultantTCI = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2887,7 +2786,7 @@ inform_or_add( reminderTuple *rt, gboolean okFlag,
|
||||
|
||||
if ( okFlag ) {
|
||||
/* Add selected instances of this rt to
|
||||
okay-to-add-to-toCreateList list. */
|
||||
* okay-to-add-to-toCreateList list. */
|
||||
for ( instances = rt->instanceList;
|
||||
instances;
|
||||
instances = instances->next ) {
|
||||
@@ -2899,6 +2798,7 @@ inform_or_add( reminderTuple *rt, gboolean okFlag,
|
||||
}
|
||||
} else {
|
||||
/* [Add to list for later] dialog issuance to user. */
|
||||
|
||||
userMsg = g_string_sized_new( 128 );
|
||||
g_string_sprintf( userMsg,
|
||||
"You cannot skip instances of Scheduled Transactions.\n"
|
||||
@@ -2907,6 +2807,7 @@ inform_or_add( reminderTuple *rt, gboolean okFlag,
|
||||
xaccSchedXactionGetName( rt->sx ) );
|
||||
g_list_foreach( badList, create_bad_reminders_msg, userMsg );
|
||||
gnc_error_dialog( userMsg->str );
|
||||
g_string_free( userMsg, TRUE );
|
||||
}
|
||||
|
||||
return okFlag;
|
||||
@@ -3040,25 +2941,59 @@ sxsld_ledger_get_parent( GNCLedgerDisplay *ld )
|
||||
static void
|
||||
clean_sincelast_data( sxSinceLastData *sxsld )
|
||||
{
|
||||
/* FIXME: much more to go, here. */
|
||||
g_list_foreach( sxsld->toCreateList, _free_toCreate_list_elts, NULL );
|
||||
if ( sxsld->toCreateList ) {
|
||||
g_list_free( sxsld->toCreateList );
|
||||
sxsld->toCreateList = NULL;
|
||||
GList *l, *m;
|
||||
|
||||
/* Free the reminder list */
|
||||
for ( l = sxsld->reminderList; l; l = l->next ) {
|
||||
reminderTuple *rt;
|
||||
reminderInstanceTuple *rit;
|
||||
|
||||
rt = (reminderTuple*)l->data;
|
||||
for ( m = rt->instanceList; m; m = m->next ) {
|
||||
rit = (reminderInstanceTuple*)m->data;
|
||||
g_date_free( rit->endDate );
|
||||
g_date_free( rit->occurDate );
|
||||
g_free( rit );
|
||||
}
|
||||
g_list_free( rt->instanceList );
|
||||
rt->instanceList = NULL;
|
||||
g_free( rt );
|
||||
}
|
||||
#if 0
|
||||
g_list_foreach( autoCreateList, free_gdate_list_elts, NULL );
|
||||
g_list_free( autoCreateList );
|
||||
autoCreateList = NULL;
|
||||
g_list_free( sxsld->reminderList );
|
||||
|
||||
/* We have moved the GDates over to the toCreateList in
|
||||
* sxsld, so we don't free them here. */
|
||||
g_list_free( toCreateList );
|
||||
toCreateList = NULL;
|
||||
|
||||
g_list_free( instanceList );
|
||||
instanceList = NULL;
|
||||
#endif /* 0 */
|
||||
/* Free the auto-create and to-create lists */
|
||||
gnc_sxsld_free_toCreateTuple_list( sxsld->autoCreateList );
|
||||
g_list_free( sxsld->autoCreateList );
|
||||
sxsld->autoCreateList = NULL;
|
||||
|
||||
gnc_sxsld_free_toCreateTuple_list( sxsld->toCreateList );
|
||||
g_list_free( sxsld->toCreateList );
|
||||
sxsld->toCreateList = NULL;
|
||||
|
||||
/* Free the to-remove list */
|
||||
for ( l = sxsld->toRemoveList; l; l = l->next ) {
|
||||
toDeleteTuple *tdt;
|
||||
|
||||
tdt = (toDeleteTuple*)l->data;
|
||||
g_date_free( tdt->endDate );
|
||||
tdt->endDate = NULL;
|
||||
|
||||
g_free( tdt );
|
||||
}
|
||||
g_list_free( sxsld->toRemoveList );
|
||||
sxsld->toRemoveList = NULL;
|
||||
|
||||
/* free the created-txn-guid list */
|
||||
g_list_free( sxsld->createdTxnGUIDList );
|
||||
sxsld->createdTxnGUIDList = NULL;
|
||||
|
||||
/* Free the saved SX temporal states */
|
||||
g_hash_table_foreach( sxsld->sxInitStates,
|
||||
gnc_sxsld_free_sxState,
|
||||
NULL );
|
||||
g_hash_table_destroy( sxsld->sxInitStates );
|
||||
sxsld->sxInitStates = NULL;
|
||||
|
||||
}
|
||||
|
||||
@@ -3072,7 +3007,9 @@ gnc_sxsld_free_tci( toCreateInstance *tci )
|
||||
}
|
||||
|
||||
if ( tci->varBindings ) {
|
||||
/* FIXME: free keys/values, too. */
|
||||
g_hash_table_foreach( tci->varBindings,
|
||||
_free_varBindings_hash_elts,
|
||||
NULL );
|
||||
g_hash_table_destroy( tci->varBindings );
|
||||
tci->varBindings = NULL;
|
||||
}
|
||||
@@ -3086,3 +3023,44 @@ gnc_sxsld_free_tci( toCreateInstance *tci )
|
||||
|
||||
g_free( tci );
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a list of toCreateTuples, like the autoCreateList and
|
||||
* toCreateList.
|
||||
**/
|
||||
static
|
||||
void
|
||||
gnc_sxsld_free_toCreateTuple_list( GList *l )
|
||||
{
|
||||
GList *m;
|
||||
toCreateTuple *tct;
|
||||
|
||||
for ( ; l; l = l->next ) {
|
||||
tct = (toCreateTuple*)l->data;
|
||||
for ( m = tct->instanceList; m; m = m->next ) {
|
||||
gnc_sxsld_free_tci( (toCreateInstance*)m->data );
|
||||
}
|
||||
g_list_free( tct->instanceList );
|
||||
tct->instanceList = NULL;
|
||||
g_free( tct );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gnc_sxsld_free_sxState( gpointer key,
|
||||
gpointer value,
|
||||
gpointer userdata )
|
||||
{
|
||||
gnc_sx_destroy_temporal_state_snapshot( (void*)value );
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
gnc_sxsld_free_entry_numeric( GtkObject *o, gpointer ud )
|
||||
{
|
||||
gnc_numeric *num;
|
||||
num = (gnc_numeric*)gtk_object_get_data( o, "numeric" );
|
||||
g_free( num );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user