merge first round of entity rework back into head branch

The net total of this work is (i beleive) fewer lines of code.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9530 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2003-10-17 04:25:53 +00:00
parent aaf73968e1
commit c90c817e64
49 changed files with 1812 additions and 2375 deletions

View File

@ -52,6 +52,7 @@
#include "qofbook-p.h"
#include "qofclass.h"
#include "qofid-p.h"
#include "qofinstance-p.h"
#include "qofobject.h"
static short module = MOD_ACCOUNT;
@ -69,22 +70,12 @@ static void xaccAccountBringUpToDate (Account *);
/********************************************************************\
\********************************************************************/
G_INLINE_FUNC void account_event (Account *account);
G_INLINE_FUNC void
account_event (Account *account)
{
gnc_engine_gen_event (&account->inst.entity, GNC_EVENT_MODIFY);
}
G_INLINE_FUNC void mark_account (Account *account);
G_INLINE_FUNC void
mark_account (Account *account)
{
if (account->parent)
account->parent->saved = FALSE;
account_event (account);
if (account->parent) account->parent->saved = FALSE;
account->inst.dirty = TRUE;
}
/********************************************************************\
@ -335,16 +326,27 @@ xaccFreeAccount (Account *acc)
void
xaccAccountBeginEdit (Account *acc)
{
GNC_BEGIN_EDIT (&acc->inst, GNC_ID_ACCOUNT);
GNC_BEGIN_EDIT (&acc->inst);
}
static inline void noop(QofInstance *inst) {}
static inline void on_err (QofInstance *inst, QofBackendError errcode)
{
PERR("commit error: %d", errcode);
}
static inline void acc_free (QofInstance *inst)
{
Account *acc = (Account *) inst;
xaccGroupRemoveAccount(acc->parent, acc);
xaccFreeAccount(acc);
}
void
xaccAccountCommitEdit (Account *acc)
{
QofBackend * be;
GNC_COMMIT_EDIT_PART1 (&acc->inst);
ENTER (" ");
/* If marked for deletion, get rid of subaccounts first,
* and then the splits ... */
@ -391,39 +393,9 @@ xaccAccountCommitEdit (Account *acc)
xaccGroupInsertAccount(acc->parent, acc);
}
/* See if there's a backend. If there is, invoke it. */
be = acc->inst.book->backend;
if (be && be->commit)
{
QofBackendError errcode;
GNC_COMMIT_EDIT_PART2 (&acc->inst, on_err, noop, acc_free);
/* clear errors */
do {
errcode = qof_backend_get_error (be);
} while (ERR_BACKEND_NO_ERR != errcode);
(be->commit) (be, GNC_ID_ACCOUNT, acc);
errcode = qof_backend_get_error (be);
if (ERR_BACKEND_NO_ERR != errcode)
{
/* Destroys must be rolled back as well ... */
acc->inst.do_free = FALSE;
/* XXX hack alert FIXME implement account rollback */
PERR ("Backend asked engine to rollback, but this isn't"
" handled yet. Return code=%d", errcode);
}
}
acc->inst.dirty = FALSE;
/* final stages of freeing the account */
if (acc->inst.do_free)
{
xaccGroupRemoveAccount(acc->parent, acc);
xaccFreeAccount(acc);
}
LEAVE (" ");
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY);
}
void
@ -435,7 +407,6 @@ xaccAccountDestroy (Account *acc)
xaccAccountCommitEdit (acc);
}
void
xaccAccountSetVersion (Account *acc, gint32 vers)
{
@ -450,13 +421,6 @@ xaccAccountGetVersion (Account *acc)
return (acc->version);
}
QofBook *
xaccAccountGetBook (Account *account)
{
if (!account) return NULL;
return account->inst.book;
}
/********************************************************************\
\********************************************************************/
@ -705,56 +669,6 @@ xaccAccountBringUpToDate(Account *acc)
xaccAccountRecomputeBalance(acc);
}
/********************************************************************
* xaccAccountGetSlots
********************************************************************/
KvpFrame *
xaccAccountGetSlots(Account * account)
{
if (!account) return NULL;
return(account->inst.kvp_data);
}
void
xaccAccountSetSlots_nc(Account *account, KvpFrame *frame)
{
if (!account) return;
xaccAccountBeginEdit (account);
if (account->inst.kvp_data && frame != account->inst.kvp_data)
{
kvp_frame_delete (account->inst.kvp_data);
}
account->inst.kvp_data = frame;
account->inst.dirty = TRUE;
mark_account (account);
xaccAccountCommitEdit (account);
}
/********************************************************************\
\********************************************************************/
const GUID *
xaccAccountGetGUID (Account *account)
{
if (!account)
return guid_null();
return &account->inst.entity.guid;
}
GUID
xaccAccountReturnGUID (Account *account)
{
if (!account)
return *guid_null();
return account->inst.entity.guid;
}
/********************************************************************\
\********************************************************************/
@ -777,17 +691,10 @@ xaccAccountSetGUID (Account *account, const GUID *guid)
Account *
xaccAccountLookup (const GUID *guid, QofBook *book)
{
QofCollection *col;
if (!guid || !book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book),
guid, GNC_ID_ACCOUNT);
}
Account *
xaccAccountLookupDirect (GUID guid, QofBook *book)
{
if (!book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book),
&guid, GNC_ID_ACCOUNT);
col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
return (Account *) qof_collection_lookup_entity (col, guid);
}
/********************************************************************\
@ -1044,7 +951,7 @@ xaccAccountRemoveSplit (Account *acc, Split *split)
mark_account (acc);
if (split->parent)
gnc_engine_generate_event (&split->parent->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
gnc_engine_gen_event (&split->parent->inst.entity, GNC_EVENT_MODIFY);
}
}
xaccAccountCommitEdit(acc);
@ -1131,7 +1038,7 @@ xaccAccountRecomputeBalance (Account * acc)
acc->reconciled_balance = reconciled_balance;
acc->balance_dirty = FALSE;
account_event (acc);
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY);
}
/********************************************************************\
@ -2903,33 +2810,32 @@ xaccAccountFindTransByDesc(Account *account, const char *description)
/* gncObject function implementation and registration */
static void
account_foreach (QofBook *book, QofEntityForeachCB cb, gpointer ud)
account_foreach (QofBook *book, QofForeachCB cb, gpointer ud)
{
QofEntityTable *et;
QofCollection *col;
g_return_if_fail (book);
g_return_if_fail (cb);
et = qof_book_get_entity_table (book);
qof_entity_foreach (et, GNC_ID_ACCOUNT, cb, ud);
col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
qof_collection_foreach (col, (QofEntityForeachCB) cb, ud);
}
static QofObject account_object_def = {
QOF_OBJECT_VERSION,
GNC_ID_ACCOUNT,
"Account",
NULL, /* book_begin */
NULL, /* book_end */
NULL, /* is_dirty */
NULL, /* mark_clean */
account_foreach, /* foreach */
(const char* (*)(gpointer)) xaccAccountGetName /* printable */
interface_version: QOF_OBJECT_VERSION,
e_type: GNC_ID_ACCOUNT,
type_label: "Account",
book_begin: NULL,
book_end: NULL,
is_dirty: NULL,
mark_clean: NULL,
foreach: account_foreach,
printable: (const char* (*)(gpointer)) xaccAccountGetName
};
gboolean xaccAccountRegister (void)
{
static QofParam params[] = {
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccAccountGetSlots, NULL },
{ ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, NULL },
{ ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, NULL },
{ ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, NULL },
@ -2942,6 +2848,7 @@ gboolean xaccAccountRegister (void)
{ ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, NULL },
{ QOF_QUERY_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_guid, NULL },
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
{ NULL },
};

View File

@ -158,21 +158,16 @@ int xaccAccountOrder (Account **account_1, Account **account_2);
/** @name Account lookup and GUID routines */
/** @{ */
/** The xaccAccountGetGUID() subroutine will return the
* globally unique id associated with that account. */
const GUID * xaccAccountGetGUID (Account *account);
/** The xaccAccountReturnGUID() subroutine returns the
* same GUID as xaccAccountGetGUID, but as a struct. */
GUID xaccAccountReturnGUID (Account *account);
/** deprecated */
#define xaccAccountGetBook(X) qof_instance_get_book(QOF_INSTANCE(X))
#define xaccAccountGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
#define xaccAccountReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
/** The xaccAccountLookup() subroutine will return the
* account associated with the given id, or NULL
* if there is no such account. */
Account * xaccAccountLookup (const GUID *guid, QofBook *book);
/** xaccAccountLookupDirect performs the same function as
* xaccAccountLookup but takes a GUID struct directly. */
Account * xaccAccountLookupDirect (GUID guid, QofBook *book);
#define xaccAccountLookupDirect(g,b) xaccAccountLookup(&(g),b)
/** @} */
@ -181,8 +176,6 @@ Account * xaccAccountLookupDirect (GUID guid, QofBook *book);
/** @name Account general setters/getters */
/** @{ */
/** @return The book where the account is stored */
QofBook * xaccAccountGetBook (Account *account);
/** Set the account's type */
void xaccAccountSetType (Account *account, GNCAccountType);
@ -409,15 +402,11 @@ gboolean xaccAccountGetReconcileChildrenStatus(Account *account);
* Returns false if either one is NULL.
*/
gboolean xaccAccountHasAncestor (Account *account, Account *ancestor);
#define xaccAccountGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
/** @} */
/* ------------------ */
/** @name Account KvpFrame getters/setters */
/** @{ */
KvpFrame * xaccAccountGetSlots (Account *account);
void xaccAccountSetSlots_nc(Account *account, KvpFrame *frame);
/** @} */
/* ------------------ */
@ -571,8 +560,6 @@ LotList * xaccAccountFindOpenLots (Account *acc,
gpointer user_data, GCompareFunc sort_func);
/*@}*/
/* ------------------ */
/** @name Account Reconciliation information getters/setters */

View File

@ -52,6 +52,7 @@
#include "qofbook.h"
#include "qofid.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
/** STRUCTS *********************************************************/
@ -201,4 +202,9 @@ gint32 xaccAccountGetVersion (Account*);
/* Register Accounts with the engine */
gboolean xaccAccountRegister (void);
/** killed for now, need to resurect this or something similar
* * for transactional/dirty kvp. Later. Right now a place holder
* */
#define xaccAccountSetSlots_nc(A,S) qof_instance_set_slots(QOF_INSTANCE(A),S)
#endif /* XACC_ACCOUNT_P_H */

File diff suppressed because it is too large Load Diff

View File

