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 "qofbook-p.h"
#include "qofclass.h" #include "qofclass.h"
#include "qofid-p.h" #include "qofid-p.h"
#include "qofinstance-p.h"
#include "qofobject.h" #include "qofobject.h"
static short module = MOD_ACCOUNT; 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);
G_INLINE_FUNC void G_INLINE_FUNC void
mark_account (Account *account) mark_account (Account *account)
{ {
if (account->parent) if (account->parent) account->parent->saved = FALSE;
account->parent->saved = FALSE; account->inst.dirty = TRUE;
account_event (account);
} }
/********************************************************************\ /********************************************************************\
@ -335,16 +326,27 @@ xaccFreeAccount (Account *acc)
void void
xaccAccountBeginEdit (Account *acc) 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 void
xaccAccountCommitEdit (Account *acc) xaccAccountCommitEdit (Account *acc)
{ {
QofBackend * be;
GNC_COMMIT_EDIT_PART1 (&acc->inst); GNC_COMMIT_EDIT_PART1 (&acc->inst);
ENTER (" ");
/* If marked for deletion, get rid of subaccounts first, /* If marked for deletion, get rid of subaccounts first,
* and then the splits ... */ * and then the splits ... */
@ -391,39 +393,9 @@ xaccAccountCommitEdit (Account *acc)
xaccGroupInsertAccount(acc->parent, acc); xaccGroupInsertAccount(acc->parent, acc);
} }
/* See if there's a backend. If there is, invoke it. */ GNC_COMMIT_EDIT_PART2 (&acc->inst, on_err, noop, acc_free);
be = acc->inst.book->backend;
if (be && be->commit)
{
QofBackendError errcode;
/* clear errors */ gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY);
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 (" ");
} }
void void
@ -435,7 +407,6 @@ xaccAccountDestroy (Account *acc)
xaccAccountCommitEdit (acc); xaccAccountCommitEdit (acc);
} }
void void
xaccAccountSetVersion (Account *acc, gint32 vers) xaccAccountSetVersion (Account *acc, gint32 vers)
{ {
@ -450,13 +421,6 @@ xaccAccountGetVersion (Account *acc)
return (acc->version); return (acc->version);
} }
QofBook *
xaccAccountGetBook (Account *account)
{
if (!account) return NULL;
return account->inst.book;
}
/********************************************************************\ /********************************************************************\
\********************************************************************/ \********************************************************************/
@ -705,56 +669,6 @@ xaccAccountBringUpToDate(Account *acc)
xaccAccountRecomputeBalance(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 * Account *
xaccAccountLookup (const GUID *guid, QofBook *book) xaccAccountLookup (const GUID *guid, QofBook *book)
{ {
QofCollection *col;
if (!guid || !book) return NULL; if (!guid || !book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book), col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
guid, GNC_ID_ACCOUNT); return (Account *) qof_collection_lookup_entity (col, guid);
}
Account *
xaccAccountLookupDirect (GUID guid, QofBook *book)
{
if (!book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book),
&guid, GNC_ID_ACCOUNT);
} }
/********************************************************************\ /********************************************************************\
@ -1044,7 +951,7 @@ xaccAccountRemoveSplit (Account *acc, Split *split)
mark_account (acc); mark_account (acc);
if (split->parent) 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); xaccAccountCommitEdit(acc);
@ -1131,7 +1038,7 @@ xaccAccountRecomputeBalance (Account * acc)
acc->reconciled_balance = reconciled_balance; acc->reconciled_balance = reconciled_balance;
acc->balance_dirty = FALSE; 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 */ /* gncObject function implementation and registration */
static void 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 (book);
g_return_if_fail (cb); g_return_if_fail (cb);
et = qof_book_get_entity_table (book); col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
qof_entity_foreach (et, GNC_ID_ACCOUNT, cb, ud); qof_collection_foreach (col, (QofEntityForeachCB) cb, ud);
} }
static QofObject account_object_def = { static QofObject account_object_def = {
QOF_OBJECT_VERSION, interface_version: QOF_OBJECT_VERSION,
GNC_ID_ACCOUNT, e_type: GNC_ID_ACCOUNT,
"Account", type_label: "Account",
NULL, /* book_begin */ book_begin: NULL,
NULL, /* book_end */ book_end: NULL,
NULL, /* is_dirty */ is_dirty: NULL,
NULL, /* mark_clean */ mark_clean: NULL,
account_foreach, /* foreach */ foreach: account_foreach,
(const char* (*)(gpointer)) xaccAccountGetName /* printable */ printable: (const char* (*)(gpointer)) xaccAccountGetName
}; };
gboolean xaccAccountRegister (void) gboolean xaccAccountRegister (void)
{ {
static QofParam params[] = { static QofParam params[] = {
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccAccountGetSlots, NULL },
{ ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, NULL }, { ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, NULL },
{ ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, NULL }, { ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, NULL },
{ ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, 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 }, { 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_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_guid, NULL },
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (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 }, { NULL },
}; };

View File

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

View File

@ -52,6 +52,7 @@
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h" #include "qofid.h"
#include "qofinstance.h" #include "qofinstance.h"
#include "qofinstance-p.h"
/** STRUCTS *********************************************************/ /** STRUCTS *********************************************************/
@ -201,4 +202,9 @@ gint32 xaccAccountGetVersion (Account*);
/* Register Accounts with the engine */ /* Register Accounts with the engine */
gboolean xaccAccountRegister (void); 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 */ #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: * This still needs to deal with:
* . exceptions * . exceptions
* . 13 periods: (4 weeks/period 4x13=52 weeks/year)
* . yearly 360/365? * . yearly 360/365?
* . re-based frequencies [based around a non-standard [read: * . re-based frequencies [based around a non-standard [read:
* not-Jan-1-based/fiscal] year] * not-Jan-1-based/fiscal] year]
* . "business days" -- m-f sans holidays [per-user list thereof] * . "business days" -- m-f sans holidays [per-user list thereof]
**/ **/
struct gncp_freq_spec { struct gncp_freq_spec
{
QofEntity entity;
FreqType type; FreqType type;
UIFreqType uift; UIFreqType uift;
union u { union u {
struct { struct {
/** The date on which the single event occurs. */ /** The date on which the single event occurs. */
@ -107,8 +110,6 @@ struct gncp_freq_spec {
GList *subSpecs; GList *subSpecs;
} composites; } composites;
} s; } s;
GUID guid;
QofEntityTable *entity_table;
}; };
#endif /* XACC_FREQSPECP_H */ #endif /* XACC_FREQSPECP_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,6 +26,8 @@
#include "SchedXaction.h" #include "SchedXaction.h"
#include "qofid.h" #include "qofid.h"
#include "qofid-p.h"
#include "qofinstance-p.h"
/** /**
* A single scheduled transaction. * A single scheduled transaction.
@ -50,6 +52,7 @@
**/ **/
struct gncp_SchedXaction struct gncp_SchedXaction
{ {
QofInstance inst;
gchar *name; gchar *name;
FreqSpec *freq; FreqSpec *freq;
@ -74,17 +77,10 @@ struct gncp_SchedXaction
gint advanceRemindDays; gint advanceRemindDays;
Account *template_acct; Account *template_acct;
GUID guid;
QofEntityTable *entity_table;
/** The list of deferred SX instances. This list is of temporalStateData /** The list of deferred SX instances. This list is of temporalStateData
* instances. */ * instances. */
GList /* <temporalStateData*> */ *deferredList; GList /* <temporalStateData*> */ *deferredList;
/* Changed since last save? */
gboolean dirty;
KvpFrame *kvp_data;
}; };
/** Just the variable temporal bits from the SX structure. */ /** Just the variable temporal bits from the SX structure. */
@ -94,4 +90,6 @@ typedef struct _temporalStateData {
gint num_inst; gint num_inst;
} temporalStateData; } 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; GList *node;
if (!trans) return; if (!trans) return;
g_return_if_fail (root);
for (node = trans->splits; node; node = node->next) 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 */ /* Put split into account before setting split value */
if (!balance_split) if (!balance_split)
{ {
balance_split = xaccMallocSplit (trans->book); balance_split = xaccMallocSplit (trans->inst.book);
xaccAccountBeginEdit (account); xaccAccountBeginEdit (account);
xaccAccountInsertSplit (account, balance_split); xaccAccountInsertSplit (account, balance_split);
@ -544,7 +545,7 @@ xaccTransScrubCurrency (Transaction *trans)
currency = xaccTransGetCurrency (trans); currency = xaccTransGetCurrency (trans);
if (currency) return; if (currency) return;
currency = xaccTransFindOldCommonCurrency (trans, trans->book); currency = xaccTransFindOldCommonCurrency (trans, trans->inst.book);
if (currency) if (currency)
{ {
xaccTransBeginEdit (trans); xaccTransBeginEdit (trans);

View File

@ -295,7 +295,7 @@ remove_guids (Split *sa, Split *sb)
/* Find and remove the matching guid's */ /* Find and remove the matching guid's */
ksub = gnc_kvp_bag_find_by_guid (sa->kvp_data, "lot-split", ksub = gnc_kvp_bag_find_by_guid (sa->kvp_data, "lot-split",
"peer_guid", &sb->guid); "peer_guid", &sb->entity.guid);
if (ksub) if (ksub)
{ {
gnc_kvp_bag_remove_frame (sa->kvp_data, "lot-split", 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 */ /* Now do it in the other direction */
ksub = gnc_kvp_bag_find_by_guid (sb->kvp_data, "lot-split", ksub = gnc_kvp_bag_find_by_guid (sb->kvp_data, "lot-split",
"peer_guid", &sa->guid); "peer_guid", &sa->entity.guid);
if (ksub) if (ksub)
{ {
gnc_kvp_bag_remove_frame (sb->kvp_data, "lot-split", 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 "guid.h"
#include "kvp_frame.h" #include "kvp_frame.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofinstance.h"
/** @name Split Reconciled field values /** @name Split Reconciled field values
If you change these If you change these
@ -135,17 +136,18 @@ void xaccTransCommitEdit (Transaction *trans);
void xaccTransRollbackEdit (Transaction *trans); void xaccTransRollbackEdit (Transaction *trans);
/** The xaccTransIsOpen() method returns TRUE if the transaction /** 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); gboolean xaccTransIsOpen (const Transaction *trans);
/** The xaccTransLookup() subroutine will return the /** The xaccTransLookup() subroutine will return the
transaction associated with the given id, or NULL transaction associated with the given id, or NULL
if there is no such transaction. */ if there is no such transaction. */
Transaction * xaccTransLookup (const GUID *guid, QofBook *book); Transaction * xaccTransLookup (const GUID *guid, QofBook *book);
/** The xaccTransLookup() subroutine will return the #define xaccTransLookupDirect(g,b) xaccTransLookup(&(g),b)
transaction associated with the given id, or NULL
if there is no such transaction. */
Transaction * xaccTransLookupDirect (GUID guid, QofBook *book);
/** \warning XXX FIXME /** \warning XXX FIXME
* gnc_book_count_transactions is a utility function, * gnc_book_count_transactions is a utility function,
@ -158,16 +160,6 @@ guint gnc_book_count_transactions(QofBook *book);
/** @name Transaction general getters/setters */ /** @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, /** Sorts the splits in a transaction, putting the debits first,
* followed by the credits. * followed by the credits.
@ -178,17 +170,6 @@ void xaccTransSortSplits (Transaction *trans);
*/ */
void xaccTransDump (Transaction *trans, const char *tag); 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 /** Set the Transaction Type
* *
* See #define TXN_TYPE_NONE, TXN_TYPE_INVOICE and TXN_TYPE_PAYMENT */ * 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); 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 /** The memo is an arbitrary string associated with a split. It is
* intended to hold a short (zero to forty character) string that is * intended to hold a short (zero to forty character) string that is
* displayed by the GUI along with this split. Users typically type * 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 * split associated with the given id, or NULL
* if there is no such split. */ * if there is no such split. */
Split * xaccSplitLookup (const GUID *guid, QofBook *book); Split * xaccSplitLookup (const GUID *guid, QofBook *book);
/** Returns the split associated with the given id, or NULL if there #define xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
* is no such split. */
Split * xaccSplitLookupDirect (GUID guid, QofBook *book);
/** /**
@ -887,5 +857,13 @@ Timespec xaccTransGetVoidTime(const Transaction *tr);
#define RECONCILED_MATCH_TYPE "reconciled-match" #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 */ #endif /* XACC_TRANSACTION_H */
/** @} */ /** @} */

View File

@ -56,6 +56,9 @@
#include "qofbackend.h" #include "qofbackend.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h" #include "qofid.h"
#include "qofid-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
/** STRUCTS *********************************************************/ /** STRUCTS *********************************************************/
@ -90,7 +93,7 @@
struct split_s struct split_s
{ {
GUID guid; /* globally unique id */ QofEntity entity; /* globally unique id */
QofBook *book; /* The enitity table where this split is stored. */ QofBook *book; /* The enitity table where this split is stored. */
@ -160,12 +163,7 @@ struct split_s
struct transaction_s struct transaction_s
{ {
/* guid is a globally unique identifier which can be used to QofInstance inst; /* glbally unique id */
* reference the transaction.
*/
GUID guid;
QofBook *book; /* The entity_table where the transaction is stored */
Timespec date_entered; /* date register entry was made */ Timespec date_entered; /* date register entry was made */
Timespec date_posted; /* date transaction was posted at bank */ Timespec date_posted; /* date transaction was posted at bank */
@ -181,12 +179,6 @@ struct transaction_s
*/ */
char * description; 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 /* The common_currency field is the balancing common currency for
* all the splits in the transaction. Alternate, better(?) name: * all the splits in the transaction. Alternate, better(?) name:
* "valuation currency": it is the currency in which all of the * "valuation currency": it is the currency in which all of the
@ -207,9 +199,6 @@ struct transaction_s
* corresponding to the current traversal. */ * corresponding to the current traversal. */
unsigned char marker; 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, /* The orig pointer points at a copy of the original transaction,
* before editing was started. This orig copy is used to rollback * before editing was started. This orig copy is used to rollback
* any changes made if/when the edit is abandoned. * 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 /* Set the transaction's GUID. This should only be done when reading
* a transaction from a datafile, or some other external source. Never * a transaction from a datafile, or some other external source. Never
* call this on an existing transaction! */ * 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 /* Set the split's GUID. This should only be done when reading
* a split from a datafile, or some other external source. Never * a split from a datafile, or some other external source. Never
* call this on an existing split! */ * 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 /* The xaccFreeSplit() method simply frees all memory associated
* with the split. It does not verify that the split isn't * with the split. It does not verify that the split isn't
@ -302,6 +291,14 @@ void DxaccSplitSetSharePriceAndAmount (Split *split,
double amount); double amount);
void DxaccSplitSetShareAmount (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); gains_guid = kvp_value_get_guid (val);
if (!gains_guid) return NULL; if (!gains_guid) return NULL;
gains_split = qof_entity_lookup (qof_book_get_entity_table(split->book), /* Both splits will be in the same collection, so seearch there. */
gains_guid, GNC_ID_SPLIT); gains_split = (Split*) qof_collection_lookup_entity (split->entity.collection, gains_guid);
PINFO ("split=%p has gains-split=%p", split, gains_split); PINFO ("split=%p has gains-split=%p", split, gains_split);
return 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); g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
existing_acc_guid = kvp_value_get_guid(val); 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", kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
stock_acc_guid_kvpval); 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); g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
existing_acc_guid = kvp_value_get_guid(val); 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", kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
stock_acc_guid_kvpval); stock_acc_guid_kvpval);
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account-category", 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"); "associated-stock-account");
stock_account_guid = kvp_value_get_guid(stock_account_kvpval); 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, category_kvpval = kvp_frame_get_slot(current_account_kvpframe,
"associated-stock-account-category"); "associated-stock-account-category");

View File

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

View File

@ -41,11 +41,11 @@
#include "kvp_frame.h" #include "kvp_frame.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h" #include "qofid.h"
#include "qofid-p.h"
struct gnc_lot_struct struct gnc_lot_struct
{ {
/* Unique guid for this lot */ QofEntity entity; /* Unique guid for this lot */
GUID guid;
/* Book that this lot belongs to */ /* Book that this lot belongs to */
QofBook *book; QofBook *book;
@ -69,7 +69,7 @@ struct gnc_lot_struct
unsigned char marker; 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 */ /* Register with the Query engine */
void gnc_lot_register (void); void gnc_lot_register (void);

View File

@ -61,6 +61,7 @@ static short module = MOD_LOT;
static void static void
gnc_lot_init (GNCLot *lot, QofBook *book) gnc_lot_init (GNCLot *lot, QofBook *book)
{ {
QofCollection *col;
ENTER ("(lot=%p, book=%p)", lot, book); ENTER ("(lot=%p, book=%p)", lot, book);
lot->kvp_data = kvp_frame_new(); lot->kvp_data = kvp_frame_new();
lot->account = NULL; lot->account = NULL;
@ -69,8 +70,8 @@ gnc_lot_init (GNCLot *lot, QofBook *book)
lot->marker = 0; lot->marker = 0;
lot->book = book; lot->book = book;
qof_entity_guid_new (book->entity_table, &lot->guid); col = qof_book_get_collection (book, GNC_ID_LOT);
qof_entity_store (book->entity_table, lot, &lot->guid, GNC_ID_LOT); qof_entity_init (&lot->entity, GNC_ID_LOT, col);
LEAVE ("(lot=%p, book=%p)", lot, book); LEAVE ("(lot=%p, book=%p)", lot, book);
} }
@ -82,7 +83,7 @@ gnc_lot_new (QofBook *book)
lot = g_new (GNCLot, 1); lot = g_new (GNCLot, 1);
gnc_lot_init (lot, book); 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; return lot;
} }
@ -93,9 +94,9 @@ gnc_lot_destroy (GNCLot *lot)
if (!lot) return; if (!lot) return;
ENTER ("(lot=%p)", lot); 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) 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 * GNCLot *
gnc_lot_lookup (const GUID *guid, QofBook *book) gnc_lot_lookup (const GUID *guid, QofBook *book)
{ {
QofCollection *col;
if (!guid || !book) return NULL; if (!guid || !book) return NULL;
return qof_entity_lookup (qof_book_get_entity_table (book), col = qof_book_get_collection (book, GNC_ID_LOT);
guid, GNC_ID_LOT); return (GNCLot *) qof_collection_lookup_entity (col, guid);
} }
QofBook * QofBook *
@ -149,7 +132,6 @@ gnc_lot_get_book (GNCLot *lot)
return lot->book; return lot->book;
} }
/* ============================================================= */ /* ============================================================= */
gboolean gboolean
@ -292,7 +274,7 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
/* for recomputation of is-closed */ /* for recomputation of is-closed */
lot->is_closed = -1; 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 void
@ -310,7 +292,7 @@ gnc_lot_remove_split (GNCLot *lot, Split *split)
xaccAccountRemoveLot (lot->account, lot); xaccAccountRemoveLot (lot->account, lot);
lot->account = NULL; 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) void gnc_lot_register (void)
{ {
static const QofParam params[] = { 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_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_IS_CLOSED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gnc_lot_is_closed, NULL },
{ LOT_BALANCE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_lot_get_balance, NULL }, { LOT_BALANCE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_lot_get_balance, NULL },
{ NULL }, { NULL },

View File

@ -45,11 +45,11 @@
#include "gnc-engine.h" #include "gnc-engine.h"
#include "gnc-numeric.h" #include "gnc-numeric.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h"
GNCLot * gnc_lot_new (QofBook *); GNCLot * gnc_lot_new (QofBook *);
void gnc_lot_destroy (GNCLot *); void gnc_lot_destroy (GNCLot *);
const GUID * gnc_lot_get_guid (GNCLot *p);
GNCLot * gnc_lot_lookup (const GUID *guid, QofBook *book); GNCLot * gnc_lot_lookup (const GUID *guid, QofBook *book);
QofBook * gnc_lot_get_book (GNCLot *); QofBook * gnc_lot_get_book (GNCLot *);
@ -114,6 +114,8 @@ void gnc_lot_set_notes (GNCLot *, const char *);
* */ * */
KvpFrame * gnc_lot_get_slots (GNCLot *); 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_IS_CLOSED "is-closed?"
#define LOT_BALANCE "balance" #define LOT_BALANCE "balance"

View File

@ -32,12 +32,14 @@
#include "qofbackend.h" #include "qofbackend.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h" #include "qofid.h"
#include "qofid-p.h"
#include "qofinstance.h"
#include "qofinstance-p.h"
struct gnc_price_s struct gnc_price_s
{ {
/* 'public' data fields */ /* 'public' data fields */
GUID guid; /* globally unique price id */ QofInstance inst; /* globally unique object identifier */
QofBook *book; /* book to which this price belongs to */
GNCPriceDB *db; GNCPriceDB *db;
gnc_commodity *commodity; gnc_commodity *commodity;
@ -50,11 +52,7 @@ struct gnc_price_s
guint32 version_check; /* data aging timestamp */ guint32 version_check; /* data aging timestamp */
/* 'private' object management fields */ /* 'private' object management fields */
QofEntityTable *entity_table; /* table in which price is stored */
guint32 refcount; /* garbage collection reference count */ 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; Timespec time;
} GNCPriceLookupHelper; } 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_set_db(QofBook *book, GNCPriceDB *db);
void gnc_pricedb_mark_clean(GNCPriceDB *db); void gnc_pricedb_mark_clean(GNCPriceDB *db);
void gnc_pricedb_substitute_commodity(GNCPriceDB *db, void gnc_pricedb_substitute_commodity(GNCPriceDB *db,
gnc_commodity *old_c, gnc_commodity *old_c,
gnc_commodity *new_c); gnc_commodity *new_c);
void gnc_price_set_guid (GNCPrice *p, const GUID *guid);
/** register the pricedb object with the gncObject system */ /** register the pricedb object with the gncObject system */
gboolean gnc_pricedb_register (void); gboolean gnc_pricedb_register (void);

View File

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

View File

@ -31,6 +31,7 @@
#include "gnc-numeric.h" #include "gnc-numeric.h"
#include "guid.h" #include "guid.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofinstance.h"
/** @addtogroup Engine /** @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 /** As mentioned above all of the getters return data that's internal
to the GNCPrice, not copies, so don't free these values. */ to the GNCPrice, not copies, so don't free these values. */
GNCPrice * gnc_price_lookup (const GUID *guid, QofBook *book); 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_commodity(GNCPrice *p);
gnc_commodity * gnc_price_get_currency(GNCPrice *p); gnc_commodity * gnc_price_get_currency(GNCPrice *p);
Timespec gnc_price_get_time(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); gint32 gnc_price_get_version(GNCPrice *p);
gboolean gnc_price_equal(GNCPrice *p1, GNCPrice *p2); 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: /** GNCPrice lists:

View File

@ -285,6 +285,20 @@ init_from_time(void)
return total; 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 void
guid_init(void) guid_init(void)
{ {
@ -458,6 +472,20 @@ guid_new(GUID *guid)
/* update the global context */ /* update the global context */
init_from_time(); 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) if (counter == 0)
{ {
FILE *fp; FILE *fp;

View File

@ -99,6 +99,14 @@ void guid_shutdown (void);
* *
* @param guid A pointer to an existing guid data structure. The * @param guid A pointer to an existing guid data structure. The
* existing value will be replaced with a new value. * 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); void guid_new(GUID *guid);

View File

@ -34,11 +34,11 @@
#include "qofbackend.h" #include "qofbackend.h"
#include "qofbook.h" #include "qofbook.h"
#include "qofid.h" #include "qofid.h"
#include "qofid-p.h"
struct _QofBook struct _QofBook
{ {
/* Unique guid for this book. */ QofEntity entity; /* Unique guid for this book. */
GUID guid;
/* The KvpFrame provides a place for top-level data associated /* The KvpFrame provides a place for top-level data associated
* with this book. */ * with this book. */
@ -48,7 +48,7 @@ struct _QofBook
* belonging to this book, with their pointers to the respective * belonging to this book, with their pointers to the respective
* objects. This allows a lookup of objects based on thier guid. * 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 /* In order to store arbitrary data, for extensibility, add a table
* that will be used to hold arbitrary pointers. * 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 * if the backends should even be doing this much, but for
* backwards compatibility, we leave these here.) * 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_schedxactions( QofBook *book, GList *newList );
void qof_book_set_backend (QofBook *book, QofBackend *be); 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 */ /* Register books with the engine */
gboolean qof_book_register (void); 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 */ #endif /* QOF_BOOK_P_H */

View File

@ -58,12 +58,13 @@ static short module = MOD_ENGINE;
static void static void
qof_book_init (QofBook *book) qof_book_init (QofBook *book)
{ {
QofCollection *col;
if (!book) return; 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); col = qof_book_get_collection (book, QOF_ID_BOOK);
qof_entity_store(book->entity_table, book, &book->guid, QOF_ID_BOOK); qof_entity_init (&book->entity, QOF_ID_BOOK, col);
book->kvp_data = kvp_frame_new (); book->kvp_data = kvp_frame_new ();
@ -84,30 +85,41 @@ qof_book_new (void)
qof_book_init(book); qof_book_init(book);
qof_object_book_begin (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); LEAVE ("book=%p", book);
return book; return book;
} }
static gboolean
coll_destroy(gpointer key, gpointer value, gpointer not_used)
{
QofCollection *col = value;
qof_collection_destroy (col);
return TRUE;
}
void void
qof_book_destroy (QofBook *book) qof_book_destroy (QofBook *book)
{ {
if (!book) return; if (!book) return;
ENTER ("book=%p etable=%p", book, book->entity_table); ENTER ("book=%p", book);
gnc_engine_force_event (&book->guid, QOF_ID_BOOK, GNC_EVENT_DESTROY); gnc_engine_force_event (&book->entity.guid, QOF_ID_BOOK, GNC_EVENT_DESTROY);
qof_object_book_end (book); 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); kvp_frame_delete (book->kvp_data);
/* FIXME: Make sure the data_table is empty */ /* FIXME: Make sure the data_table is empty */
g_hash_table_destroy (book->data_tables); 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); g_free (book);
LEAVE ("book=%p", book); LEAVE ("book=%p", book);
} }
@ -145,13 +157,6 @@ qof_book_mark_saved(QofBook *book)
/* ====================================================================== */ /* ====================================================================== */
/* getters */ /* getters */
const GUID *
qof_book_get_guid (QofBook *book)
{
if (!book) return NULL;
return &book->guid;
}
KvpFrame * KvpFrame *
qof_book_get_slots (QofBook *book) qof_book_get_slots (QofBook *book)
{ {
@ -159,13 +164,6 @@ qof_book_get_slots (QofBook *book)
return book->kvp_data; return book->kvp_data;
} }
QofEntityTable *
qof_book_get_entity_table (QofBook *book)
{
if (!book) return NULL;
return book->entity_table;
}
QofBackend * QofBackend *
qof_book_get_backend (QofBook *book) qof_book_get_backend (QofBook *book)
{ {
@ -176,18 +174,6 @@ qof_book_get_backend (QofBook *book)
/* ====================================================================== */ /* ====================================================================== */
/* setters */ /* 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 void
qof_book_set_backend (QofBook *book, QofBackend *be) 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 gint64
qof_book_get_counter (QofBook *book, const char *counter_name) qof_book_get_counter (QofBook *book, const char *counter_name)
{ {
@ -287,7 +295,7 @@ gboolean qof_book_register (void)
{ {
static QofParam params[] = { static QofParam params[] = {
{ QOF_BOOK_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_book_get_slots, NULL }, { 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 }, { NULL },
}; };

View File

@ -48,7 +48,7 @@ typedef struct _QofBook QofBook;
/** GList of QofBook */ /** GList of QofBook */
typedef GList QofBookList; 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); gboolean qof_book_register (void);
/** Allocate, initialise and return a new QofBook. Books contain references /** 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); void qof_book_destroy (QofBook *book);
/** \return The Entity table for the book. */ /** \return The Entity table for the book. */
QofEntityTable * qof_book_get_entity_table (QofBook *book); QofCollection * qof_book_get_collection (QofBook *, QofIdType);
/** \return The GUID for the book. */
const GUID * qof_book_get_guid (QofBook *book);
/** \return The kvp data for the book */ /** \return The kvp data for the book */
KvpFrame * qof_book_get_slots (QofBook *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 */ #endif /* QOF_BOOK_H */
/** @} */ /** @} */

View File

@ -31,45 +31,16 @@
/* This file defines an engine-only API for using gnucash entity /* This file defines an engine-only API for using gnucash entity
* identifiers. */ * 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); void qof_entity_set_guid (QofEntity *ent, const GUID *guid);
/* Create and destroy entity tables */ /** Take entity, remove it from whatever collection its currently
QofEntityTable * qof_entity_new (void); * in, and place it in a new collection. To be used only for
void qof_entity_destroy (QofEntityTable *table); * moving entity from one book to another.
/* 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.
*/ */
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 */ #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_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 CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (gpointer)(str));
#define QOFID_DEBUG 0
static short module = MOD_ENGINE; 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 struct QofCollection_s
{ {
QofIdType e_type; QofIdType e_type;
@ -95,6 +45,71 @@ struct QofCollection_s
GHashTable * hash_of_entities; 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 static guint
id_hash (gconstpointer key) id_hash (gconstpointer key)
{ {
@ -130,312 +145,94 @@ id_compare(gconstpointer key_1, gconstpointer key_2)
return guid_equal (key_1, key_2); return guid_equal (key_1, key_2);
} }
QofCollection * qof_collection_new (QofIdType type);
QofCollection * QofCollection *
qof_collection_new (QofIdType type) qof_collection_new (QofIdType type)
{ {
QofCollection *col; QofCollection *col;
col = g_new0(QofCollection, 1); 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); col->hash_of_entities = g_hash_table_new (id_hash, id_compare);
return col; return col;
} }
void qof_collection_destroy (QofCollection *col);
void void
qof_collection_destroy (QofCollection *col) qof_collection_destroy (QofCollection *col)
{ {
/* col->e_type = xxx */ CACHE_REMOVE (col->e_type);
g_hash_table_destroy(col->hash_of_entities); g_hash_table_destroy(col->hash_of_entities);
col->e_type = NULL;
col->hash_of_entities = NULL;
g_free (col); 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; return col->e_type;
qof_collection_destroy (col);
return TRUE;
} }
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 */ static void
typedef struct entity_node qof_collection_remove_entity (QofEntity *ent)
{ {
QofIdType entity_type; QofCollection *col = ent->collection;
gpointer entity; if (!col) return;
} EntityNode; g_hash_table_remove (col->hash_of_entities, &ent->guid);
ent->collection = NULL;
/** 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;
} }
void void
qof_entity_destroy (QofEntityTable *entity_table) qof_collection_insert_entity (QofCollection *col, QofEntity *ent)
{ {
if (entity_table == NULL) if (guid_equal(&ent->guid, guid_null())) return;
return; g_return_if_fail (col->e_type == ent->e_type);
qof_collection_remove_entity (ent);
g_hash_table_foreach_remove (entity_table->hash_by_guid, entity_node_destroy, g_hash_table_insert (col->hash_of_entities, &ent->guid, ent);
NULL); ent->collection = col;
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);
} }
QofEntity *
#if QOFID_DEBUG qof_collection_lookup_entity (QofCollection *col, const GUID * guid)
static void
print_node(gpointer key, gpointer value, gpointer not_used)
{ {
GUID *guid = key; QofEntity *ent;
EntityNode *node = value; g_return_val_if_fail (col, NULL);
if (guid == NULL) return NULL;
fprintf(stderr, "%s %s %p\n", ent = g_hash_table_lookup (col->hash_of_entities, guid->data);
guid_to_string(guid), node->entity_type, node->entity); 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 { struct _iterate {
QofEntityForeachCB fcn; QofEntityForeachCB fcn;
gpointer data; gpointer data;
QofIdType type;
}; };
static void foreach_cb (gpointer key, gpointer item, gpointer arg) static void foreach_cb (gpointer key, gpointer item, gpointer arg)
{ {
struct _iterate *iter = 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 void
qof_entity_foreach (QofEntityTable *entity_table, QofIdType type, qof_collection_foreach (QofCollection *col,
QofEntityForeachCB cb_func, gpointer user_data) QofEntityForeachCB cb_func, gpointer user_data)
{ {
QofCollection *col;
struct _iterate iter; struct _iterate iter;
g_return_if_fail (entity_table); g_return_if_fail (col);
g_return_if_fail (type);
g_return_if_fail (*type);
g_return_if_fail (cb_func); g_return_if_fail (cb_func);
iter.fcn = cb_func; iter.fcn = cb_func;
iter.data = user_data; 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); 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_NULL "null"
#define QOF_ID_SESSION "Session" #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 QofEntity_s QofEntity;
typedef struct _QofEntityTable QofEntityTable; typedef struct QofCollection_s QofCollection;
struct QofEntity_s struct QofEntity_s
{ {
QofIdType e_type; QofIdType e_type;
GUID guid; GUID guid;
QofEntityTable * e_table; QofCollection * collection;
}; };
/** Initialise the memory associated with an entity */ /** 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. */ * the memory associated with the instance. */
void qof_entity_release (QofEntity *); 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 */ /** collections of entities */
QofIdType qof_entity_type (QofEntityTable *entity_table, const GUID * guid); 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 */ /* 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 */ #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.h"
#include "qofid-p.h" #include "qofid-p.h"
#include "qofinstance.h" #include "qofinstance.h"
#include "qofinstance-p.h"
static short module = MOD_ENGINE; static short module = MOD_ENGINE;
@ -43,13 +44,16 @@ static short module = MOD_ENGINE;
void void
qof_instance_init (QofInstance *inst, QofIdType type, QofBook *book) qof_instance_init (QofInstance *inst, QofIdType type, QofBook *book)
{ {
QofCollection *col;
inst->book = book; inst->book = book;
inst->kvp_data = kvp_frame_new(); inst->kvp_data = kvp_frame_new();
inst->editlevel = 0; inst->editlevel = 0;
inst->do_free = FALSE; inst->do_free = FALSE;
inst->dirty = 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 void
@ -90,6 +94,29 @@ qof_instance_is_dirty (QofInstance *inst)
return inst->dirty; 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 void
@ -101,11 +128,11 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
/* Make a note of where the copy came from */ /* Make a note of where the copy came from */
gnc_kvp_bag_add (to->kvp_data, "gemini", now, gnc_kvp_bag_add (to->kvp_data, "gemini", now,
"inst_guid", &from->entity.guid, "inst_guid", &from->entity.guid,
"book_guid", &from->book->guid, "book_guid", &from->book->entity.guid,
NULL); NULL);
gnc_kvp_bag_add (from->kvp_data, "gemini", now, gnc_kvp_bag_add (from->kvp_data, "gemini", now,
"inst_guid", &to->entity.guid, "inst_guid", &to->entity.guid,
"book_guid", &to->book->guid, "book_guid", &to->book->entity.guid,
NULL); NULL);
to->dirty = TRUE; to->dirty = TRUE;
@ -114,6 +141,7 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
QofInstance * QofInstance *
qof_instance_lookup_twin (QofInstance *src, QofBook *target_book) qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
{ {
QofCollection *col;
KvpFrame *fr; KvpFrame *fr;
GUID * twin_guid; GUID * twin_guid;
QofInstance * twin; 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_guid = kvp_frame_get_guid (fr, "inst_guid");
twin = qof_entity_lookup (target_book->entity_table, col = qof_book_get_collection (target_book, src->entity.e_type);
twin_guid, src->entity.e_type); twin = (QofInstance *) qof_collection_lookup_entity (col, twin_guid);
LEAVE (" found twin=%p", twin); LEAVE (" found twin=%p", twin);
return twin; return twin;

View File

@ -41,36 +41,6 @@
typedef struct QofInstance_s QofInstance; 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 */ /** Initialise the memory associated with an instance */
void qof_instance_init (QofInstance *, QofIdType, QofBook *); void qof_instance_init (QofInstance *, QofIdType, QofBook *);

View File

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

View File

@ -40,6 +40,7 @@
typedef struct _QofObject QofObject; typedef struct _QofObject QofObject;
typedef void (*QofForeachCB) (gpointer obj, gpointer user_data);
typedef void (*QofForeachTypeCB) (QofObject *type, gpointer user_data); typedef void (*QofForeachTypeCB) (QofObject *type, gpointer user_data);
typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type, typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
gpointer backend_data, gpointer backend_data,
@ -49,7 +50,7 @@ typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
struct _QofObject struct _QofObject
{ {
gint interface_version; /* of this object interface */ 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 */ const char * type_label; /* "Printable" type-label string */
/* book_begin is called from within the Book routines to create /* 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 /* foreach() is used to execute a callback over each object
* stored in the particular book * stored in the particular book
*/ */
void (*foreach)(QofBook *, QofEntityForeachCB, gpointer); void (*foreach)(QofBook *, QofForeachCB, gpointer);
/* Given a particular object, return a printable string */ /* Given a particular object, return a printable string */
/* Argument should really be QofInstance not gpointer.. */ /* 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_type (QofForeachTypeCB cb, gpointer user_data);
void qof_object_foreach (QofIdTypeConst type_name, QofBook *book, 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); const char * qof_object_printable (QofIdTypeConst type_name, gpointer obj);

View File

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

View File

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

View File

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

View File

@ -2,7 +2,6 @@
#include <glib.h> #include <glib.h>
#include <time.h> #include <time.h>
#include "TransLog.h"
#include "gnc-date.h" #include "gnc-date.h"
#include "gnc-module.h" #include "gnc-module.h"
#include "test-stuff.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; QofBook *book;
AccountGroup *grp; 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 /* 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. */ * without crashing. We don't check to see if data is good. */
sess = get_random_session (); sess = get_random_session ();
book = qof_session_get_book (sess); book = qof_session_get_book (sess);
if (!book) do_test ((NULL != book), "book not created");
{
failure("book not created");
exit(get_rv());
}
add_random_transactions_to_book (book, 720); add_random_transactions_to_book (book, 720);
@ -60,6 +50,9 @@ run_test (void)
static void static void
main_helper (void *closure, int argc, char **argv) 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 (); run_test ();
print_test_results(); print_test_results();

View File

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