Convert GNCLot to use more gobject features. Removes all direct access to lot object fields, which are now accessed through functions or property names (for backend sql load).

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18745 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Phil Longstaff 2010-02-27 15:54:20 +00:00
parent 5066daa770
commit a3ca714396
12 changed files with 398 additions and 248 deletions

View File

@ -31,6 +31,7 @@
#include <glib.h>
#include "qof.h"
#include "Account.h"
#include "gnc-lot.h"
#include "gnc-backend-sql.h"
@ -49,7 +50,6 @@
static /*@ dependent @*//*@ null @*/ gpointer get_lot_account( gpointer pObject );
static void set_lot_account( gpointer pObject, /*@ null @*/ gpointer pValue );
static void set_lot_is_closed( gpointer pObject, gboolean value );
static const GncSqlColumnTableEntry col_table[] =
{
@ -57,8 +57,7 @@ static const GncSqlColumnTableEntry col_table[] =
{ "guid", CT_GUID, 0, COL_NNUL|COL_PKEY, "guid" },
{ "account_guid", CT_GUID, 0, 0, NULL, NULL,
(QofAccessFunc)get_lot_account, set_lot_account },
{ "is_closed", CT_BOOLEAN, 0, COL_NNUL, NULL, NULL,
(QofAccessFunc)gnc_lot_is_closed, (QofSetterFunc)set_lot_is_closed },
{ "is_closed", CT_BOOLEAN, 0, COL_NNUL, "is-closed" },
{ NULL }
/*@ +full_init_block @*/
};
@ -98,18 +97,6 @@ set_lot_account( gpointer pObject, /*@ null @*/ gpointer pValue )
}
}
static void
set_lot_is_closed( gpointer pObject, gboolean closed )
{
GNCLot* lot;
g_return_if_fail( pObject != NULL );
g_return_if_fail( GNC_IS_LOT(pObject) );
lot = GNC_LOT(pObject);
lot->is_closed = (char)closed;
}
static /*@ dependent @*//*@ null @*/ GNCLot*
load_single_lot( GncSqlBackend* be, GncSqlRow* row )
{

View File

@ -1730,7 +1730,7 @@ xaccAccountRemoveLot (Account *acc, GNCLot *lot)
ENTER ("(acc=%p, lot=%p)", acc, lot);
priv->lots = g_list_remove(priv->lots, lot);
qof_event_gen (&lot->inst, QOF_EVENT_REMOVE, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_REMOVE, NULL);
qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, NULL);
LEAVE ("(acc=%p, lot=%p)", acc, lot);
}
@ -1740,34 +1740,36 @@ xaccAccountInsertLot (Account *acc, GNCLot *lot)
{
AccountPrivate *priv, *opriv;
Account * old_acc = NULL;
Account* lot_account;
/* errors */
g_return_if_fail(GNC_IS_ACCOUNT(acc));
g_return_if_fail(GNC_IS_LOT(lot));
/* optimizations */
if (lot->account == acc)
lot_account = gnc_lot_get_account(lot);
if (lot_account == acc)
return;
ENTER ("(acc=%p, lot=%p)", acc, lot);
/* pull it out of the old account */
if (lot->account) {
old_acc = lot->account;
if (lot_account) {
old_acc = lot_account;
opriv = GET_PRIVATE(old_acc);
opriv->lots = g_list_remove(opriv->lots, lot);
}
priv = GET_PRIVATE(acc);
priv->lots = g_list_prepend(priv->lots, lot);
lot->account = acc;
gnc_lot_set_account(lot, acc);
/* Don't move the splits to the new account. The caller will do this
* if appropriate, and doing it here will not work if we are being
* called from gnc_book_close_period since xaccAccountInsertSplit
* will try to balance capital gains and things aren't ready for that. */
qof_event_gen (&lot->inst, QOF_EVENT_ADD, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_ADD, NULL);
qof_event_gen (&acc->inst, QOF_EVENT_MODIFY, NULL);
LEAVE ("(acc=%p, lot=%p)", acc, lot);

View File

@ -228,11 +228,11 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
col = qof_book_get_collection (book, GNC_ID_LOT);
qof_instance_set_book(lot, book);
qof_collection_insert_entity (col, &lot->inst);
qof_collection_insert_entity (col, QOF_INSTANCE(lot));
/* Move the splits over (only if they haven't already been moved). */
col = qof_book_get_collection (book, GNC_ID_SPLIT);
for (snode = lot->splits; snode; snode=snode->next)
for (snode = gnc_lot_get_split_list(lot); snode; snode=snode->next)
{
Split *s = snode->data;
if (qof_instance_get_book(s) != book)
@ -242,7 +242,7 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
}
}
twin = xaccAccountLookupTwin (lot->account, book);
twin = xaccAccountLookupTwin (gnc_lot_get_account(lot), book);
if (!twin)
{
PERR ("near-fatal: twin account not found");
@ -358,13 +358,13 @@ lot_has_open_trans_tree (GNCLot *lot)
{
SplitList *split_list, *snode;
if (1 == lot->marker) return FALSE;
if (2 == lot->marker) return TRUE;
lot->marker = 1;
if (1 == gnc_lot_get_marker(lot)) return FALSE;
if (2 == gnc_lot_get_marker(lot)) return TRUE;
gnc_lot_set_marker(lot, 1);
if (FALSE == gnc_lot_is_closed(lot))
{
lot->marker = 2;
gnc_lot_set_marker(lot, 2);
return TRUE;
}
@ -375,7 +375,7 @@ lot_has_open_trans_tree (GNCLot *lot)
Transaction *trans = s->parent;
if (trans_has_open_lot_tree (trans))
{
lot->marker = 2;
gnc_lot_set_marker(lot, 2);
return TRUE;
}
}
@ -445,7 +445,7 @@ clear_markers (Account *account, gpointer dummy)
Transaction *trans = s->parent;
GNCLot *lot = s->lot;
trans->marker = 0;
if (lot) lot->marker = 0;
if (lot) gnc_lot_set_marker(lot, 0);
}
}