@ -52,14 +52,17 @@ Currently the only files which include this file are:
*
* This still needs to deal with:
* . exceptions
* . 13 periods: (4 weeks/period 4x13=52 weeks/year)
* . yearly 360/365?
* . re-based frequencies [based around a non-standard [read:
* not-Jan-1-based/fiscal] year]
* . "business days" -- m-f sans holidays [per-user list thereof]
**/
struct gncp_freq_spec {
struct gncp_freq_spec
{
QofEntity entity;
FreqType type;
UIFreqType uift;
UIFreqType uift;
union u {
struct {
/** The date on which the single event occurs. */
@ -107,8 +110,6 @@ struct gncp_freq_spec {
GList *subSpecs;
} composites;
} s;
GUID guid;
QofEntityTable *entity_table;
};
#endif /* XACC_FREQSPECP_H */

View File

@ -6,8 +6,7 @@
* QofIdType xaccGUIDType (const GUID * guid, QofBook *book);
*/
#define xaccGUIDType(guid,book) \
qof_entity_type (qof_book_get_entity_table (book), (guid))
#define xaccGUIDType(obj) (QOF_INSTANCE(obj)->e_type)
/* Equivalent function prototype:
* void xaccGUIDNew (GUID *guid, QofBook *book)

View File

@ -731,6 +731,7 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
/* switch over between books, if needed */
if (grp->book != acc->inst.book)
{
QofCollection *col;
// xxxxxxxxxxxxxxxxxxxxxxx
/* hack alert -- this implementation is not exactly correct.
* If the entity tables are not identical, then the 'from' book
@ -746,9 +747,8 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
PWARN ("reparenting accounts accross books is not correctly supported\n");
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_DESTROY);
qof_entity_release (&acc->inst.entity);
qof_entity_store (grp->book->entity_table, acc, &acc->inst.entity.guid, GNC_ID_ACCOUNT);
col = qof_book_get_collection (grp->book, GNC_ID_ACCOUNT);
qof_collection_insert_entity (col, &acc->inst.entity);
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_CREATE);
}
}
@ -1243,7 +1243,7 @@ group_mark_clean(QofBook *book)
static QofObject group_object_def =
{
interface_version: QOF_OBJECT_VERSION,
name: GNC_ID_GROUP,
e_type: GNC_ID_GROUP,
type_label: "AccountGroup",
book_begin: group_book_begin,
book_end: group_book_end,

View File

@ -130,6 +130,7 @@ noinst_HEADERS = \
qofbook-p.h \
qofclass-p.h \
qofid-p.h \
qofinstance-p.h \
qofobject-p.h \
qofquery-p.h \
qofquerycore-p.h \

View File

@ -72,13 +72,14 @@ xaccAccountLookupTwin (Account *acc, QofBook *book)
void
gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
{
QofCollection *col;
Transaction *newtrans;
GList *node;
if (!trans || !book) return;
/* If this is the same book, its a no-op. */
if (trans->book == book) return;
if (trans->inst.book == book) return;
ENTER ("trans=%p %s", trans, trans->description);
newtrans = xaccDupeTransaction (trans);
@ -93,10 +94,12 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
xaccTransDestroy (trans);
xaccTransCommitEdit (trans);
/* fiddle the transaction into place in the new book */
qof_entity_store(book->entity_table, newtrans, &newtrans->guid, GNC_ID_TRANS);
newtrans->book = book;
/* Fiddle the transaction into place in the new book */
col = qof_book_get_collection (book, GNC_ID_TRANS);
qof_collection_insert_entity (col, &newtrans->inst.entity);
newtrans->inst.book = book;
col = qof_book_get_collection (book, GNC_ID_SPLIT);
xaccTransBeginEdit (newtrans);
for (node = newtrans->splits; node; node = node->next)
{
@ -105,7 +108,7 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
/* move the split into the new book ... */
s->book = book;
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
qof_collection_insert_entity(col, &s->entity);
/* find the twin account, and re-parent to that. */
twin = xaccAccountLookupTwin (s->acc, book);
@ -122,7 +125,7 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
}
xaccTransCommitEdit (newtrans);
gnc_engine_generate_event (&newtrans->guid, GNC_ID_TRANS, GNC_EVENT_CREATE);
gnc_engine_gen_event (&newtrans->inst.entity, GNC_EVENT_CREATE);
LEAVE ("trans=%p %s", trans, trans->description);
}
@ -134,16 +137,17 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
void
gnc_book_insert_trans (QofBook *book, Transaction *trans)
{
QofCollection *col;
GList *node;
if (!trans || !book) return;
/* If this is the same book, its a no-op. */
if (trans->book == book) return;
if (trans->inst.book == book) return;
/* If the old and new book don't share backends, then clobber-copy;
* i.e. destroy it in one backend, create it in another. */
if (book->backend != trans->book->backend)
if (book->backend != trans->inst.book->backend)
{
gnc_book_insert_trans_clobber (book, trans);
return;
@ -153,10 +157,11 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
/* Fiddle the transaction into place in the new book */
xaccTransBeginEdit (trans);
qof_entity_remove (trans->book->entity_table, &trans->guid);
trans->book = book;
qof_entity_store(book->entity_table, trans, &trans->guid, GNC_ID_TRANS);
col = qof_book_get_collection (book, GNC_ID_TRANS);
trans->inst.book = book;
qof_collection_insert_entity (col, &trans->inst.entity);
col = qof_book_get_collection (book, GNC_ID_SPLIT);
for (node = trans->splits; node; node = node->next)
{
Account *twin;
@ -165,9 +170,8 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
/* Move the splits over (only if they haven't already been moved). */
if (s->book != book)
{
qof_entity_remove (s->book->entity_table, &s->guid);
s->book = book;
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
qof_collection_insert_entity (col, &s->entity);
}
/* Find the twin account, and re-parent to that. */
@ -189,7 +193,7 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
}
xaccTransCommitEdit (trans);
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
gnc_engine_gen_event (&trans->inst.entity, GNC_EVENT_MODIFY);
LEAVE ("trans=%p %s", trans, trans->description);
}
@ -212,6 +216,7 @@ gnc_book_insert_lot_clobber (QofBook *book, GNCLot *lot)
void
gnc_book_insert_lot (QofBook *book, GNCLot *lot)
{
QofCollection *col;
SplitList *snode;
Account *twin;
if (!lot || !book) return;
@ -225,19 +230,20 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
return;
}
ENTER ("lot=%p", lot);
qof_entity_remove (lot->book->entity_table, &lot->guid);
col = qof_book_get_collection (book, GNC_ID_LOT);
lot->book = book;
qof_entity_store(book->entity_table, lot, &lot->guid, GNC_ID_LOT);
qof_collection_insert_entity (col, &lot->entity);
/* 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)
{
Split *s = snode->data;
if (s->book != book)
{
qof_entity_remove (s->book->entity_table, &s->guid);
s->book = book;
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
qof_collection_insert_entity (col, &s->entity);
}
}
@ -258,14 +264,15 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
void
gnc_book_insert_price (QofBook *book, GNCPrice *pr)
{
QofCollection *col;
if (!pr || !book) return;
/* If this is the same book, its a no-op. */
if (pr->book == book) return;
if (pr->inst.book == book) return;
/* If the old and new book don't share backends, then clobber-copy;
* i.e. destroy it in one backend, create it in another. */
if (book->backend != pr->book->backend)
if (book->backend != pr->inst.book->backend)
{
gnc_book_insert_price_clobber (book, pr);
return;
@ -276,9 +283,9 @@ gnc_book_insert_price (QofBook *book, GNCPrice *pr)
gnc_price_ref (pr);
gnc_price_begin_edit (pr);
qof_entity_remove (pr->book->entity_table, &pr->guid);
pr->book = book;
qof_entity_store(book->entity_table, pr, &pr->guid, GNC_ID_PRICE);
col = qof_book_get_collection (book, GNC_ID_PRICE);
pr->inst.book = book;
qof_collection_insert_entity (col, &pr->inst.entity);
gnc_pricedb_remove_price (pr->db, pr);
gnc_pricedb_add_price (gnc_pricedb_get_db (book), pr);
@ -592,10 +599,10 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query)
/* Make note of the sibling books */
now = time(0);
gnc_kvp_bag_add (src_book->kvp_data, "gemini", now,
"book_guid", &dest_book->guid,
"book_guid", &dest_book->entity.guid,
NULL);
gnc_kvp_bag_add (dest_book->kvp_data, "gemini", now,
"book_guid", &src_book->guid,
"book_guid", &src_book->entity.guid,
NULL);
LEAVE (" ");
}
@ -686,7 +693,7 @@ add_closing_balances (AccountGroup *closed_grp,
xaccAccountBeginEdit (twin);
cwd = xaccAccountGetSlots (twin);
kvp_frame_set_guid (cwd, "/book/prev-acct", xaccAccountGetGUID (candidate));
kvp_frame_set_guid (cwd, "/book/prev-book", &closed_book->guid);
kvp_frame_set_guid (cwd, "/book/prev-book", &closed_book->entity.guid);
xaccAccountSetSlots_nc (twin, twin->inst.kvp_data);
@ -695,7 +702,7 @@ add_closing_balances (AccountGroup *closed_grp,
* the next book is. */
xaccAccountBeginEdit (candidate);
cwd = xaccAccountGetSlots (candidate);
kvp_frame_set_guid (cwd, "/book/next-book", &open_book->guid);
kvp_frame_set_guid (cwd, "/book/next-book", &open_book->entity.guid);
kvp_frame_set_guid (cwd, "/book/next-acct", xaccAccountGetGUID (twin));
xaccAccountSetSlots_nc (candidate, candidate->inst.kvp_data);
@ -753,7 +760,7 @@ add_closing_balances (AccountGroup *closed_grp,
/* Add KVP data showing where the balancing
* transaction came from */
cwd = xaccTransGetSlots (trans);
kvp_frame_set_guid (cwd, "/book/closed-book", &closed_book->guid);
kvp_frame_set_guid (cwd, "/book/closed-book", &closed_book->entity.guid);
kvp_frame_set_guid (cwd, "/book/closed-acct", xaccAccountGetGUID(candidate));
xaccTransCommitEdit (trans);
@ -876,8 +883,8 @@ gnc_book_close_period (QofBook *existing_book, Timespec calve_date,
kvp_frame_set_timespec (partn_cwd, "/book/log-date", ts);
/* Set up pointers to each book from the other. */
kvp_frame_set_guid (partn_cwd, "/book/next-book", &existing_book->guid);
kvp_frame_set_guid (exist_cwd, "/book/prev-book", &closing_book->guid);
kvp_frame_set_guid (partn_cwd, "/book/next-book", &existing_book->entity.guid);
kvp_frame_set_guid (exist_cwd, "/book/prev-book", &closing_book->entity.guid);
/* add in transactions to equity accounts that will
* hold the colsing balances */

View File

@ -45,8 +45,11 @@
#include "SchedXaction.h"
#include "SX-book.h"
#include "SX-book-p.h"
#include "qofbook.h"
#include "qofbook-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
#include "qofobject.h"
static short module = MOD_SX;
@ -158,7 +161,7 @@ static void
mark_sx_clean(gpointer data, gpointer user_data)
{
SchedXaction *sx = (SchedXaction *) data;
xaccSchedXactionSetDirtyness(sx, FALSE);
qof_instance_mark_clean (QOF_INSTANCE(sx));
}
static void
@ -208,7 +211,7 @@ sxtt_mark_clean(QofBook *book)
static QofObject sxtt_object_def =
{
interface_version: QOF_OBJECT_VERSION,
name: GNC_ID_SXTT,
e_type: GNC_ID_SXTT,
type_label: "SXTT",
book_begin: sxtt_book_begin,
book_end: sxtt_book_end,

View File

@ -55,30 +55,25 @@ xaccSchedXactionInit( SchedXaction *sx, QofBook *book)
{
AccountGroup *ag;
sx->entity_table = qof_book_get_entity_table (book);
qof_instance_init (&sx->inst, GNC_ID_SCHEDXACTION, book);
sx->freq = xaccFreqSpecMalloc(book);
qof_entity_guid_new (sx->entity_table, &sx->guid);
qof_entity_store( sx->entity_table, sx,
&sx->guid, GNC_ID_SCHEDXACTION );
g_date_clear( &sx->last_date, 1 );
g_date_clear( &sx->start_date, 1 );
g_date_clear( &sx->end_date, 1 );
sx->num_occurances_total = 0;
sx->kvp_data = kvp_frame_new();
sx->autoCreateOption = FALSE;
sx->autoCreateNotify = FALSE;
sx->advanceCreateDays = 0;
sx->advanceRemindDays = 0;
sx->instance_num = 0;
sx->dirty = TRUE;
sx->deferredList = NULL;
/* create a new template account for our splits */
sx->template_acct = xaccMallocAccount(book);
xaccAccountSetName( sx->template_acct, guid_to_string( &sx->guid ));
xaccAccountSetName( sx->template_acct, guid_to_string( &sx->inst.entity.guid ));
xaccAccountSetCommodity
(sx->template_acct,
gnc_commodity_new( "template", "template",
@ -97,7 +92,7 @@ xaccSchedXactionMalloc(QofBook *book)
sx = g_new0( SchedXaction, 1 );
xaccSchedXactionInit( sx, book );
gnc_engine_generate_event( &sx->guid, GNC_ID_SCHEDXACTION, GNC_EVENT_CREATE );
gnc_engine_gen_event( &sx->inst.entity, GNC_EVENT_CREATE );
return sx;
}
@ -133,13 +128,13 @@ delete_template_trans(SchedXaction *sx)
if(! (g_list_find(templ_acct_transactions, split_trans)))
{
templ_acct_transactions
= g_list_prepend(templ_acct_transactions, split_trans);
= g_list_prepend(templ_acct_transactions, split_trans);
}
}
g_list_foreach(templ_acct_transactions,
sxprivTransMapDelete,
NULL);
sxprivTransMapDelete,
NULL);
return;
}
@ -151,8 +146,7 @@ xaccSchedXactionFree( SchedXaction *sx )
if ( sx == NULL ) return;
xaccFreqSpecFree( sx->freq );
gnc_engine_generate_event( &sx->guid, GNC_ID_SCHEDXACTION, GNC_EVENT_DESTROY );
qof_entity_remove( sx->entity_table, &sx->guid );
gnc_engine_gen_event( &sx->inst.entity, GNC_EVENT_DESTROY );
if ( sx->name )
g_free( sx->name );
@ -181,29 +175,26 @@ xaccSchedXactionFree( SchedXaction *sx )
sx->deferredList = NULL;
}
qof_instance_release (&sx->inst);
g_free( sx );
return;
}
/* ============================================================ */
FreqSpec *
xaccSchedXactionGetFreqSpec( SchedXaction *sx )
{
return sx->freq;
return sx->freq;
}
void
xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
{
g_return_if_fail( fs );
g_return_if_fail( fs );
xaccFreqSpecFree( sx->freq );
sx->freq = fs;
sx->dirty = TRUE;
xaccFreqSpecFree( sx->freq );
sx->freq = fs;
sx->inst.dirty = TRUE;
}
gchar *
@ -220,7 +211,7 @@ xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName )
g_free( sx->name );
sx->name = NULL;
}
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
sx->name = g_strdup( newName );
}
@ -234,7 +225,7 @@ void
xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart )
{
sx->start_date = *newStart;
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
}
gboolean
@ -264,8 +255,7 @@ xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd )
}
sx->end_date = *newEnd;
sx->dirty = TRUE;
return;
sx->inst.dirty = TRUE;
}
GDate*
@ -278,8 +268,7 @@ void
xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur )
{
sx->last_date = *newLastOccur;
sx->dirty = TRUE;
return;
sx->inst.dirty = TRUE;
}
gboolean
@ -298,8 +287,7 @@ void
xaccSchedXactionSetNumOccur( SchedXaction *sx, gint newNum )
{
sx->num_occurances_remain = sx->num_occurances_total = newNum;
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
}
gint
@ -313,68 +301,35 @@ xaccSchedXactionSetRemOccur( SchedXaction *sx,
gint numRemain )
{
/* FIXME This condition can be tightened up */
if ( numRemain > sx->num_occurances_total ) {
if ( numRemain > sx->num_occurances_total )
{
PWARN("The number remaining is greater than the total occurrences");
}
else
{
sx->num_occurances_remain = numRemain;
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
}
return;
}
KvpValue *
xaccSchedXactionGetSlot( SchedXaction *sx, const char *slot )
{
if (!sx)
{
return NULL;
}
if (!sx) return NULL;
return kvp_frame_get_slot(sx->kvp_data, slot);
return kvp_frame_get_slot(sx->inst.kvp_data, slot);
}
void
xaccSchedXactionSetSlot( SchedXaction *sx,
const char *slot,
const KvpValue *value )
const char *slot,
const KvpValue *value )
{
if (!sx)
{
return;
}
if (!sx) return;
kvp_frame_set_slot( sx->kvp_data, slot, value );
sx->dirty = TRUE;
return;
}
KvpFrame*
xaccSchedXactionGetSlots( SchedXaction *sx )
{
return sx->kvp_data;
}
void
xaccSchedXactionSetSlots( SchedXaction *sx, KvpFrame *frm )
{
sx->kvp_data = frm;
sx->dirty = TRUE;
}
const GUID*
xaccSchedXactionGetGUID( SchedXaction *sx )
{
return &sx->guid;
}
void
xaccSchedXactionSetGUID( SchedXaction *sx, GUID g )
{
sx->guid = g;
sx->dirty = TRUE;
kvp_frame_set_slot( sx->inst.kvp_data, slot, value );
sx->inst.dirty = TRUE;
}
void
@ -395,7 +350,7 @@ xaccSchedXactionSetAutoCreate( SchedXaction *sx,
sx->autoCreateOption = newAutoCreate;
sx->autoCreateNotify = newNotify;
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
return;
}
@ -409,19 +364,19 @@ void
xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays )
{
sx->advanceCreateDays = createDays;
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
}
gint
xaccSchedXactionGetAdvanceReminder( SchedXaction *sx )
{
return sx->advanceRemindDays;
return sx->advanceRemindDays;
}
void
xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays )
{
sx->dirty = TRUE;
sx->inst.dirty = TRUE;
sx->advanceRemindDays = reminderDays;
}
@ -429,64 +384,64 @@ xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays )
GDate
xaccSchedXactionGetNextInstance( SchedXaction *sx, void *stateData )
{
GDate last_occur, next_occur, tmpDate;
GDate last_occur, next_occur, tmpDate;
g_date_clear( &last_occur, 1 );
g_date_clear( &next_occur, 1 );
g_date_clear( &tmpDate, 1 );
g_date_clear( &last_occur, 1 );
g_date_clear( &next_occur, 1 );
g_date_clear( &tmpDate, 1 );
if ( g_date_valid( &sx->last_date ) ) {
last_occur = sx->last_date;
}
if ( g_date_valid( &sx->last_date ) ) {
last_occur = sx->last_date;
}
if ( stateData != NULL ) {
temporalStateData *tsd = (temporalStateData*)stateData;
last_occur = tsd->last_date;
}
if ( stateData != NULL ) {
temporalStateData *tsd = (temporalStateData*)stateData;
last_occur = tsd->last_date;
}
if ( g_date_valid( &sx->start_date ) ) {
if ( g_date_valid(&last_occur) ) {
last_occur =
( g_date_compare( &last_occur,
&sx->start_date ) > 0 ?
last_occur : sx->start_date );
} else {
/* Think about this for a second, and you realize that if the
* start date is _today_, we need a last-occur date such that
* the 'next instance' is after that date, and equal to the
* start date... one day should be good.
*
* This only holds for the first instance [read: if the
* last[-occur]_date is invalid] */
last_occur = sx->start_date;
g_date_subtract_days( &last_occur, 1 );
}
}
if ( g_date_valid( &sx->start_date ) ) {
if ( g_date_valid(&last_occur) ) {
last_occur =
( g_date_compare( &last_occur,
&sx->start_date ) > 0 ?
last_occur : sx->start_date );
} else {
/* Think about this for a second, and you realize that if the
* start date is _today_, we need a last-occur date such that
* the 'next instance' is after that date, and equal to the
* start date... one day should be good.
*
* This only holds for the first instance [read: if the
* last[-occur]_date is invalid] */
last_occur = sx->start_date;
g_date_subtract_days( &last_occur, 1 );
}
}
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
/* out-of-bounds check */
if ( xaccSchedXactionHasEndDate( sx ) ) {
GDate *end_date = xaccSchedXactionGetEndDate( sx );
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
PINFO( "next_occur past end date" );
g_date_clear( &next_occur, 1 );
}
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
if ( stateData ) {
temporalStateData *tsd = (temporalStateData*)stateData;
if ( tsd->num_occur_rem == 0 ) {
PINFO( "no more occurances remain" );
g_date_clear( &next_occur, 1 );
}
} else {
if ( sx->num_occurances_remain == 0 ) {
g_date_clear( &next_occur, 1 );
}
}
}
/* out-of-bounds check */
if ( xaccSchedXactionHasEndDate( sx ) ) {
GDate *end_date = xaccSchedXactionGetEndDate( sx );
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
PINFO( "next_occur past end date" );
g_date_clear( &next_occur, 1 );
}
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
if ( stateData ) {
temporalStateData *tsd = (temporalStateData*)stateData;
if ( tsd->num_occur_rem == 0 ) {
PINFO( "no more occurances remain" );
g_date_clear( &next_occur, 1 );
}
} else {
if ( sx->num_occurances_remain == 0 ) {
g_date_clear( &next_occur, 1 );
}
}
}
return next_occur;
return next_occur;
}
GDate
@ -494,46 +449,46 @@ xaccSchedXactionGetInstanceAfter( SchedXaction *sx,
GDate *date,
void *stateData )
{
GDate prev_occur, next_occur;
GDate prev_occur, next_occur;
g_date_clear( &prev_occur, 1 );
if ( date ) {
prev_occur = *date;
}
g_date_clear( &prev_occur, 1 );
if ( date ) {
prev_occur = *date;
}
if ( stateData != NULL ) {
temporalStateData *tsd = (temporalStateData*)stateData;
prev_occur = tsd->last_date;
}
if ( stateData != NULL ) {
temporalStateData *tsd = (temporalStateData*)stateData;
prev_occur = tsd->last_date;
}
if ( ! g_date_valid( &prev_occur ) ) {
/* We must be at the beginning. */
prev_occur = sx->start_date;
g_date_subtract_days( &prev_occur, 1 );
}
if ( ! g_date_valid( &prev_occur ) ) {
/* We must be at the beginning. */
prev_occur = sx->start_date;
g_date_subtract_days( &prev_occur, 1 );
}
xaccFreqSpecGetNextInstance( sx->freq, &prev_occur, &next_occur );
xaccFreqSpecGetNextInstance( sx->freq, &prev_occur, &next_occur );
if ( xaccSchedXactionHasEndDate( sx ) ) {
GDate *end_date;
if ( xaccSchedXactionHasEndDate( sx ) ) {
GDate *end_date;
end_date = xaccSchedXactionGetEndDate( sx );
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
g_date_clear( &next_occur, 1 );
}
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
if ( stateData ) {
temporalStateData *tsd = (temporalStateData*)stateData;
if ( tsd->num_occur_rem == 0 ) {
g_date_clear( &next_occur, 1 );
}
} else {
if ( sx->num_occurances_remain == 0 ) {
g_date_clear( &next_occur, 1 );
}
}
}
return next_occur;
end_date = xaccSchedXactionGetEndDate( sx );
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
g_date_clear( &next_occur, 1 );
}
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
if ( stateData ) {
temporalStateData *tsd = (temporalStateData*)stateData;
if ( tsd->num_occur_rem == 0 ) {
g_date_clear( &next_occur, 1 );
}
} else {
if ( sx->num_occurances_remain == 0 ) {
g_date_clear( &next_occur, 1 );
}
}
}
return next_occur;
}
gint
@ -566,23 +521,9 @@ xaccSchedXactionGetSplits( SchedXaction *sx )
return xaccAccountGetSplitList(sx->template_acct);
}
void
xaccSchedXactionSetDirtyness( SchedXaction *sx, gboolean dirty_p)
{
sx->dirty = dirty_p;
return;
}
gboolean
xaccSchedXactionIsDirty(SchedXaction *sx)
{
return sx->dirty;
}
static Split *
pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
Transaction *parent_trans, QofBook *book)
Transaction *parent_trans, QofBook *book)
{
Split *split;
KvpFrame *split_frame;
@ -592,14 +533,14 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
split = xaccMallocSplit(book);
xaccSplitSetMemo(split,
gnc_ttsplitinfo_get_memo(s_info));
gnc_ttsplitinfo_get_memo(s_info));
xaccSplitSetAction(split,
gnc_ttsplitinfo_get_action(s_info));
gnc_ttsplitinfo_get_action(s_info));
xaccAccountInsertSplit(parent_acct,
split);
split);
split_frame = xaccSplitGetSlots(split);
@ -607,20 +548,20 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
= kvp_value_new_string(gnc_ttsplitinfo_get_credit_formula(s_info));
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
tmp_value,
GNC_SX_ID,
GNC_SX_CREDIT_FORMULA,
NULL);
kvp_value_delete(tmp_value);
tmp_value
= kvp_value_new_string(gnc_ttsplitinfo_get_debit_formula(s_info));
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
tmp_value,
GNC_SX_ID,
GNC_SX_DEBIT_FORMULA,
NULL);
kvp_value_delete(tmp_value);
@ -629,10 +570,10 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
tmp_value = kvp_value_new_guid(acc_guid);
kvp_frame_set_slot_path(split_frame,
tmp_value,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
tmp_value,
GNC_SX_ID,
GNC_SX_ACCOUNT,
NULL);
kvp_value_delete(tmp_value);
@ -642,7 +583,7 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
void
xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
QofBook *book)
QofBook *book)
{
Transaction *new_trans;
TTInfo *tti;
@ -664,20 +605,20 @@ xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
xaccTransBeginEdit(new_trans);
xaccTransSetDescription(new_trans,
gnc_ttinfo_get_description(tti));
gnc_ttinfo_get_description(tti));
xaccTransSetNum(new_trans,
gnc_ttinfo_get_num(tti));
gnc_ttinfo_get_num(tti));
xaccTransSetCurrency( new_trans,
gnc_ttinfo_get_currency(tti) );
gnc_ttinfo_get_currency(tti) );
for(split_list = gnc_ttinfo_get_template_splits(tti);
split_list;
split_list = split_list->next)
split_list;
split_list = split_list->next)
{
s_info = split_list->data;
new_split = pack_split_info(s_info, sx->template_acct,
new_trans, book);
new_trans, book);
xaccTransAppendSplit(new_trans, new_split);
}
xaccTransCommitEdit(new_trans);
@ -687,72 +628,72 @@ xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
void*
gnc_sx_create_temporal_state( SchedXaction *sx )
{
temporalStateData *toRet =
g_new0( temporalStateData, 1 );
toRet->last_date = sx->last_date;
toRet->num_occur_rem = sx->num_occurances_remain;
toRet->num_inst = sx->instance_num;
return (void*)toRet;
temporalStateData *toRet =
g_new0( temporalStateData, 1 );
toRet->last_date = sx->last_date;
toRet->num_occur_rem = sx->num_occurances_remain;
toRet->num_inst = sx->instance_num;
return (void*)toRet;
}
void
gnc_sx_incr_temporal_state( SchedXaction *sx, void *stateData )
{
GDate unused;
temporalStateData *tsd = (temporalStateData*)stateData;
GDate unused;
temporalStateData *tsd = (temporalStateData*)stateData;
g_date_clear( &unused, 1 );
tsd->last_date =
xaccSchedXactionGetInstanceAfter( sx,
&unused,
stateData );
if ( xaccSchedXactionHasOccurDef( sx ) ) {
tsd->num_occur_rem -= 1;
}
tsd->num_inst += 1;
g_date_clear( &unused, 1 );
tsd->last_date =
xaccSchedXactionGetInstanceAfter( sx,
&unused,
stateData );
if ( xaccSchedXactionHasOccurDef( sx ) ) {
tsd->num_occur_rem -= 1;
}
tsd->num_inst += 1;
}
void
gnc_sx_revert_to_temporal_state( SchedXaction *sx, void *stateData )
{
temporalStateData *tsd = (temporalStateData*)stateData;
sx->last_date = tsd->last_date;
sx->num_occurances_remain = tsd->num_occur_rem;
sx->instance_num = tsd->num_inst;
sx->dirty = TRUE;
temporalStateData *tsd = (temporalStateData*)stateData;
sx->last_date = tsd->last_date;
sx->num_occurances_remain = tsd->num_occur_rem;
sx->instance_num = tsd->num_inst;
sx->inst.dirty = TRUE;
}
void
gnc_sx_destroy_temporal_state( void *stateData )
{
g_free( (temporalStateData*)stateData );
g_free( (temporalStateData*)stateData );
}
void*
gnc_sx_clone_temporal_state( void *stateData )
{
temporalStateData *toRet, *tsd;
tsd = (temporalStateData*)stateData;
toRet = g_memdup( tsd, sizeof( temporalStateData ) );
return (void*)toRet;
temporalStateData *toRet, *tsd;
tsd = (temporalStateData*)stateData;
toRet = g_memdup( tsd, sizeof( temporalStateData ) );
return (void*)toRet;
}
static
gint
_temporal_state_data_cmp( gconstpointer a, gconstpointer b )
{
temporalStateData *tsd_a, *tsd_b;
tsd_a = (temporalStateData*)a;
tsd_b = (temporalStateData*)b;
temporalStateData *tsd_a, *tsd_b;
tsd_a = (temporalStateData*)a;
tsd_b = (temporalStateData*)b;
if ( !tsd_a && !tsd_b )
return 0;
if ( !tsd_a )
return 1;
if ( !tsd_b )
return -1;
return g_date_compare( &tsd_a->last_date,
&tsd_b->last_date );
if ( !tsd_a && !tsd_b )
return 0;
if ( !tsd_a )
return 1;
if ( !tsd_b )
return -1;
return g_date_compare( &tsd_a->last_date,
&tsd_b->last_date );
}
/**
@ -762,9 +703,9 @@ _temporal_state_data_cmp( gconstpointer a, gconstpointer b )
void
gnc_sx_add_defer_instance( SchedXaction *sx, void *deferStateData )
{
sx->deferredList = g_list_insert_sorted( sx->deferredList,
deferStateData,
_temporal_state_data_cmp );
sx->deferredList = g_list_insert_sorted( sx->deferredList,
deferStateData,
_temporal_state_data_cmp );
}
/**
@ -774,7 +715,7 @@ gnc_sx_add_defer_instance( SchedXaction *sx, void *deferStateData )
void
gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData )
{
sx->deferredList = g_list_remove( sx->deferredList, deferStateData );
sx->deferredList = g_list_remove( sx->deferredList, deferStateData );
}
/**
@ -786,6 +727,6 @@ gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData )
GList*
gnc_sx_get_defer_instances( SchedXaction *sx )
{
return sx->deferredList;
return sx->deferredList;
}

View File

@ -64,21 +64,6 @@ typedef struct gncp_SchedXaction SchedXaction;
**/
SchedXaction *xaccSchedXactionMalloc(QofBook *book);
/**
* @return True if the scheduled transaction is dirty and needs to
* be saved.
**/
gboolean xaccSchedXactionIsDirty(SchedXaction *sx);
/**
* Set dirtyness state. Only save/load code should modify this outside
* SX engine CODE . . .
* (set it to FALSE after backend completes reading in data
*
* FIXME: put this into a private header . . . .
**/
void xaccSchedXactionSetDirtyness(SchedXaction *sx, gboolean dirty_p);
/**
* Cleans up and frees a SchedXaction and it's associated data.
**/
@ -156,37 +141,6 @@ void xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays );
gint xaccSchedXactionGetAdvanceReminder( SchedXaction *sx );
void xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays );
/*
* The following function is slightly risky. If you change
* the retrieved KvpFrame you must mark the SchedXaction
* dirty with xaccSchedXactionSetDirtyness
*/
KvpFrame *xaccSchedXactionGetSlots( SchedXaction *sx );
/**
* Sets the SX kvp data to the given kvp_frame.
* NOTE: This is not copied, but set directly.
**/
void xaccSchedXactionSetSlots( SchedXaction *sx,
KvpFrame *frm );
/**
* Use the following two functions in preference to
* the above two . . .
*/
KvpValue *xaccSchedXactionGetSlot( SchedXaction *sx,
const char *slot );
/*
* This function copies value, so you don't have to
*/
void xaccSchedXactionSetSlot( SchedXaction *sx,
const char *slot,
const KvpValue *value );
const GUID *xaccSchedXactionGetGUID( SchedXaction *sx );
void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g );
///@{
/**
* Temporal state data.
@ -254,6 +208,19 @@ void gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData );
GList *gnc_sx_get_defer_instances( SchedXaction *sx );
/** deprecated routines */
#define xaccSchedXactionIsDirty(X) qof_instance_is_dirty (QOF_INSTANCE(X))
#define xaccSchedXactionGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
#define xaccSchedXactionGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
/** Deprecated, to be replaced with 'dirty' kvp's */
KvpValue *xaccSchedXactionGetSlot( SchedXaction *sx,
const char *slot );
void xaccSchedXactionSetSlot( SchedXaction *sx,
const char *slot,
const KvpValue *value );
#endif /* XACC_SCHEDXACTION_H */
/** @} */

