mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
large invasive patch to send account-deletion info to the backend
Hopefully the last such invasion ... git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3597 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -478,7 +478,6 @@ acc_restore_parent_end_handler(gpointer data_for_children,
|
||||
|
||||
g_return_val_if_fail(parent, FALSE);
|
||||
|
||||
xaccRemoveAccount(acc); /* just to be anal */
|
||||
xaccAccountInsertSubAccount(parent, acc);
|
||||
|
||||
return(TRUE);
|
||||
|
||||
@@ -53,6 +53,8 @@ static short module = MOD_ENGINE;
|
||||
* of the internals of the Account in one file. *
|
||||
\********************************************************************/
|
||||
|
||||
static void xaccAccountBringUpToDate(Account *acc);
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@@ -109,6 +111,8 @@ xaccInitAccount (Account * acc)
|
||||
acc->editlevel = 0;
|
||||
acc->balance_dirty = FALSE;
|
||||
acc->sort_dirty = FALSE;
|
||||
acc->core_dirty = FALSE;
|
||||
acc->do_free = FALSE;
|
||||
|
||||
xaccGUIDNew(&acc->guid);
|
||||
xaccStoreEntity(acc, &acc->guid, GNC_ID_ACCOUNT);
|
||||
@@ -145,36 +149,52 @@ xaccFreeAccount (Account *acc)
|
||||
|
||||
xaccRemoveEntity(&acc->guid);
|
||||
|
||||
/* First, recursively free children */
|
||||
xaccFreeAccountGroup (acc->children);
|
||||
if (acc->children)
|
||||
{
|
||||
PERR (" xinstead of calling xaccFreeAccount(), please call \n"
|
||||
" xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
|
||||
|
||||
/* First, recursively free children */
|
||||
xaccFreeAccountGroup (acc->children);
|
||||
acc->children = NULL;
|
||||
}
|
||||
|
||||
/* Next, clean up the splits */
|
||||
/* any split pointing at this account needs to be unmarked */
|
||||
for(lp = acc->splits; lp; lp = lp->next) {
|
||||
Split *s = (Split *) lp->data;
|
||||
s->acc = NULL;
|
||||
/* NB there shouldn't be any splits by now ... they should
|
||||
* have been all been freed by CommitEdit(). We can remove this
|
||||
* check once we know the warning isn't occurring any more. */
|
||||
if (acc->splits)
|
||||
{
|
||||
PERR (" instead of calling xaccFreeAccount(), please call \n"
|
||||
" xaccAccountBeginEdit(); xaccAccountDestroy(); \n");
|
||||
|
||||
/* any split pointing at this account needs to be unmarked */
|
||||
for(lp = acc->splits; lp; lp = lp->next)
|
||||
{
|
||||
Split *s = (Split *) lp->data;
|
||||
s->acc = NULL;
|
||||
}
|
||||
|
||||
acc->editlevel = 0;
|
||||
|
||||
for(lp = acc->splits; lp; lp = lp->next) {
|
||||
Split *s = (Split *) lp->data;
|
||||
t = s->parent;
|
||||
xaccTransBeginEdit (t);
|
||||
xaccSplitDestroy (s);
|
||||
xaccTransCommitEdit (t);
|
||||
}
|
||||
|
||||
/* free up array of split pointers */
|
||||
g_list_free(acc->splits);
|
||||
acc->splits = NULL;
|
||||
}
|
||||
|
||||
/* FIXME: is this right? */
|
||||
acc->editlevel = 0;
|
||||
|
||||
for(lp = acc->splits; lp; lp = lp->next) {
|
||||
Split *s = (Split *) lp->data;
|
||||
t = s->parent;
|
||||
xaccTransBeginEdit (t);
|
||||
xaccSplitDestroy (s);
|
||||
xaccTransCommitEdit (t);
|
||||
}
|
||||
|
||||
/* free up array of split pointers */
|
||||
g_list_free(acc->splits);
|
||||
acc->splits = NULL;
|
||||
|
||||
g_free (acc->accountName);
|
||||
if (acc->accountName) g_free (acc->accountName);
|
||||
acc->accountName = NULL;
|
||||
g_free (acc->accountCode);
|
||||
if (acc->accountCode) g_free (acc->accountCode);
|
||||
acc->accountCode = NULL;
|
||||
g_free (acc->description);
|
||||
if (acc->description) g_free (acc->description);
|
||||
acc->description = NULL;
|
||||
|
||||
kvp_frame_delete (acc->kvp_data);
|
||||
@@ -207,10 +227,129 @@ xaccFreeAccount (Account *acc)
|
||||
acc->editlevel = 0;
|
||||
acc->balance_dirty = FALSE;
|
||||
acc->sort_dirty = FALSE;
|
||||
acc->core_dirty = FALSE;
|
||||
|
||||
g_free(acc);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* transactional routines
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccAccountBeginEdit (Account *acc)
|
||||
{
|
||||
Backend * be;
|
||||
if (!acc) return;
|
||||
|
||||
acc->editlevel++;
|
||||
if (1 < acc->editlevel) return;
|
||||
|
||||
if (0 >= acc->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", acc->editlevel);
|
||||
acc->editlevel = 0;
|
||||
}
|
||||
|
||||
acc->core_dirty = FALSE;
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
be = xaccAccountGetBackend (acc);
|
||||
if (be && be->account_begin_edit) {
|
||||
(be->account_begin_edit) (be, acc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountCommitEdit (Account *acc)
|
||||
{
|
||||
Backend * be;
|
||||
int rc;
|
||||
|
||||
if (!acc) return;
|
||||
|
||||
acc->editlevel--;
|
||||
if (0 < acc->editlevel) return;
|
||||
|
||||
if (0 > acc->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", acc->editlevel);
|
||||
acc->editlevel = 0;
|
||||
}
|
||||
|
||||
/* If marked for deletion, get rid of subaccounts first,
|
||||
* and then the splits ... */
|
||||
if (acc->do_free)
|
||||
{
|
||||
GList *lp;
|
||||
|
||||
/* First, recursively free children */
|
||||
xaccFreeAccountGroup (acc->children);
|
||||
acc->children = NULL;
|
||||
|
||||
PINFO ("freeing splits for account %p (%s)\n", acc, acc->accountName);
|
||||
|
||||
/* any split pointing at this account needs to be unmarked */
|
||||
for(lp = acc->splits; lp; lp = lp->next)
|
||||
{
|
||||
Split *s = (Split *) lp->data;
|
||||
s->acc = NULL;
|
||||
}
|
||||
|
||||
for(lp = acc->splits; lp; lp = lp->next)
|
||||
{
|
||||
Split *s = (Split *) lp->data;
|
||||
Transaction *t = s->parent;
|
||||
xaccTransBeginEdit (t);
|
||||
xaccSplitDestroy (s);
|
||||
xaccTransCommitEdit (t);
|
||||
}
|
||||
|
||||
/* free up array of split pointers */
|
||||
g_list_free(acc->splits);
|
||||
acc->splits = NULL;
|
||||
|
||||
acc->core_dirty = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xaccAccountBringUpToDate(acc);
|
||||
}
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
be = xaccAccountGetBackend (acc);
|
||||
if (be && be->account_commit_edit)
|
||||
{
|
||||
rc = (be->account_commit_edit) (be, acc);
|
||||
/* hack alert -- we really really should be checking
|
||||
* for errors returned by the back end ... */
|
||||
if (rc)
|
||||
{
|
||||
/* destroys must be rolled back as well ... ??? */
|
||||
acc->do_free = FALSE;
|
||||
PERR (" backend asked engine to rollback, but this isn't"
|
||||
" handled yet. Return code=%d", rc);
|
||||
}
|
||||
}
|
||||
acc->core_dirty = FALSE;
|
||||
|
||||
/* final stages of freeing the account */
|
||||
if (acc->do_free)
|
||||
{
|
||||
xaccRemoveAccount(acc);
|
||||
xaccFreeAccount(acc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountDestroy (Account *acc)
|
||||
{
|
||||
if (!acc) return;
|
||||
acc->do_free = TRUE;
|
||||
|
||||
xaccAccountCommitEdit (acc);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@@ -272,7 +411,8 @@ split_sort_func(gconstpointer a, gconstpointer b) {
|
||||
}
|
||||
|
||||
static void
|
||||
xaccAccountSortSplits (Account *acc) {
|
||||
xaccAccountSortSplits (Account *acc)
|
||||
{
|
||||
if(!acc) return;
|
||||
|
||||
if(!acc->sort_dirty) return;
|
||||
@@ -282,7 +422,8 @@ xaccAccountSortSplits (Account *acc) {
|
||||
}
|
||||
|
||||
static void
|
||||
xaccAccountBringUpToDate(Account *acc) {
|
||||
xaccAccountBringUpToDate(Account *acc)
|
||||
{
|
||||
if(!acc) return;
|
||||
|
||||
/* if a re-sort happens here, then everything will update, so the
|
||||
@@ -291,60 +432,6 @@ xaccAccountBringUpToDate(Account *acc) {
|
||||
xaccAccountRecomputeBalance(acc);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountBeginEdit (Account *acc)
|
||||
{
|
||||
Backend * be;
|
||||
if (!acc) return;
|
||||
|
||||
acc->editlevel++;
|
||||
if (1 < acc->editlevel) return;
|
||||
|
||||
if (0 >= acc->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", acc->editlevel);
|
||||
acc->editlevel = 0;
|
||||
}
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
be = xaccAccountGetBackend (acc);
|
||||
if (be && be->account_begin_edit) {
|
||||
(be->account_begin_edit) (be, acc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountCommitEdit (Account *acc)
|
||||
{
|
||||
Backend * be;
|
||||
int rc;
|
||||
|
||||
if (!acc) return;
|
||||
|
||||
acc->editlevel--;
|
||||
if (0 < acc->editlevel) return;
|
||||
|
||||
if (0 > acc->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", acc->editlevel);
|
||||
acc->editlevel = 0;
|
||||
}
|
||||
xaccAccountBringUpToDate(acc);
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
be = xaccAccountGetBackend (acc);
|
||||
if (be && be->account_commit_edit) {
|
||||
rc = (be->account_commit_edit) (be, acc);
|
||||
/* hack alert -- we really really should be checking
|
||||
* for errors returned by the back end ... */
|
||||
if (rc)
|
||||
{
|
||||
PERR (" backend asked engine to rollback, but this isn't"
|
||||
" handled yet. Return code=%d", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* xaccAccountGetSlots
|
||||
@@ -376,11 +463,14 @@ xaccAccountSetGUID (Account *account, GUID *guid)
|
||||
if (!account || !guid) return;
|
||||
|
||||
PINFO("acct=%p", account);
|
||||
xaccAccountBeginEdit (account);
|
||||
xaccRemoveEntity(&account->guid);
|
||||
|
||||
account->guid = *guid;
|
||||
|
||||
xaccStoreEntity(account, &account->guid, GNC_ID_ACCOUNT);
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@@ -482,22 +572,6 @@ xaccClearMarkDownGr (AccountGroup *grp, short val)
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
G_INLINE_FUNC void check_open (Account *account);
|
||||
G_INLINE_FUNC void
|
||||
check_open (Account *account)
|
||||
{
|
||||
if (account->editlevel <= 0)
|
||||
{
|
||||
/* not today, some day in the future ... */
|
||||
/* PERR ("Account not open for editing\n"); */
|
||||
/* assert (0); */
|
||||
/* return; */
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccAccountInsertSplit (Account *acc, Split *split)
|
||||
{
|
||||
@@ -520,7 +594,6 @@ xaccAccountInsertSplit (Account *acc, Split *split)
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
Account *oldacc;
|
||||
check_open (acc);
|
||||
|
||||
acc->balance_dirty = TRUE;
|
||||
acc->sort_dirty = TRUE;
|
||||
@@ -572,8 +645,6 @@ xaccAccountRemoveSplit (Account *acc, Split *split)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
check_open (acc);
|
||||
|
||||
node = g_list_find (acc->splits, split);
|
||||
if (!node)
|
||||
{
|
||||
@@ -793,16 +864,15 @@ xaccAccountSetStartingBalance(Account *acc,
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccAccountFixSplitDateOrder (Account * acc, Split *split ) {
|
||||
xaccAccountFixSplitDateOrder (Account * acc, Split *split )
|
||||
{
|
||||
if (NULL == acc) return;
|
||||
if (NULL == split) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
acc->sort_dirty = TRUE;
|
||||
acc->balance_dirty = TRUE;
|
||||
}
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@@ -913,6 +983,7 @@ xaccAccountAutoCode (Account *acc, int digits) {
|
||||
{
|
||||
acc->accountCode = xaccGroupGetNextFreeCode (acc->parent, digits);
|
||||
acc->parent->saved = FALSE;
|
||||
acc->core_dirty = TRUE;
|
||||
}
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
@@ -927,8 +998,6 @@ xaccAccountSetType (Account *acc, int tip) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
/* refuse invalid account types, and don't bother if not new type. */
|
||||
if((NUM_ACCOUNT_TYPES > tip) && (acc->type != tip)) {
|
||||
acc->type = tip;
|
||||
@@ -937,6 +1006,7 @@ xaccAccountSetType (Account *acc, int tip) {
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -948,15 +1018,14 @@ xaccAccountSetName (Account *acc, const char *str) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
/* make strdup before freeing */
|
||||
/* make strdup before freeing (just in case str==accountName !!) */
|
||||
tmp = g_strdup (str);
|
||||
g_free (acc->accountName);
|
||||
acc->accountName = tmp;
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -967,8 +1036,6 @@ xaccAccountSetCode (Account *acc, const char *str) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
/* make strdup before freeing */
|
||||
tmp = g_strdup (str);
|
||||
g_free (acc->accountCode);
|
||||
@@ -976,6 +1043,7 @@ xaccAccountSetCode (Account *acc, const char *str) {
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -986,15 +1054,14 @@ xaccAccountSetDescription (Account *acc, const char *str) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
/* make strdup before freeing */
|
||||
/* make strdup before freeing (just in case str==description !!) */
|
||||
tmp = g_strdup (str);
|
||||
g_free (acc->description);
|
||||
acc->description = tmp;
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -1006,8 +1073,6 @@ xaccAccountSetNotes (Account *acc, const char *str) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
new_value = kvp_value_new_string(str);
|
||||
if(new_value) {
|
||||
kvp_frame_set_slot(xaccAccountGetSlots(acc), "notes", new_value);
|
||||
@@ -1019,16 +1084,19 @@ xaccAccountSetNotes (Account *acc, const char *str) {
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
/* FIXME : is this the right way to do this? */
|
||||
static void
|
||||
update_split_currency(Account * acc) {
|
||||
update_split_currency(Account * acc)
|
||||
{
|
||||
GList *lp;
|
||||
|
||||
if(!acc) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
/* iterate over splits */
|
||||
for(lp = acc->splits; lp; lp = lp->next) {
|
||||
Split *s = (Split *) lp->data;
|
||||
@@ -1039,6 +1107,7 @@ update_split_currency(Account * acc) {
|
||||
xaccAccountGetSecuritySCU(acc),
|
||||
GNC_RND_ROUND);
|
||||
}
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@@ -1053,6 +1122,7 @@ xaccAccountSetCommodity (Account * acc, const gnc_commodity * com)
|
||||
{
|
||||
if ((!acc) || (!com)) return;
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
switch (acc->type)
|
||||
{
|
||||
case BANK:
|
||||
@@ -1072,6 +1142,8 @@ xaccAccountSetCommodity (Account * acc, const gnc_commodity * com)
|
||||
break;
|
||||
default:
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@@ -1085,8 +1157,6 @@ xaccAccountSetCurrency (Account * acc, const gnc_commodity * currency) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
acc->currency = currency;
|
||||
acc->currency_scu = gnc_commodity_get_fraction(currency);
|
||||
update_split_currency(acc);
|
||||
@@ -1096,6 +1166,7 @@ xaccAccountSetCurrency (Account * acc, const gnc_commodity * currency) {
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -1106,8 +1177,6 @@ xaccAccountSetSecurity (Account *acc, const gnc_commodity * security) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
|
||||
acc->security = security;
|
||||
acc->security_scu = gnc_commodity_get_fraction(security);
|
||||
update_split_currency(acc);
|
||||
@@ -1117,6 +1186,7 @@ xaccAccountSetSecurity (Account *acc, const gnc_commodity * security) {
|
||||
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -1127,10 +1197,10 @@ xaccAccountSetCurrencySCU (Account * acc, int scu) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
acc->currency_scu = scu;
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -1141,10 +1211,10 @@ xaccAccountSetSecuritySCU (Account *acc, int scu) {
|
||||
|
||||
xaccAccountBeginEdit(acc);
|
||||
{
|
||||
check_open (acc);
|
||||
acc->security_scu = scu;
|
||||
mark_account (acc);
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
@@ -1449,8 +1519,6 @@ xaccAccountSetTaxRelated (Account *account, gboolean tax_related)
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
{
|
||||
check_open (account);
|
||||
|
||||
kvp_frame_set_slot(xaccAccountGetSlots (account),
|
||||
"tax-related", new_value);
|
||||
|
||||
@@ -1459,6 +1527,7 @@ xaccAccountSetTaxRelated (Account *account, gboolean tax_related)
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1685,9 +1754,6 @@ xaccAccountSetReconcileLastDate (Account *account, time_t last_date)
|
||||
xaccAccountBeginEdit (account);
|
||||
{
|
||||
kvp_value *value;
|
||||
|
||||
check_open (account);
|
||||
|
||||
value = kvp_value_new_gint64 (last_date);
|
||||
|
||||
kvp_frame_set_slot_path (xaccAccountGetSlots (account), value,
|
||||
@@ -1697,6 +1763,7 @@ xaccAccountSetReconcileLastDate (Account *account, time_t last_date)
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1740,8 +1807,6 @@ xaccAccountSetReconcilePostponeDate (Account *account,
|
||||
{
|
||||
kvp_value *value;
|
||||
|
||||
check_open (account);
|
||||
|
||||
value = kvp_value_new_gint64 (postpone_date);
|
||||
|
||||
kvp_frame_set_slot_path (xaccAccountGetSlots (account), value,
|
||||
@@ -1751,6 +1816,7 @@ xaccAccountSetReconcilePostponeDate (Account *account,
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1795,8 +1861,6 @@ xaccAccountSetReconcilePostponeBalance (Account *account,
|
||||
{
|
||||
kvp_value *value;
|
||||
|
||||
check_open (account);
|
||||
|
||||
value = kvp_value_new_gnc_numeric (balance);
|
||||
|
||||
kvp_frame_set_slot_path (xaccAccountGetSlots (account), value,
|
||||
@@ -1806,6 +1870,7 @@ xaccAccountSetReconcilePostponeBalance (Account *account,
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1819,13 +1884,12 @@ xaccAccountClearReconcilePostpone (Account *account)
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
{
|
||||
check_open (account);
|
||||
|
||||
kvp_frame_set_slot_path (xaccAccountGetSlots (account), NULL,
|
||||
"reconcile-info", "postpone", NULL);
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1858,8 +1922,6 @@ xaccAccountSetLastNum (Account *account, const char *num)
|
||||
{
|
||||
kvp_value *value;
|
||||
|
||||
check_open (account);
|
||||
|
||||
value = kvp_value_new_string (num);
|
||||
|
||||
kvp_frame_set_slot (xaccAccountGetSlots (account), "last-num", value);
|
||||
@@ -1868,6 +1930,7 @@ xaccAccountSetLastNum (Account *account, const char *num)
|
||||
|
||||
mark_account (account);
|
||||
}
|
||||
account->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
@@ -1886,7 +1949,6 @@ xaccAccountSetPriceSrc(Account *acc, const char *src) {
|
||||
if((t == STOCK) || (t == MUTUAL)) {
|
||||
kvp_value *new_value = kvp_value_new_string(src);
|
||||
if(new_value) {
|
||||
check_open (acc);
|
||||
kvp_frame_set_slot(xaccAccountGetSlots(acc),
|
||||
"old-price-source",
|
||||
new_value);
|
||||
@@ -1897,6 +1959,7 @@ xaccAccountSetPriceSrc(Account *acc, const char *src) {
|
||||
}
|
||||
}
|
||||
}
|
||||
acc->core_dirty = TRUE;
|
||||
xaccAccountCommitEdit(acc);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,21 +116,22 @@ GNCAccountType xaccAccountStringToEnum (const char* str);
|
||||
|
||||
gboolean xaccAccountTypesCompatible (int parent_type, int child_type);
|
||||
|
||||
Account *xaccMallocAccount (void);
|
||||
void xaccFreeAccount (Account *account);
|
||||
|
||||
/* Compare two accounts for equality - this is a deep compare. */
|
||||
gboolean xaccAccountEqual(Account *a, Account* b, gboolean check_guids);
|
||||
|
||||
/*
|
||||
* The xaccAccountBeginEdit() and xaccAccountCommitEdit() subroutines
|
||||
* provide a pseudo-two-phase-commit wrapper for account updates.
|
||||
* They are mildly useful for detecting attempted updates outside
|
||||
* of their scope. However, they do not provide any true two-phase-anything
|
||||
* in the current implementation.
|
||||
* provide a two-phase-commit wrapper for account updates.
|
||||
* They are incompletely implemented ....
|
||||
*
|
||||
* The xaccAccountDestroy() routine can be used to get rid of an
|
||||
* account. The account should have been opened for editing
|
||||
* (by calling xaccAccountBeginEdit()) before calling this routine.
|
||||
*/
|
||||
Account *xaccMallocAccount (void);
|
||||
void xaccAccountBeginEdit (Account *account);
|
||||
void xaccAccountCommitEdit (Account *account);
|
||||
void xaccAccountDestroy (Account *account);
|
||||
|
||||
kvp_frame * xaccAccountGetSlots (Account *account);
|
||||
|
||||
|
||||
@@ -126,20 +126,13 @@ struct _account {
|
||||
|
||||
GList *splits; /* list of split pointers */
|
||||
|
||||
/* The "changed" flag is used to invalidate cached values in this structure.
|
||||
* Currently, the balances and the cost basis are cached.
|
||||
*/
|
||||
/*short changed;*/
|
||||
|
||||
/* The "open" flag indicates if the account has been
|
||||
* opened for editing. */
|
||||
/* short open; */
|
||||
|
||||
/* keep track of nesting level of begin/end edit calls */
|
||||
gint32 editlevel;
|
||||
|
||||
gboolean balance_dirty;
|
||||
gboolean sort_dirty;
|
||||
gboolean core_dirty; /* fields in this struct have changed */
|
||||
gboolean do_free;
|
||||
|
||||
/* The "mark" flag can be used by the user to mark this account
|
||||
* in any way desired. Handy for specialty traversals of the
|
||||
@@ -147,16 +140,6 @@ struct _account {
|
||||
short mark;
|
||||
};
|
||||
|
||||
/* bitfields for the changed flag */
|
||||
#define ACC_INVALID_BALN 0x1
|
||||
#define ACC_INVALID_COSTB 0x2
|
||||
#define ACC_INVALIDATE_ALL 0x3
|
||||
|
||||
/* bitflields for the open flag */
|
||||
#define ACC_BEGIN_EDIT 0x1
|
||||
#define ACC_DEFER_REBALANCE 0x2
|
||||
#define ACC_BEING_DESTROYED 0x4
|
||||
|
||||
|
||||
/* The xaccAccountRemoveSplit() routine will remove the indicated split
|
||||
* from the indicated account. Note that this will leave the split
|
||||
@@ -197,4 +180,11 @@ void xaccAccountSetStartingBalance(Account *account,
|
||||
const gnc_numeric start_cleared_baln,
|
||||
const gnc_numeric start_reconciled_baln);
|
||||
|
||||
/* The xaccFreeAccount() routine releases memory associated with the
|
||||
* account. It should never be called directly from user code;
|
||||
* instead, the xaccAccountDestroy() routine should be used
|
||||
* (because xaccAccountDestroy() has the correct commit semantics).
|
||||
*/
|
||||
|
||||
void xaccFreeAccount (Account *account);
|
||||
#endif /* __XACC_ACCOUNT_P_H__ */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
* *
|
||||
\********************************************************************/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "Account.h"
|
||||
#include "AccountP.h"
|
||||
#include "BackendP.h"
|
||||
@@ -68,13 +70,13 @@ xaccAccountGetBackend (Account * acc)
|
||||
if (!acc) return NULL;
|
||||
|
||||
/* find the first account group that has a backend */
|
||||
grp = (AccountGroup *) acc->parent;
|
||||
grp = acc->parent;
|
||||
while (grp) {
|
||||
if (grp->backend) return (grp->backend);
|
||||
parent_acc = grp -> parent;
|
||||
grp = NULL;
|
||||
if (parent_acc) {
|
||||
grp = (AccountGroup *) parent_acc->parent;
|
||||
grp = parent_acc->parent;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -87,17 +89,34 @@ xaccAccountGetBackend (Account * acc)
|
||||
Backend *
|
||||
xaccTransactionGetBackend (Transaction *trans)
|
||||
{
|
||||
Split *s;
|
||||
GList *snode, *node;
|
||||
Split *s=NULL;
|
||||
|
||||
if (!trans) return NULL;
|
||||
|
||||
/* find an account */
|
||||
s = xaccTransGetSplit (trans, 0);
|
||||
if (!s) {
|
||||
s = xaccTransGetSplit (trans->orig, 0);
|
||||
if (!s) return NULL;
|
||||
}
|
||||
snode = xaccTransGetSplitList(trans);
|
||||
for (node = snode; node; node=node->next)
|
||||
{
|
||||
s = node->data;
|
||||
if (s->acc) break;
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
/* if transaction is being deleted, it won't have any splits
|
||||
* so lets take a look at the 'original' transaction */
|
||||
if (!s)
|
||||
{
|
||||
snode = xaccTransGetSplitList(trans->orig);
|
||||
for (node = snode; node; node=node->next)
|
||||
{
|
||||
s = node->data;
|
||||
if (s->acc) break;
|
||||
s = NULL;
|
||||
}
|
||||
}
|
||||
if (!s) return NULL;
|
||||
|
||||
/* I suppose it would be more 'technically correct' to make sure that
|
||||
* 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
|
||||
|
||||
@@ -159,28 +159,37 @@ xaccAccountGroupCommitEdit (AccountGroup *grp)
|
||||
void
|
||||
xaccFreeAccountGroup (AccountGroup *grp)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
if (!grp) return;
|
||||
|
||||
xaccAccountGroupBeginEdit (grp);
|
||||
|
||||
for (node = grp->accounts; node; node = node->next)
|
||||
if (grp->accounts)
|
||||
{
|
||||
Account *account = node->data;
|
||||
|
||||
xaccFreeAccount (account);
|
||||
Account *account;
|
||||
/* This is a weird iterator & needs some explanation.
|
||||
* xaccAccountDestroy() will rip the account out
|
||||
* of the list, thus iterating while grp->accounts
|
||||
* is non-null is enough to iterate the loop. But
|
||||
* when it deletes the last account, then it will also
|
||||
* delete the group, making the grp pointer invalid.
|
||||
* So we have to be careful with the last deletion:
|
||||
* in particular, g_free(grp) would be freeing that
|
||||
* memory a second time, so don't do it.
|
||||
*/
|
||||
while (grp->accounts->next)
|
||||
{
|
||||
account = grp->accounts->next->data;
|
||||
xaccAccountBeginEdit (account);
|
||||
xaccAccountDestroy (account);
|
||||
}
|
||||
account = grp->accounts->data;
|
||||
xaccAccountBeginEdit (account);
|
||||
xaccAccountDestroy (account);
|
||||
}
|
||||
else
|
||||
{
|
||||
grp->parent = NULL;
|
||||
grp->balance = gnc_numeric_zero();
|
||||
g_free (grp);
|
||||
}
|
||||
|
||||
g_list_free (grp->accounts);
|
||||
|
||||
/* null everything out, just in case somebody
|
||||
* tries to traverse freed memory */
|
||||
grp->parent = NULL;
|
||||
grp->accounts = NULL;
|
||||
grp->balance = gnc_numeric_zero();
|
||||
|
||||
g_free (grp);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@@ -925,7 +934,8 @@ xaccGroupMergeAccounts (AccountGroup *grp)
|
||||
/* remove from list -- node_a is ok, it's before node_b */
|
||||
grp->accounts = g_list_remove (grp->accounts, acc_b);
|
||||
|
||||
xaccFreeAccount (acc_b);
|
||||
xaccAccountBeginEdit (acc_b);
|
||||
xaccAccountDestroy (acc_b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1118,6 +1118,13 @@ xaccTransFindCommonCurrency (Transaction *trans)
|
||||
gnc_commodity_get_unique_name (retval));
|
||||
}
|
||||
|
||||
if (NULL == retval)
|
||||
{
|
||||
/* in every situation I can think of, this routine should return
|
||||
* common currency. So make note of this ... */
|
||||
PWARN ("unable to find a common currency, and that is strange.");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1298,7 +1305,8 @@ xaccTransCommitEdit (Transaction *trans)
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
PINFO ("descr is %s", xaccTransGetDescription(trans));
|
||||
be = xaccTransactionGetBackend (trans);
|
||||
if (be && be->trans_commit_edit) {
|
||||
if (be && be->trans_commit_edit)
|
||||
{
|
||||
int rc = 0;
|
||||
rc = (be->trans_commit_edit) (be, trans, trans->orig);
|
||||
|
||||
@@ -1593,21 +1601,20 @@ xaccSplitDestroy (Split *split)
|
||||
if (!split) return;
|
||||
|
||||
trans = split->parent;
|
||||
if (trans)
|
||||
{
|
||||
check_open (trans);
|
||||
}
|
||||
|
||||
check_open (trans);
|
||||
|
||||
mark_split (split);
|
||||
xaccRemoveEntity (&split->guid);
|
||||
|
||||
if (trans)
|
||||
{
|
||||
gboolean ismember = (g_list_find (trans->splits, split) != NULL);
|
||||
assert (ismember);
|
||||
}
|
||||
|
||||
mark_split (split);
|
||||
|
||||
if (trans)
|
||||
xaccTransRemoveSplit (trans, split);
|
||||
}
|
||||
|
||||
xaccAccountRemoveSplit (split->acc, split);
|
||||
xaccAccountRecomputeBalance (split->acc);
|
||||
@@ -1623,8 +1630,7 @@ xaccTransAppendSplit (Transaction *trans, Split *split)
|
||||
{
|
||||
Transaction *oldtrans;
|
||||
|
||||
if (!trans) return;
|
||||
if (!split) return;
|
||||
if (!trans || !split) return;
|
||||
|
||||
check_open (trans);
|
||||
|
||||
|
||||
@@ -578,6 +578,8 @@ gnc_book_save (GNCBook *book)
|
||||
if (ERR_BACKEND_NO_ERR != retval)
|
||||
{
|
||||
gnc_book_push_error (book, retval);
|
||||
|
||||
/* we close the backend here ... isn't this a bit harsh ??? */
|
||||
if (be->book_end)
|
||||
{
|
||||
(be->book_end)(be);
|
||||
@@ -655,6 +657,7 @@ gnc_book_destroy (GNCBook *book)
|
||||
|
||||
/* destroy the backend */
|
||||
if (book->backend) g_free(book->backend);
|
||||
xaccGroupSetBackend (book->topgroup, NULL);
|
||||
|
||||
xaccFreeAccountGroup (book->topgroup);
|
||||
book->topgroup = NULL;
|
||||
|
||||
Reference in New Issue
Block a user