View File

@ -101,7 +101,7 @@ xaccLotFill (GNCLot *lot)
GNCPolicy *pcy;
if (!lot) return;
acc = lot->account;
acc = gnc_lot_get_account(lot);
pcy = gnc_account_get_policy(acc);
ENTER ("(lot=%s, acc=%s)", gnc_lot_get_title(lot), xaccAccountGetName(acc));
@ -160,7 +160,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
ENTER ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title"));
for (snode = lot->splits; snode; snode=snode->next)
for (snode = gnc_lot_get_split_list(lot); snode; snode=snode->next)
{
Split *s = snode->data;
xaccSplitComputeCapGains (s, NULL);
@ -169,7 +169,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
/* We double-check only closed lots */
if (FALSE == gnc_lot_is_closed (lot)) return;
for (snode = lot->splits; snode; snode=snode->next)
for (snode = gnc_lot_get_split_list(lot); snode; snode=snode->next)
{
Split *s = snode->data;
Transaction *trans = s->parent;
@ -208,7 +208,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
*/
PERR ("Closed lot fails to double-balance !! lot value=%s",
gnc_num_dbg_to_string (value));
for (node=lot->splits; node; node=node->next)
for (node = gnc_lot_get_split_list(lot); node; node=node->next)
{
Split *s = node->data;
PERR ("s=%p amt=%s val=%s", s,

View File

@ -309,7 +309,7 @@ void mark_split (Split *s)
}
/* set dirty flag on lot too. */
if (s->lot) s->lot->is_closed = -1;
if (s->lot) gnc_lot_set_closed_unknown(s->lot);
}
/*
@ -527,7 +527,7 @@ xaccSplitCommitEdit(Split *s)
acc = s->acc;
/* Remove from lot (but only if it hasn't been moved to
new lot already) */
if (s->lot && (s->lot->account != acc || qof_instance_get_destroying(s)))
if (s->lot && (gnc_lot_get_account(s->lot) != acc || qof_instance_get_destroying(s)))
gnc_lot_remove_split (s->lot, s);
/* Possibly remove the split from the original account... */
@ -542,7 +542,7 @@ xaccSplitCommitEdit(Split *s)
if (gnc_account_insert_split(acc, s)) {
/* If the split's lot belonged to some other account, we
leave it so. */
if (s->lot && (NULL == s->lot->account))
if (s->lot && (NULL == gnc_lot_get_account(s->lot)))
xaccAccountInsertLot (acc, s->lot);
} else {
PERR("Account grabbed split prematurely.");
@ -558,7 +558,7 @@ xaccSplitCommitEdit(Split *s)
}
if (s->lot) {
/* A change of value/amnt affects gains display, etc. */
qof_event_gen (&s->lot->inst, QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(s->lot), QOF_EVENT_MODIFY, NULL);
}
/* Important: we save off the original parent transaction and account

View File

@ -235,7 +235,7 @@ void gen_event_trans (Transaction *trans)
if (lot)
{
/* A change of transaction date might affect opening date of lot */
qof_event_gen (&lot->inst, QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
}
}
#endif

View File

@ -690,7 +690,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
if (!split) return;
lot = split->lot;
if (!lot) return;
pcy = gnc_account_get_policy(lot->account);
pcy = gnc_account_get_policy(gnc_lot_get_account(lot));
currency = split->parent->common_currency;
ENTER ("(split=%p gains=%p status=0x%x lot=%s)", split,
@ -770,7 +770,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
/* Note: if the value of the 'opening' split(s) has changed,
* then the cap gains are changed. So we need to check not
* only if this split is dirty, but also the lot-opening splits. */
for (node=lot->splits; node; node=node->next)
for (node=gnc_lot_get_split_list(lot); node; node=node->next)
{
Split *s = node->data;
if (pcy->PolicyIsOpeningSplit(pcy,lot,s))
@ -830,7 +830,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
gnc_numeric_abs(split->amount)))
{
GList *n;
for (n = lot->splits; n; n = n->next)
for (n = gnc_lot_get_split_list(lot); n; n = n->next)
{
Split *s = n->data;
PINFO ("split amt=%s", gnc_num_dbg_to_string(s->amount));
@ -849,7 +849,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
gnc_numeric_negative_p(split->amount)))
{
GList *n;
for (n = lot->splits; n; n = n->next)
for (n = gnc_lot_get_split_list(lot); n; n = n->next)
{
Split *s = n->data;
PINFO ("split amt=%s", gnc_num_dbg_to_string(s->amount));
@ -925,7 +925,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
if (NULL == lot_split)
{
Account *lot_acc = lot->account;
Account *lot_acc = gnc_lot_get_account(lot);
QofBook *book = qof_instance_get_book(lot_acc);
new_gain_split = TRUE;
@ -1081,8 +1081,8 @@ xaccLotComputeCapGains (GNCLot *lot, Account *gain_acc)
* to mark all splits dirty if the opening splits are dirty. */
ENTER("(lot=%p)", lot);
pcy = gnc_account_get_policy(lot->account);
for (node = lot->splits; node; node = node->next)
pcy = gnc_account_get_policy(gnc_lot_get_account(lot));
for (node = gnc_lot_get_split_list(lot); node; node = node->next)
{
Split *s = node->data;
if (pcy->PolicyIsOpeningSplit(pcy,lot,s))
@ -1099,14 +1099,14 @@ xaccLotComputeCapGains (GNCLot *lot, Account *gain_acc)
if (is_dirty)
{
for (node = lot->splits; node; node = node->next)
for (node = gnc_lot_get_split_list(lot); node; node = node->next)
{
Split *s = node->data;
s->gains |= GAINS_STATUS_VDIRTY;
}
}
for (node = lot->splits; node; node = node->next)
for (node = gnc_lot_get_split_list(lot); node; node = node->next)
{
Split *s = node->data;
xaccSplitComputeCapGains (s, gain_acc);

View File

@ -185,7 +185,7 @@ typedef struct gnc_commodity_table_s gnc_commodity_table;
*
* See the file src/doc/lots.txt for implmentation overview.
*/
typedef struct gnc_lot_struct GNCLot;
typedef struct gnc_lot_s GNCLot;
/** @brief Price of commodity on a given date.
* A GNCPrice encapsulates price information: the cost of a commodity

View File

@ -37,34 +37,6 @@
#ifndef GNC_LOT_P_H
#define GNC_LOT_P_H
#include "gnc-lot.h"
#include "Account.h"
struct gnc_lot_struct
{
QofInstance inst;
/* Account to which this lot applies. All splits in the lot must
* belong to this account.
*/
Account * account;
/* List of splits that belong to this lot. */
SplitList *splits;
/* Handy cached value to indicate if lot is closed. */
/* If value is negative, then the cache is invalid. */
signed char is_closed;
/* traversal marker, handy for preventing recursion */
unsigned char marker;
};
struct _GncLotClass
{
QofInstanceClass parent_class;
};
#define gnc_lot_set_guid(L,G) qof_instance_set_guid(QOF_INSTANCE(L),&(G))
/* Register with the Query engine */

View File

@ -39,10 +39,11 @@
* Copyright (c) 2002,2003 Linas Vepstas <linas@linas.org>
*/
#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#include "config.h"
#include "Account.h"
#include "AccountP.h"
#include "gnc-lot.h"
@ -54,37 +55,143 @@
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_LOT;
struct gnc_lot_s
{
QofInstance inst;
};
enum {
PROP_0,
PROP_IS_CLOSED,
PROP_MARKER
};
typedef struct LotPrivate
{
/* Account to which this lot applies. All splits in the lot must
* belong to this account.
*/
Account * account;
/* List of splits that belong to this lot. */
SplitList *splits;
/* Handy cached value to indicate if lot is closed. */
/* If value is negative, then the cache is invalid. */
signed char is_closed;
#define LOT_CLOSED_UNKNOWN (-1)
/* traversal marker, handy for preventing recursion */
unsigned char marker;
} LotPrivate;
#define GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), GNC_TYPE_LOT, LotPrivate))
#define gnc_lot_set_guid(L,G) qof_instance_set_guid(QOF_INSTANCE(L),&(G))
/* ============================================================= */
/* GObject Initialization */
QOF_GOBJECT_IMPL(gnc_lot, GNCLot, QOF_TYPE_INSTANCE);
G_DEFINE_TYPE(GNCLot, gnc_lot, QOF_TYPE_INSTANCE)
static void
gnc_lot_init(GNCLot* lot)
{
LotPrivate* priv;
priv = GET_PRIVATE(lot);
priv->account = NULL;
priv->splits = NULL;
priv->is_closed = LOT_CLOSED_UNKNOWN;
priv->marker = 0;
}
static void
gnc_lot_dispose_real (GObject *lotp)
gnc_lot_dispose(GObject *lotp)
{
G_OBJECT_CLASS(gnc_lot_parent_class)->dispose(lotp);
}
static void
gnc_lot_finalize_real(GObject* lotp)
gnc_lot_finalize(GObject* lotp)
{
G_OBJECT_CLASS(gnc_lot_parent_class)->finalize(lotp);
}
static void
gnc_lot_init_data (GNCLot *lot, QofBook *book)
gnc_lot_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
{
ENTER ("(lot=%p, book=%p)", lot, book);
lot->account = NULL;
lot->splits = NULL;
lot->is_closed = -1;
lot->marker = 0;
GNCLot* lot;
LotPrivate* priv;
g_return_if_fail(GNC_IS_LOT(object));
lot = GNC_LOT(object);
priv = GET_PRIVATE(lot);
switch(prop_id) {
case PROP_IS_CLOSED:
g_value_set_int(value, priv->is_closed);
break;
case PROP_MARKER:
g_value_set_int(value, priv->marker);
break;
}
}
static void
gnc_lot_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
{
GNCLot* lot;
LotPrivate* priv;
g_return_if_fail(GNC_IS_LOT(object));
lot = GNC_LOT(object);
priv = GET_PRIVATE(lot);
switch(prop_id) {
case PROP_IS_CLOSED:
priv->is_closed = g_value_get_int(value);
break;
case PROP_MARKER:
priv->marker = g_value_get_int(value);
break;
}
}
static void
gnc_lot_class_init(GNCLotClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gnc_lot_dispose;
gobject_class->finalize = gnc_lot_finalize;
gobject_class->get_property = gnc_lot_get_property;
gobject_class->set_property = gnc_lot_set_property;
g_type_class_add_private(klass, sizeof(LotPrivate));
g_object_class_install_property(
gobject_class,
PROP_IS_CLOSED,
g_param_spec_int("is-closed",
"Is Lot Closed",
"Indication of whether this lot is open "
"or closed to further changes.",
-1, 1, 0,
G_PARAM_READWRITE));
g_object_class_install_property(
gobject_class,
PROP_MARKER,
g_param_spec_int("marker",
"Lot marker",
"Ipsum Lorem",
0, G_MAXINT8, 0,
G_PARAM_READWRITE));
qof_instance_init_data(&lot->inst, GNC_ID_LOT, book);
LEAVE ("(lot=%p, book=%p)", lot, book);
}
GNCLot *
@ -94,8 +201,8 @@ gnc_lot_new (QofBook *book)
g_return_val_if_fail (book, NULL);
lot = g_object_new (GNC_TYPE_LOT, NULL);
gnc_lot_init_data (lot, book);
qof_event_gen (&lot->inst, QOF_EVENT_CREATE, NULL);
qof_instance_init_data(QOF_INSTANCE(lot), GNC_ID_LOT, book);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_CREATE, NULL);
return lot;
}
@ -103,21 +210,22 @@ static void
gnc_lot_free(GNCLot* lot)
{
GList *node;
LotPrivate* priv;
if (!lot) return;
ENTER ("(lot=%p)", lot);
qof_event_gen (&lot->inst, QOF_EVENT_DESTROY, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_DESTROY, NULL);
for (node=lot->splits; node; node=node->next)
priv = GET_PRIVATE(lot);
for (node=priv->splits; node; node=node->next)
{
Split *s = node->data;
s->lot = NULL;
}
g_list_free (lot->splits);
g_list_free (priv->splits);
lot->account = NULL;
lot->is_closed = TRUE;
priv->account = NULL;
priv->is_closed = TRUE;
/* qof_instance_release (&lot->inst); */
g_object_unref (lot);
}
@ -137,7 +245,7 @@ gnc_lot_destroy (GNCLot *lot)
void
gnc_lot_begin_edit (GNCLot *lot)
{
qof_begin_edit(&lot->inst);
qof_begin_edit(QOF_INSTANCE(lot));
}
static void commit_err (QofInstance *inst, QofBackendError errcode)
@ -159,7 +267,7 @@ void
gnc_lot_commit_edit (GNCLot *lot)
{
if (!qof_commit_edit (QOF_INSTANCE(lot))) return;
qof_commit_edit_part2 (&lot->inst, commit_err, noop, lot_free);
qof_commit_edit_part2 (QOF_INSTANCE(lot), commit_err, noop, lot_free);
}
/* ============================================================= */
@ -184,16 +292,62 @@ gnc_lot_get_book (GNCLot *lot)
gboolean
gnc_lot_is_closed (GNCLot *lot)
{
LotPrivate* priv;
if (!lot) return TRUE;
if (0 > lot->is_closed) gnc_lot_get_balance (lot);
return lot->is_closed;
priv = GET_PRIVATE(lot);
if (0 > priv->is_closed) gnc_lot_get_balance (lot);
return priv->is_closed;
}
Account *
gnc_lot_get_account (const GNCLot *lot)
{
LotPrivate* priv;
if (!lot) return NULL;
return lot->account;
priv = GET_PRIVATE(lot);
return priv->account;
}
void
gnc_lot_set_account(GNCLot* lot, Account* account)
{
if (lot != NULL)
{
LotPrivate* priv;
priv = GET_PRIVATE(lot);
priv->account = account;
}
}
unsigned char
gnc_lot_get_marker(const GNCLot* lot)
{
LotPrivate* priv;
if (lot == NULL) return 0;
priv = GET_PRIVATE(lot);
return priv->marker;
}
void
gnc_lot_set_marker(GNCLot* lot, unsigned char m)
{
LotPrivate* priv;
if (lot != NULL)
{
priv = GET_PRIVATE(lot);
priv->marker = m;
}
}
void
gnc_lot_set_closed_unknown(GNCLot* lot)
{
LotPrivate* priv;
if (lot != NULL)
{
priv = GET_PRIVATE(lot);
priv->is_closed = LOT_CLOSED_UNKNOWN;
}
}
KvpFrame *
@ -205,14 +359,18 @@ gnc_lot_get_slots (const GNCLot *lot)
SplitList *
gnc_lot_get_split_list (const GNCLot *lot)
{
LotPrivate* priv;
if (!lot) return NULL;
return lot->splits;
priv = GET_PRIVATE(lot);
return priv->splits;
}
gint gnc_lot_count_splits (const GNCLot *lot)
{
LotPrivate* priv;
if (!lot) return 0;
return g_list_length (lot->splits);
priv = GET_PRIVATE(lot);
return g_list_length (priv->splits);
}
/* ============================================================== */
@ -222,14 +380,14 @@ const char *
gnc_lot_get_title (const GNCLot *lot)
{
if (!lot) return NULL;
return kvp_frame_get_string (lot->inst.kvp_data, "/title");
return kvp_frame_get_string (gnc_lot_get_slots(lot), "/title");
}
const char *
gnc_lot_get_notes (const GNCLot *lot)
{
if (!lot) return NULL;
return kvp_frame_get_string (lot->inst.kvp_data, "/notes");
return kvp_frame_get_string (gnc_lot_get_slots(lot), "/notes");
}
void
@ -238,7 +396,7 @@ gnc_lot_set_title (GNCLot *lot, const char *str)
if (!lot) return;
qof_begin_edit(QOF_INSTANCE(lot));
qof_instance_set_dirty(QOF_INSTANCE(lot));
kvp_frame_set_str (lot->inst.kvp_data, "/title", str);
kvp_frame_set_str (gnc_lot_get_slots(lot), "/title", str);
gnc_lot_commit_edit(lot);
}
@ -248,7 +406,7 @@ gnc_lot_set_notes (GNCLot *lot, const char *str)
if (!lot) return;
gnc_lot_begin_edit(lot);
qof_instance_set_dirty(QOF_INSTANCE(lot));
kvp_frame_set_str (lot->inst.kvp_data, "/notes", str);
kvp_frame_set_str (gnc_lot_get_slots(lot), "/notes", str);
gnc_lot_commit_edit(lot);
}
@ -257,21 +415,23 @@ gnc_lot_set_notes (GNCLot *lot, const char *str)
gnc_numeric
gnc_lot_get_balance (GNCLot *lot)
{
LotPrivate* priv;
GList *node;
gnc_numeric zero = gnc_numeric_zero();
gnc_numeric baln = zero;
if (!lot) return zero;
if (!lot->splits)
priv = GET_PRIVATE(lot);
if (!priv->splits)
{
lot->is_closed = FALSE;
priv->is_closed = FALSE;
return zero;
}
/* Sum over splits; because they all belong to same account
* they will have same denominator.
*/
for (node=lot->splits; node; node=node->next)
for (node=priv->splits; node; node=node->next)
{
Split *s = node->data;
gnc_numeric amt = xaccSplitGetAmount (s);
@ -281,11 +441,11 @@ gnc_lot_get_balance (GNCLot *lot)
/* cache a zero balance as a closed lot */
if (gnc_numeric_equal (baln, zero))
{
lot->is_closed = TRUE;
priv->is_closed = TRUE;
}
else
{
lot->is_closed = FALSE;
priv->is_closed = FALSE;
}
return baln;
@ -297,12 +457,18 @@ void
gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
gnc_numeric *amount, gnc_numeric *value)
{
LotPrivate* priv;
GList *node;
gnc_numeric zero = gnc_numeric_zero();
gnc_numeric amt = zero;
gnc_numeric val = zero;
if (lot && lot->splits)
*amount = amt;
*value = val;
if (lot == NULL) return;
priv = GET_PRIVATE(lot);
if (priv->splits)
{
Transaction *ta, *tb;
const Split *target;
@ -313,7 +479,7 @@ gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
if (target == NULL)
target = split;
tb = xaccSplitGetParent (target);
for (node = lot->splits; node; node = node->next)
for (node = priv->splits; node; node = node->next)
{
Split *s = node->data;
Split *source = xaccSplitGetGainsSourceSplit (s);
@ -340,8 +506,10 @@ gnc_lot_get_balance_before (const GNCLot *lot, const Split *split,
void
gnc_lot_add_split (GNCLot *lot, Split *split)
{
LotPrivate* priv;
Account * acc;
if (!lot || !split) return;
priv = GET_PRIVATE(lot);
ENTER ("(lot=%p, split=%p) %s amt=%s val=%s", lot, split,
gnc_lot_get_title (lot),
@ -350,16 +518,16 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
gnc_lot_begin_edit(lot);
acc = xaccSplitGetAccount (split);
qof_instance_set_dirty(QOF_INSTANCE(lot));
if (NULL == lot->account)
if (NULL == priv->account)
{
xaccAccountInsertLot (acc, lot);
}
else if (lot->account != acc)
else if (priv->account != acc)
{
PERR ("splits from different accounts cannot "
"be added to this lot!\n"
"\tlot account=\'%s\', split account=\'%s\'\n",
xaccAccountGetName(lot->account), xaccAccountGetName (acc));
xaccAccountGetName(priv->account), xaccAccountGetName (acc));
gnc_lot_commit_edit(lot);
LEAVE("different accounts");
return;
@ -376,35 +544,37 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
}
xaccSplitSetLot(split, lot);
lot->splits = g_list_append (lot->splits, split);
priv->splits = g_list_append (priv->splits, split);
/* for recomputation of is-closed */
lot->is_closed = -1;
priv->is_closed = LOT_CLOSED_UNKNOWN;
gnc_lot_commit_edit(lot);
qof_event_gen (&lot->inst, QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
LEAVE("added to lot");
}
void
gnc_lot_remove_split (GNCLot *lot, Split *split)
{
LotPrivate* priv;
if (!lot || !split) return;
priv = GET_PRIVATE(lot);
ENTER ("(lot=%p, split=%p)", lot, split);
gnc_lot_begin_edit(lot);
qof_instance_set_dirty(QOF_INSTANCE(lot));
lot->splits = g_list_remove (lot->splits, split);
priv->splits = g_list_remove (priv->splits, split);
xaccSplitSetLot(split, NULL);
lot->is_closed = -1; /* force an is-closed computation */
priv->is_closed = LOT_CLOSED_UNKNOWN; /* force an is-closed computation */
if (NULL == lot->splits)
if (NULL == priv->splits)
{
xaccAccountRemoveLot (lot->account, lot);
lot->account = NULL;
xaccAccountRemoveLot (priv->account, lot);
priv->account = NULL;
}
gnc_lot_commit_edit(lot);
qof_event_gen (&lot->inst, QOF_EVENT_MODIFY, NULL);
qof_event_gen (QOF_INSTANCE(lot), QOF_EVENT_MODIFY, NULL);
}
/* ============================================================== */
@ -413,22 +583,26 @@ gnc_lot_remove_split (GNCLot *lot, Split *split)
Split *
gnc_lot_get_earliest_split (GNCLot *lot)
{
if (! lot->splits)
return NULL;
lot->splits = g_list_sort (lot->splits, (GCompareFunc) xaccSplitOrderDateOnly);
return lot->splits->data;
LotPrivate* priv;
if (!lot) return NULL;
priv = GET_PRIVATE(lot);
if (! priv->splits) return NULL;
priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
return priv->splits->data;
}
Split *
gnc_lot_get_latest_split (GNCLot *lot)
{
LotPrivate* priv;
SplitList *node;
if (! lot->splits)
return NULL;
lot->splits = g_list_sort (lot->splits, (GCompareFunc) xaccSplitOrderDateOnly);
if (!lot) return NULL;
priv = GET_PRIVATE(lot);
if (! priv->splits) return NULL;
priv->splits = g_list_sort (priv->splits, (GCompareFunc) xaccSplitOrderDateOnly);
for (node = lot->splits; node->next; node = node->next)
for (node = priv->splits; node->next; node = node->next)
;
return node->data;

View File

@ -59,10 +59,16 @@
#ifndef GNC_LOT_H
#define GNC_LOT_H
typedef struct _GncLotClass GNCLotClass;
//typedef struct _GncLotClass GNCLotClass;
#include "qof.h"
#include "gnc-lot-p.h"
#include "gnc-engine.h"
/*#include "gnc-lot-p.h"*/
typedef struct {
QofInstanceClass parent_class;
} GncLotClass;
#define GNCLotClass GncLotClass
/* --- type macros --- */
#define GNC_TYPE_LOT (gnc_lot_get_type ())
@ -114,6 +120,7 @@ gint gnc_lot_count_splits (const GNCLot *);
* this lot is associated. */
/*@ dependent @*/
Account * gnc_lot_get_account (const GNCLot *);
void gnc_lot_set_account(GNCLot*, Account*);
/** The gnc_lot_get_balance() routine returns the balance of the lot.
* The commodity in which this balance is expressed is the commodity
@ -148,6 +155,11 @@ Split * gnc_lot_get_earliest_split (GNCLot *lot);
*/
Split * gnc_lot_get_latest_split (GNCLot *lot);
unsigned char gnc_lot_get_marker(const GNCLot*);
void gnc_lot_set_marker(GNCLot*, unsigned char);
void gnc_lot_set_closed_unknown(GNCLot*);
/** Get and set the account title, or the account notes. */
const char * gnc_lot_get_title (const GNCLot *);
const char * gnc_lot_get_notes (const GNCLot *);

View File

@ -56,8 +56,11 @@ DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
Split *osplit;
Transaction *otrans;
Timespec open_ts;
Account* lot_account;
if (!pcy || !lot || !lot->account || !lot->splits) return NULL;
if (!pcy || !lot || !gnc_lot_get_split_list(lot)) return NULL;
lot_account = gnc_lot_get_account(lot);
if (!lot_account) return NULL;
/* Recomputing the balance re-evaluates the lot closure */
baln = gnc_lot_get_balance (lot);
@ -66,7 +69,7 @@ DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
want_positive = gnc_numeric_negative_p (baln);
/* All splits in lot must share a common transaction currency. */
split = lot->splits->data;
split = gnc_lot_get_split_list(lot)->data;
common_currency = split->parent->common_currency;
/* Don't add a split to the lot unless it will be the new last
@ -80,7 +83,7 @@ DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
* hasn't been assigned to a lot. Return that split.
* Make use of the fact that the splits in an account are
* already in date order; so we don't have to sort. */
node = xaccAccountGetSplitList (lot->account);
node = xaccAccountGetSplitList (lot_account);
if (reverse)
{
node = g_list_last (node);