View File

@ -26,6 +26,8 @@
#include "SchedXaction.h"
#include "qofid.h"
#include "qofid-p.h"
#include "qofinstance-p.h"
/**
* A single scheduled transaction.
@ -50,6 +52,7 @@
**/
struct gncp_SchedXaction
{
QofInstance inst;
gchar *name;
FreqSpec *freq;
@ -74,17 +77,10 @@ struct gncp_SchedXaction
gint advanceRemindDays;
Account *template_acct;
GUID guid;
QofEntityTable *entity_table;
/** The list of deferred SX instances. This list is of temporalStateData
* instances. */
GList /* <temporalStateData*> */ *deferredList;
/* Changed since last save? */
gboolean dirty;
KvpFrame *kvp_data;
};
/** Just the variable temporal bits from the SX structure. */
@ -94,4 +90,6 @@ typedef struct _temporalStateData {
gint num_inst;
} temporalStateData;
#endif
#define xaccSchedXactionSetGUID(X,G) qof_entity_set_guid(QOF_ENTITY(X),(G))
#endif /* XACC_SCHEDXACTION_P_H */

View File

@ -91,6 +91,7 @@ TransScrubOrphansFast (Transaction *trans, AccountGroup *root)
GList *node;
if (!trans) return;
g_return_if_fail (root);
for (node = trans->splits; node; node = node->next)
{
@ -373,7 +374,7 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
/* Put split into account before setting split value */
if (!balance_split)
{
balance_split = xaccMallocSplit (trans->book);
balance_split = xaccMallocSplit (trans->inst.book);
xaccAccountBeginEdit (account);
xaccAccountInsertSplit (account, balance_split);
@ -544,7 +545,7 @@ xaccTransScrubCurrency (Transaction *trans)
currency = xaccTransGetCurrency (trans);
if (currency) return;
currency = xaccTransFindOldCommonCurrency (trans, trans->book);
currency = xaccTransFindOldCommonCurrency (trans, trans->inst.book);
if (currency)
{
xaccTransBeginEdit (trans);

View File

@ -295,7 +295,7 @@ remove_guids (Split *sa, Split *sb)
/* Find and remove the matching guid's */
ksub = gnc_kvp_bag_find_by_guid (sa->kvp_data, "lot-split",
"peer_guid", &sb->guid);
"peer_guid", &sb->entity.guid);
if (ksub)
{
gnc_kvp_bag_remove_frame (sa->kvp_data, "lot-split", ksub);
@ -304,7 +304,7 @@ remove_guids (Split *sa, Split *sb)
/* Now do it in the other direction */
ksub = gnc_kvp_bag_find_by_guid (sb->kvp_data, "lot-split",
"peer_guid", &sa->guid);
"peer_guid", &sa->entity.guid);
if (ksub)
{
gnc_kvp_bag_remove_frame (sb->kvp_data, "lot-split", ksub);

File diff suppressed because it is too large Load Diff

View File

@ -36,6 +36,7 @@
#include "guid.h"
#include "kvp_frame.h"
#include "qofbook.h"
#include "qofinstance.h"
/** @name Split Reconciled field values
If you change these
@ -135,17 +136,18 @@ void xaccTransCommitEdit (Transaction *trans);
void xaccTransRollbackEdit (Transaction *trans);
/** The xaccTransIsOpen() method returns TRUE if the transaction
is open for editing. Otherwise, it returns false. */
is open for editing. Otherwise, it returns false.
XXX this routne should probably be deprecated. its, umm,
hard to imagine legitamate uses (but it is used by
the import/export code for reasons I can't understand.)
*/
gboolean xaccTransIsOpen (const Transaction *trans);
/** The xaccTransLookup() subroutine will return the
transaction associated with the given id, or NULL
if there is no such transaction. */
Transaction * xaccTransLookup (const GUID *guid, QofBook *book);
/** The xaccTransLookup() subroutine will return the
transaction associated with the given id, or NULL
if there is no such transaction. */
Transaction * xaccTransLookupDirect (GUID guid, QofBook *book);
#define xaccTransLookupDirect(g,b) xaccTransLookup(&(g),b)
/** \warning XXX FIXME
* gnc_book_count_transactions is a utility function,
@ -158,16 +160,6 @@ guint gnc_book_count_transactions(QofBook *book);
/** @name Transaction general getters/setters */
/**@{*/
/** The xaccTransGetGUID() subroutine will return the
globally unique id associated with that transaction. */
const GUID * xaccTransGetGUID (const Transaction *trans);
/** xaccTransReturnGUID() will returns a GUID struct
associated with that transaction. */
GUID xaccTransReturnGUID (const Transaction *trans);
/** Returns the book in which the transaction is stored */
QofBook * xaccTransGetBook (const Transaction *trans);
/** Sorts the splits in a transaction, putting the debits first,
* followed by the credits.
@ -178,17 +170,6 @@ void xaccTransSortSplits (Transaction *trans);
*/
void xaccTransDump (Transaction *trans, const char *tag);
/** Returns the transaction's KvpFrame slots.
*
Transaction slots are used to store arbitrary strings, numbers, and
structures which aren't members of the transaction struct. */
KvpFrame *xaccTransGetSlots(const Transaction *trans);
/** Set the KvpFrame slots of this transaction to the given frm by
* directly using the frm pointer (i.e. non-copying). */
void xaccTransSetSlots_nc(Transaction *t, KvpFrame *frm);
/** Set the Transaction Type
*
* See #define TXN_TYPE_NONE, TXN_TYPE_INVOICE and TXN_TYPE_PAYMENT */
@ -439,15 +420,6 @@ KvpFrame *xaccSplitGetSlots(const Split *split);
void xaccSplitSetSlots_nc(Split *s, KvpFrame *frm);
/** The xaccSplitGetGUID() subroutine will return the
* globally unique id associated with that split. */
const GUID * xaccSplitGetGUID (const Split *split);
/** xaccSplitReturnGUID also returns the guid (globally unique id),
* but in a GUID struct.*/
GUID xaccSplitReturnGUID (const Split *split);
/** The memo is an arbitrary string associated with a split. It is
* intended to hold a short (zero to forty character) string that is
* displayed by the GUI along with this split. Users typically type
@ -642,9 +614,7 @@ gboolean xaccSplitEqual(const Split *sa, const Split *sb,
* split associated with the given id, or NULL
* if there is no such split. */
Split * xaccSplitLookup (const GUID *guid, QofBook *book);
/** Returns the split associated with the given id, or NULL if there
* is no such split. */
Split * xaccSplitLookupDirect (GUID guid, QofBook *book);
#define xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
/**
@ -887,5 +857,13 @@ Timespec xaccTransGetVoidTime(const Transaction *tr);
#define RECONCILED_MATCH_TYPE "reconciled-match"
/** deprecated rouitines */
#define xaccSplitGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
#define xaccSplitReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
#define xaccTransGetBook(X) qof_instance_get_book (QOF_INSTANCE(X))
#define xaccTransGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
#define xaccTransReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
#define xaccTransGetSlots(X) qof_instance_get_slots (QOF_INSTANCE(X))
#endif /* XACC_TRANSACTION_H */
/** @} */

View File

@ -56,6 +56,9 @@
#include "qofbackend.h"
#include "qofbook.h"
#include "qofid.h"
#include "qofid-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
/** STRUCTS *********************************************************/
@ -90,7 +93,7 @@
struct split_s
{
GUID guid; /* globally unique id */
QofEntity entity; /* globally unique id */
QofBook *book; /* The enitity table where this split is stored. */
@ -160,12 +163,7 @@ struct split_s
struct transaction_s
{
/* guid is a globally unique identifier which can be used to
* reference the transaction.
*/
GUID guid;
QofBook *book; /* The entity_table where the transaction is stored */
QofInstance inst; /* glbally unique id */
Timespec date_entered; /* date register entry was made */
Timespec date_posted; /* date transaction was posted at bank */
@ -181,12 +179,6 @@ struct transaction_s
*/
char * description;
/* kvp_data is a key-value pair database for storing simple
* "extra" information in splits, transactions, and accounts.
* it's NULL until accessed. */
KvpFrame * kvp_data;
/* The common_currency field is the balancing common currency for
* all the splits in the transaction. Alternate, better(?) name:
* "valuation currency": it is the currency in which all of the
@ -207,9 +199,6 @@ struct transaction_s
* corresponding to the current traversal. */
unsigned char marker;
gint32 editlevel; /* nestcount of begin/end edit calls */
gboolean do_free; /* transaction in process of being destroyed */
/* The orig pointer points at a copy of the original transaction,
* before editing was started. This orig copy is used to rollback
* any changes made if/when the edit is abandoned.
@ -224,12 +213,12 @@ struct transaction_s
/* Set the transaction's GUID. This should only be done when reading
* a transaction from a datafile, or some other external source. Never
* call this on an existing transaction! */
void xaccTransSetGUID (Transaction *trans, const GUID *guid);
#define xaccTransSetGUID(t,g) qof_entity_set_guid(QOF_ENTITY(t),g)
/* Set the split's GUID. This should only be done when reading
* a split from a datafile, or some other external source. Never
* call this on an existing split! */
void xaccSplitSetGUID (Split *split, const GUID *guid);
#define xaccSplitSetGUID(s,g) qof_entity_set_guid(QOF_ENTITY(s),g)
/* The xaccFreeSplit() method simply frees all memory associated
* with the split. It does not verify that the split isn't
@ -302,6 +291,14 @@ void DxaccSplitSetSharePriceAndAmount (Split *split,
double amount);
void DxaccSplitSetShareAmount (Split *split, double amount);
/** Set the KvpFrame slots of this transaction to the given frm by
* * directly using the frm pointer (i.e. non-copying).
* * XXX this is wrong, nedds to be replaced with a transactional thingy
* in kvp + qofinstance. for now, this is a quasi-unctional placeholder.
* */
#define xaccTransSetSlots_nc(T,F) qof_instance_set_slots(QOF_INSTANCE(T),F)
/*@}*/

View File

@ -574,8 +574,8 @@ xaccSplitGetCapGainsSplit (Split *split)
gains_guid = kvp_value_get_guid (val);
if (!gains_guid) return NULL;
gains_split = qof_entity_lookup (qof_book_get_entity_table(split->book),
gains_guid, GNC_ID_SPLIT);
/* Both splits will be in the same collection, so seearch there. */
gains_split = (Split*) qof_collection_lookup_entity (split->entity.collection, gains_guid);
PINFO ("split=%p has gains-split=%p", split, gains_split);
return gains_split;
}

View File

@ -95,8 +95,6 @@ back_associate_expense_accounts(Account *stock_account,
g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
existing_acc_guid = kvp_value_get_guid(val);
g_return_if_fail(GNC_ID_NONE == qof_entity_type (qof_book_get_entity_table (stock_account->inst.book), existing_acc_guid));
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
stock_acc_guid_kvpval);
@ -130,9 +128,6 @@ back_associate_income_accounts(Account *stock_account,
g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
existing_acc_guid = kvp_value_get_guid(val);
g_return_if_fail(qof_entity_type(qof_book_get_entity_table(stock_account->inst.book), existing_acc_guid) ==
GNC_ID_NONE);
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
stock_acc_guid_kvpval);
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account-category",
@ -448,10 +443,6 @@ gnc_tracking_dissociate_account(Account *inc_or_expense_account)
"associated-stock-account");
stock_account_guid = kvp_value_get_guid(stock_account_kvpval);
if(!safe_strcmp
(qof_entity_type(qof_book_get_entity_table(inc_or_expense_account->inst.book), stock_account_guid),
GNC_ID_NULL))
return;
category_kvpval = kvp_frame_get_slot(current_account_kvpframe,
"associated-stock-account-category");

View File

@ -35,37 +35,35 @@
#include "qofbook.h"
/* begin_edit helper
*
* assumes:
* obj->editlevel (int)
* obj->book (QofBook*)
*
* @args:
* obj: the object to begin editing
* type: the object type
* inst: an instance of QofInstance
*
* The caller should use this macro first and then perform any other operations.
*/
#define GNC_BEGIN_EDIT(obj,type) { \
QofBackend * be; \
if (!(obj)) return; \
\
(obj)->editlevel++; \
if (1 < (obj)->editlevel) return; \
\
if (0 >= (obj)->editlevel) \
{ \
PERR ("unbalanced call - resetting (was %d)", (obj)->editlevel); \
(obj)->editlevel = 1; \
} \
\
/* See if there's a backend. If there is, invoke it. */ \
be = qof_book_get_backend ((obj)->book); \
if (be && be->begin) { \
(be->begin) (be, (type), (obj)); \
} \
}
#define GNC_BEGIN_EDIT(inst) \
QofBackend * be; \
if (!(inst)) return; \
\
(inst)->editlevel++; \
if (1 < (inst)->editlevel) return; \
\
if (0 >= (inst)->editlevel) \
{ \
PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
(inst)->editlevel = 1; \
} \
ENTER ("inst=%p", (inst)); \
\
/* See if there's a backend. If there is, invoke it. */ \
be = qof_book_get_backend ((inst)->book); \
if (be && be->begin) { \
(be->begin) (be, (inst)->entity.e_type, (inst)); \
} else { \
/* We tried and failed to start transaction! */ \
(inst)->dirty = TRUE; \
}
/*
@ -73,84 +71,93 @@
*
* The caller should call PART1 as the first thing, then
* perform any local operations prior to calling the backend.
* Then call PART2. You cannot do anything after PART2.
*
* assumes:
* obj->editlevel (int)
* obj->book (QofBook*)
* obj->do_free (gboolean)
* obj->dirty (gboolean)
* Then call PART2.
*/
/*
* part1 -- deal with the editlevel
*
* assumes:
* obj->editlevel (int)
*
* @args:
* obj: the object being committed
* inst: an instance of QofInstance
*/
#define GNC_COMMIT_EDIT_PART1(obj) { \
if (!(obj)) return; \
\
(obj)->editlevel--; \
if (0 < (obj)->editlevel) return; \
\
if (0 > (obj)->editlevel) \
{ \
PERR ("unbalanced call - resetting (was %d)", (obj)->editlevel); \
(obj)->editlevel = 0; \
} \
#define GNC_COMMIT_EDIT_PART1(inst) { \
if (!(inst)) return; \
\
(inst)->editlevel--; \
if (0 < (inst)->editlevel) return; \
\
/* The pricedb sufffers from delayed update... */ \
/* This may be setting a bad precedent for other types, I fear. */ \
/* Other types probably really should handle begin like this. */ \
if ((-1 == (inst)->editlevel) && (inst)->dirty) \
{ \
QofBackend * be; \
be = qof_book_get_backend ((inst)->book); \
if (be && be->begin) { \
(be->begin) (be, (inst)->entity.e_type, (inst)); \
} \
(inst)->editlevel = 0; \
} \
if (0 > (inst)->editlevel) \
{ \
PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
(inst)->editlevel = 0; \
} \
ENTER ("inst=%p, dirty=%d do-free=%d", \
(inst), (inst)->dirty, (inst)->do_free); \
}
/*
* part2 -- deal with the backend
*
* assumes:
* obj->book (QofBook*)
* obj->do_free (gboolean)
*
* @args:
* obj: the object being committed
* type: the type of the object
* inst: an instance of QofInstance
* on_error: a function called if there is a backend error.
* void (*on_error)(obj, QofBackendError)
* on_done: a function called after the commit is complete but before
* the object is freed. This is where you clear the "dirty"
* flag, and perform any other operations after the commit.
* void (*on_done)(obj)
* on_free: a function called if obj->do_free is TRUE.
* void (*on_free)(obj)
* void (*on_error)(inst, QofBackendError)
* on_done: a function called after the commit is complete
* but before the instect is freed. Perform any other
* operations after the commit.
* void (*on_done)(inst)
* on_free: a function called if inst->do_free is TRUE.
* void (*on_free)(inst)
*/
#define GNC_COMMIT_EDIT_PART2(obj,type,on_error,on_done,on_free) { \
QofBackend * be; \
\
/* See if there's a backend. If there is, invoke it. */ \
be = qof_book_get_backend ((obj)->book); \
if (be && be->commit) \
{ \
QofBackendError errcode; \
\
/* clear errors */ \
do { \
errcode = qof_backend_get_error (be); \
} while (ERR_BACKEND_NO_ERR != errcode); \
\
(be->commit) (be, (type), (obj)); \
errcode = qof_backend_get_error (be); \
if (ERR_BACKEND_NO_ERR != errcode) \
{ \
(obj)->do_free = FALSE; \
(on_error)((obj), errcode); \
qof_backend_set_error (be, errcode); \
} \
} \
(on_done)(obj); \
(obj)->dirty = FALSE; \
\
if ((obj)->do_free) { (on_free)(obj); } \
#define GNC_COMMIT_EDIT_PART2(inst,on_error,on_done,on_free) { \
QofBackend * be; \
\
/* See if there's a backend. If there is, invoke it. */ \
be = qof_book_get_backend ((inst)->book); \
if (be && be->commit) \
{ \
QofBackendError errcode; \
\
/* clear errors */ \
do { \
errcode = qof_backend_get_error (be); \
} while (ERR_BACKEND_NO_ERR != errcode); \
\
(be->commit) (be, (inst)->entity.e_type, (inst)); \
errcode = qof_backend_get_error (be); \
if (ERR_BACKEND_NO_ERR != errcode) \
{ \
/* XXX Should perform a rollback here */ \
(inst)->do_free = FALSE; \
\
/* Push error back onto the stack */ \
qof_backend_set_error (be, errcode); \
(on_error)((inst), errcode); \
} \
/* XXX the backend commit code should clear dirty!! */ \
(inst)->dirty = FALSE; \
} \
(on_done)(inst); \
\
LEAVE ("inst=%p, dirty=%d do-free=%d", \
(inst), (inst)->dirty, (inst)->do_free); \
if ((inst)->do_free) { \
(on_free)(inst); \
return; \
} \
}

View File

@ -1572,7 +1572,7 @@ commodity_table_book_end (QofBook *book)
static QofObject commodity_table_object_def =
{
interface_version: QOF_OBJECT_VERSION,
name: GNC_ID_COMMODITY_TABLE,
e_type: GNC_ID_COMMODITY_TABLE,
type_label: "CommodityTable",
book_begin: commodity_table_book_begin,
book_end: commodity_table_book_end,

View File

@ -41,11 +41,11 @@
#include "kvp_frame.h"
#include "qofbook.h"
#include "qofid.h"
#include "qofid-p.h"
struct gnc_lot_struct
{
/* Unique guid for this lot */
GUID guid;
QofEntity entity; /* Unique guid for this lot */
/* Book that this lot belongs to */
QofBook *book;
@ -69,7 +69,7 @@ struct gnc_lot_struct
unsigned char marker;
};
void gnc_lot_set_guid(GNCLot *lot, GUID guid);
#define gnc_lot_set_guid(L,G) qof_entity_set_guid(QOF_ENTITY(L),&(G))
/* Register with the Query engine */
void gnc_lot_register (void);

View File

@ -61,6 +61,7 @@ static short module = MOD_LOT;
static void
gnc_lot_init (GNCLot *lot, QofBook *book)
{
QofCollection *col;
ENTER ("(lot=%p, book=%p)", lot, book);
lot->kvp_data = kvp_frame_new();
lot->account = NULL;
@ -69,8 +70,8 @@ gnc_lot_init (GNCLot *lot, QofBook *book)
lot->marker = 0;
lot->book = book;
qof_entity_guid_new (book->entity_table, &lot->guid);
qof_entity_store (book->entity_table, lot, &lot->guid, GNC_ID_LOT);
col = qof_book_get_collection (book, GNC_ID_LOT);
qof_entity_init (&lot->entity, GNC_ID_LOT, col);
LEAVE ("(lot=%p, book=%p)", lot, book);
}
@ -82,7 +83,7 @@ gnc_lot_new (QofBook *book)
lot = g_new (GNCLot, 1);
gnc_lot_init (lot, book);
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_CREATE);
gnc_engine_gen_event (&lot->entity, GNC_EVENT_CREATE);
return lot;
}
@ -93,9 +94,9 @@ gnc_lot_destroy (GNCLot *lot)
if (!lot) return;
ENTER ("(lot=%p)", lot);
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_DESTROY);
gnc_engine_gen_event (&lot->entity, GNC_EVENT_DESTROY);
qof_entity_remove (lot->book->entity_table, &lot->guid);
qof_entity_release (&lot->entity);
for (node=lot->splits; node; node=node->next)
{
@ -115,31 +116,13 @@ gnc_lot_destroy (GNCLot *lot)
/* ============================================================= */
const GUID *
gnc_lot_get_guid (GNCLot *lot)
{
if (!lot) return NULL;
return &lot->guid;
}
void
gnc_lot_set_guid (GNCLot *lot, GUID uid)
{
if (!lot) return;
if (guid_equal (&lot->guid, &uid)) return;
qof_entity_remove(lot->book->entity_table, &lot->guid);
lot->guid = uid;
qof_entity_store(lot->book->entity_table, lot, &lot->guid, GNC_ID_LOT);
}
GNCLot *
gnc_lot_lookup (const GUID *guid, QofBook *book)
{
QofCollection *col;
if (!guid || !book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book),
guid, GNC_ID_LOT);
col = qof_book_get_collection (book, GNC_ID_LOT);
return (GNCLot *) qof_collection_lookup_entity (col, guid);
}
QofBook *
@ -149,7 +132,6 @@ gnc_lot_get_book (GNCLot *lot)
return lot->book;
}
/* ============================================================= */
gboolean
@ -292,7 +274,7 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
/* for recomputation of is-closed */
lot->is_closed = -1;
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
gnc_engine_gen_event (&lot->entity, GNC_EVENT_MODIFY);
}
void
@ -310,7 +292,7 @@ gnc_lot_remove_split (GNCLot *lot, Split *split)
xaccAccountRemoveLot (lot->account, lot);
lot->account = NULL;
}
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
gnc_engine_gen_event (&lot->entity, GNC_EVENT_MODIFY);
}
/* ============================================================== */
@ -379,8 +361,8 @@ gnc_lot_get_latest_split (GNCLot *lot)
void gnc_lot_register (void)
{
static const QofParam params[] = {
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
{ QOF_QUERY_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)gnc_lot_get_book, NULL },
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)gnc_lot_get_guid, NULL },
{ LOT_IS_CLOSED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gnc_lot_is_closed, NULL },
{ LOT_BALANCE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_lot_get_balance, NULL },
{ NULL },

