Use GLists to store splits in transactions. Remove cruft.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3120 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-11-04 01:05:41 +00:00
parent 134940aab9
commit 4f84ccd735
12 changed files with 396 additions and 529 deletions

View File

@ -3230,9 +3230,10 @@ xaccSRLoadRegister (SplitRegister *reg, Split **slist,
xaccTransBeginEdit (trans, TRUE); xaccTransBeginEdit (trans, TRUE);
xaccTransSetDateSecs (trans, info->last_date_entered); xaccTransSetDateSecs (trans, info->last_date_entered);
blank_split = xaccMallocSplit ();
xaccTransAppendSplit (trans, blank_split);
xaccTransCommitEdit (trans); xaccTransCommitEdit (trans);
blank_split = xaccTransGetSplit (trans, 0);
info->blank_split_guid = *xaccSplitGetGUID (blank_split); info->blank_split_guid = *xaccSplitGetGUID (blank_split);
info->blank_split_edited = FALSE; info->blank_split_edited = FALSE;

View File

@ -664,30 +664,25 @@ xaccAccountFixSplitDateOrder (Account * acc, Split *split ) {
/********************************************************************\ /********************************************************************\
* xaccCheckTransDateOrder * * xaccCheckTransDateOrder *
* check this transaction to see if the date is in correct order * * check this transaction to see if the date is in correct order *
* If it is not, reorder the transactions ... * * If it is not, reorder the transactions. *
* This routine perfroms the check for both of the double-entry * * This routine perfroms the check for both of the double-entry *
* transaction entries ... * * transaction entries. *
* * * *
* Args: trans -- the transaction to check * * Args: trans -- the transaction to check *
* Return: int -- non-zero if out of order * * Return: int -- non-zero if out of order *
\********************************************************************/ \********************************************************************/
void void
xaccTransFixSplitDateOrder (Transaction *trans ) xaccTransFixSplitDateOrder (Transaction *trans)
{ {
Account * acc; GList *node;
Split *s;
int i = 0;
if (NULL == trans) return; if (trans == NULL) return;
i=0; for (node = trans->splits; node; node = node->next)
s = trans->splits[0]; {
while (s) { Split *s = node->data;
acc = (Account *) (s->acc); xaccAccountFixSplitDateOrder (s->acc, s);
xaccAccountFixSplitDateOrder (acc, s);
i++;
s = trans->splits[i];
} }
} }

View File

@ -114,7 +114,7 @@ struct _account {
gnc_numeric share_cleared_balance; gnc_numeric share_cleared_balance;
gnc_numeric share_reconciled_balance; gnc_numeric share_reconciled_balance;
GList *splits; /* ptr to array of ptrs to splits */ GList *splits; /* list of split pointers */
/* The "changed" flag is used to invalidate cached values in this structure. /* The "changed" flag is used to invalidate cached values in this structure.
* Currently, the balances and the cost basis are cached. * Currently, the balances and the cost basis are cached.

View File

@ -64,21 +64,21 @@ xaccAccountGetBackend (Account * acc)
Backend * Backend *
xaccTransactionGetBackend (Transaction *trans) xaccTransactionGetBackend (Transaction *trans)
{ {
Backend *be; GList *node;
Split *s; Split *s;
if (!trans) return NULL; if (!trans) return NULL;
/* find an account */ /* find an account */
s = trans->splits[0]; s = xaccTransGetSplit (trans, 0);
if (!s) return NULL; if (!s) return NULL;
/* I suppose it would be more 'technically correct' to make sure that /* I suppose it would be more 'technically correct' to make sure that
* all splits share teh same backend, and flag an error if they * all splits share the same backend, and flag an error if they
* don't. However, at this point, it seems quite unlikely, so we'll * don't. However, at this point, it seems quite unlikely, so we'll
* just use teh first backend we find. * just use the first backend we find.
*/ */
be = xaccAccountGetBackend (s->acc); return xaccAccountGetBackend (s->acc);
return be;
} }
/********************************************************************\ /********************************************************************\

View File

@ -22,12 +22,12 @@
\********************************************************************/ \********************************************************************/
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "config.h"
#include "Account.h" #include "Account.h"
#include "AccountP.h" #include "AccountP.h"
#include "DateUtils.h" #include "DateUtils.h"
@ -189,8 +189,7 @@ xaccCloseLog (void)
void void
xaccTransWriteLog (Transaction *trans, char flag) xaccTransWriteLog (Transaction *trans, char flag)
{ {
Split *split; GList *node;
int i = 0;
char *dnow, *dent, *dpost, *drecn; char *dnow, *dent, *dpost, *drecn;
if (!gen_logs) return; if (!gen_logs) return;
@ -202,10 +201,13 @@ xaccTransWriteLog (Transaction *trans, char flag)
fprintf (trans_log, "===== START\n"); fprintf (trans_log, "===== START\n");
split = trans->splits[0]; for (node = trans->splits; node; node = node->next) {
while (split) { Split *split = node->data;
char * accname = ""; char * accname = "";
if (split->acc) accname = split->acc->accountName;
if (split->acc)
accname = split->acc->accountName;
drecn = xaccDateUtilGetStamp (split->date_reconciled.tv_sec); drecn = xaccDateUtilGetStamp (split->date_reconciled.tv_sec);
/* use tab-separated fields */ /* use tab-separated fields */
@ -229,9 +231,8 @@ xaccTransWriteLog (Transaction *trans, char flag)
drecn drecn
); );
free (drecn); free (drecn);
i++;
split = trans->splits[i];
} }
fprintf (trans_log, "===== END\n"); fprintf (trans_log, "===== END\n");
free (dnow); free (dnow);
free (dent); free (dent);

File diff suppressed because it is too large Load Diff

View File

@ -172,16 +172,6 @@ void xaccTransSetDateEnteredTS (Transaction *trans,
void xaccTransSetNum (Transaction *trans, const char *num); void xaccTransSetNum (Transaction *trans, const char *num);
void xaccTransSetDescription (Transaction *trans, const char *desc); void xaccTransSetDescription (Transaction *trans, const char *desc);
/* The xaccTransSetMemo() and xaccTransSetAction() methods are
* convenience routines to keep the memo and action fields
* of two-split transactions in sync. If the transaction has
* precisely two splits, then these routines will set the memo
* and action of both splits. Otherwise, they will set the
* memo and action of the first split (source split) only.
*/
void xaccTransSetMemo (Transaction *trans, const char *memo);
void xaccTransSetAction (Transaction *trans, const char *action);
/* The xaccTransAppendSplit() method will append the indicated /* The xaccTransAppendSplit() method will append the indicated
* split to the collection of splits in this transaction. * split to the collection of splits in this transaction.
* If the split is already a part of another transaction, * If the split is already a part of another transaction,
@ -473,10 +463,6 @@ int xaccSplitDateOrder (Split *sa, Split *sb);
/********************************************************************\ /********************************************************************\
* Miscellaneous utility routines. * Miscellaneous utility routines.
\********************************************************************/ \********************************************************************/
/*
* count the number of transactions in the null-terminated array
*/
int xaccCountTransactions (Transaction **tarray);
/* count the number of splits in the indicated array */ /* count the number of splits in the indicated array */
int xaccCountSplits (Split **sarray); int xaccCountSplits (Split **sarray);
@ -507,12 +493,11 @@ Split * xaccGetOtherSplit (Split *split);
*/ */
int xaccIsPeerSplit (Split *split_1, Split *split_2); int xaccIsPeerSplit (Split *split_1, Split *split_2);
/* The IthSplit() and IthTransaction() routines merely dereference /* The IthSplit() routine merely dereferences
* the lists supplied as arguments; i.e. they return list[i]. * the list supplied as argument; i.e. it returns list[i].
* These routines are needed by the perl swig wrappers, which * This routine is needed by the perl swig wrappers, which
* are unable to dereference on their own. * is unable to dereference on their own.
*/ */
Transaction * IthTransaction (Transaction **tarray, int i);
Split * IthSplit (Split **sarray, int i); Split * IthSplit (Split **sarray, int i);
#endif /* __XACC_TRANSACTION_H__ */ #endif /* __XACC_TRANSACTION_H__ */

View File

@ -100,9 +100,7 @@ struct _split
* it's NULL until accessed. */ * it's NULL until accessed. */
kvp_frame * kvp_data; kvp_frame * kvp_data;
/* The reconciled field ... char reconciled; /* The reconciled field */
*/
char reconciled;
Timespec date_reconciled; /* date split was reconciled */ Timespec date_reconciled; /* date split was reconciled */
/* value is the amount of the account's currency involved, /* value is the amount of the account's currency involved,
@ -155,7 +153,7 @@ struct _transaction
* it's NULL until accessed. */ * it's NULL until accessed. */
kvp_frame * kvp_data; kvp_frame * kvp_data;
Split **splits; /* list of splits, null terminated */ GList *splits; /* list of splits */
/* marker is used to track the progress of transaction traversals. /* marker is used to track the progress of transaction traversals.
* 0 is never a legitimate marker value, so we can tell is we hit * 0 is never a legitimate marker value, so we can tell is we hit
@ -192,7 +190,7 @@ void xaccSplitSetGUID (Split *split, GUID *guid);
* not check to see if any of the member splits are referenced * not check to see if any of the member splits are referenced
* by an account. * by an account.
*/ */
void xaccFreeTransaction (Transaction *); void xaccFreeTransaction (Transaction *trans);
/* The xaccFreeSplit() method simply frees all memory associated /* The xaccFreeSplit() method simply frees all memory associated
* with the split. It does not verify that the split isn't * with the split. It does not verify that the split isn't
@ -200,13 +198,7 @@ void xaccFreeTransaction (Transaction *);
* account, then calling this method will leave the system in an * account, then calling this method will leave the system in an
* inconsistent state. * inconsistent state.
*/ */
void xaccFreeSplit (Split *); /* frees memory */ void xaccFreeSplit (Split *split); /* frees memory */
/* The xaccTransRemoveSplit() routine will remove the indicated
* split from the transaction. It will *NOT* otherwise
* re-adjust balances, modify accounts, etc.
*/
void xaccTransRemoveSplit (Transaction*, Split *);
/* /*
@ -216,7 +208,7 @@ void xaccTransRemoveSplit (Transaction*, Split *);
* splits in a transaction to total up to exactly zero. * splits in a transaction to total up to exactly zero.
* *
* It is worthwhile to understand the algorithm that this routine * It is worthwhile to understand the algorithm that this routine
* uses to acheive balance. It goes like this: * uses to achieve balance. It goes like this:
* If the indicated split is a destination split (i.e. is not * If the indicated split is a destination split (i.e. is not
* the first split), then the total value of the destination * the first split), then the total value of the destination
* splits is computed, and the value of the source split (ie. * splits is computed, and the value of the source split (ie.
@ -224,7 +216,7 @@ void xaccTransRemoveSplit (Transaction*, Split *);
* (the share price of the source split is not changed). * (the share price of the source split is not changed).
* If the indicated split is the source split, then the value * If the indicated split is the source split, then the value
* of the very first destination split is adjusted so that * of the very first destination split is adjusted so that
* the balance is zero. If there is not destination split, * the balance is zero. If there is not destination split,
* one of two outcomes are possible, depending on whether * one of two outcomes are possible, depending on whether
* "forced_double_entry" is enabled or disabled. * "forced_double_entry" is enabled or disabled.
* (1) if forced-double-entry is disabled, the fact that * (1) if forced-double-entry is disabled, the fact that
@ -236,12 +228,12 @@ void xaccTransRemoveSplit (Transaction*, Split *);
* destination split properly. * destination split properly.
*/ */
void xaccSplitRebalance (Split *); void xaccSplitRebalance (Split *split);
/* FIXME: this is probably wrong, but it'll have to wait until Bill /* FIXME: this is probably wrong, but it'll have to wait until Bill
returns. It's *ONLY* for file IO. Don't use these elsewhere. */ returns. It's *ONLY* for file IO. Don't use these elsewhere. */
void xaccSplitSetValueDirectly(Split *s, gnc_numeric n); void xaccSplitSetValueDirectly(Split *split, gnc_numeric value);
void xaccSplitSetQuantityDirectly(Split *s, gnc_numeric n); void xaccSplitSetQuantityDirectly(Split *split, gnc_numeric quantity);
#endif /* __XACC_TRANSACTION_P_H__ */ #endif /* __XACC_TRANSACTION_P_H__ */

View File

@ -662,20 +662,6 @@ readAccount( int fd, AccountGroup *grp, int token )
"\texpected %d got %d transactions \n",numTrans,i); "\texpected %d got %d transactions \n",numTrans,i);
break; break;
} }
#ifdef DELINT_BLANK_SPLITS_HACK
/* This is dangerous, as it can destroy real data. */
{
int j=0;
Split *s = trans->splits[0];
while (s) {
if (DEQ(0.0,s->damount) && DEQ (1.0,s->share_price)) {
xaccTransRemoveSplit (trans, s);
break;
}
j++; s=trans->splits[j];
}
}
#endif /* DELINT_BLANK_SPLITS_HACK */
} }
/* Not needed now. Since we always look in ids_to_finished_accounts /* Not needed now. Since we always look in ids_to_finished_accounts
@ -780,6 +766,40 @@ readAccInfo(int fd, Account *acc, int token) {
return(TRUE); return(TRUE);
} }
static void
xaccTransSetMemo (Transaction *trans, const char *memo)
{
Split *s;
if (!trans || !memo) return;
s = xaccTransGetSplit (trans, 0);
xaccSplitSetMemo (s, memo);
if (xaccTransCountSplits (trans) != 2)
return;
s = xaccTransGetSplit (trans, 1);
xaccSplitSetMemo (s, memo);
}
static void
xaccTransSetAction (Transaction *trans, const char *action)
{
Split *s;
if (!trans || !action) return;
s = xaccTransGetSplit (trans, 0);
xaccSplitSetAction (s, action);
if (xaccTransCountSplits (trans) != 2)
return;
s = xaccTransGetSplit (trans, 1);
xaccSplitSetAction (s, action);
}
/********************************************************************\ /********************************************************************\
* readTransaction * * readTransaction *
* reads in the data for a transaction from the datafile * * reads in the data for a transaction from the datafile *
@ -809,6 +829,12 @@ readTransaction( int fd, Account *acc, int token )
trans = xaccMallocTransaction(); trans = xaccMallocTransaction();
xaccTransBeginEdit (trans, 1); xaccTransBeginEdit (trans, 1);
/* add in one split -- xaccMallocTransaction no longer auto-creates them. */
{
Split *s = xaccMallocSplit ();
xaccTransAppendSplit (trans, s);
}
tmp = readString( fd, token ); tmp = readString( fd, token );
if (NULL == tmp) if (NULL == tmp)
{ {
@ -1084,14 +1110,16 @@ readTransaction( int fd, Account *acc, int token )
if (5 == token) if (5 == token)
{ {
Split *s = trans->splits->data;
/* Version 5 files included a split that immediately /* Version 5 files included a split that immediately
* followed the transaction, before the destination splits. * followed the transaction, before the destination splits.
* Later versions don't have this. */ * Later versions don't have this. */
offset = 1; offset = 1;
split = readSplit (fd, token); split = readSplit (fd, token);
xaccRemoveEntity(&trans->splits[0]->guid); xaccRemoveEntity(&s->guid);
xaccFreeSplit (trans->splits[0]); xaccFreeSplit (s);
trans->splits[0] = split; trans->splits->data = split;
split->parent = trans; split->parent = trans;
} }
@ -1108,13 +1136,14 @@ readTransaction( int fd, Account *acc, int token )
for (i=0; i<numSplits; i++) { for (i=0; i<numSplits; i++) {
split = readSplit (fd, token); split = readSplit (fd, token);
if (0 == i+offset) { if (0 == i+offset) {
Split *s = trans->splits->data;
/* the first split has been malloced. just replace it */ /* the first split has been malloced. just replace it */
xaccRemoveEntity (&trans->splits[i+offset]->guid); xaccRemoveEntity (&s->guid);
xaccFreeSplit (trans->splits[i+offset]); xaccFreeSplit (s);
trans->splits[i+offset] = split; trans->splits->data = split;
split->parent = trans; split->parent = trans;
} else { } else {
xaccTransAppendSplit( trans, split); xaccTransAppendSplit(trans, split);
} }
} }
} }