View File

@ -45,11 +45,11 @@
#include "gnc-engine.h"
#include "gnc-numeric.h"
#include "qofbook.h"
#include "qofid.h"
GNCLot * gnc_lot_new (QofBook *);
void gnc_lot_destroy (GNCLot *);
const GUID * gnc_lot_get_guid (GNCLot *p);
GNCLot * gnc_lot_lookup (const GUID *guid, QofBook *book);
QofBook * gnc_lot_get_book (GNCLot *);
@ -114,6 +114,8 @@ void gnc_lot_set_notes (GNCLot *, const char *);
* */
KvpFrame * gnc_lot_get_slots (GNCLot *);
#define gnc_lot_get_guid(X) qof_entity_get_guid(QOF_ENTITY(X))
#define LOT_IS_CLOSED "is-closed?"
#define LOT_BALANCE "balance"

View File

@ -32,12 +32,14 @@
#include "qofbackend.h"
#include "qofbook.h"
#include "qofid.h"
#include "qofid-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
struct gnc_price_s
{
/* 'public' data fields */
GUID guid; /* globally unique price id */
QofBook *book; /* book to which this price belongs to */
QofInstance inst; /* globally unique object identifier */
GNCPriceDB *db;
gnc_commodity *commodity;
@ -50,11 +52,7 @@ struct gnc_price_s
guint32 version_check; /* data aging timestamp */
/* 'private' object management fields */
QofEntityTable *entity_table; /* table in which price is stored */
guint32 refcount; /* garbage collection reference count */
gint32 editlevel; /* nesting level of begin/end edit calls */
gboolean not_saved; /* price edit saved flag */
gboolean do_free; /* price is going to be destroyed soon */
};
@ -99,13 +97,14 @@ typedef struct gnc_price_lookup_helper_s
Timespec time;
} GNCPriceLookupHelper;
#define gnc_price_set_guid(P,G) qof_entity_set_guid(QOF_ENTITY(P),(G))
void gnc_pricedb_set_db(QofBook *book, GNCPriceDB *db);
void gnc_pricedb_mark_clean(GNCPriceDB *db);
void gnc_pricedb_substitute_commodity(GNCPriceDB *db,
gnc_commodity *old_c,
gnc_commodity *new_c);
void gnc_price_set_guid (GNCPrice *p, const GUID *guid);
/** register the pricedb object with the gncObject system */
gboolean gnc_pricedb_register (void);

View File

@ -27,6 +27,7 @@
#include <glib.h>
#include <string.h>
#include "gnc-be-utils.h"
#include "gnc-engine.h"
#include "gnc-engine-util.h"
#include "gnc-event-p.h"
@ -34,6 +35,7 @@
#include "gnc-trace.h"
#include "guid.h"
#include "kvp-util.h"
#include "qofbackend-p.h"
#include "qofbook.h"
#include "qofbook-p.h"
@ -62,21 +64,14 @@ gnc_price_create (QofBook *book)
p = g_new0(GNCPrice, 1);
p->refcount = 1;
p->editlevel = 0;
p->not_saved = FALSE;
p->do_free = FALSE;
p->version = 0;
p->version_check = 0;
p->value = gnc_numeric_zero();
p->type = NULL;
p->source = NULL;
p->book = book;
p->entity_table = qof_book_get_entity_table (book);
qof_entity_guid_new (p->entity_table, &p->guid);
qof_entity_store (p->entity_table, p, &p->guid, GNC_ID_PRICE);
gnc_engine_generate_event (&p->guid, GNC_ID_PRICE, GNC_EVENT_CREATE);
qof_instance_init (&p->inst, GNC_ID_PRICE, book);
gnc_engine_gen_event (&p->inst.entity, GNC_EVENT_CREATE);
return p;
}
@ -85,12 +80,12 @@ static void
gnc_price_destroy (GNCPrice *p)
{
ENTER(" ");
gnc_engine_generate_event (&p->guid, GNC_ID_PRICE, GNC_EVENT_DESTROY);
qof_entity_remove(p->entity_table, &p->guid);
gnc_engine_gen_event (&p->inst.entity, GNC_EVENT_DESTROY);
if(p->type) g_cache_remove(gnc_engine_get_string_cache(), p->type);
if(p->source) g_cache_remove(gnc_engine_get_string_cache(), p->source);
qof_instance_release (&p->inst);
memset(p, 0, sizeof(GNCPrice));
g_free(p);
}
@ -159,85 +154,21 @@ gnc_price_clone (GNCPrice* p, QofBook *book)
void
gnc_price_begin_edit (GNCPrice *p)
{
if (!p) return;
p->editlevel++;
if (1 < p->editlevel) return;
ENTER ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
if (0 >= p->editlevel)
{
PERR ("unbalanced call - resetting (was %d)", p->editlevel);
p->editlevel = 1;
}
/* See if there's a backend. If there is, invoke it. */
/* We may not be able to find the backend, so make not of that .. */
if (p->db) {
QofBackend *be;
be = xaccPriceDBGetBackend (p->db);
if (be && be->begin) {
(be->begin) (be, GNC_ID_PRICE, p);
}
p->not_saved = FALSE;
} else {
p->not_saved = TRUE;
}
LEAVE ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
GNC_BEGIN_EDIT (&p->inst);
}
static inline void commit_err (QofInstance *inst, QofBackendError errcode)
{
PERR ("Failed to commit: %d", errcode);
}
static inline void noop (QofInstance *inst) {}
void
gnc_price_commit_edit (GNCPrice *p)
{
if (!p) return;
p->editlevel--;
if (0 < p->editlevel) return;
ENTER ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
if (0 > p->editlevel)
{
PERR ("unbalanced call - resetting (was %d)", p->editlevel);
p->editlevel = 0;
}
/* See if there's a backend. If there is, invoke it. */
/* We may not be able to find the backend, so make not of that .. */
if (p->db) {
QofBackend *be;
be = xaccPriceDBGetBackend (p->db);
if (be && be->commit) {
QofBackendError errcode;
/* clear errors */
do {
errcode = qof_backend_get_error (be);
} while (ERR_BACKEND_NO_ERR != errcode);
/* if we haven't been able to call begin edit before, call it now */
if (TRUE == p->not_saved) {
if (be->begin) {
(be->begin) (be, GNC_ID_PRICE, p);
}
}
(be->commit) (be, GNC_ID_PRICE, p);
errcode = qof_backend_get_error (be);
if (ERR_BACKEND_NO_ERR != errcode)
{
/* XXX hack alert FIXME implement price rollback */
PERR (" backend asked engine to rollback, but this isn't"
" handled yet. Return code=%d", errcode);
/* push error back onto the stack */
qof_backend_set_error (be, errcode);
}
}
p->not_saved = FALSE;
} else {
p->not_saved = TRUE;
}
LEAVE ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
GNC_COMMIT_EDIT_PART1 (&p->inst);
GNC_COMMIT_EDIT_PART2 (&p->inst, commit_err, noop, noop);
}
/* ==================================================================== */
@ -325,16 +256,6 @@ gnc_pricedb_commit_edit (GNCPriceDB *pdb)
/* ==================================================================== */
/* setters */
void
gnc_price_set_guid (GNCPrice *p, const GUID *guid)
{
if (!p || !guid) return;
qof_entity_remove (p->entity_table, &p->guid);
p->guid = *guid;
if(p->db) p->db->dirty = TRUE;
qof_entity_store(p->entity_table, p, &p->guid, GNC_ID_PRICE);
}
void
gnc_price_set_commodity(GNCPrice *p, gnc_commodity *c)
{
@ -464,31 +385,11 @@ gnc_price_set_version(GNCPrice *p, gint32 vers)
GNCPrice *
gnc_price_lookup (const GUID *guid, QofBook *book)
{
if (!guid) return NULL;
g_return_val_if_fail (book, NULL);
return qof_entity_lookup (qof_book_get_entity_table (book),
guid, GNC_ID_PRICE);
}
const GUID *
gnc_price_get_guid (GNCPrice *p)
{
if (!p) return guid_null();
return &p->guid;
}
const GUID
gnc_price_return_guid (GNCPrice *p)
{
if (!p) return *guid_null();
return p->guid;
}
QofBook *
gnc_price_get_book (GNCPrice *p)
{
if (!p) return NULL;
return p->book;
QofCollection *col;
if (!guid || !book) return NULL;
col = qof_book_get_collection (book, GNC_ID_PRICE);
return (GNCPrice *) qof_collection_lookup_entity (col, guid);
}
gnc_commodity *
@ -923,12 +824,12 @@ add_price(GNCPriceDB *db, GNCPrice *p)
GHashTable *currency_hash;
if(!db || !p) return FALSE;
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
db, p, p->not_saved, p->do_free);
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
db, p, p->inst.dirty, p->inst.do_free);
/* initialize the book pointer for teh first time, if needed */
if (NULL == db->book) db->book = p->book;
if (db->book != p->book)
/* initialize the book pointer for the first time, if needed */
if (NULL == db->book) db->book = p->inst.book;
if (db->book != p->inst.book)
{
PERR ("attempted to mix up prices across different books");
return FALSE;
@ -958,8 +859,8 @@ add_price(GNCPriceDB *db, GNCPrice *p)
g_hash_table_insert(currency_hash, currency, price_list);
p->db = db;
LEAVE ("db=%p, pr=%p not-saved=%d do-free=%d commodity=%s/%s currency_hash=%p",
db, p, p->not_saved, p->do_free,
LEAVE ("db=%p, pr=%p dirty=%d do-free=%d commodity=%s/%s currency_hash=%p",
db, p, p->inst.dirty, p->inst.do_free,
gnc_commodity_get_namespace(p->commodity),
gnc_commodity_get_mnemonic(p->commodity),
currency_hash);
@ -973,20 +874,21 @@ gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
{
if(!db || !p) return FALSE;
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
db, p, p->not_saved, p->do_free);
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
db, p, p->inst.dirty, p->inst.do_free);
if (FALSE == add_price(db, p)) return FALSE;
/* if we haven't been able to call the backend before, call it now */
if (TRUE == p->not_saved) {
/* If we haven't been able to call the backend before, call it now */
if (TRUE == p->inst.dirty)
{
gnc_price_begin_edit(p);
db->dirty = TRUE;
gnc_price_commit_edit(p);
}
LEAVE ("db=%p, pr=%p not-saved=%d do-free=%d",
db, p, p->not_saved, p->do_free);
LEAVE ("db=%p, pr=%p dirty=%d do-free=%d",
db, p, p->inst.dirty, p->inst.do_free);
return TRUE;
}
@ -1004,8 +906,8 @@ remove_price(GNCPriceDB *db, GNCPrice *p, gboolean cleanup)
GHashTable *currency_hash;
if(!db || !p) return FALSE;
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
db, p, p->not_saved, p->do_free);
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
db, p, p->inst.dirty, p->inst.do_free);
commodity = gnc_price_get_commodity(p);
if(!commodity) return FALSE;
@ -1052,8 +954,8 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
{
gboolean rc;
if(!db || !p) return FALSE;
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
db, p, p->not_saved, p->do_free);
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
db, p, p->inst.dirty, p->inst.do_free);
gnc_price_ref(p);
rc = remove_price (db, p, TRUE);
@ -1061,7 +963,7 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
/* invoke the backend to delete this price */
gnc_price_begin_edit (p);
db->dirty = TRUE;
p->do_free = TRUE;
p->inst.do_free = TRUE;
gnc_price_commit_edit (p);
p->db = NULL;
@ -2100,7 +2002,7 @@ void_unstable_price_traversal(GNCPriceDB *db,
}
static void
pricedb_foreach(QofBook *book, QofEntityForeachCB cb, gpointer data)
pricedb_foreach(QofBook *book, QofForeachCB cb, gpointer data)
{
GNCPriceDB *db = gnc_pricedb_get_db(book);
void_unstable_price_traversal(db,
@ -2109,6 +2011,7 @@ pricedb_foreach(QofBook *book, QofEntityForeachCB cb, gpointer data)
}
/* ==================================================================== */
static const char *
pricedb_printable(gpointer obj)
{
@ -2138,7 +2041,7 @@ pricedb_printable(gpointer obj)
static QofObject pricedb_object_def =
{
interface_version: QOF_OBJECT_VERSION,
name: GNC_ID_PRICE,
e_type: GNC_ID_PRICE,
type_label: "Price",
book_begin: pricedb_book_begin,
book_end: pricedb_book_end,

View File

@ -31,6 +31,7 @@
#include "gnc-numeric.h"
#include "guid.h"
#include "qofbook.h"
#include "qofinstance.h"
/** @addtogroup Engine
@ -172,9 +173,6 @@ void gnc_price_set_version(GNCPrice *p, gint32 versn);
/** As mentioned above all of the getters return data that's internal
to the GNCPrice, not copies, so don't free these values. */
GNCPrice * gnc_price_lookup (const GUID *guid, QofBook *book);
const GUID * gnc_price_get_guid (GNCPrice *p);
const GUID gnc_price_return_guid (GNCPrice *p);
QofBook * gnc_price_get_book (GNCPrice *p);
gnc_commodity * gnc_price_get_commodity(GNCPrice *p);
gnc_commodity * gnc_price_get_currency(GNCPrice *p);
Timespec gnc_price_get_time(GNCPrice *p);
@ -184,6 +182,10 @@ gnc_numeric gnc_price_get_value(GNCPrice *p);
gint32 gnc_price_get_version(GNCPrice *p);
gboolean gnc_price_equal(GNCPrice *p1, GNCPrice *p2);
#define gnc_price_get_guid(X) qof_entity_get_guid(QOF_ENTITY(X))
#define gnc_price_return_guid(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
#define gnc_price_get_book(X) qof_instance_get_book(QOF_INSTANCE(X))
/* ******************************************************************** */
/** GNCPrice lists:

View File

@ -285,6 +285,20 @@ init_from_time(void)
return total;
}
static size_t
init_from_int(int val)
{
md5_process_bytes(&val, sizeof(val), &guid_context);
return sizeof(int);
}
static size_t
init_from_buff(char * buf, size_t buflen)
{
md5_process_bytes(buf, buflen, &guid_context);
return buflen;
}
void
guid_init(void)
{
@ -458,6 +472,20 @@ guid_new(GUID *guid)
/* update the global context */
init_from_time();
/* Make it a little extra salty. I think init_from_time was buggy,
* or something, since duplicate id's actually happened. Or something
* like that. I think this is because init_from_time kept returning
* the same values too many times in a row. So we'll do some 'block
* chaining', and feed in the old guid as new random data.
*
* Anyway, I think the whole fact that I saw a bunch of duplicate
* id's at one point, but can't reproduce the bug is rather alarming.
* Something must be broken somewhere, and merely adding more salt
* is just hiding the problem, not fixing it.
*/
init_from_int (433781*counter);
init_from_buff (guid->data, 16);
if (counter == 0)
{
FILE *fp;

View File

@ -99,6 +99,14 @@ void guid_shutdown (void);
*
* @param guid A pointer to an existing guid data structure. The
* existing value will be replaced with a new value.
*
* This routine uses the md5 algorithm to build strong random guids.
* Note that while guid's are generated randomly, the odds of this
* routine returning a non-unique id are astronomically small.
* (Literally astronomically: If you had Cray's on every solar
* system in the universe running for the entire age of teh universe,
* you'd still have less than a one-in-a-million chance of coming up
* with a duplicate id. 2^128 == 10^38 is a really really big number.)
*/
void guid_new(GUID *guid);

View File

@ -34,11 +34,11 @@
#include "qofbackend.h"
#include "qofbook.h"
#include "qofid.h"
#include "qofid-p.h"
struct _QofBook
{
/* Unique guid for this book. */
GUID guid;
QofEntity entity; /* Unique guid for this book. */
/* The KvpFrame provides a place for top-level data associated
* with this book. */
@ -48,7 +48,7 @@ struct _QofBook
* belonging to this book, with their pointers to the respective
* objects. This allows a lookup of objects based on thier guid.
*/
QofEntityTable *entity_table;
GHashTable * hash_of_collections;
/* In order to store arbitrary data, for extensibility, add a table
* that will be used to hold arbitrary pointers.
@ -87,7 +87,6 @@ struct _QofBook
* if the backends should even be doing this much, but for
* backwards compatibility, we leave these here.)
*/
void qof_book_set_guid(QofBook *book, GUID guid);
void qof_book_set_schedxactions( QofBook *book, GList *newList );
void qof_book_set_backend (QofBook *book, QofBackend *be);
@ -101,4 +100,8 @@ void qof_book_mark_saved(QofBook *book);
/* Register books with the engine */
gboolean qof_book_register (void);
/* deprecated */
#define qof_book_set_guid(book,guid) \
qof_entity_set_guid(QOF_ENTITY(book), guid)
#endif /* QOF_BOOK_P_H */

View File

@ -58,12 +58,13 @@ static short module = MOD_ENGINE;
static void
qof_book_init (QofBook *book)
{
QofCollection *col;
if (!book) return;
book->entity_table = qof_entity_new ();
book->hash_of_collections = g_hash_table_new (g_str_hash, g_str_equal);
qof_entity_guid_new (book->entity_table, &book->guid);
qof_entity_store(book->entity_table, book, &book->guid, QOF_ID_BOOK);
col = qof_book_get_collection (book, QOF_ID_BOOK);
qof_entity_init (&book->entity, QOF_ID_BOOK, col);
book->kvp_data = kvp_frame_new ();
@ -84,30 +85,41 @@ qof_book_new (void)
qof_book_init(book);
qof_object_book_begin (book);
gnc_engine_generate_event (&book->guid, QOF_ID_BOOK, GNC_EVENT_CREATE);
gnc_engine_gen_event (&book->entity, GNC_EVENT_CREATE);
LEAVE ("book=%p", book);
return book;
}
static gboolean
coll_destroy(gpointer key, gpointer value, gpointer not_used)
{
QofCollection *col = value;
qof_collection_destroy (col);
return TRUE;
}
void
qof_book_destroy (QofBook *book)
{
if (!book) return;
ENTER ("book=%p etable=%p", book, book->entity_table);
gnc_engine_force_event (&book->guid, QOF_ID_BOOK, GNC_EVENT_DESTROY);
ENTER ("book=%p", book);
gnc_engine_force_event (&book->entity.guid, QOF_ID_BOOK, GNC_EVENT_DESTROY);
qof_object_book_end (book);
qof_entity_remove (book->entity_table, &book->guid);
qof_entity_destroy (book->entity_table);
book->entity_table = NULL;
kvp_frame_delete (book->kvp_data);
/* FIXME: Make sure the data_table is empty */
g_hash_table_destroy (book->data_tables);
qof_entity_release (&book->entity);
g_hash_table_foreach_remove (book->hash_of_collections,
coll_destroy, NULL);
g_hash_table_destroy (book->hash_of_collections);
book->hash_of_collections = NULL;
g_free (book);
LEAVE ("book=%p", book);
}
@ -145,13 +157,6 @@ qof_book_mark_saved(QofBook *book)
/* ====================================================================== */
/* getters */
const GUID *
qof_book_get_guid (QofBook *book)
{
if (!book) return NULL;
return &book->guid;
}
KvpFrame *
qof_book_get_slots (QofBook *book)
{
@ -159,13 +164,6 @@ qof_book_get_slots (QofBook *book)
return book->kvp_data;
}
QofEntityTable *
qof_book_get_entity_table (QofBook *book)
{
if (!book) return NULL;
return book->entity_table;
}
QofBackend *
qof_book_get_backend (QofBook *book)
{
@ -176,18 +174,6 @@ qof_book_get_backend (QofBook *book)
/* ====================================================================== */
/* setters */
void
qof_book_set_guid (QofBook *book, GUID uid)
{
if (!book) return;
if (guid_equal (&book->guid, &uid)) return;
qof_entity_remove(book->entity_table, &book->guid);
book->guid = uid;
qof_entity_store(book->entity_table, book, &book->guid, QOF_ID_BOOK);
}
void
qof_book_set_backend (QofBook *book, QofBackend *be)
{
@ -230,6 +216,28 @@ qof_book_get_data (QofBook *book, const char *key)
/* ====================================================================== */
QofCollection *
qof_book_get_collection (QofBook *book, QofIdType entity_type)
{
QofCollection *col;
col = g_hash_table_lookup (book->hash_of_collections, entity_type);
if (col) return col;
col = qof_collection_new (entity_type);
/* XXX should use string_cache instead of strdup */
/* Need strdup because values are sometimes freed */
/* this is a memory leak, since malloc'ed value is not freed */
/* ??? huh ?? freed where? by whom? */
g_hash_table_insert (book->hash_of_collections,
(gpointer)g_strdup(entity_type), col);
return col;
}
/* ====================================================================== */
gint64
qof_book_get_counter (QofBook *book, const char *counter_name)
{
@ -287,7 +295,7 @@ gboolean qof_book_register (void)
{
static QofParam params[] = {
{ QOF_BOOK_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_book_get_slots, NULL },
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_book_get_guid, NULL },
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
{ NULL },
};

View File

@ -48,7 +48,7 @@ typedef struct _QofBook QofBook;
/** GList of QofBook */
typedef GList QofBookList;
/** Register the book boject with the QOF object system. */
/** Register the book object with the QOF object system. */
gboolean qof_book_register (void);
/** Allocate, initialise and return a new QofBook. Books contain references
@ -60,10 +60,7 @@ QofBook * qof_book_new (void);
void qof_book_destroy (QofBook *book);
/** \return The Entity table for the book. */
QofEntityTable * qof_book_get_entity_table (QofBook *book);
/** \return The GUID for the book. */
const GUID * qof_book_get_guid (QofBook *book);
QofCollection * qof_book_get_collection (QofBook *, QofIdType);
/** \return The kvp data for the book */
KvpFrame * qof_book_get_slots (QofBook *book);
@ -113,5 +110,8 @@ gint64 qof_book_get_counter (QofBook *book, const char *counter_name);
/**@}*/
/** deprecated */
#define qof_book_get_guid(X) qof_entity_get_guid (QOF_ENTITY(X))
#endif /* QOF_BOOK_H */
/** @} */

View File

@ -31,45 +31,16 @@
/* This file defines an engine-only API for using gnucash entity
* identifiers. */
/** Set the ID of the entity, over-riding teh previous ID.
* Very dangerous, use only for file i/o work.
*/
void qof_entity_set_guid (QofEntity *ent, const GUID *guid);
/* Create and destroy entity tables */
QofEntityTable * qof_entity_new (void);
void qof_entity_destroy (QofEntityTable *table);
/* Generate a new id. This function is guaranteed to return an id that
* is unique within the scope of all GnuCash entities being managed by
* the current invocation of GnuCash. GnuCash routines should always
* use this function and not guid_new!
*
* When considered over all possible instances of gnucash, the odds of
* this routine returning a non-unique id are still astronomically small.
* If you had a gazzillion computers computing new ids, for the entire
* age of the universe, you'd still have a one-in-a-million chance of
* coming up with a duplicate. 2^128 is a really really big number.
/** Take entity, remove it from whatever collection its currently
* in, and place it in a new collection. To be used only for
* moving entity from one book to another.
*/
void qof_entity_guid_new (QofEntityTable *entity_table, GUID *guid);
void qof_collection_insert_entity (QofCollection *, QofEntity *);
/* Lookup an entity given an id and a type. If there is no entity
* associated with the id, or if it has a different type, NULL
* is returned. Input: GUID, returns reference (pointer) to object.
*/
gpointer qof_entity_lookup (QofEntityTable *entity_table,
const GUID * guid, QofIdType entity_type);
/* Store the given entity under the given id with the given type. */
/* this routine obsolete, remove asap */
void qof_entity_store (QofEntityTable *entity_table,
gpointer entity, const GUID * guid,
QofIdType entity_type);
/* Remove any existing association between an entity and the given
* id. The entity is not changed in any way. */
void qof_entity_remove (QofEntityTable *entity_table, const GUID * guid);
/* Call a function for each object of type 'type' in the entity table */
void qof_entity_foreach (QofEntityTable *entity_table, QofIdType type,
QofEntityForeachCB cb_func, gpointer user_data);
#endif /* QOF_ID_P_H */

View File

@ -35,58 +35,8 @@
#define CACHE_INSERT(str) g_cache_insert(gnc_engine_get_string_cache(), (gpointer)(str));
#define CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (gpointer)(str));
#define QOFID_DEBUG 0
static short module = MOD_ENGINE;
/* =============================================================== */
/* XXX under construction, the entity_store thing can be vastly simplified */
void
qof_entity_init (QofEntity *ent, QofIdType type, QofEntityTable * tab)
{
ent->e_type = type;
do
{
guid_new(&ent->guid);
if (qof_entity_type (tab, &ent->guid) == QOF_ID_NONE)
break;
PWARN("duplicate id created, trying again");
} while(1);
ent->e_table = tab;
qof_entity_store (tab, ent, &ent->guid, type);
}
void
qof_entity_release (QofEntity *ent)
{
qof_entity_remove (ent->e_table, &ent->guid);
ent->e_table = NULL;
}
/* This is a restricted function, should be used only during
* read from file */
void
qof_entity_set_guid (QofEntity *ent, const GUID *guid)
{
if (guid_equal (guid, &ent->guid)) return;
qof_entity_remove (ent->e_table, &ent->guid);
ent->guid = *guid;
qof_entity_store (ent->e_table, ent, &ent->guid, ent->e_type);
}
/* =============================================================== */
/** a collection of entities */
/* XXX this is supposed to be a replacement for GncBookInfo/gncBusinessCreate
* when we finish */
typedef struct QofCollection_s QofCollection;
struct QofCollection_s
{
QofIdType e_type;
@ -95,6 +45,71 @@ struct QofCollection_s
GHashTable * hash_of_entities;
};
/* =============================================================== */
static void qof_collection_remove_entity (QofEntity *ent);
void
qof_entity_init (QofEntity *ent, QofIdType type, QofCollection * tab)
{
g_return_if_fail (NULL != tab);
/* XXX We passed redundant info to this routine ... but I think that's
* OK, it might eliminate programming errors. */
if (safe_strcmp(tab->e_type, type))
{
PERR ("attempt to insert \"%s\" into \"%s\"", type, tab->e_type);
return;
}
ent->e_type = CACHE_INSERT (type);
do
{
guid_new(&ent->guid);
if (NULL == qof_collection_lookup_entity (tab, &ent->guid)) break;
PWARN("duplicate id created, trying again");
} while(1);
ent->collection = tab;
qof_collection_insert_entity (tab, ent);
}
void
qof_entity_release (QofEntity *ent)
{
if (!ent->collection) return;
qof_collection_remove_entity (ent);
CACHE_REMOVE (ent->e_type);
ent->e_type = NULL;
}
/* This is a restricted function, should be used only during
* read from file */
void
qof_entity_set_guid (QofEntity *ent, const GUID *guid)
{
QofCollection *col;
if (guid_equal (guid, &ent->guid)) return;
col = ent->collection;
qof_collection_remove_entity (ent);
ent->guid = *guid;
qof_collection_insert_entity (col, ent);
}
GUID *
qof_entity_get_guid (QofEntity *ent)
{
if (!ent) return NULL;
return &ent->guid;
}
/* =============================================================== */
static guint
id_hash (gconstpointer key)
{
@ -130,312 +145,94 @@ id_compare(gconstpointer key_1, gconstpointer key_2)
return guid_equal (key_1, key_2);
}
QofCollection * qof_collection_new (QofIdType type);
QofCollection *
qof_collection_new (QofIdType type)
{
QofCollection *col;
col = g_new0(QofCollection, 1);
col->e_type = type;
col->e_type = CACHE_INSERT (type);
col->hash_of_entities = g_hash_table_new (id_hash, id_compare);
return col;
}
void qof_collection_destroy (QofCollection *col);
void
qof_collection_destroy (QofCollection *col)
{
/* col->e_type = xxx */
CACHE_REMOVE (col->e_type);
g_hash_table_destroy(col->hash_of_entities);
col->e_type = NULL;
col->hash_of_entities = NULL;
g_free (col);
}
static gboolean
coll_destroy(gpointer key, gpointer value, gpointer not_used)
/* =============================================================== */
/* getters */
QofIdType
qof_collection_get_type (QofCollection *col)
{
QofCollection *col = value;
qof_collection_destroy (col);
return TRUE;
return col->e_type;
}
struct _QofEntityTable
{
GHashTable * hash_by_guid;
GHashTable * hash_of_collections;
};
static inline QofCollection *
entity_get_collection (QofEntityTable *entity_table, QofIdType entity_type)
{
QofCollection *col;
col = g_hash_table_lookup (entity_table->hash_of_collections, entity_type);
if (col) return col;
col = qof_collection_new (entity_type);
/* XXX should use string_cache instead of strdup */
/* Need strdup because values are sometimes freed */
/* this is a memory leak, since malloc'ed value is not freed */
g_hash_table_insert (entity_table->hash_of_collections,
(gpointer)g_strdup(entity_type), col);
return col;
}
/* =============================================================== */
/* Almost everything below is obsolete and should be removed */
/* XXX this structure should be replaced by QofEntity ASAP */
typedef struct entity_node
static void
qof_collection_remove_entity (QofEntity *ent)
{
QofIdType entity_type;
gpointer entity;
} EntityNode;
/** Function implementations ****************************************/
static gboolean
entity_node_destroy(gpointer key, gpointer value, gpointer not_used)
{
GUID *guid = key;
EntityNode *e_node = value;
CACHE_REMOVE (e_node->entity_type);
e_node->entity_type = QOF_ID_NONE;
e_node->entity = NULL;
guid_free(guid);
g_free(e_node);
return TRUE;
QofCollection *col = ent->collection;
if (!col) return;
g_hash_table_remove (col->hash_of_entities, &ent->guid);
ent->collection = NULL;
}
void
qof_entity_destroy (QofEntityTable *entity_table)
qof_collection_insert_entity (QofCollection *col, QofEntity *ent)
{
if (entity_table == NULL)
return;
g_hash_table_foreach_remove (entity_table->hash_by_guid, entity_node_destroy,
NULL);
g_hash_table_destroy (entity_table->hash_by_guid);
entity_table->hash_by_guid = NULL;
g_hash_table_foreach_remove (entity_table->hash_of_collections,
coll_destroy, NULL);
g_hash_table_destroy (entity_table->hash_of_collections);
entity_table->hash_of_collections = NULL;
g_free (entity_table);
if (guid_equal(&ent->guid, guid_null())) return;
g_return_if_fail (col->e_type == ent->e_type);
qof_collection_remove_entity (ent);
g_hash_table_insert (col->hash_of_entities, &ent->guid, ent);
ent->collection = col;
}
#if QOFID_DEBUG
static void
print_node(gpointer key, gpointer value, gpointer not_used)
QofEntity *
qof_collection_lookup_entity (QofCollection *col, const GUID * guid)
{
GUID *guid = key;
EntityNode *node = value;
fprintf(stderr, "%s %s %p\n",
guid_to_string(guid), node->entity_type, node->entity);
QofEntity *ent;
g_return_val_if_fail (col, NULL);
if (guid == NULL) return NULL;
ent = g_hash_table_lookup (col->hash_of_entities, guid->data);
return ent;
}
static void
summarize_table (QofEntityTable *entity_table)
{
if (entity_table == NULL)
return;
g_hash_table_foreach (entity_table->hash_by_guid, print_node, NULL);
}
#endif /* QOFID_DEBUG */
QofEntityTable *
qof_entity_new (void)
{
QofEntityTable *entity_table;
entity_table = g_new0 (QofEntityTable, 1);
entity_table->hash_by_guid = g_hash_table_new (id_hash, id_compare);
entity_table->hash_of_collections = g_hash_table_new (g_str_hash, g_str_equal);
qof_entity_store (entity_table, NULL, guid_null(), QOF_ID_NULL);
return entity_table;
}
/* XXX There should be no need for this after we start
* using QofEntity everywhere, and, once we do that, there will be
* no need for the hash_by_guid */
QofIdType
qof_entity_type (QofEntityTable *entity_table, const GUID * guid)
{
EntityNode *e_node;
if (guid == NULL)
return QOF_ID_NONE;
g_return_val_if_fail (entity_table, QOF_ID_NONE);
e_node = g_hash_table_lookup (entity_table->hash_by_guid, guid->data);
if (e_node == NULL)
return QOF_ID_NONE;
return e_node->entity_type;
}
void
qof_entity_guid_new (QofEntityTable *entity_table, GUID *guid)
{
if (guid == NULL)
return;
g_return_if_fail (entity_table);
do
{
guid_new(guid);
if (qof_entity_type (entity_table, guid) == QOF_ID_NONE)
break;
PWARN("duplicate id created, trying again");
} while(1);
}
gpointer
qof_entity_lookup (QofEntityTable *entity_table,
const GUID * guid, QofIdType entity_type)
{
QofCollection *col;
EntityNode *e_node;
g_return_val_if_fail (entity_table, NULL);
if (guid == NULL)
return NULL;
col = entity_get_collection (entity_table, entity_type);
e_node = g_hash_table_lookup (col->hash_of_entities, guid->data);
if (e_node == NULL)
return NULL;
return e_node->entity;
}
static void
entity_store_by_type (QofEntityTable *entity_table,
GUID *new_guid, EntityNode *e_node)
{
QofCollection *col;
col = entity_get_collection (entity_table, e_node->entity_type);
g_hash_table_insert (col->hash_of_entities, new_guid, e_node);
}
void
qof_entity_store (QofEntityTable *entity_table, gpointer entity,
const GUID * guid, QofIdType entity_type)
{
EntityNode *e_node;
GUID *new_guid;
g_return_if_fail (entity_table);
if (guid == NULL)
return;
if (!entity_type) return;
if (guid_equal(guid, guid_null())) return;
qof_entity_remove (entity_table, guid);
e_node = g_new(EntityNode, 1);
e_node->entity_type = CACHE_INSERT (entity_type);
e_node->entity = entity;
new_guid = guid_malloc ();
if (!new_guid) return;
*new_guid = *guid;
g_hash_table_insert (entity_table->hash_by_guid, new_guid, e_node);
entity_store_by_type (entity_table, new_guid, e_node);
}
static void
entity_remove_by_type (QofEntityTable *entity_table, GUID *guid, QofIdType type)
{
QofCollection *col;
col = entity_get_collection (entity_table, type);
g_hash_table_remove (col->hash_of_entities, guid);
}
void
qof_entity_remove (QofEntityTable *entity_table, const GUID * guid)
{
EntityNode *e_node;
gpointer old_guid;
gpointer node;
g_return_if_fail (entity_table);
if (guid == NULL)
return;
if (g_hash_table_lookup_extended(entity_table->hash_by_guid, guid, &old_guid, &node))
{
e_node = node;
if (!safe_strcmp (e_node->entity_type, QOF_ID_NULL))
return;
g_hash_table_remove (entity_table->hash_by_guid, old_guid);
entity_remove_by_type (entity_table, old_guid, e_node->entity_type);
entity_node_destroy (old_guid, node, NULL);
}
}
/* =============================================================== */
struct _iterate {
QofEntityForeachCB fcn;
QofEntityForeachCB fcn;
gpointer data;
QofIdType type;
};
static void foreach_cb (gpointer key, gpointer item, gpointer arg)
{
struct _iterate *iter = arg;
EntityNode *e_node = item;
QofEntity *ent = item;
iter->fcn (e_node->entity, iter->data);
iter->fcn (ent, iter->data);
}
void
qof_entity_foreach (QofEntityTable *entity_table, QofIdType type,
qof_collection_foreach (QofCollection *col,
QofEntityForeachCB cb_func, gpointer user_data)
{
QofCollection *col;
struct _iterate iter;
g_return_if_fail (entity_table);
g_return_if_fail (type);
g_return_if_fail (*type);
g_return_if_fail (col);
g_return_if_fail (cb_func);
iter.fcn = cb_func;
iter.data = user_data;
iter.type = type;
/* Iterate over the objects of the particular type */
col = entity_get_collection (entity_table, type);
g_hash_table_foreach (col->hash_of_entities, foreach_cb, &iter);
}
/* =============================================================== */

View File

@ -62,31 +62,46 @@ typedef const char * QofIdTypeConst;
#define QOF_ID_NULL "null"
#define QOF_ID_SESSION "Session"
/* simple,cheesy cast but holds water for now */
#define QOF_ENTITY(object) ((QofEntity *)(object))
typedef struct QofEntity_s QofEntity;
typedef struct _QofEntityTable QofEntityTable;
typedef struct QofCollection_s QofCollection;
struct QofEntity_s
{
QofIdType e_type;
GUID guid;
QofEntityTable * e_table;
QofCollection * collection;
};
/** Initialise the memory associated with an entity */
void qof_entity_init (QofEntity *, QofIdType, QofEntityTable *);
void qof_entity_init (QofEntity *, QofIdType, QofCollection *);
/** release the data associated with this entity. Dont actually free
/** Release the data associated with this entity. Dont actually free
* the memory associated with the instance. */
void qof_entity_release (QofEntity *);
/** The stuff below is obsolete and should be removed ASAP. */
/* Return the GUID of this entity */
GUID * qof_entity_get_guid (QofEntity *);
/** Return the type of the indicated guid */
QofIdType qof_entity_type (QofEntityTable *entity_table, const GUID * guid);
/** collections of entities */
QofCollection * qof_collection_new (QofIdType type);
void qof_collection_destroy (QofCollection *col);
/** return the type that the collection stores */
QofIdType qof_collection_get_type (QofCollection *);
/** Find the entity going only from its guid */
QofEntity * qof_collection_lookup_entity (QofCollection *, const GUID *);
/* Callback type for qof_entity_foreach */
typedef void (*QofEntityForeachCB) (gpointer object, gpointer user_data);
typedef void (*QofEntityForeachCB) (QofEntity *, gpointer user_data);
void qof_collection_foreach (QofCollection *,
QofEntityForeachCB, gpointer user_data);
#endif /* QOF_ID_H */
/** @} */

View File

@ -0,0 +1,69 @@
/********************************************************************\
* qofinstance-p.h -- private fields common to all object instances *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
/*
* Object instance holds many common fields that most
* gnucash objects use.
*
* Copyright (C) 2003 Linas Vepstas <linas@linas.org>
*/
#ifndef QOF_INSTANCE_P_H
#define QOF_INSTANCE_P_H
#include "qofinstance.h"
struct QofInstance_s
{
/*
* UNDER CONSTRUCTION!
* This is mostly scaffolding for now,
* eventually, it may hold more fields, such as refrence counting...
*
*/
/* Globally unique id identifying this instance */
QofEntity entity;
/* The entity_table in which this instance is stored */
QofBook * book;
/* kvp_data is a key-value pair database for storing arbirtary
* information associated with this instance.
* See src/engine/kvp_doc.txt for a list and description of the
* important keys. */
KvpFrame *kvp_data;
/* Keep track of nesting level of begin/end edit calls */
int editlevel;
/* In process of being destroyed */
gboolean do_free;
/* This instance has not been saved yet */
gboolean dirty;
};
/** reset the dirty flag */
void qof_instance_mark_clean (QofInstance *);
void qof_instance_set_slots (QofInstance *, KvpFrame *);
#endif /* QOF_INSTANCE_P_H */

View File

@ -35,6 +35,7 @@
#include "qofid.h"
#include "qofid-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
static short module = MOD_ENGINE;
@ -43,13 +44,16 @@ static short module = MOD_ENGINE;
void
qof_instance_init (QofInstance *inst, QofIdType type, QofBook *book)
{
QofCollection *col;
inst->book = book;
inst->kvp_data = kvp_frame_new();
inst->editlevel = 0;
inst->do_free = FALSE;
inst->dirty = FALSE;
qof_entity_init (&inst->entity, type, book->entity_table);
col = qof_book_get_collection (book, type);
qof_entity_init (&inst->entity, type, col);
}
void
@ -90,6 +94,29 @@ qof_instance_is_dirty (QofInstance *inst)
return inst->dirty;
}
/* ========================================================== */
/* setters */
void
qof_instance_mark_clean (QofInstance *inst)
{
if(!inst) return;
inst->dirty = FALSE;
}
void
qof_instance_set_slots (QofInstance *inst, KvpFrame *frm)
{
if (!inst) return;
if (inst->kvp_data && (inst->kvp_data != frm))
{
kvp_frame_delete(inst->kvp_data);
}
inst->dirty = TRUE;
inst->kvp_data = frm;
}
/* ========================================================== */
void
@ -101,11 +128,11 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
/* Make a note of where the copy came from */
gnc_kvp_bag_add (to->kvp_data, "gemini", now,
"inst_guid", &from->entity.guid,
"book_guid", &from->book->guid,
"book_guid", &from->book->entity.guid,
NULL);
gnc_kvp_bag_add (from->kvp_data, "gemini", now,
"inst_guid", &to->entity.guid,
"book_guid", &to->book->guid,
"book_guid", &to->book->entity.guid,
NULL);
to->dirty = TRUE;
@ -114,6 +141,7 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
QofInstance *
qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
{
QofCollection *col;
KvpFrame *fr;
GUID * twin_guid;
QofInstance * twin;
@ -126,8 +154,8 @@ qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
twin_guid = kvp_frame_get_guid (fr, "inst_guid");
twin = qof_entity_lookup (target_book->entity_table,
twin_guid, src->entity.e_type);
col = qof_book_get_collection (target_book, src->entity.e_type);
twin = (QofInstance *) qof_collection_lookup_entity (col, twin_guid);
LEAVE (" found twin=%p", twin);
return twin;

View File

@ -41,36 +41,6 @@
typedef struct QofInstance_s QofInstance;
struct QofInstance_s
{
/*
* UNDER CONSTRUCTION!
* This is mostly scaffolding for now,
* eventually, it may hold more fields, such as refrence counting...
*
*/
/* Globally unique id identifying this instance */
QofEntity entity;
/* The entity_table in which this instance is stored */
QofBook * book;
/* kvp_data is a key-value pair database for storing arbirtary
* information associated with this instance.
* See src/engine/kvp_doc.txt for a list and description of the
* important keys. */
KvpFrame *kvp_data;
/* Keep track of nesting level of begin/end edit calls */
int editlevel;
/* In process of being destroyed */
gboolean do_free;
/* This instance has not been saved yet */
gboolean dirty;
};
/** Initialise the memory associated with an instance */
void qof_instance_init (QofInstance *, QofIdType, QofBook *);

View File

@ -84,7 +84,7 @@ gboolean qof_object_is_dirty (QofBook *book)
QofObject *obj = l->data;
if (obj->is_dirty)
if (obj->is_dirty (book))
return TRUE;
return TRUE;
}
return FALSE;
}
@ -114,7 +114,7 @@ void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
}
void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
QofEntityForeachCB cb, gpointer user_data)
QofForeachCB cb, gpointer user_data)
{
const QofObject *obj;
@ -147,7 +147,7 @@ qof_object_printable (QofIdTypeConst type_name, gpointer obj)
if (b_obj->printable)
return (b_obj->printable (obj));
return NULL;
return NULL;
}
const char * qof_object_get_type_label (QofIdTypeConst type_name)
@ -230,15 +230,15 @@ const QofObject * qof_object_lookup (QofIdTypeConst name)
for (iter = object_modules; iter; iter = iter->next) {
obj = iter->data;
if (!safe_strcmp (obj->name, name))
if (!safe_strcmp (obj->e_type, name))
return obj;
}
return NULL;
}
gboolean qof_object_register_backend (QofIdTypeConst type_name,
const char *backend_name,
gpointer be_data)
const char *backend_name,
gpointer be_data)
{
GHashTable *ht;
g_return_val_if_fail (object_is_initialized, FALSE);
@ -263,7 +263,7 @@ gboolean qof_object_register_backend (QofIdTypeConst type_name,
}
gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
const char *backend_name)
const char *backend_name)
{
GHashTable *ht;
@ -279,8 +279,8 @@ gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
}
struct foreach_data {
QofForeachBackendTypeCB cb;
gpointer user_data;
QofForeachBackendTypeCB cb;
gpointer user_data;
};
static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
@ -295,8 +295,8 @@ static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
}
void qof_object_foreach_backend (const char *backend_name,
QofForeachBackendTypeCB cb,
gpointer user_data)
QofForeachBackendTypeCB cb,
gpointer user_data)
{
GHashTable *ht;
struct foreach_data cb_data;

View File

@ -40,6 +40,7 @@
typedef struct _QofObject QofObject;
typedef void (*QofForeachCB) (gpointer obj, gpointer user_data);
typedef void (*QofForeachTypeCB) (QofObject *type, gpointer user_data);
typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
gpointer backend_data,
@ -49,7 +50,7 @@ typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
struct _QofObject
{
gint interface_version; /* of this object interface */
QofIdType name; /* the Object's QOF_ID */
QofIdType e_type; /* the Object's QOF_ID */
const char * type_label; /* "Printable" type-label string */
/* book_begin is called from within the Book routines to create
@ -69,7 +70,7 @@ struct _QofObject
/* foreach() is used to execute a callback over each object
* stored in the particular book
*/
void (*foreach)(QofBook *, QofEntityForeachCB, gpointer);
void (*foreach)(QofBook *, QofForeachCB, gpointer);
/* Given a particular object, return a printable string */
/* Argument should really be QofInstance not gpointer.. */
@ -86,7 +87,7 @@ void qof_object_shutdown (void);
void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data);
void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
QofEntityForeachCB cb, gpointer user_data);
QofForeachCB cb, gpointer user_data);
const char * qof_object_printable (QofIdTypeConst type_name, gpointer obj);