View File

@ -3344,22 +3344,11 @@ txn_restore_start_handler(GSList* sibling_data,
gpointer *result, gpointer *result,
const gchar *tag) { const gchar *tag) {
Transaction *trans = xaccMallocTransaction(); Transaction *trans = xaccMallocTransaction();
if(!trans) return(FALSE); if(!trans) return(FALSE);
xaccTransBeginEdit(trans, 1); xaccTransBeginEdit(trans, 1);
/* Kill the pointless initial splits -- why are these here?
FIXME: Can we kill them in Transaction.c? */
{
int i = 0;
Split *useless;
while((useless = xaccTransGetSplit(trans, i))) {
xaccSplitDestroy(useless);
i++;
}
}
*data_for_children = trans; *data_for_children = trans;
return(TRUE); return(TRUE);

View File

@ -726,9 +726,11 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data)
string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
xaccTransSetDescription(trans, string); xaccTransSetDescription(trans, string);
/* first split is already there */ /* create first split */
curr_split = xaccTransGetSplit(trans, 0); curr_split = xaccMallocSplit();
/* second split must be created */ xaccTransAppendSplit(trans, curr_split);
/* create second split */
from_split = xaccMallocSplit(); from_split = xaccMallocSplit();
xaccTransAppendSplit(trans, from_split); xaccTransAppendSplit(trans, from_split);
@ -741,9 +743,10 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data)
DxaccSplitSetBaseValue(curr_split, amount, from_currency); DxaccSplitSetBaseValue(curr_split, amount, from_currency);
DxaccSplitSetBaseValue(curr_split, to_amount, to_currency); DxaccSplitSetBaseValue(curr_split, to_amount, to_currency);
/* TransSetMemo will set the memo for both splits */ /* Set the memo fields */
string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
xaccTransSetMemo(trans, string); xaccSplitSetMemo(curr_split, string);
xaccSplitSetMemo(from_split, string);
/* finish transaction */ /* finish transaction */
xaccAccountCommitEdit(from); xaccAccountCommitEdit(from);
@ -763,9 +766,11 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data)
string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
xaccTransSetDescription(trans, string); xaccTransSetDescription(trans, string);
/* first split is already there */ /* create first split */
curr_split = xaccTransGetSplit(trans, 0); curr_split = xaccMallocSplit();
/* second split must be created */ xaccTransAppendSplit(trans, curr_split);
/* create second split */
to_split = xaccMallocSplit(); to_split = xaccMallocSplit();
xaccTransAppendSplit(trans, to_split); xaccTransAppendSplit(trans, to_split);
@ -778,9 +783,10 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data)
DxaccSplitSetBaseValue(curr_split, -amount, from_currency); DxaccSplitSetBaseValue(curr_split, -amount, from_currency);
DxaccSplitSetBaseValue(curr_split, -to_amount, to_currency); DxaccSplitSetBaseValue(curr_split, -to_amount, to_currency);
/* TransSetMemo will set the memo for both splits */ /* set the memo fields */
string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
xaccTransSetMemo(trans, string); xaccSplitSetMemo(curr_split, string);
xaccSplitSetMemo(to_split, string);
/* finish transaction */ /* finish transaction */
xaccAccountCommitEdit(curr); xaccAccountCommitEdit(curr);
@ -806,18 +812,20 @@ gnc_xfer_dialog_ok_cb(GtkWidget * widget, gpointer data)
string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->description_entry));
xaccTransSetDescription(trans, string); xaccTransSetDescription(trans, string);
/* first split is already there */ /* create first split */
to_split = xaccTransGetSplit(trans, 0); to_split = xaccMallocSplit();
xaccTransAppendSplit(trans, to_split);
DxaccSplitSetShareAmount(to_split, amount); DxaccSplitSetShareAmount(to_split, amount);
/* second split must be created */ /* create second split */
from_split = xaccMallocSplit(); from_split = xaccMallocSplit();
DxaccSplitSetShareAmount(from_split, -amount); DxaccSplitSetShareAmount(from_split, -amount);
xaccTransAppendSplit(trans, from_split); xaccTransAppendSplit(trans, from_split);
/* TransSetMemo will set the memo for both splits */ /* set the memo fields */
string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry)); string = gtk_entry_get_text(GTK_ENTRY(xferData->memo_entry));
xaccTransSetMemo(trans, string); xaccSplitSetMemo(to_split, string);
xaccSplitSetMemo(from_split, string);
/* Now do the 'to' account */ /* Now do the 'to' account */
xaccAccountBeginEdit(to); xaccAccountBeginEdit(to);

View File

@ -234,20 +234,11 @@
(let ((gnc-xtn (gnc:transaction-create))) (let ((gnc-xtn (gnc:transaction-create)))
(gnc:transaction-begin-edit gnc-xtn 1) (gnc:transaction-begin-edit gnc-xtn 1)
;; destroy any automagic splits in the transaction
(let ((numsplits (gnc:transaction-get-split-count gnc-xtn)))
(if (not (eqv? 0 numsplits))
(let splitloop ((ind (- numsplits 1)))
(gnc:split-destroy
(gnc:transaction-get-split gnc-xtn ind))
(if (> ind 0)
(loop (- ind 1))))))
;; build the transaction ;; build the transaction
(qif-import:qif-xtn-to-gnc-xtn (qif-import:qif-xtn-to-gnc-xtn
xtn qif-file gnc-xtn gnc-acct-hash xtn qif-file gnc-xtn gnc-acct-hash
qif-acct-map qif-cat-map) qif-acct-map qif-cat-map)
;; rebalance and commit everything ;; rebalance and commit everything
(gnc:transaction-commit-edit gnc-xtn))))) (gnc:transaction-commit-edit gnc-xtn)))))
(qif-file:xtns qif-file))) (qif-file:xtns qif-file)))