View File

@ -10,11 +10,13 @@
#include <sys/stat.h>
#include <unistd.h>
#include "AccountP.h"
#include "Group.h"
#include "gnc-date.h"
#include "gnc-engine.h"
#include "gnc-engine-util.h"
#include "Transaction.h"
#include "TransactionP.h"
#include "qofquerycore.h"
#include "test-engine-stuff.h"
@ -988,18 +990,15 @@ get_random_transaction_with_currency(QofBook *book,
ret = xaccMallocTransaction(book);
xaccTransBeginEdit(ret);
xaccTransSetCurrency (ret,
currency ? currency :
get_random_commodity (book));
set_tran_random_string(ret, xaccTransSetNum);
set_tran_random_string(ret, xaccTransSetDescription);
trn_add_ran_timespec(ret, xaccTransSetDatePostedTS);
trn_add_ran_timespec(ret, xaccTransSetDateEnteredTS);
set_tran_random_string(ret, xaccTransSetDescription);
xaccTransSetSlots_nc(ret, get_random_kvp_frame());
add_random_splits(book, ret);
@ -1012,7 +1011,6 @@ get_random_transaction_with_currency(QofBook *book,
}
xaccTransCommitEdit(ret);
return ret;
}
@ -1585,7 +1583,6 @@ add_random_transactions_to_book (QofBook *book, gint num_transactions)
Split *split;
com = get_random_commodity_from_table (table);
trans = get_random_transaction_with_currency (book, com);
xaccTransBeginEdit (trans);
@ -1600,7 +1597,6 @@ add_random_transactions_to_book (QofBook *book, gint num_transactions)
xaccTransCommitEdit (trans);
}
g_list_free (accounts);
}

View File

@ -7,6 +7,7 @@ test-load-engine
test-commodities
test-date
test-freq-spec
test-guid
test-group-vs-book
test-lots
test-object

View File

@ -18,14 +18,18 @@ LDADD = \
${GLIB_LIBS} \
-lltdl
# these tests are ordered kind more or less in the order
# that they should be executed, with more basic tests coming first.
#
TESTS = \
test-load-engine \
test-create-account \
test-commodities \
test-guid \
test-date \
test-object \
test-commodities \
test-create-account \
test-group-vs-book \
test-lots \
test-object \
test-period \
test-querynew \
test-query \
@ -53,6 +57,7 @@ noinst_PROGRAMS = \
test-commodities \
test-date \
test-freq-spec \
test-guid \
test-group-vs-book \
test-load-engine \
test-lots \

View File

@ -1,5 +1,6 @@
This directory contains test cases to excercise basic GnuCash engine functions.
This directory contains unit test cases to excercise basic
GnuCash engine functions.
To run the tests, just do 'make check'

View File

@ -2,7 +2,6 @@
#include <glib.h>
#include <time.h>
#include "TransLog.h"
#include "gnc-date.h"
#include "gnc-module.h"
#include "test-stuff.h"

View File

@ -0,0 +1,69 @@
/* Test file created by Linas Vepstas <linas@linas.org>
* Try to create duplicate GUID's, which should never happen.
*
* October 2003
* License: GPL
*/
#include <ctype.h>
#include <glib.h>
#include "gnc-module.h"
#include "test-stuff.h"
#include "test-engine-stuff.h"
#include "qofbook.h"
#include "qofid.h"
#include "qofid-p.h"
#include "qofsession.h"
static void
run_test (void)
{
int i;
QofSession *sess;
QofBook *book;
QofEntity *eblk;
QofCollection *col;
QofIdType type;
sess = get_random_session ();
book = qof_session_get_book (sess);
do_test ((NULL != book), "book not created");
col = qof_book_get_collection (book, "asdf");
type = qof_collection_get_type (col);
#define NENT 500123
eblk = g_new0(QofEntity, NENT);
for (i=0; i<NENT; i++)
{
QofEntity *ent = &eblk[i];
guid_new(&ent->guid);
do_test ((NULL == qof_collection_lookup_entity (col, &ent->guid)),
"duplicate guid");
ent->e_type = type;
qof_collection_insert_entity (col, ent);
}
}
static void
main_helper (void *closure, int argc, char **argv)
{
g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING );
do_test((NULL!=gnc_module_load("gnucash/engine", 0)), "couldn't load engine");
run_test ();
print_test_results();
exit(get_rv());
}
int
main (int argc, char **argv)
{
scm_boot_guile(argc, argv, main_helper, NULL);
return 0;
}

View File

@ -26,22 +26,12 @@ run_test (void)
QofBook *book;
AccountGroup *grp;
if(!gnc_module_load("gnucash/engine", 0))
{
failure("couldn't load gnucash/engine");
exit(get_rv());
}
/* --------------------------------------------------------- */
/* In the first test, we will merely try to see if we can run
* without crashing. We don't check to see if data is good. */
sess = get_random_session ();
book = qof_session_get_book (sess);
if (!book)
{
failure("book not created");
exit(get_rv());
}
do_test ((NULL != book), "book not created");
add_random_transactions_to_book (book, 720);
@ -60,6 +50,9 @@ run_test (void)
static void
main_helper (void *closure, int argc, char **argv)
{
g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING );
do_test((NULL!=gnc_module_load("gnucash/engine", 0)), "couldn't load engine");
run_test ();
print_test_results();

View File

@ -13,7 +13,7 @@
#define TEST_MODULE_NAME "object-test"
#define TEST_MODULE_DESC "Test Object"
static void foreach (QofBook *, QofEntityForeachCB, gpointer);
static void foreach (QofBook *, QofForeachCB, gpointer);
static const char * printable (gpointer obj);
static void test_printable (const char *name, gpointer obj);
static void test_foreach (QofBook *, const char *);
@ -52,7 +52,7 @@ static void test_object (void)
}
static void
foreach (QofBook *book, QofEntityForeachCB cb, gpointer u_d)
foreach (QofBook *book, QofForeachCB cb, gpointer u_d)
{
int *foo = u_d;