mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
aaf73968e1
commit
c90c817e64
@ -52,6 +52,7 @@
|
||||
#include "qofbook-p.h"
|
||||
#include "qofclass.h"
|
||||
#include "qofid-p.h"
|
||||
#include "qofinstance-p.h"
|
||||
#include "qofobject.h"
|
||||
|
||||
static short module = MOD_ACCOUNT;
|
||||
@ -69,22 +70,12 @@ static void xaccAccountBringUpToDate (Account *);
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
G_INLINE_FUNC void account_event (Account *account);
|
||||
G_INLINE_FUNC void
|
||||
account_event (Account *account)
|
||||
{
|
||||
gnc_engine_gen_event (&account->inst.entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
|
||||
|
||||
G_INLINE_FUNC void mark_account (Account *account);
|
||||
G_INLINE_FUNC void
|
||||
mark_account (Account *account)
|
||||
{
|
||||
if (account->parent)
|
||||
account->parent->saved = FALSE;
|
||||
|
||||
account_event (account);
|
||||
if (account->parent) account->parent->saved = FALSE;
|
||||
account->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@ -335,16 +326,27 @@ xaccFreeAccount (Account *acc)
|
||||
void
|
||||
xaccAccountBeginEdit (Account *acc)
|
||||
{
|
||||
GNC_BEGIN_EDIT (&acc->inst, GNC_ID_ACCOUNT);
|
||||
GNC_BEGIN_EDIT (&acc->inst);
|
||||
}
|
||||
|
||||
static inline void noop(QofInstance *inst) {}
|
||||
|
||||
static inline void on_err (QofInstance *inst, QofBackendError errcode)
|
||||
{
|
||||
PERR("commit error: %d", errcode);
|
||||
}
|
||||
|
||||
static inline void acc_free (QofInstance *inst)
|
||||
{
|
||||
Account *acc = (Account *) inst;
|
||||
xaccGroupRemoveAccount(acc->parent, acc);
|
||||
xaccFreeAccount(acc);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountCommitEdit (Account *acc)
|
||||
{
|
||||
QofBackend * be;
|
||||
|
||||
GNC_COMMIT_EDIT_PART1 (&acc->inst);
|
||||
ENTER (" ");
|
||||
|
||||
/* If marked for deletion, get rid of subaccounts first,
|
||||
* and then the splits ... */
|
||||
@ -391,39 +393,9 @@ xaccAccountCommitEdit (Account *acc)
|
||||
xaccGroupInsertAccount(acc->parent, acc);
|
||||
}
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
be = acc->inst.book->backend;
|
||||
if (be && be->commit)
|
||||
{
|
||||
QofBackendError errcode;
|
||||
GNC_COMMIT_EDIT_PART2 (&acc->inst, on_err, noop, acc_free);
|
||||
|
||||
/* clear errors */
|
||||
do {
|
||||
errcode = qof_backend_get_error (be);
|
||||
} while (ERR_BACKEND_NO_ERR != errcode);
|
||||
|
||||
(be->commit) (be, GNC_ID_ACCOUNT, acc);
|
||||
errcode = qof_backend_get_error (be);
|
||||
|
||||
if (ERR_BACKEND_NO_ERR != errcode)
|
||||
{
|
||||
/* Destroys must be rolled back as well ... */
|
||||
acc->inst.do_free = FALSE;
|
||||
|
||||
/* XXX hack alert FIXME implement account rollback */
|
||||
PERR ("Backend asked engine to rollback, but this isn't"
|
||||
" handled yet. Return code=%d", errcode);
|
||||
}
|
||||
}
|
||||
acc->inst.dirty = FALSE;
|
||||
|
||||
/* final stages of freeing the account */
|
||||
if (acc->inst.do_free)
|
||||
{
|
||||
xaccGroupRemoveAccount(acc->parent, acc);
|
||||
xaccFreeAccount(acc);
|
||||
}
|
||||
LEAVE (" ");
|
||||
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
|
||||
void
|
||||
@ -435,7 +407,6 @@ xaccAccountDestroy (Account *acc)
|
||||
xaccAccountCommitEdit (acc);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xaccAccountSetVersion (Account *acc, gint32 vers)
|
||||
{
|
||||
@ -450,13 +421,6 @@ xaccAccountGetVersion (Account *acc)
|
||||
return (acc->version);
|
||||
}
|
||||
|
||||
QofBook *
|
||||
xaccAccountGetBook (Account *account)
|
||||
{
|
||||
if (!account) return NULL;
|
||||
return account->inst.book;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@ -705,56 +669,6 @@ xaccAccountBringUpToDate(Account *acc)
|
||||
xaccAccountRecomputeBalance(acc);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* xaccAccountGetSlots
|
||||
********************************************************************/
|
||||
|
||||
KvpFrame *
|
||||
xaccAccountGetSlots(Account * account)
|
||||
{
|
||||
if (!account) return NULL;
|
||||
return(account->inst.kvp_data);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountSetSlots_nc(Account *account, KvpFrame *frame)
|
||||
{
|
||||
if (!account) return;
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
if (account->inst.kvp_data && frame != account->inst.kvp_data)
|
||||
{
|
||||
kvp_frame_delete (account->inst.kvp_data);
|
||||
}
|
||||
account->inst.kvp_data = frame;
|
||||
account->inst.dirty = TRUE;
|
||||
mark_account (account);
|
||||
xaccAccountCommitEdit (account);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
const GUID *
|
||||
xaccAccountGetGUID (Account *account)
|
||||
{
|
||||
if (!account)
|
||||
return guid_null();
|
||||
|
||||
return &account->inst.entity.guid;
|
||||
}
|
||||
|
||||
GUID
|
||||
xaccAccountReturnGUID (Account *account)
|
||||
{
|
||||
if (!account)
|
||||
return *guid_null();
|
||||
|
||||
return account->inst.entity.guid;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
@ -777,17 +691,10 @@ xaccAccountSetGUID (Account *account, const GUID *guid)
|
||||
Account *
|
||||
xaccAccountLookup (const GUID *guid, QofBook *book)
|
||||
{
|
||||
QofCollection *col;
|
||||
if (!guid || !book) return NULL;
|
||||
return qof_entity_lookup (qof_book_get_entity_table (book),
|
||||
guid, GNC_ID_ACCOUNT);
|
||||
}
|
||||
|
||||
Account *
|
||||
xaccAccountLookupDirect (GUID guid, QofBook *book)
|
||||
{
|
||||
if (!book) return NULL;
|
||||
return qof_entity_lookup (qof_book_get_entity_table (book),
|
||||
&guid, GNC_ID_ACCOUNT);
|
||||
col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
|
||||
return (Account *) qof_collection_lookup_entity (col, guid);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@ -1044,7 +951,7 @@ xaccAccountRemoveSplit (Account *acc, Split *split)
|
||||
|
||||
mark_account (acc);
|
||||
if (split->parent)
|
||||
gnc_engine_generate_event (&split->parent->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
|
||||
gnc_engine_gen_event (&split->parent->inst.entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
}
|
||||
xaccAccountCommitEdit(acc);
|
||||
@ -1131,7 +1038,7 @@ xaccAccountRecomputeBalance (Account * acc)
|
||||
acc->reconciled_balance = reconciled_balance;
|
||||
|
||||
acc->balance_dirty = FALSE;
|
||||
account_event (acc);
|
||||
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
@ -2903,33 +2810,32 @@ xaccAccountFindTransByDesc(Account *account, const char *description)
|
||||
/* gncObject function implementation and registration */
|
||||
|
||||
static void
|
||||
account_foreach (QofBook *book, QofEntityForeachCB cb, gpointer ud)
|
||||
account_foreach (QofBook *book, QofForeachCB cb, gpointer ud)
|
||||
{
|
||||
QofEntityTable *et;
|
||||
QofCollection *col;
|
||||
|
||||
g_return_if_fail (book);
|
||||
g_return_if_fail (cb);
|
||||
|
||||
et = qof_book_get_entity_table (book);
|
||||
qof_entity_foreach (et, GNC_ID_ACCOUNT, cb, ud);
|
||||
col = qof_book_get_collection (book, GNC_ID_ACCOUNT);
|
||||
qof_collection_foreach (col, (QofEntityForeachCB) cb, ud);
|
||||
}
|
||||
|
||||
static QofObject account_object_def = {
|
||||
QOF_OBJECT_VERSION,
|
||||
GNC_ID_ACCOUNT,
|
||||
"Account",
|
||||
NULL, /* book_begin */
|
||||
NULL, /* book_end */
|
||||
NULL, /* is_dirty */
|
||||
NULL, /* mark_clean */
|
||||
account_foreach, /* foreach */
|
||||
(const char* (*)(gpointer)) xaccAccountGetName /* printable */
|
||||
interface_version: QOF_OBJECT_VERSION,
|
||||
e_type: GNC_ID_ACCOUNT,
|
||||
type_label: "Account",
|
||||
book_begin: NULL,
|
||||
book_end: NULL,
|
||||
is_dirty: NULL,
|
||||
mark_clean: NULL,
|
||||
foreach: account_foreach,
|
||||
printable: (const char* (*)(gpointer)) xaccAccountGetName
|
||||
};
|
||||
|
||||
gboolean xaccAccountRegister (void)
|
||||
{
|
||||
static QofParam params[] = {
|
||||
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)xaccAccountGetSlots, NULL },
|
||||
{ ACCOUNT_NAME_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetName, NULL },
|
||||
{ ACCOUNT_CODE_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetCode, NULL },
|
||||
{ ACCOUNT_DESCRIPTION_, QOF_TYPE_STRING, (QofAccessFunc)xaccAccountGetDescription, NULL },
|
||||
@ -2942,6 +2848,7 @@ gboolean xaccAccountRegister (void)
|
||||
{ ACCOUNT_TAX_RELATED, QOF_TYPE_BOOLEAN, (QofAccessFunc)xaccAccountGetTaxRelated, NULL },
|
||||
{ QOF_QUERY_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_guid, NULL },
|
||||
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
|
||||
{ ACCOUNT_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
@ -158,21 +158,16 @@ int xaccAccountOrder (Account **account_1, Account **account_2);
|
||||
/** @name Account lookup and GUID routines */
|
||||
/** @{ */
|
||||
|
||||
/** The xaccAccountGetGUID() subroutine will return the
|
||||
* globally unique id associated with that account. */
|
||||
const GUID * xaccAccountGetGUID (Account *account);
|
||||
/** The xaccAccountReturnGUID() subroutine returns the
|
||||
* same GUID as xaccAccountGetGUID, but as a struct. */
|
||||
GUID xaccAccountReturnGUID (Account *account);
|
||||
/** deprecated */
|
||||
#define xaccAccountGetBook(X) qof_instance_get_book(QOF_INSTANCE(X))
|
||||
#define xaccAccountGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
#define xaccAccountReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
|
||||
|
||||
/** The xaccAccountLookup() subroutine will return the
|
||||
* account associated with the given id, or NULL
|
||||
* if there is no such account. */
|
||||
Account * xaccAccountLookup (const GUID *guid, QofBook *book);
|
||||
|
||||
/** xaccAccountLookupDirect performs the same function as
|
||||
* xaccAccountLookup but takes a GUID struct directly. */
|
||||
Account * xaccAccountLookupDirect (GUID guid, QofBook *book);
|
||||
#define xaccAccountLookupDirect(g,b) xaccAccountLookup(&(g),b)
|
||||
|
||||
/** @} */
|
||||
|
||||
@ -181,8 +176,6 @@ Account * xaccAccountLookupDirect (GUID guid, QofBook *book);
|
||||
/** @name Account general setters/getters */
|
||||
/** @{ */
|
||||
|
||||
/** @return The book where the account is stored */
|
||||
QofBook * xaccAccountGetBook (Account *account);
|
||||
|
||||
/** Set the account's type */
|
||||
void xaccAccountSetType (Account *account, GNCAccountType);
|
||||
@ -409,15 +402,11 @@ gboolean xaccAccountGetReconcileChildrenStatus(Account *account);
|
||||
* Returns false if either one is NULL.
|
||||
*/
|
||||
gboolean xaccAccountHasAncestor (Account *account, Account *ancestor);
|
||||
|
||||
#define xaccAccountGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
|
||||
|
||||
/** @} */
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
/** @name Account KvpFrame getters/setters */
|
||||
/** @{ */
|
||||
KvpFrame * xaccAccountGetSlots (Account *account);
|
||||
void xaccAccountSetSlots_nc(Account *account, KvpFrame *frame);
|
||||
/** @} */
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
@ -571,8 +560,6 @@ LotList * xaccAccountFindOpenLots (Account *acc,
|
||||
gpointer user_data, GCompareFunc sort_func);
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
/** @name Account Reconciliation information getters/setters */
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
#include "qofinstance.h"
|
||||
#include "qofinstance-p.h"
|
||||
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
@ -201,4 +202,9 @@ gint32 xaccAccountGetVersion (Account*);
|
||||
/* Register Accounts with the engine */
|
||||
gboolean xaccAccountRegister (void);
|
||||
|
||||
/** killed for now, need to resurect this or something similar
|
||||
* * for transactional/dirty kvp. Later. Right now a place holder
|
||||
* */
|
||||
#define xaccAccountSetSlots_nc(A,S) qof_instance_set_slots(QOF_INSTANCE(A),S)
|
||||
|
||||
#endif /* XACC_ACCOUNT_P_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -52,14 +52,17 @@ Currently the only files which include this file are:
|
||||
*
|
||||
* This still needs to deal with:
|
||||
* . exceptions
|
||||
* . 13 periods: (4 weeks/period 4x13=52 weeks/year)
|
||||
* . yearly 360/365?
|
||||
* . re-based frequencies [based around a non-standard [read:
|
||||
* not-Jan-1-based/fiscal] year]
|
||||
* . "business days" -- m-f sans holidays [per-user list thereof]
|
||||
**/
|
||||
struct gncp_freq_spec {
|
||||
struct gncp_freq_spec
|
||||
{
|
||||
QofEntity entity;
|
||||
FreqType type;
|
||||
UIFreqType uift;
|
||||
UIFreqType uift;
|
||||
union u {
|
||||
struct {
|
||||
/** The date on which the single event occurs. */
|
||||
@ -107,8 +110,6 @@ struct gncp_freq_spec {
|
||||
GList *subSpecs;
|
||||
} composites;
|
||||
} s;
|
||||
GUID guid;
|
||||
QofEntityTable *entity_table;
|
||||
};
|
||||
|
||||
#endif /* XACC_FREQSPECP_H */
|
||||
|
@ -6,8 +6,7 @@
|
||||
* QofIdType xaccGUIDType (const GUID * guid, QofBook *book);
|
||||
*/
|
||||
|
||||
#define xaccGUIDType(guid,book) \
|
||||
qof_entity_type (qof_book_get_entity_table (book), (guid))
|
||||
#define xaccGUIDType(obj) (QOF_INSTANCE(obj)->e_type)
|
||||
|
||||
/* Equivalent function prototype:
|
||||
* void xaccGUIDNew (GUID *guid, QofBook *book)
|
||||
|
@ -731,6 +731,7 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
|
||||
/* switch over between books, if needed */
|
||||
if (grp->book != acc->inst.book)
|
||||
{
|
||||
QofCollection *col;
|
||||
// xxxxxxxxxxxxxxxxxxxxxxx
|
||||
/* hack alert -- this implementation is not exactly correct.
|
||||
* If the entity tables are not identical, then the 'from' book
|
||||
@ -746,9 +747,8 @@ xaccGroupInsertAccount (AccountGroup *grp, Account *acc)
|
||||
PWARN ("reparenting accounts accross books is not correctly supported\n");
|
||||
|
||||
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_DESTROY);
|
||||
qof_entity_release (&acc->inst.entity);
|
||||
|
||||
qof_entity_store (grp->book->entity_table, acc, &acc->inst.entity.guid, GNC_ID_ACCOUNT);
|
||||
col = qof_book_get_collection (grp->book, GNC_ID_ACCOUNT);
|
||||
qof_collection_insert_entity (col, &acc->inst.entity);
|
||||
gnc_engine_gen_event (&acc->inst.entity, GNC_EVENT_CREATE);
|
||||
}
|
||||
}
|
||||
@ -1243,7 +1243,7 @@ group_mark_clean(QofBook *book)
|
||||
static QofObject group_object_def =
|
||||
{
|
||||
interface_version: QOF_OBJECT_VERSION,
|
||||
name: GNC_ID_GROUP,
|
||||
e_type: GNC_ID_GROUP,
|
||||
type_label: "AccountGroup",
|
||||
book_begin: group_book_begin,
|
||||
book_end: group_book_end,
|
||||
|
@ -130,6 +130,7 @@ noinst_HEADERS = \
|
||||
qofbook-p.h \
|
||||
qofclass-p.h \
|
||||
qofid-p.h \
|
||||
qofinstance-p.h \
|
||||
qofobject-p.h \
|
||||
qofquery-p.h \
|
||||
qofquerycore-p.h \
|
||||
|
@ -72,13 +72,14 @@ xaccAccountLookupTwin (Account *acc, QofBook *book)
|
||||
void
|
||||
gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
|
||||
{
|
||||
QofCollection *col;
|
||||
Transaction *newtrans;
|
||||
GList *node;
|
||||
|
||||
if (!trans || !book) return;
|
||||
|
||||
/* If this is the same book, its a no-op. */
|
||||
if (trans->book == book) return;
|
||||
if (trans->inst.book == book) return;
|
||||
|
||||
ENTER ("trans=%p %s", trans, trans->description);
|
||||
newtrans = xaccDupeTransaction (trans);
|
||||
@ -93,10 +94,12 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
|
||||
xaccTransDestroy (trans);
|
||||
xaccTransCommitEdit (trans);
|
||||
|
||||
/* fiddle the transaction into place in the new book */
|
||||
qof_entity_store(book->entity_table, newtrans, &newtrans->guid, GNC_ID_TRANS);
|
||||
newtrans->book = book;
|
||||
/* Fiddle the transaction into place in the new book */
|
||||
col = qof_book_get_collection (book, GNC_ID_TRANS);
|
||||
qof_collection_insert_entity (col, &newtrans->inst.entity);
|
||||
newtrans->inst.book = book;
|
||||
|
||||
col = qof_book_get_collection (book, GNC_ID_SPLIT);
|
||||
xaccTransBeginEdit (newtrans);
|
||||
for (node = newtrans->splits; node; node = node->next)
|
||||
{
|
||||
@ -105,7 +108,7 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
|
||||
|
||||
/* move the split into the new book ... */
|
||||
s->book = book;
|
||||
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
|
||||
qof_collection_insert_entity(col, &s->entity);
|
||||
|
||||
/* find the twin account, and re-parent to that. */
|
||||
twin = xaccAccountLookupTwin (s->acc, book);
|
||||
@ -122,7 +125,7 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
|
||||
}
|
||||
|
||||
xaccTransCommitEdit (newtrans);
|
||||
gnc_engine_generate_event (&newtrans->guid, GNC_ID_TRANS, GNC_EVENT_CREATE);
|
||||
gnc_engine_gen_event (&newtrans->inst.entity, GNC_EVENT_CREATE);
|
||||
LEAVE ("trans=%p %s", trans, trans->description);
|
||||
}
|
||||
|
||||
@ -134,16 +137,17 @@ gnc_book_insert_trans_clobber (QofBook *book, Transaction *trans)
|
||||
void
|
||||
gnc_book_insert_trans (QofBook *book, Transaction *trans)
|
||||
{
|
||||
QofCollection *col;
|
||||
GList *node;
|
||||
|
||||
if (!trans || !book) return;
|
||||
|
||||
/* If this is the same book, its a no-op. */
|
||||
if (trans->book == book) return;
|
||||
if (trans->inst.book == book) return;
|
||||
|
||||
/* If the old and new book don't share backends, then clobber-copy;
|
||||
* i.e. destroy it in one backend, create it in another. */
|
||||
if (book->backend != trans->book->backend)
|
||||
if (book->backend != trans->inst.book->backend)
|
||||
{
|
||||
gnc_book_insert_trans_clobber (book, trans);
|
||||
return;
|
||||
@ -153,10 +157,11 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
|
||||
/* Fiddle the transaction into place in the new book */
|
||||
xaccTransBeginEdit (trans);
|
||||
|
||||
qof_entity_remove (trans->book->entity_table, &trans->guid);
|
||||
trans->book = book;
|
||||
qof_entity_store(book->entity_table, trans, &trans->guid, GNC_ID_TRANS);
|
||||
col = qof_book_get_collection (book, GNC_ID_TRANS);
|
||||
trans->inst.book = book;
|
||||
qof_collection_insert_entity (col, &trans->inst.entity);
|
||||
|
||||
col = qof_book_get_collection (book, GNC_ID_SPLIT);
|
||||
for (node = trans->splits; node; node = node->next)
|
||||
{
|
||||
Account *twin;
|
||||
@ -165,9 +170,8 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
|
||||
/* Move the splits over (only if they haven't already been moved). */
|
||||
if (s->book != book)
|
||||
{
|
||||
qof_entity_remove (s->book->entity_table, &s->guid);
|
||||
s->book = book;
|
||||
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
|
||||
qof_collection_insert_entity (col, &s->entity);
|
||||
}
|
||||
|
||||
/* Find the twin account, and re-parent to that. */
|
||||
@ -189,7 +193,7 @@ gnc_book_insert_trans (QofBook *book, Transaction *trans)
|
||||
}
|
||||
|
||||
xaccTransCommitEdit (trans);
|
||||
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
|
||||
gnc_engine_gen_event (&trans->inst.entity, GNC_EVENT_MODIFY);
|
||||
LEAVE ("trans=%p %s", trans, trans->description);
|
||||
}
|
||||
|
||||
@ -212,6 +216,7 @@ gnc_book_insert_lot_clobber (QofBook *book, GNCLot *lot)
|
||||
void
|
||||
gnc_book_insert_lot (QofBook *book, GNCLot *lot)
|
||||
{
|
||||
QofCollection *col;
|
||||
SplitList *snode;
|
||||
Account *twin;
|
||||
if (!lot || !book) return;
|
||||
@ -225,19 +230,20 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
|
||||
return;
|
||||
}
|
||||
ENTER ("lot=%p", lot);
|
||||
qof_entity_remove (lot->book->entity_table, &lot->guid);
|
||||
|
||||
col = qof_book_get_collection (book, GNC_ID_LOT);
|
||||
lot->book = book;
|
||||
qof_entity_store(book->entity_table, lot, &lot->guid, GNC_ID_LOT);
|
||||
qof_collection_insert_entity (col, &lot->entity);
|
||||
|
||||
/* Move the splits over (only if they haven't already been moved). */
|
||||
col = qof_book_get_collection (book, GNC_ID_SPLIT);
|
||||
for (snode = lot->splits; snode; snode=snode->next)
|
||||
{
|
||||
Split *s = snode->data;
|
||||
if (s->book != book)
|
||||
{
|
||||
qof_entity_remove (s->book->entity_table, &s->guid);
|
||||
s->book = book;
|
||||
qof_entity_store(book->entity_table, s, &s->guid, GNC_ID_SPLIT);
|
||||
qof_collection_insert_entity (col, &s->entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,14 +264,15 @@ gnc_book_insert_lot (QofBook *book, GNCLot *lot)
|
||||
void
|
||||
gnc_book_insert_price (QofBook *book, GNCPrice *pr)
|
||||
{
|
||||
QofCollection *col;
|
||||
if (!pr || !book) return;
|
||||
|
||||
/* If this is the same book, its a no-op. */
|
||||
if (pr->book == book) return;
|
||||
if (pr->inst.book == book) return;
|
||||
|
||||
/* If the old and new book don't share backends, then clobber-copy;
|
||||
* i.e. destroy it in one backend, create it in another. */
|
||||
if (book->backend != pr->book->backend)
|
||||
if (book->backend != pr->inst.book->backend)
|
||||
{
|
||||
gnc_book_insert_price_clobber (book, pr);
|
||||
return;
|
||||
@ -276,9 +283,9 @@ gnc_book_insert_price (QofBook *book, GNCPrice *pr)
|
||||
gnc_price_ref (pr);
|
||||
gnc_price_begin_edit (pr);
|
||||
|
||||
qof_entity_remove (pr->book->entity_table, &pr->guid);
|
||||
pr->book = book;
|
||||
qof_entity_store(book->entity_table, pr, &pr->guid, GNC_ID_PRICE);
|
||||
col = qof_book_get_collection (book, GNC_ID_PRICE);
|
||||
pr->inst.book = book;
|
||||
qof_collection_insert_entity (col, &pr->inst.entity);
|
||||
|
||||
gnc_pricedb_remove_price (pr->db, pr);
|
||||
gnc_pricedb_add_price (gnc_pricedb_get_db (book), pr);
|
||||
@ -592,10 +599,10 @@ gnc_book_partition_txn (QofBook *dest_book, QofBook *src_book, QofQuery *query)
|
||||
/* Make note of the sibling books */
|
||||
now = time(0);
|
||||
gnc_kvp_bag_add (src_book->kvp_data, "gemini", now,
|
||||
"book_guid", &dest_book->guid,
|
||||
"book_guid", &dest_book->entity.guid,
|
||||
NULL);
|
||||
gnc_kvp_bag_add (dest_book->kvp_data, "gemini", now,
|
||||
"book_guid", &src_book->guid,
|
||||
"book_guid", &src_book->entity.guid,
|
||||
NULL);
|
||||
LEAVE (" ");
|
||||
}
|
||||
@ -686,7 +693,7 @@ add_closing_balances (AccountGroup *closed_grp,
|
||||
xaccAccountBeginEdit (twin);
|
||||
cwd = xaccAccountGetSlots (twin);
|
||||
kvp_frame_set_guid (cwd, "/book/prev-acct", xaccAccountGetGUID (candidate));
|
||||
kvp_frame_set_guid (cwd, "/book/prev-book", &closed_book->guid);
|
||||
kvp_frame_set_guid (cwd, "/book/prev-book", &closed_book->entity.guid);
|
||||
|
||||
xaccAccountSetSlots_nc (twin, twin->inst.kvp_data);
|
||||
|
||||
@ -695,7 +702,7 @@ add_closing_balances (AccountGroup *closed_grp,
|
||||
* the next book is. */
|
||||
xaccAccountBeginEdit (candidate);
|
||||
cwd = xaccAccountGetSlots (candidate);
|
||||
kvp_frame_set_guid (cwd, "/book/next-book", &open_book->guid);
|
||||
kvp_frame_set_guid (cwd, "/book/next-book", &open_book->entity.guid);
|
||||
kvp_frame_set_guid (cwd, "/book/next-acct", xaccAccountGetGUID (twin));
|
||||
|
||||
xaccAccountSetSlots_nc (candidate, candidate->inst.kvp_data);
|
||||
@ -753,7 +760,7 @@ add_closing_balances (AccountGroup *closed_grp,
|
||||
/* Add KVP data showing where the balancing
|
||||
* transaction came from */
|
||||
cwd = xaccTransGetSlots (trans);
|
||||
kvp_frame_set_guid (cwd, "/book/closed-book", &closed_book->guid);
|
||||
kvp_frame_set_guid (cwd, "/book/closed-book", &closed_book->entity.guid);
|
||||
kvp_frame_set_guid (cwd, "/book/closed-acct", xaccAccountGetGUID(candidate));
|
||||
|
||||
xaccTransCommitEdit (trans);
|
||||
@ -876,8 +883,8 @@ gnc_book_close_period (QofBook *existing_book, Timespec calve_date,
|
||||
kvp_frame_set_timespec (partn_cwd, "/book/log-date", ts);
|
||||
|
||||
/* Set up pointers to each book from the other. */
|
||||
kvp_frame_set_guid (partn_cwd, "/book/next-book", &existing_book->guid);
|
||||
kvp_frame_set_guid (exist_cwd, "/book/prev-book", &closing_book->guid);
|
||||
kvp_frame_set_guid (partn_cwd, "/book/next-book", &existing_book->entity.guid);
|
||||
kvp_frame_set_guid (exist_cwd, "/book/prev-book", &closing_book->entity.guid);
|
||||
|
||||
/* add in transactions to equity accounts that will
|
||||
* hold the colsing balances */
|
||||
|
@ -45,8 +45,11 @@
|
||||
#include "SchedXaction.h"
|
||||
#include "SX-book.h"
|
||||
#include "SX-book-p.h"
|
||||
|
||||
#include "qofbook.h"
|
||||
#include "qofbook-p.h"
|
||||
#include "qofinstance.h"
|
||||
#include "qofinstance-p.h"
|
||||
#include "qofobject.h"
|
||||
|
||||
static short module = MOD_SX;
|
||||
@ -158,7 +161,7 @@ static void
|
||||
mark_sx_clean(gpointer data, gpointer user_data)
|
||||
{
|
||||
SchedXaction *sx = (SchedXaction *) data;
|
||||
xaccSchedXactionSetDirtyness(sx, FALSE);
|
||||
qof_instance_mark_clean (QOF_INSTANCE(sx));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -208,7 +211,7 @@ sxtt_mark_clean(QofBook *book)
|
||||
static QofObject sxtt_object_def =
|
||||
{
|
||||
interface_version: QOF_OBJECT_VERSION,
|
||||
name: GNC_ID_SXTT,
|
||||
e_type: GNC_ID_SXTT,
|
||||
type_label: "SXTT",
|
||||
book_begin: sxtt_book_begin,
|
||||
book_end: sxtt_book_end,
|
||||
|
@ -55,30 +55,25 @@ xaccSchedXactionInit( SchedXaction *sx, QofBook *book)
|
||||
{
|
||||
AccountGroup *ag;
|
||||
|
||||
sx->entity_table = qof_book_get_entity_table (book);
|
||||
qof_instance_init (&sx->inst, GNC_ID_SCHEDXACTION, book);
|
||||
|
||||
sx->freq = xaccFreqSpecMalloc(book);
|
||||
|
||||
qof_entity_guid_new (sx->entity_table, &sx->guid);
|
||||
qof_entity_store( sx->entity_table, sx,
|
||||
&sx->guid, GNC_ID_SCHEDXACTION );
|
||||
g_date_clear( &sx->last_date, 1 );
|
||||
g_date_clear( &sx->start_date, 1 );
|
||||
g_date_clear( &sx->end_date, 1 );
|
||||
|
||||
sx->num_occurances_total = 0;
|
||||
sx->kvp_data = kvp_frame_new();
|
||||
sx->autoCreateOption = FALSE;
|
||||
sx->autoCreateNotify = FALSE;
|
||||
sx->advanceCreateDays = 0;
|
||||
sx->advanceRemindDays = 0;
|
||||
sx->instance_num = 0;
|
||||
sx->dirty = TRUE;
|
||||
sx->deferredList = NULL;
|
||||
|
||||
/* create a new template account for our splits */
|
||||
sx->template_acct = xaccMallocAccount(book);
|
||||
xaccAccountSetName( sx->template_acct, guid_to_string( &sx->guid ));
|
||||
xaccAccountSetName( sx->template_acct, guid_to_string( &sx->inst.entity.guid ));
|
||||
xaccAccountSetCommodity
|
||||
(sx->template_acct,
|
||||
gnc_commodity_new( "template", "template",
|
||||
@ -97,7 +92,7 @@ xaccSchedXactionMalloc(QofBook *book)
|
||||
|
||||
sx = g_new0( SchedXaction, 1 );
|
||||
xaccSchedXactionInit( sx, book );
|
||||
gnc_engine_generate_event( &sx->guid, GNC_ID_SCHEDXACTION, GNC_EVENT_CREATE );
|
||||
gnc_engine_gen_event( &sx->inst.entity, GNC_EVENT_CREATE );
|
||||
|
||||
return sx;
|
||||
}
|
||||
@ -133,13 +128,13 @@ delete_template_trans(SchedXaction *sx)
|
||||
if(! (g_list_find(templ_acct_transactions, split_trans)))
|
||||
{
|
||||
templ_acct_transactions
|
||||
= g_list_prepend(templ_acct_transactions, split_trans);
|
||||
= g_list_prepend(templ_acct_transactions, split_trans);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_foreach(templ_acct_transactions,
|
||||
sxprivTransMapDelete,
|
||||
NULL);
|
||||
sxprivTransMapDelete,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -151,8 +146,7 @@ xaccSchedXactionFree( SchedXaction *sx )
|
||||
if ( sx == NULL ) return;
|
||||
|
||||
xaccFreqSpecFree( sx->freq );
|
||||
gnc_engine_generate_event( &sx->guid, GNC_ID_SCHEDXACTION, GNC_EVENT_DESTROY );
|
||||
qof_entity_remove( sx->entity_table, &sx->guid );
|
||||
gnc_engine_gen_event( &sx->inst.entity, GNC_EVENT_DESTROY );
|
||||
|
||||
if ( sx->name )
|
||||
g_free( sx->name );
|
||||
@ -181,29 +175,26 @@ xaccSchedXactionFree( SchedXaction *sx )
|
||||
sx->deferredList = NULL;
|
||||
}
|
||||
|
||||
qof_instance_release (&sx->inst);
|
||||
g_free( sx );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
FreqSpec *
|
||||
xaccSchedXactionGetFreqSpec( SchedXaction *sx )
|
||||
{
|
||||
return sx->freq;
|
||||
return sx->freq;
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetFreqSpec( SchedXaction *sx, FreqSpec *fs )
|
||||
{
|
||||
g_return_if_fail( fs );
|
||||
g_return_if_fail( fs );
|
||||
|
||||
xaccFreqSpecFree( sx->freq );
|
||||
sx->freq = fs;
|
||||
sx->dirty = TRUE;
|
||||
xaccFreqSpecFree( sx->freq );
|
||||
sx->freq = fs;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
gchar *
|
||||
@ -220,7 +211,7 @@ xaccSchedXactionSetName( SchedXaction *sx, const gchar *newName )
|
||||
g_free( sx->name );
|
||||
sx->name = NULL;
|
||||
}
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
sx->name = g_strdup( newName );
|
||||
}
|
||||
|
||||
@ -234,7 +225,7 @@ void
|
||||
xaccSchedXactionSetStartDate( SchedXaction *sx, GDate* newStart )
|
||||
{
|
||||
sx->start_date = *newStart;
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -264,8 +255,7 @@ xaccSchedXactionSetEndDate( SchedXaction *sx, GDate *newEnd )
|
||||
}
|
||||
|
||||
sx->end_date = *newEnd;
|
||||
sx->dirty = TRUE;
|
||||
return;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
GDate*
|
||||
@ -278,8 +268,7 @@ void
|
||||
xaccSchedXactionSetLastOccurDate( SchedXaction *sx, GDate* newLastOccur )
|
||||
{
|
||||
sx->last_date = *newLastOccur;
|
||||
sx->dirty = TRUE;
|
||||
return;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -298,8 +287,7 @@ void
|
||||
xaccSchedXactionSetNumOccur( SchedXaction *sx, gint newNum )
|
||||
{
|
||||
sx->num_occurances_remain = sx->num_occurances_total = newNum;
|
||||
sx->dirty = TRUE;
|
||||
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
@ -313,68 +301,35 @@ xaccSchedXactionSetRemOccur( SchedXaction *sx,
|
||||
gint numRemain )
|
||||
{
|
||||
/* FIXME This condition can be tightened up */
|
||||
if ( numRemain > sx->num_occurances_total ) {
|
||||
if ( numRemain > sx->num_occurances_total )
|
||||
{
|
||||
PWARN("The number remaining is greater than the total occurrences");
|
||||
}
|
||||
else
|
||||
{
|
||||
sx->num_occurances_remain = numRemain;
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
KvpValue *
|
||||
xaccSchedXactionGetSlot( SchedXaction *sx, const char *slot )
|
||||
{
|
||||
if (!sx)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!sx) return NULL;
|
||||
|
||||
return kvp_frame_get_slot(sx->kvp_data, slot);
|
||||
return kvp_frame_get_slot(sx->inst.kvp_data, slot);
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetSlot( SchedXaction *sx,
|
||||
const char *slot,
|
||||
const KvpValue *value )
|
||||
const char *slot,
|
||||
const KvpValue *value )
|
||||
{
|
||||
if (!sx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!sx) return;
|
||||
|
||||
kvp_frame_set_slot( sx->kvp_data, slot, value );
|
||||
sx->dirty = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
KvpFrame*
|
||||
xaccSchedXactionGetSlots( SchedXaction *sx )
|
||||
{
|
||||
return sx->kvp_data;
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetSlots( SchedXaction *sx, KvpFrame *frm )
|
||||
{
|
||||
sx->kvp_data = frm;
|
||||
sx->dirty = TRUE;
|
||||
}
|
||||
|
||||
const GUID*
|
||||
xaccSchedXactionGetGUID( SchedXaction *sx )
|
||||
{
|
||||
return &sx->guid;
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetGUID( SchedXaction *sx, GUID g )
|
||||
{
|
||||
sx->guid = g;
|
||||
sx->dirty = TRUE;
|
||||
kvp_frame_set_slot( sx->inst.kvp_data, slot, value );
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -395,7 +350,7 @@ xaccSchedXactionSetAutoCreate( SchedXaction *sx,
|
||||
|
||||
sx->autoCreateOption = newAutoCreate;
|
||||
sx->autoCreateNotify = newNotify;
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -409,19 +364,19 @@ void
|
||||
xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays )
|
||||
{
|
||||
sx->advanceCreateDays = createDays;
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
gint
|
||||
xaccSchedXactionGetAdvanceReminder( SchedXaction *sx )
|
||||
{
|
||||
return sx->advanceRemindDays;
|
||||
return sx->advanceRemindDays;
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays )
|
||||
{
|
||||
sx->dirty = TRUE;
|
||||
sx->inst.dirty = TRUE;
|
||||
sx->advanceRemindDays = reminderDays;
|
||||
}
|
||||
|
||||
@ -429,64 +384,64 @@ xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays )
|
||||
GDate
|
||||
xaccSchedXactionGetNextInstance( SchedXaction *sx, void *stateData )
|
||||
{
|
||||
GDate last_occur, next_occur, tmpDate;
|
||||
GDate last_occur, next_occur, tmpDate;
|
||||
|
||||
g_date_clear( &last_occur, 1 );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
g_date_clear( &tmpDate, 1 );
|
||||
g_date_clear( &last_occur, 1 );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
g_date_clear( &tmpDate, 1 );
|
||||
|
||||
if ( g_date_valid( &sx->last_date ) ) {
|
||||
last_occur = sx->last_date;
|
||||
}
|
||||
if ( g_date_valid( &sx->last_date ) ) {
|
||||
last_occur = sx->last_date;
|
||||
}
|
||||
|
||||
if ( stateData != NULL ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
last_occur = tsd->last_date;
|
||||
}
|
||||
if ( stateData != NULL ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
last_occur = tsd->last_date;
|
||||
}
|
||||
|
||||
if ( g_date_valid( &sx->start_date ) ) {
|
||||
if ( g_date_valid(&last_occur) ) {
|
||||
last_occur =
|
||||
( g_date_compare( &last_occur,
|
||||
&sx->start_date ) > 0 ?
|
||||
last_occur : sx->start_date );
|
||||
} else {
|
||||
/* Think about this for a second, and you realize that if the
|
||||
* start date is _today_, we need a last-occur date such that
|
||||
* the 'next instance' is after that date, and equal to the
|
||||
* start date... one day should be good.
|
||||
*
|
||||
* This only holds for the first instance [read: if the
|
||||
* last[-occur]_date is invalid] */
|
||||
last_occur = sx->start_date;
|
||||
g_date_subtract_days( &last_occur, 1 );
|
||||
}
|
||||
}
|
||||
if ( g_date_valid( &sx->start_date ) ) {
|
||||
if ( g_date_valid(&last_occur) ) {
|
||||
last_occur =
|
||||
( g_date_compare( &last_occur,
|
||||
&sx->start_date ) > 0 ?
|
||||
last_occur : sx->start_date );
|
||||
} else {
|
||||
/* Think about this for a second, and you realize that if the
|
||||
* start date is _today_, we need a last-occur date such that
|
||||
* the 'next instance' is after that date, and equal to the
|
||||
* start date... one day should be good.
|
||||
*
|
||||
* This only holds for the first instance [read: if the
|
||||
* last[-occur]_date is invalid] */
|
||||
last_occur = sx->start_date;
|
||||
g_date_subtract_days( &last_occur, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
|
||||
xaccFreqSpecGetNextInstance( sx->freq, &last_occur, &next_occur );
|
||||
|
||||
/* out-of-bounds check */
|
||||
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
||||
GDate *end_date = xaccSchedXactionGetEndDate( sx );
|
||||
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
||||
PINFO( "next_occur past end date" );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
if ( stateData ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
if ( tsd->num_occur_rem == 0 ) {
|
||||
PINFO( "no more occurances remain" );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else {
|
||||
if ( sx->num_occurances_remain == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
/* out-of-bounds check */
|
||||
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
||||
GDate *end_date = xaccSchedXactionGetEndDate( sx );
|
||||
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
||||
PINFO( "next_occur past end date" );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
if ( stateData ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
if ( tsd->num_occur_rem == 0 ) {
|
||||
PINFO( "no more occurances remain" );
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else {
|
||||
if ( sx->num_occurances_remain == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next_occur;
|
||||
return next_occur;
|
||||
}
|
||||
|
||||
GDate
|
||||
@ -494,46 +449,46 @@ xaccSchedXactionGetInstanceAfter( SchedXaction *sx,
|
||||
GDate *date,
|
||||
void *stateData )
|
||||
{
|
||||
GDate prev_occur, next_occur;
|
||||
GDate prev_occur, next_occur;
|
||||
|
||||
g_date_clear( &prev_occur, 1 );
|
||||
if ( date ) {
|
||||
prev_occur = *date;
|
||||
}
|
||||
g_date_clear( &prev_occur, 1 );
|
||||
if ( date ) {
|
||||
prev_occur = *date;
|
||||
}
|
||||
|
||||
if ( stateData != NULL ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
prev_occur = tsd->last_date;
|
||||
}
|
||||
if ( stateData != NULL ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
prev_occur = tsd->last_date;
|
||||
}
|
||||
|
||||
if ( ! g_date_valid( &prev_occur ) ) {
|
||||
/* We must be at the beginning. */
|
||||
prev_occur = sx->start_date;
|
||||
g_date_subtract_days( &prev_occur, 1 );
|
||||
}
|
||||
if ( ! g_date_valid( &prev_occur ) ) {
|
||||
/* We must be at the beginning. */
|
||||
prev_occur = sx->start_date;
|
||||
g_date_subtract_days( &prev_occur, 1 );
|
||||
}
|
||||
|
||||
xaccFreqSpecGetNextInstance( sx->freq, &prev_occur, &next_occur );
|
||||
xaccFreqSpecGetNextInstance( sx->freq, &prev_occur, &next_occur );
|
||||
|
||||
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
||||
GDate *end_date;
|
||||
if ( xaccSchedXactionHasEndDate( sx ) ) {
|
||||
GDate *end_date;
|
||||
|
||||
end_date = xaccSchedXactionGetEndDate( sx );
|
||||
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
if ( stateData ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
if ( tsd->num_occur_rem == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else {
|
||||
if ( sx->num_occurances_remain == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return next_occur;
|
||||
end_date = xaccSchedXactionGetEndDate( sx );
|
||||
if ( g_date_compare( &next_occur, end_date ) > 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
if ( stateData ) {
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
if ( tsd->num_occur_rem == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
} else {
|
||||
if ( sx->num_occurances_remain == 0 ) {
|
||||
g_date_clear( &next_occur, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return next_occur;
|
||||
}
|
||||
|
||||
gint
|
||||
@ -566,23 +521,9 @@ xaccSchedXactionGetSplits( SchedXaction *sx )
|
||||
return xaccAccountGetSplitList(sx->template_acct);
|
||||
}
|
||||
|
||||
void
|
||||
xaccSchedXactionSetDirtyness( SchedXaction *sx, gboolean dirty_p)
|
||||
{
|
||||
sx->dirty = dirty_p;
|
||||
return;
|
||||
}
|
||||
|
||||
gboolean
|
||||
xaccSchedXactionIsDirty(SchedXaction *sx)
|
||||
{
|
||||
return sx->dirty;
|
||||
}
|
||||
|
||||
|
||||
static Split *
|
||||
pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
||||
Transaction *parent_trans, QofBook *book)
|
||||
Transaction *parent_trans, QofBook *book)
|
||||
{
|
||||
Split *split;
|
||||
KvpFrame *split_frame;
|
||||
@ -592,14 +533,14 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
||||
split = xaccMallocSplit(book);
|
||||
|
||||
xaccSplitSetMemo(split,
|
||||
gnc_ttsplitinfo_get_memo(s_info));
|
||||
gnc_ttsplitinfo_get_memo(s_info));
|
||||
|
||||
xaccSplitSetAction(split,
|
||||
gnc_ttsplitinfo_get_action(s_info));
|
||||
gnc_ttsplitinfo_get_action(s_info));
|
||||
|
||||
|
||||
xaccAccountInsertSplit(parent_acct,
|
||||
split);
|
||||
split);
|
||||
|
||||
split_frame = xaccSplitGetSlots(split);
|
||||
|
||||
@ -607,20 +548,20 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
||||
= kvp_value_new_string(gnc_ttsplitinfo_get_credit_formula(s_info));
|
||||
|
||||
kvp_frame_set_slot_path(split_frame,
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_CREDIT_FORMULA,
|
||||
NULL);
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_CREDIT_FORMULA,
|
||||
NULL);
|
||||
kvp_value_delete(tmp_value);
|
||||
|
||||
|
||||
tmp_value
|
||||
= kvp_value_new_string(gnc_ttsplitinfo_get_debit_formula(s_info));
|
||||
|
||||
kvp_frame_set_slot_path(split_frame,
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_DEBIT_FORMULA,
|
||||
NULL);
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_DEBIT_FORMULA,
|
||||
NULL);
|
||||
|
||||
kvp_value_delete(tmp_value);
|
||||
|
||||
@ -629,10 +570,10 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
||||
tmp_value = kvp_value_new_guid(acc_guid);
|
||||
|
||||
kvp_frame_set_slot_path(split_frame,
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_ACCOUNT,
|
||||
NULL);
|
||||
tmp_value,
|
||||
GNC_SX_ID,
|
||||
GNC_SX_ACCOUNT,
|
||||
NULL);
|
||||
|
||||
kvp_value_delete(tmp_value);
|
||||
|
||||
@ -642,7 +583,7 @@ pack_split_info (TTSplitInfo *s_info, Account *parent_acct,
|
||||
|
||||
void
|
||||
xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
|
||||
QofBook *book)
|
||||
QofBook *book)
|
||||
{
|
||||
Transaction *new_trans;
|
||||
TTInfo *tti;
|
||||
@ -664,20 +605,20 @@ xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
|
||||
xaccTransBeginEdit(new_trans);
|
||||
|
||||
xaccTransSetDescription(new_trans,
|
||||
gnc_ttinfo_get_description(tti));
|
||||
gnc_ttinfo_get_description(tti));
|
||||
|
||||
xaccTransSetNum(new_trans,
|
||||
gnc_ttinfo_get_num(tti));
|
||||
gnc_ttinfo_get_num(tti));
|
||||
xaccTransSetCurrency( new_trans,
|
||||
gnc_ttinfo_get_currency(tti) );
|
||||
gnc_ttinfo_get_currency(tti) );
|
||||
|
||||
for(split_list = gnc_ttinfo_get_template_splits(tti);
|
||||
split_list;
|
||||
split_list = split_list->next)
|
||||
split_list;
|
||||
split_list = split_list->next)
|
||||
{
|
||||
s_info = split_list->data;
|
||||
new_split = pack_split_info(s_info, sx->template_acct,
|
||||
new_trans, book);
|
||||
new_trans, book);
|
||||
xaccTransAppendSplit(new_trans, new_split);
|
||||
}
|
||||
xaccTransCommitEdit(new_trans);
|
||||
@ -687,72 +628,72 @@ xaccSchedXactionSetTemplateTrans(SchedXaction *sx, GList *t_t_list,
|
||||
void*
|
||||
gnc_sx_create_temporal_state( SchedXaction *sx )
|
||||
{
|
||||
temporalStateData *toRet =
|
||||
g_new0( temporalStateData, 1 );
|
||||
toRet->last_date = sx->last_date;
|
||||
toRet->num_occur_rem = sx->num_occurances_remain;
|
||||
toRet->num_inst = sx->instance_num;
|
||||
return (void*)toRet;
|
||||
temporalStateData *toRet =
|
||||
g_new0( temporalStateData, 1 );
|
||||
toRet->last_date = sx->last_date;
|
||||
toRet->num_occur_rem = sx->num_occurances_remain;
|
||||
toRet->num_inst = sx->instance_num;
|
||||
return (void*)toRet;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_sx_incr_temporal_state( SchedXaction *sx, void *stateData )
|
||||
{
|
||||
GDate unused;
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
GDate unused;
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
|
||||
g_date_clear( &unused, 1 );
|
||||
tsd->last_date =
|
||||
xaccSchedXactionGetInstanceAfter( sx,
|
||||
&unused,
|
||||
stateData );
|
||||
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
tsd->num_occur_rem -= 1;
|
||||
}
|
||||
tsd->num_inst += 1;
|
||||
g_date_clear( &unused, 1 );
|
||||
tsd->last_date =
|
||||
xaccSchedXactionGetInstanceAfter( sx,
|
||||
&unused,
|
||||
stateData );
|
||||
if ( xaccSchedXactionHasOccurDef( sx ) ) {
|
||||
tsd->num_occur_rem -= 1;
|
||||
}
|
||||
tsd->num_inst += 1;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_sx_revert_to_temporal_state( SchedXaction *sx, void *stateData )
|
||||
{
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
sx->last_date = tsd->last_date;
|
||||
sx->num_occurances_remain = tsd->num_occur_rem;
|
||||
sx->instance_num = tsd->num_inst;
|
||||
sx->dirty = TRUE;
|
||||
temporalStateData *tsd = (temporalStateData*)stateData;
|
||||
sx->last_date = tsd->last_date;
|
||||
sx->num_occurances_remain = tsd->num_occur_rem;
|
||||
sx->instance_num = tsd->num_inst;
|
||||
sx->inst.dirty = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_sx_destroy_temporal_state( void *stateData )
|
||||
{
|
||||
g_free( (temporalStateData*)stateData );
|
||||
g_free( (temporalStateData*)stateData );
|
||||
}
|
||||
|
||||
void*
|
||||
gnc_sx_clone_temporal_state( void *stateData )
|
||||
{
|
||||
temporalStateData *toRet, *tsd;
|
||||
tsd = (temporalStateData*)stateData;
|
||||
toRet = g_memdup( tsd, sizeof( temporalStateData ) );
|
||||
return (void*)toRet;
|
||||
temporalStateData *toRet, *tsd;
|
||||
tsd = (temporalStateData*)stateData;
|
||||
toRet = g_memdup( tsd, sizeof( temporalStateData ) );
|
||||
return (void*)toRet;
|
||||
}
|
||||
|
||||
static
|
||||
gint
|
||||
_temporal_state_data_cmp( gconstpointer a, gconstpointer b )
|
||||
{
|
||||
temporalStateData *tsd_a, *tsd_b;
|
||||
tsd_a = (temporalStateData*)a;
|
||||
tsd_b = (temporalStateData*)b;
|
||||
temporalStateData *tsd_a, *tsd_b;
|
||||
tsd_a = (temporalStateData*)a;
|
||||
tsd_b = (temporalStateData*)b;
|
||||
|
||||
if ( !tsd_a && !tsd_b )
|
||||
return 0;
|
||||
if ( !tsd_a )
|
||||
return 1;
|
||||
if ( !tsd_b )
|
||||
return -1;
|
||||
return g_date_compare( &tsd_a->last_date,
|
||||
&tsd_b->last_date );
|
||||
if ( !tsd_a && !tsd_b )
|
||||
return 0;
|
||||
if ( !tsd_a )
|
||||
return 1;
|
||||
if ( !tsd_b )
|
||||
return -1;
|
||||
return g_date_compare( &tsd_a->last_date,
|
||||
&tsd_b->last_date );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -762,9 +703,9 @@ _temporal_state_data_cmp( gconstpointer a, gconstpointer b )
|
||||
void
|
||||
gnc_sx_add_defer_instance( SchedXaction *sx, void *deferStateData )
|
||||
{
|
||||
sx->deferredList = g_list_insert_sorted( sx->deferredList,
|
||||
deferStateData,
|
||||
_temporal_state_data_cmp );
|
||||
sx->deferredList = g_list_insert_sorted( sx->deferredList,
|
||||
deferStateData,
|
||||
_temporal_state_data_cmp );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -774,7 +715,7 @@ gnc_sx_add_defer_instance( SchedXaction *sx, void *deferStateData )
|
||||
void
|
||||
gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData )
|
||||
{
|
||||
sx->deferredList = g_list_remove( sx->deferredList, deferStateData );
|
||||
sx->deferredList = g_list_remove( sx->deferredList, deferStateData );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -786,6 +727,6 @@ gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData )
|
||||
GList*
|
||||
gnc_sx_get_defer_instances( SchedXaction *sx )
|
||||
{
|
||||
return sx->deferredList;
|
||||
return sx->deferredList;
|
||||
}
|
||||
|
||||
|
@ -64,21 +64,6 @@ typedef struct gncp_SchedXaction SchedXaction;
|
||||
**/
|
||||
SchedXaction *xaccSchedXactionMalloc(QofBook *book);
|
||||
|
||||
/**
|
||||
* @return True if the scheduled transaction is dirty and needs to
|
||||
* be saved.
|
||||
**/
|
||||
gboolean xaccSchedXactionIsDirty(SchedXaction *sx);
|
||||
|
||||
/**
|
||||
* Set dirtyness state. Only save/load code should modify this outside
|
||||
* SX engine CODE . . .
|
||||
* (set it to FALSE after backend completes reading in data
|
||||
*
|
||||
* FIXME: put this into a private header . . . .
|
||||
**/
|
||||
void xaccSchedXactionSetDirtyness(SchedXaction *sx, gboolean dirty_p);
|
||||
|
||||
/**
|
||||
* Cleans up and frees a SchedXaction and it's associated data.
|
||||
**/
|
||||
@ -156,37 +141,6 @@ void xaccSchedXactionSetAdvanceCreation( SchedXaction *sx, gint createDays );
|
||||
gint xaccSchedXactionGetAdvanceReminder( SchedXaction *sx );
|
||||
void xaccSchedXactionSetAdvanceReminder( SchedXaction *sx, gint reminderDays );
|
||||
|
||||
/*
|
||||
* The following function is slightly risky. If you change
|
||||
* the retrieved KvpFrame you must mark the SchedXaction
|
||||
* dirty with xaccSchedXactionSetDirtyness
|
||||
*/
|
||||
KvpFrame *xaccSchedXactionGetSlots( SchedXaction *sx );
|
||||
/**
|
||||
* Sets the SX kvp data to the given kvp_frame.
|
||||
* NOTE: This is not copied, but set directly.
|
||||
**/
|
||||
void xaccSchedXactionSetSlots( SchedXaction *sx,
|
||||
KvpFrame *frm );
|
||||
|
||||
/**
|
||||
* Use the following two functions in preference to
|
||||
* the above two . . .
|
||||
*/
|
||||
KvpValue *xaccSchedXactionGetSlot( SchedXaction *sx,
|
||||
const char *slot );
|
||||
|
||||
/*
|
||||
* This function copies value, so you don't have to
|
||||
*/
|
||||
|
||||
void xaccSchedXactionSetSlot( SchedXaction *sx,
|
||||
const char *slot,
|
||||
const KvpValue *value );
|
||||
|
||||
const GUID *xaccSchedXactionGetGUID( SchedXaction *sx );
|
||||
void xaccSchedXactionSetGUID( SchedXaction *sx, GUID g );
|
||||
|
||||
///@{
|
||||
/**
|
||||
* Temporal state data.
|
||||
@ -254,6 +208,19 @@ void gnc_sx_remove_defer_instance( SchedXaction *sx, void *deferStateData );
|
||||
GList *gnc_sx_get_defer_instances( SchedXaction *sx );
|
||||
|
||||
|
||||
/** deprecated routines */
|
||||
#define xaccSchedXactionIsDirty(X) qof_instance_is_dirty (QOF_INSTANCE(X))
|
||||
#define xaccSchedXactionGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
#define xaccSchedXactionGetSlots(X) qof_instance_get_slots(QOF_INSTANCE(X))
|
||||
|
||||
/** Deprecated, to be replaced with 'dirty' kvp's */
|
||||
KvpValue *xaccSchedXactionGetSlot( SchedXaction *sx,
|
||||
const char *slot );
|
||||
void xaccSchedXactionSetSlot( SchedXaction *sx,
|
||||
const char *slot,
|
||||
const KvpValue *value );
|
||||
|
||||
|
||||
#endif /* XACC_SCHEDXACTION_H */
|
||||
|
||||
/** @} */
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#include "SchedXaction.h"
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
#include "qofinstance-p.h"
|
||||
|
||||
/**
|
||||
* A single scheduled transaction.
|
||||
@ -50,6 +52,7 @@
|
||||
**/
|
||||
struct gncp_SchedXaction
|
||||
{
|
||||
QofInstance inst;
|
||||
gchar *name;
|
||||
|
||||
FreqSpec *freq;
|
||||
@ -74,17 +77,10 @@ struct gncp_SchedXaction
|
||||
gint advanceRemindDays;
|
||||
|
||||
Account *template_acct;
|
||||
GUID guid;
|
||||
QofEntityTable *entity_table;
|
||||
|
||||
/** The list of deferred SX instances. This list is of temporalStateData
|
||||
* instances. */
|
||||
GList /* <temporalStateData*> */ *deferredList;
|
||||
|
||||
/* Changed since last save? */
|
||||
gboolean dirty;
|
||||
|
||||
KvpFrame *kvp_data;
|
||||
};
|
||||
|
||||
/** Just the variable temporal bits from the SX structure. */
|
||||
@ -94,4 +90,6 @@ typedef struct _temporalStateData {
|
||||
gint num_inst;
|
||||
} temporalStateData;
|
||||
|
||||
#endif
|
||||
#define xaccSchedXactionSetGUID(X,G) qof_entity_set_guid(QOF_ENTITY(X),(G))
|
||||
|
||||
#endif /* XACC_SCHEDXACTION_P_H */
|
||||
|
@ -91,6 +91,7 @@ TransScrubOrphansFast (Transaction *trans, AccountGroup *root)
|
||||
GList *node;
|
||||
|
||||
if (!trans) return;
|
||||
g_return_if_fail (root);
|
||||
|
||||
for (node = trans->splits; node; node = node->next)
|
||||
{
|
||||
@ -373,7 +374,7 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
|
||||
/* Put split into account before setting split value */
|
||||
if (!balance_split)
|
||||
{
|
||||
balance_split = xaccMallocSplit (trans->book);
|
||||
balance_split = xaccMallocSplit (trans->inst.book);
|
||||
|
||||
xaccAccountBeginEdit (account);
|
||||
xaccAccountInsertSplit (account, balance_split);
|
||||
@ -544,7 +545,7 @@ xaccTransScrubCurrency (Transaction *trans)
|
||||
currency = xaccTransGetCurrency (trans);
|
||||
if (currency) return;
|
||||
|
||||
currency = xaccTransFindOldCommonCurrency (trans, trans->book);
|
||||
currency = xaccTransFindOldCommonCurrency (trans, trans->inst.book);
|
||||
if (currency)
|
||||
{
|
||||
xaccTransBeginEdit (trans);
|
||||
|
@ -295,7 +295,7 @@ remove_guids (Split *sa, Split *sb)
|
||||
|
||||
/* Find and remove the matching guid's */
|
||||
ksub = gnc_kvp_bag_find_by_guid (sa->kvp_data, "lot-split",
|
||||
"peer_guid", &sb->guid);
|
||||
"peer_guid", &sb->entity.guid);
|
||||
if (ksub)
|
||||
{
|
||||
gnc_kvp_bag_remove_frame (sa->kvp_data, "lot-split", ksub);
|
||||
@ -304,7 +304,7 @@ remove_guids (Split *sa, Split *sb)
|
||||
|
||||
/* Now do it in the other direction */
|
||||
ksub = gnc_kvp_bag_find_by_guid (sb->kvp_data, "lot-split",
|
||||
"peer_guid", &sa->guid);
|
||||
"peer_guid", &sa->entity.guid);
|
||||
if (ksub)
|
||||
{
|
||||
gnc_kvp_bag_remove_frame (sb->kvp_data, "lot-split", ksub);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@
|
||||
#include "guid.h"
|
||||
#include "kvp_frame.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofinstance.h"
|
||||
|
||||
/** @name Split Reconciled field values
|
||||
If you change these
|
||||
@ -135,17 +136,18 @@ void xaccTransCommitEdit (Transaction *trans);
|
||||
void xaccTransRollbackEdit (Transaction *trans);
|
||||
|
||||
/** The xaccTransIsOpen() method returns TRUE if the transaction
|
||||
is open for editing. Otherwise, it returns false. */
|
||||
is open for editing. Otherwise, it returns false.
|
||||
XXX this routne should probably be deprecated. its, umm,
|
||||
hard to imagine legitamate uses (but it is used by
|
||||
the import/export code for reasons I can't understand.)
|
||||
*/
|
||||
gboolean xaccTransIsOpen (const Transaction *trans);
|
||||
|
||||
/** The xaccTransLookup() subroutine will return the
|
||||
transaction associated with the given id, or NULL
|
||||
if there is no such transaction. */
|
||||
Transaction * xaccTransLookup (const GUID *guid, QofBook *book);
|
||||
/** The xaccTransLookup() subroutine will return the
|
||||
transaction associated with the given id, or NULL
|
||||
if there is no such transaction. */
|
||||
Transaction * xaccTransLookupDirect (GUID guid, QofBook *book);
|
||||
#define xaccTransLookupDirect(g,b) xaccTransLookup(&(g),b)
|
||||
|
||||
/** \warning XXX FIXME
|
||||
* gnc_book_count_transactions is a utility function,
|
||||
@ -158,16 +160,6 @@ guint gnc_book_count_transactions(QofBook *book);
|
||||
|
||||
/** @name Transaction general getters/setters */
|
||||
/**@{*/
|
||||
/** The xaccTransGetGUID() subroutine will return the
|
||||
globally unique id associated with that transaction. */
|
||||
const GUID * xaccTransGetGUID (const Transaction *trans);
|
||||
|
||||
/** xaccTransReturnGUID() will returns a GUID struct
|
||||
associated with that transaction. */
|
||||
GUID xaccTransReturnGUID (const Transaction *trans);
|
||||
|
||||
/** Returns the book in which the transaction is stored */
|
||||
QofBook * xaccTransGetBook (const Transaction *trans);
|
||||
|
||||
/** Sorts the splits in a transaction, putting the debits first,
|
||||
* followed by the credits.
|
||||
@ -178,17 +170,6 @@ void xaccTransSortSplits (Transaction *trans);
|
||||
*/
|
||||
void xaccTransDump (Transaction *trans, const char *tag);
|
||||
|
||||
/** Returns the transaction's KvpFrame slots.
|
||||
*
|
||||
Transaction slots are used to store arbitrary strings, numbers, and
|
||||
structures which aren't members of the transaction struct. */
|
||||
KvpFrame *xaccTransGetSlots(const Transaction *trans);
|
||||
|
||||
/** Set the KvpFrame slots of this transaction to the given frm by
|
||||
* directly using the frm pointer (i.e. non-copying). */
|
||||
void xaccTransSetSlots_nc(Transaction *t, KvpFrame *frm);
|
||||
|
||||
|
||||
/** Set the Transaction Type
|
||||
*
|
||||
* See #define TXN_TYPE_NONE, TXN_TYPE_INVOICE and TXN_TYPE_PAYMENT */
|
||||
@ -439,15 +420,6 @@ KvpFrame *xaccSplitGetSlots(const Split *split);
|
||||
void xaccSplitSetSlots_nc(Split *s, KvpFrame *frm);
|
||||
|
||||
|
||||
/** The xaccSplitGetGUID() subroutine will return the
|
||||
* globally unique id associated with that split. */
|
||||
const GUID * xaccSplitGetGUID (const Split *split);
|
||||
|
||||
/** xaccSplitReturnGUID also returns the guid (globally unique id),
|
||||
* but in a GUID struct.*/
|
||||
GUID xaccSplitReturnGUID (const Split *split);
|
||||
|
||||
|
||||
/** The memo is an arbitrary string associated with a split. It is
|
||||
* intended to hold a short (zero to forty character) string that is
|
||||
* displayed by the GUI along with this split. Users typically type
|
||||
@ -642,9 +614,7 @@ gboolean xaccSplitEqual(const Split *sa, const Split *sb,
|
||||
* split associated with the given id, or NULL
|
||||
* if there is no such split. */
|
||||
Split * xaccSplitLookup (const GUID *guid, QofBook *book);
|
||||
/** Returns the split associated with the given id, or NULL if there
|
||||
* is no such split. */
|
||||
Split * xaccSplitLookupDirect (GUID guid, QofBook *book);
|
||||
#define xaccSplitLookupDirect(g,b) xaccSplitLookup(&(g),b)
|
||||
|
||||
|
||||
/**
|
||||
@ -887,5 +857,13 @@ Timespec xaccTransGetVoidTime(const Transaction *tr);
|
||||
|
||||
#define RECONCILED_MATCH_TYPE "reconciled-match"
|
||||
|
||||
/** deprecated rouitines */
|
||||
#define xaccSplitGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
#define xaccSplitReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
|
||||
#define xaccTransGetBook(X) qof_instance_get_book (QOF_INSTANCE(X))
|
||||
#define xaccTransGetGUID(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
#define xaccTransReturnGUID(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
|
||||
#define xaccTransGetSlots(X) qof_instance_get_slots (QOF_INSTANCE(X))
|
||||
|
||||
#endif /* XACC_TRANSACTION_H */
|
||||
/** @} */
|
||||
|
@ -56,6 +56,9 @@
|
||||
#include "qofbackend.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
#include "qofinstance.h"
|
||||
#include "qofinstance-p.h"
|
||||
|
||||
|
||||
/** STRUCTS *********************************************************/
|
||||
@ -90,7 +93,7 @@
|
||||
|
||||
struct split_s
|
||||
{
|
||||
GUID guid; /* globally unique id */
|
||||
QofEntity entity; /* globally unique id */
|
||||
|
||||
QofBook *book; /* The enitity table where this split is stored. */
|
||||
|
||||
@ -160,12 +163,7 @@ struct split_s
|
||||
|
||||
struct transaction_s
|
||||
{
|
||||
/* guid is a globally unique identifier which can be used to
|
||||
* reference the transaction.
|
||||
*/
|
||||
GUID guid;
|
||||
|
||||
QofBook *book; /* The entity_table where the transaction is stored */
|
||||
QofInstance inst; /* glbally unique id */
|
||||
|
||||
Timespec date_entered; /* date register entry was made */
|
||||
Timespec date_posted; /* date transaction was posted at bank */
|
||||
@ -181,12 +179,6 @@ struct transaction_s
|
||||
*/
|
||||
char * description;
|
||||
|
||||
/* kvp_data is a key-value pair database for storing simple
|
||||
* "extra" information in splits, transactions, and accounts.
|
||||
* it's NULL until accessed. */
|
||||
KvpFrame * kvp_data;
|
||||
|
||||
|
||||
/* The common_currency field is the balancing common currency for
|
||||
* all the splits in the transaction. Alternate, better(?) name:
|
||||
* "valuation currency": it is the currency in which all of the
|
||||
@ -207,9 +199,6 @@ struct transaction_s
|
||||
* corresponding to the current traversal. */
|
||||
unsigned char marker;
|
||||
|
||||
gint32 editlevel; /* nestcount of begin/end edit calls */
|
||||
gboolean do_free; /* transaction in process of being destroyed */
|
||||
|
||||
/* The orig pointer points at a copy of the original transaction,
|
||||
* before editing was started. This orig copy is used to rollback
|
||||
* any changes made if/when the edit is abandoned.
|
||||
@ -224,12 +213,12 @@ struct transaction_s
|
||||
/* Set the transaction's GUID. This should only be done when reading
|
||||
* a transaction from a datafile, or some other external source. Never
|
||||
* call this on an existing transaction! */
|
||||
void xaccTransSetGUID (Transaction *trans, const GUID *guid);
|
||||
#define xaccTransSetGUID(t,g) qof_entity_set_guid(QOF_ENTITY(t),g)
|
||||
|
||||
/* Set the split's GUID. This should only be done when reading
|
||||
* a split from a datafile, or some other external source. Never
|
||||
* call this on an existing split! */
|
||||
void xaccSplitSetGUID (Split *split, const GUID *guid);
|
||||
#define xaccSplitSetGUID(s,g) qof_entity_set_guid(QOF_ENTITY(s),g)
|
||||
|
||||
/* The xaccFreeSplit() method simply frees all memory associated
|
||||
* with the split. It does not verify that the split isn't
|
||||
@ -302,6 +291,14 @@ void DxaccSplitSetSharePriceAndAmount (Split *split,
|
||||
double amount);
|
||||
void DxaccSplitSetShareAmount (Split *split, double amount);
|
||||
|
||||
|
||||
/** Set the KvpFrame slots of this transaction to the given frm by
|
||||
* * directly using the frm pointer (i.e. non-copying).
|
||||
* * XXX this is wrong, nedds to be replaced with a transactional thingy
|
||||
* in kvp + qofinstance. for now, this is a quasi-unctional placeholder.
|
||||
* */
|
||||
#define xaccTransSetSlots_nc(T,F) qof_instance_set_slots(QOF_INSTANCE(T),F)
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
||||
|
@ -574,8 +574,8 @@ xaccSplitGetCapGainsSplit (Split *split)
|
||||
gains_guid = kvp_value_get_guid (val);
|
||||
if (!gains_guid) return NULL;
|
||||
|
||||
gains_split = qof_entity_lookup (qof_book_get_entity_table(split->book),
|
||||
gains_guid, GNC_ID_SPLIT);
|
||||
/* Both splits will be in the same collection, so seearch there. */
|
||||
gains_split = (Split*) qof_collection_lookup_entity (split->entity.collection, gains_guid);
|
||||
PINFO ("split=%p has gains-split=%p", split, gains_split);
|
||||
return gains_split;
|
||||
}
|
||||
|
@ -95,8 +95,6 @@ back_associate_expense_accounts(Account *stock_account,
|
||||
g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
|
||||
existing_acc_guid = kvp_value_get_guid(val);
|
||||
|
||||
g_return_if_fail(GNC_ID_NONE == qof_entity_type (qof_book_get_entity_table (stock_account->inst.book), existing_acc_guid));
|
||||
|
||||
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
|
||||
stock_acc_guid_kvpval);
|
||||
|
||||
@ -130,9 +128,6 @@ back_associate_income_accounts(Account *stock_account,
|
||||
g_return_if_fail(kvp_value_get_type(val) == KVP_TYPE_GUID);
|
||||
existing_acc_guid = kvp_value_get_guid(val);
|
||||
|
||||
g_return_if_fail(qof_entity_type(qof_book_get_entity_table(stock_account->inst.book), existing_acc_guid) ==
|
||||
GNC_ID_NONE);
|
||||
|
||||
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account",
|
||||
stock_acc_guid_kvpval);
|
||||
kvp_frame_set_slot_nc(acc_frame, "associated-stock-account-category",
|
||||
@ -448,10 +443,6 @@ gnc_tracking_dissociate_account(Account *inc_or_expense_account)
|
||||
"associated-stock-account");
|
||||
|
||||
stock_account_guid = kvp_value_get_guid(stock_account_kvpval);
|
||||
if(!safe_strcmp
|
||||
(qof_entity_type(qof_book_get_entity_table(inc_or_expense_account->inst.book), stock_account_guid),
|
||||
GNC_ID_NULL))
|
||||
return;
|
||||
|
||||
category_kvpval = kvp_frame_get_slot(current_account_kvpframe,
|
||||
"associated-stock-account-category");
|
||||
|
@ -35,37 +35,35 @@
|
||||
#include "qofbook.h"
|
||||
|
||||
/* begin_edit helper
|
||||
*
|
||||
* assumes:
|
||||
* obj->editlevel (int)
|
||||
* obj->book (QofBook*)
|
||||
*
|
||||
* @args:
|
||||
* obj: the object to begin editing
|
||||
* type: the object type
|
||||
* inst: an instance of QofInstance
|
||||
*
|
||||
* The caller should use this macro first and then perform any other operations.
|
||||
*/
|
||||
|
||||
#define GNC_BEGIN_EDIT(obj,type) { \
|
||||
QofBackend * be; \
|
||||
if (!(obj)) return; \
|
||||
\
|
||||
(obj)->editlevel++; \
|
||||
if (1 < (obj)->editlevel) return; \
|
||||
\
|
||||
if (0 >= (obj)->editlevel) \
|
||||
{ \
|
||||
PERR ("unbalanced call - resetting (was %d)", (obj)->editlevel); \
|
||||
(obj)->editlevel = 1; \
|
||||
} \
|
||||
\
|
||||
/* See if there's a backend. If there is, invoke it. */ \
|
||||
be = qof_book_get_backend ((obj)->book); \
|
||||
if (be && be->begin) { \
|
||||
(be->begin) (be, (type), (obj)); \
|
||||
} \
|
||||
}
|
||||
#define GNC_BEGIN_EDIT(inst) \
|
||||
QofBackend * be; \
|
||||
if (!(inst)) return; \
|
||||
\
|
||||
(inst)->editlevel++; \
|
||||
if (1 < (inst)->editlevel) return; \
|
||||
\
|
||||
if (0 >= (inst)->editlevel) \
|
||||
{ \
|
||||
PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
|
||||
(inst)->editlevel = 1; \
|
||||
} \
|
||||
ENTER ("inst=%p", (inst)); \
|
||||
\
|
||||
/* See if there's a backend. If there is, invoke it. */ \
|
||||
be = qof_book_get_backend ((inst)->book); \
|
||||
if (be && be->begin) { \
|
||||
(be->begin) (be, (inst)->entity.e_type, (inst)); \
|
||||
} else { \
|
||||
/* We tried and failed to start transaction! */ \
|
||||
(inst)->dirty = TRUE; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -73,84 +71,93 @@
|
||||
*
|
||||
* The caller should call PART1 as the first thing, then
|
||||
* perform any local operations prior to calling the backend.
|
||||
* Then call PART2. You cannot do anything after PART2.
|
||||
*
|
||||
* assumes:
|
||||
* obj->editlevel (int)
|
||||
* obj->book (QofBook*)
|
||||
* obj->do_free (gboolean)
|
||||
* obj->dirty (gboolean)
|
||||
* Then call PART2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* part1 -- deal with the editlevel
|
||||
*
|
||||
* assumes:
|
||||
* obj->editlevel (int)
|
||||
*
|
||||
* @args:
|
||||
* obj: the object being committed
|
||||
* inst: an instance of QofInstance
|
||||
*/
|
||||
|
||||
#define GNC_COMMIT_EDIT_PART1(obj) { \
|
||||
if (!(obj)) return; \
|
||||
\
|
||||
(obj)->editlevel--; \
|
||||
if (0 < (obj)->editlevel) return; \
|
||||
\
|
||||
if (0 > (obj)->editlevel) \
|
||||
{ \
|
||||
PERR ("unbalanced call - resetting (was %d)", (obj)->editlevel); \
|
||||
(obj)->editlevel = 0; \
|
||||
} \
|
||||
#define GNC_COMMIT_EDIT_PART1(inst) { \
|
||||
if (!(inst)) return; \
|
||||
\
|
||||
(inst)->editlevel--; \
|
||||
if (0 < (inst)->editlevel) return; \
|
||||
\
|
||||
/* The pricedb sufffers from delayed update... */ \
|
||||
/* This may be setting a bad precedent for other types, I fear. */ \
|
||||
/* Other types probably really should handle begin like this. */ \
|
||||
if ((-1 == (inst)->editlevel) && (inst)->dirty) \
|
||||
{ \
|
||||
QofBackend * be; \
|
||||
be = qof_book_get_backend ((inst)->book); \
|
||||
if (be && be->begin) { \
|
||||
(be->begin) (be, (inst)->entity.e_type, (inst)); \
|
||||
} \
|
||||
(inst)->editlevel = 0; \
|
||||
} \
|
||||
if (0 > (inst)->editlevel) \
|
||||
{ \
|
||||
PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
|
||||
(inst)->editlevel = 0; \
|
||||
} \
|
||||
ENTER ("inst=%p, dirty=%d do-free=%d", \
|
||||
(inst), (inst)->dirty, (inst)->do_free); \
|
||||
}
|
||||
|
||||
/*
|
||||
* part2 -- deal with the backend
|
||||
*
|
||||
* assumes:
|
||||
* obj->book (QofBook*)
|
||||
* obj->do_free (gboolean)
|
||||
*
|
||||
* @args:
|
||||
* obj: the object being committed
|
||||
* type: the type of the object
|
||||
* inst: an instance of QofInstance
|
||||
* on_error: a function called if there is a backend error.
|
||||
* void (*on_error)(obj, QofBackendError)
|
||||
* on_done: a function called after the commit is complete but before
|
||||
* the object is freed. This is where you clear the "dirty"
|
||||
* flag, and perform any other operations after the commit.
|
||||
* void (*on_done)(obj)
|
||||
* on_free: a function called if obj->do_free is TRUE.
|
||||
* void (*on_free)(obj)
|
||||
* void (*on_error)(inst, QofBackendError)
|
||||
* on_done: a function called after the commit is complete
|
||||
* but before the instect is freed. Perform any other
|
||||
* operations after the commit.
|
||||
* void (*on_done)(inst)
|
||||
* on_free: a function called if inst->do_free is TRUE.
|
||||
* void (*on_free)(inst)
|
||||
*/
|
||||
#define GNC_COMMIT_EDIT_PART2(obj,type,on_error,on_done,on_free) { \
|
||||
QofBackend * be; \
|
||||
\
|
||||
/* See if there's a backend. If there is, invoke it. */ \
|
||||
be = qof_book_get_backend ((obj)->book); \
|
||||
if (be && be->commit) \
|
||||
{ \
|
||||
QofBackendError errcode; \
|
||||
\
|
||||
/* clear errors */ \
|
||||
do { \
|
||||
errcode = qof_backend_get_error (be); \
|
||||
} while (ERR_BACKEND_NO_ERR != errcode); \
|
||||
\
|
||||
(be->commit) (be, (type), (obj)); \
|
||||
errcode = qof_backend_get_error (be); \
|
||||
if (ERR_BACKEND_NO_ERR != errcode) \
|
||||
{ \
|
||||
(obj)->do_free = FALSE; \
|
||||
(on_error)((obj), errcode); \
|
||||
qof_backend_set_error (be, errcode); \
|
||||
} \
|
||||
} \
|
||||
(on_done)(obj); \
|
||||
(obj)->dirty = FALSE; \
|
||||
\
|
||||
if ((obj)->do_free) { (on_free)(obj); } \
|
||||
#define GNC_COMMIT_EDIT_PART2(inst,on_error,on_done,on_free) { \
|
||||
QofBackend * be; \
|
||||
\
|
||||
/* See if there's a backend. If there is, invoke it. */ \
|
||||
be = qof_book_get_backend ((inst)->book); \
|
||||
if (be && be->commit) \
|
||||
{ \
|
||||
QofBackendError errcode; \
|
||||
\
|
||||
/* clear errors */ \
|
||||
do { \
|
||||
errcode = qof_backend_get_error (be); \
|
||||
} while (ERR_BACKEND_NO_ERR != errcode); \
|
||||
\
|
||||
(be->commit) (be, (inst)->entity.e_type, (inst)); \
|
||||
errcode = qof_backend_get_error (be); \
|
||||
if (ERR_BACKEND_NO_ERR != errcode) \
|
||||
{ \
|
||||
/* XXX Should perform a rollback here */ \
|
||||
(inst)->do_free = FALSE; \
|
||||
\
|
||||
/* Push error back onto the stack */ \
|
||||
qof_backend_set_error (be, errcode); \
|
||||
(on_error)((inst), errcode); \
|
||||
} \
|
||||
/* XXX the backend commit code should clear dirty!! */ \
|
||||
(inst)->dirty = FALSE; \
|
||||
} \
|
||||
(on_done)(inst); \
|
||||
\
|
||||
LEAVE ("inst=%p, dirty=%d do-free=%d", \
|
||||
(inst), (inst)->dirty, (inst)->do_free); \
|
||||
if ((inst)->do_free) { \
|
||||
(on_free)(inst); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
@ -1572,7 +1572,7 @@ commodity_table_book_end (QofBook *book)
|
||||
static QofObject commodity_table_object_def =
|
||||
{
|
||||
interface_version: QOF_OBJECT_VERSION,
|
||||
name: GNC_ID_COMMODITY_TABLE,
|
||||
e_type: GNC_ID_COMMODITY_TABLE,
|
||||
type_label: "CommodityTable",
|
||||
book_begin: commodity_table_book_begin,
|
||||
book_end: commodity_table_book_end,
|
||||
|
@ -41,11 +41,11 @@
|
||||
#include "kvp_frame.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
|
||||
struct gnc_lot_struct
|
||||
{
|
||||
/* Unique guid for this lot */
|
||||
GUID guid;
|
||||
QofEntity entity; /* Unique guid for this lot */
|
||||
|
||||
/* Book that this lot belongs to */
|
||||
QofBook *book;
|
||||
@ -69,7 +69,7 @@ struct gnc_lot_struct
|
||||
unsigned char marker;
|
||||
};
|
||||
|
||||
void gnc_lot_set_guid(GNCLot *lot, GUID guid);
|
||||
#define gnc_lot_set_guid(L,G) qof_entity_set_guid(QOF_ENTITY(L),&(G))
|
||||
|
||||
/* Register with the Query engine */
|
||||
void gnc_lot_register (void);
|
||||
|
@ -61,6 +61,7 @@ static short module = MOD_LOT;
|
||||
static void
|
||||
gnc_lot_init (GNCLot *lot, QofBook *book)
|
||||
{
|
||||
QofCollection *col;
|
||||
ENTER ("(lot=%p, book=%p)", lot, book);
|
||||
lot->kvp_data = kvp_frame_new();
|
||||
lot->account = NULL;
|
||||
@ -69,8 +70,8 @@ gnc_lot_init (GNCLot *lot, QofBook *book)
|
||||
lot->marker = 0;
|
||||
|
||||
lot->book = book;
|
||||
qof_entity_guid_new (book->entity_table, &lot->guid);
|
||||
qof_entity_store (book->entity_table, lot, &lot->guid, GNC_ID_LOT);
|
||||
col = qof_book_get_collection (book, GNC_ID_LOT);
|
||||
qof_entity_init (&lot->entity, GNC_ID_LOT, col);
|
||||
LEAVE ("(lot=%p, book=%p)", lot, book);
|
||||
}
|
||||
|
||||
@ -82,7 +83,7 @@ gnc_lot_new (QofBook *book)
|
||||
|
||||
lot = g_new (GNCLot, 1);
|
||||
gnc_lot_init (lot, book);
|
||||
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_CREATE);
|
||||
gnc_engine_gen_event (&lot->entity, GNC_EVENT_CREATE);
|
||||
return lot;
|
||||
}
|
||||
|
||||
@ -93,9 +94,9 @@ gnc_lot_destroy (GNCLot *lot)
|
||||
if (!lot) return;
|
||||
|
||||
ENTER ("(lot=%p)", lot);
|
||||
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_DESTROY);
|
||||
gnc_engine_gen_event (&lot->entity, GNC_EVENT_DESTROY);
|
||||
|
||||
qof_entity_remove (lot->book->entity_table, &lot->guid);
|
||||
qof_entity_release (&lot->entity);
|
||||
|
||||
for (node=lot->splits; node; node=node->next)
|
||||
{
|
||||
@ -115,31 +116,13 @@ gnc_lot_destroy (GNCLot *lot)
|
||||
|
||||
/* ============================================================= */
|
||||
|
||||
const GUID *
|
||||
gnc_lot_get_guid (GNCLot *lot)
|
||||
{
|
||||
if (!lot) return NULL;
|
||||
return &lot->guid;
|
||||
}
|
||||
|
||||
void
|
||||
gnc_lot_set_guid (GNCLot *lot, GUID uid)
|
||||
{
|
||||
if (!lot) return;
|
||||
|
||||
if (guid_equal (&lot->guid, &uid)) return;
|
||||
|
||||
qof_entity_remove(lot->book->entity_table, &lot->guid);
|
||||
lot->guid = uid;
|
||||
qof_entity_store(lot->book->entity_table, lot, &lot->guid, GNC_ID_LOT);
|
||||
}
|
||||
|
||||
GNCLot *
|
||||
gnc_lot_lookup (const GUID *guid, QofBook *book)
|
||||
{
|
||||
QofCollection *col;
|
||||
if (!guid || !book) return NULL;
|
||||
return qof_entity_lookup (qof_book_get_entity_table (book),
|
||||
guid, GNC_ID_LOT);
|
||||
col = qof_book_get_collection (book, GNC_ID_LOT);
|
||||
return (GNCLot *) qof_collection_lookup_entity (col, guid);
|
||||
}
|
||||
|
||||
QofBook *
|
||||
@ -149,7 +132,6 @@ gnc_lot_get_book (GNCLot *lot)
|
||||
return lot->book;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================= */
|
||||
|
||||
gboolean
|
||||
@ -292,7 +274,7 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
|
||||
/* for recomputation of is-closed */
|
||||
lot->is_closed = -1;
|
||||
|
||||
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
|
||||
gnc_engine_gen_event (&lot->entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
|
||||
void
|
||||
@ -310,7 +292,7 @@ gnc_lot_remove_split (GNCLot *lot, Split *split)
|
||||
xaccAccountRemoveLot (lot->account, lot);
|
||||
lot->account = NULL;
|
||||
}
|
||||
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
|
||||
gnc_engine_gen_event (&lot->entity, GNC_EVENT_MODIFY);
|
||||
}
|
||||
|
||||
/* ============================================================== */
|
||||
@ -379,8 +361,8 @@ gnc_lot_get_latest_split (GNCLot *lot)
|
||||
void gnc_lot_register (void)
|
||||
{
|
||||
static const QofParam params[] = {
|
||||
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
|
||||
{ QOF_QUERY_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)gnc_lot_get_book, NULL },
|
||||
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)gnc_lot_get_guid, NULL },
|
||||
{ LOT_IS_CLOSED, QOF_TYPE_BOOLEAN, (QofAccessFunc)gnc_lot_is_closed, NULL },
|
||||
{ LOT_BALANCE, QOF_TYPE_NUMERIC, (QofAccessFunc)gnc_lot_get_balance, NULL },
|
||||
{ NULL },
|
||||
|
@ -45,11 +45,11 @@
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-numeric.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
|
||||
GNCLot * gnc_lot_new (QofBook *);
|
||||
void gnc_lot_destroy (GNCLot *);
|
||||
|
||||
const GUID * gnc_lot_get_guid (GNCLot *p);
|
||||
GNCLot * gnc_lot_lookup (const GUID *guid, QofBook *book);
|
||||
QofBook * gnc_lot_get_book (GNCLot *);
|
||||
|
||||
@ -114,6 +114,8 @@ void gnc_lot_set_notes (GNCLot *, const char *);
|
||||
* */
|
||||
KvpFrame * gnc_lot_get_slots (GNCLot *);
|
||||
|
||||
#define gnc_lot_get_guid(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
|
||||
#define LOT_IS_CLOSED "is-closed?"
|
||||
#define LOT_BALANCE "balance"
|
||||
|
||||
|
@ -32,12 +32,14 @@
|
||||
#include "qofbackend.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
#include "qofinstance.h"
|
||||
#include "qofinstance-p.h"
|
||||
|
||||
struct gnc_price_s
|
||||
{
|
||||
/* 'public' data fields */
|
||||
GUID guid; /* globally unique price id */
|
||||
QofBook *book; /* book to which this price belongs to */
|
||||
QofInstance inst; /* globally unique object identifier */
|
||||
|
||||
GNCPriceDB *db;
|
||||
gnc_commodity *commodity;
|
||||
@ -50,11 +52,7 @@ struct gnc_price_s
|
||||
guint32 version_check; /* data aging timestamp */
|
||||
|
||||
/* 'private' object management fields */
|
||||
QofEntityTable *entity_table; /* table in which price is stored */
|
||||
guint32 refcount; /* garbage collection reference count */
|
||||
gint32 editlevel; /* nesting level of begin/end edit calls */
|
||||
gboolean not_saved; /* price edit saved flag */
|
||||
gboolean do_free; /* price is going to be destroyed soon */
|
||||
};
|
||||
|
||||
|
||||
@ -99,13 +97,14 @@ typedef struct gnc_price_lookup_helper_s
|
||||
Timespec time;
|
||||
} GNCPriceLookupHelper;
|
||||
|
||||
#define gnc_price_set_guid(P,G) qof_entity_set_guid(QOF_ENTITY(P),(G))
|
||||
|
||||
void gnc_pricedb_set_db(QofBook *book, GNCPriceDB *db);
|
||||
|
||||
void gnc_pricedb_mark_clean(GNCPriceDB *db);
|
||||
void gnc_pricedb_substitute_commodity(GNCPriceDB *db,
|
||||
gnc_commodity *old_c,
|
||||
gnc_commodity *new_c);
|
||||
void gnc_price_set_guid (GNCPrice *p, const GUID *guid);
|
||||
|
||||
/** register the pricedb object with the gncObject system */
|
||||
gboolean gnc_pricedb_register (void);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gnc-be-utils.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "gnc-event-p.h"
|
||||
@ -34,6 +35,7 @@
|
||||
#include "gnc-trace.h"
|
||||
#include "guid.h"
|
||||
#include "kvp-util.h"
|
||||
|
||||
#include "qofbackend-p.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofbook-p.h"
|
||||
@ -62,21 +64,14 @@ gnc_price_create (QofBook *book)
|
||||
p = g_new0(GNCPrice, 1);
|
||||
|
||||
p->refcount = 1;
|
||||
p->editlevel = 0;
|
||||
p->not_saved = FALSE;
|
||||
p->do_free = FALSE;
|
||||
p->version = 0;
|
||||
p->version_check = 0;
|
||||
p->value = gnc_numeric_zero();
|
||||
p->type = NULL;
|
||||
p->source = NULL;
|
||||
|
||||
p->book = book;
|
||||
p->entity_table = qof_book_get_entity_table (book);
|
||||
|
||||
qof_entity_guid_new (p->entity_table, &p->guid);
|
||||
qof_entity_store (p->entity_table, p, &p->guid, GNC_ID_PRICE);
|
||||
gnc_engine_generate_event (&p->guid, GNC_ID_PRICE, GNC_EVENT_CREATE);
|
||||
qof_instance_init (&p->inst, GNC_ID_PRICE, book);
|
||||
gnc_engine_gen_event (&p->inst.entity, GNC_EVENT_CREATE);
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -85,12 +80,12 @@ static void
|
||||
gnc_price_destroy (GNCPrice *p)
|
||||
{
|
||||
ENTER(" ");
|
||||
gnc_engine_generate_event (&p->guid, GNC_ID_PRICE, GNC_EVENT_DESTROY);
|
||||
qof_entity_remove(p->entity_table, &p->guid);
|
||||
gnc_engine_gen_event (&p->inst.entity, GNC_EVENT_DESTROY);
|
||||
|
||||
if(p->type) g_cache_remove(gnc_engine_get_string_cache(), p->type);
|
||||
if(p->source) g_cache_remove(gnc_engine_get_string_cache(), p->source);
|
||||
|
||||
qof_instance_release (&p->inst);
|
||||
memset(p, 0, sizeof(GNCPrice));
|
||||
g_free(p);
|
||||
}
|
||||
@ -159,85 +154,21 @@ gnc_price_clone (GNCPrice* p, QofBook *book)
|
||||
void
|
||||
gnc_price_begin_edit (GNCPrice *p)
|
||||
{
|
||||
if (!p) return;
|
||||
p->editlevel++;
|
||||
if (1 < p->editlevel) return;
|
||||
ENTER ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
|
||||
|
||||
if (0 >= p->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", p->editlevel);
|
||||
p->editlevel = 1;
|
||||
}
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
/* We may not be able to find the backend, so make not of that .. */
|
||||
if (p->db) {
|
||||
QofBackend *be;
|
||||
be = xaccPriceDBGetBackend (p->db);
|
||||
if (be && be->begin) {
|
||||
(be->begin) (be, GNC_ID_PRICE, p);
|
||||
}
|
||||
p->not_saved = FALSE;
|
||||
} else {
|
||||
p->not_saved = TRUE;
|
||||
}
|
||||
|
||||
LEAVE ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
|
||||
GNC_BEGIN_EDIT (&p->inst);
|
||||
}
|
||||
|
||||
static inline void commit_err (QofInstance *inst, QofBackendError errcode)
|
||||
{
|
||||
PERR ("Failed to commit: %d", errcode);
|
||||
}
|
||||
|
||||
static inline void noop (QofInstance *inst) {}
|
||||
|
||||
void
|
||||
gnc_price_commit_edit (GNCPrice *p)
|
||||
{
|
||||
if (!p) return;
|
||||
|
||||
p->editlevel--;
|
||||
if (0 < p->editlevel) return;
|
||||
|
||||
ENTER ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
|
||||
if (0 > p->editlevel)
|
||||
{
|
||||
PERR ("unbalanced call - resetting (was %d)", p->editlevel);
|
||||
p->editlevel = 0;
|
||||
}
|
||||
|
||||
/* See if there's a backend. If there is, invoke it. */
|
||||
/* We may not be able to find the backend, so make not of that .. */
|
||||
if (p->db) {
|
||||
QofBackend *be;
|
||||
be = xaccPriceDBGetBackend (p->db);
|
||||
if (be && be->commit) {
|
||||
QofBackendError errcode;
|
||||
|
||||
/* clear errors */
|
||||
do {
|
||||
errcode = qof_backend_get_error (be);
|
||||
} while (ERR_BACKEND_NO_ERR != errcode);
|
||||
|
||||
/* if we haven't been able to call begin edit before, call it now */
|
||||
if (TRUE == p->not_saved) {
|
||||
if (be->begin) {
|
||||
(be->begin) (be, GNC_ID_PRICE, p);
|
||||
}
|
||||
}
|
||||
|
||||
(be->commit) (be, GNC_ID_PRICE, p);
|
||||
errcode = qof_backend_get_error (be);
|
||||
if (ERR_BACKEND_NO_ERR != errcode)
|
||||
{
|
||||
/* XXX hack alert FIXME implement price rollback */
|
||||
PERR (" backend asked engine to rollback, but this isn't"
|
||||
" handled yet. Return code=%d", errcode);
|
||||
|
||||
/* push error back onto the stack */
|
||||
qof_backend_set_error (be, errcode);
|
||||
}
|
||||
}
|
||||
p->not_saved = FALSE;
|
||||
} else {
|
||||
p->not_saved = TRUE;
|
||||
}
|
||||
LEAVE ("pr=%p, not-saved=%d do-free=%d", p, p->not_saved, p->do_free);
|
||||
GNC_COMMIT_EDIT_PART1 (&p->inst);
|
||||
GNC_COMMIT_EDIT_PART2 (&p->inst, commit_err, noop, noop);
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
@ -325,16 +256,6 @@ gnc_pricedb_commit_edit (GNCPriceDB *pdb)
|
||||
/* ==================================================================== */
|
||||
/* setters */
|
||||
|
||||
void
|
||||
gnc_price_set_guid (GNCPrice *p, const GUID *guid)
|
||||
{
|
||||
if (!p || !guid) return;
|
||||
qof_entity_remove (p->entity_table, &p->guid);
|
||||
p->guid = *guid;
|
||||
if(p->db) p->db->dirty = TRUE;
|
||||
qof_entity_store(p->entity_table, p, &p->guid, GNC_ID_PRICE);
|
||||
}
|
||||
|
||||
void
|
||||
gnc_price_set_commodity(GNCPrice *p, gnc_commodity *c)
|
||||
{
|
||||
@ -464,31 +385,11 @@ gnc_price_set_version(GNCPrice *p, gint32 vers)
|
||||
GNCPrice *
|
||||
gnc_price_lookup (const GUID *guid, QofBook *book)
|
||||
{
|
||||
if (!guid) return NULL;
|
||||
g_return_val_if_fail (book, NULL);
|
||||
return qof_entity_lookup (qof_book_get_entity_table (book),
|
||||
guid, GNC_ID_PRICE);
|
||||
}
|
||||
|
||||
const GUID *
|
||||
gnc_price_get_guid (GNCPrice *p)
|
||||
{
|
||||
if (!p) return guid_null();
|
||||
return &p->guid;
|
||||
}
|
||||
|
||||
const GUID
|
||||
gnc_price_return_guid (GNCPrice *p)
|
||||
{
|
||||
if (!p) return *guid_null();
|
||||
return p->guid;
|
||||
}
|
||||
|
||||
QofBook *
|
||||
gnc_price_get_book (GNCPrice *p)
|
||||
{
|
||||
if (!p) return NULL;
|
||||
return p->book;
|
||||
QofCollection *col;
|
||||
|
||||
if (!guid || !book) return NULL;
|
||||
col = qof_book_get_collection (book, GNC_ID_PRICE);
|
||||
return (GNCPrice *) qof_collection_lookup_entity (col, guid);
|
||||
}
|
||||
|
||||
gnc_commodity *
|
||||
@ -923,12 +824,12 @@ add_price(GNCPriceDB *db, GNCPrice *p)
|
||||
GHashTable *currency_hash;
|
||||
|
||||
if(!db || !p) return FALSE;
|
||||
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
|
||||
db, p, p->not_saved, p->do_free);
|
||||
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
|
||||
db, p, p->inst.dirty, p->inst.do_free);
|
||||
|
||||
/* initialize the book pointer for teh first time, if needed */
|
||||
if (NULL == db->book) db->book = p->book;
|
||||
if (db->book != p->book)
|
||||
/* initialize the book pointer for the first time, if needed */
|
||||
if (NULL == db->book) db->book = p->inst.book;
|
||||
if (db->book != p->inst.book)
|
||||
{
|
||||
PERR ("attempted to mix up prices across different books");
|
||||
return FALSE;
|
||||
@ -958,8 +859,8 @@ add_price(GNCPriceDB *db, GNCPrice *p)
|
||||
g_hash_table_insert(currency_hash, currency, price_list);
|
||||
p->db = db;
|
||||
|
||||
LEAVE ("db=%p, pr=%p not-saved=%d do-free=%d commodity=%s/%s currency_hash=%p",
|
||||
db, p, p->not_saved, p->do_free,
|
||||
LEAVE ("db=%p, pr=%p dirty=%d do-free=%d commodity=%s/%s currency_hash=%p",
|
||||
db, p, p->inst.dirty, p->inst.do_free,
|
||||
gnc_commodity_get_namespace(p->commodity),
|
||||
gnc_commodity_get_mnemonic(p->commodity),
|
||||
currency_hash);
|
||||
@ -973,20 +874,21 @@ gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p)
|
||||
{
|
||||
if(!db || !p) return FALSE;
|
||||
|
||||
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
|
||||
db, p, p->not_saved, p->do_free);
|
||||
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
|
||||
db, p, p->inst.dirty, p->inst.do_free);
|
||||
|
||||
if (FALSE == add_price(db, p)) return FALSE;
|
||||
|
||||
/* if we haven't been able to call the backend before, call it now */
|
||||
if (TRUE == p->not_saved) {
|
||||
/* If we haven't been able to call the backend before, call it now */
|
||||
if (TRUE == p->inst.dirty)
|
||||
{
|
||||
gnc_price_begin_edit(p);
|
||||
db->dirty = TRUE;
|
||||
gnc_price_commit_edit(p);
|
||||
}
|
||||
|
||||
LEAVE ("db=%p, pr=%p not-saved=%d do-free=%d",
|
||||
db, p, p->not_saved, p->do_free);
|
||||
LEAVE ("db=%p, pr=%p dirty=%d do-free=%d",
|
||||
db, p, p->inst.dirty, p->inst.do_free);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1004,8 +906,8 @@ remove_price(GNCPriceDB *db, GNCPrice *p, gboolean cleanup)
|
||||
GHashTable *currency_hash;
|
||||
|
||||
if(!db || !p) return FALSE;
|
||||
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
|
||||
db, p, p->not_saved, p->do_free);
|
||||
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
|
||||
db, p, p->inst.dirty, p->inst.do_free);
|
||||
|
||||
commodity = gnc_price_get_commodity(p);
|
||||
if(!commodity) return FALSE;
|
||||
@ -1052,8 +954,8 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
|
||||
{
|
||||
gboolean rc;
|
||||
if(!db || !p) return FALSE;
|
||||
ENTER ("db=%p, pr=%p not-saved=%d do-free=%d",
|
||||
db, p, p->not_saved, p->do_free);
|
||||
ENTER ("db=%p, pr=%p dirty=%d do-free=%d",
|
||||
db, p, p->inst.dirty, p->inst.do_free);
|
||||
|
||||
gnc_price_ref(p);
|
||||
rc = remove_price (db, p, TRUE);
|
||||
@ -1061,7 +963,7 @@ gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p)
|
||||
/* invoke the backend to delete this price */
|
||||
gnc_price_begin_edit (p);
|
||||
db->dirty = TRUE;
|
||||
p->do_free = TRUE;
|
||||
p->inst.do_free = TRUE;
|
||||
gnc_price_commit_edit (p);
|
||||
|
||||
p->db = NULL;
|
||||
@ -2100,7 +2002,7 @@ void_unstable_price_traversal(GNCPriceDB *db,
|
||||
}
|
||||
|
||||
static void
|
||||
pricedb_foreach(QofBook *book, QofEntityForeachCB cb, gpointer data)
|
||||
pricedb_foreach(QofBook *book, QofForeachCB cb, gpointer data)
|
||||
{
|
||||
GNCPriceDB *db = gnc_pricedb_get_db(book);
|
||||
void_unstable_price_traversal(db,
|
||||
@ -2109,6 +2011,7 @@ pricedb_foreach(QofBook *book, QofEntityForeachCB cb, gpointer data)
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
static const char *
|
||||
pricedb_printable(gpointer obj)
|
||||
{
|
||||
@ -2138,7 +2041,7 @@ pricedb_printable(gpointer obj)
|
||||
static QofObject pricedb_object_def =
|
||||
{
|
||||
interface_version: QOF_OBJECT_VERSION,
|
||||
name: GNC_ID_PRICE,
|
||||
e_type: GNC_ID_PRICE,
|
||||
type_label: "Price",
|
||||
book_begin: pricedb_book_begin,
|
||||
book_end: pricedb_book_end,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "gnc-numeric.h"
|
||||
#include "guid.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofinstance.h"
|
||||
|
||||
|
||||
/** @addtogroup Engine
|
||||
@ -172,9 +173,6 @@ void gnc_price_set_version(GNCPrice *p, gint32 versn);
|
||||
/** As mentioned above all of the getters return data that's internal
|
||||
to the GNCPrice, not copies, so don't free these values. */
|
||||
GNCPrice * gnc_price_lookup (const GUID *guid, QofBook *book);
|
||||
const GUID * gnc_price_get_guid (GNCPrice *p);
|
||||
const GUID gnc_price_return_guid (GNCPrice *p);
|
||||
QofBook * gnc_price_get_book (GNCPrice *p);
|
||||
gnc_commodity * gnc_price_get_commodity(GNCPrice *p);
|
||||
gnc_commodity * gnc_price_get_currency(GNCPrice *p);
|
||||
Timespec gnc_price_get_time(GNCPrice *p);
|
||||
@ -184,6 +182,10 @@ gnc_numeric gnc_price_get_value(GNCPrice *p);
|
||||
gint32 gnc_price_get_version(GNCPrice *p);
|
||||
gboolean gnc_price_equal(GNCPrice *p1, GNCPrice *p2);
|
||||
|
||||
#define gnc_price_get_guid(X) qof_entity_get_guid(QOF_ENTITY(X))
|
||||
#define gnc_price_return_guid(X) (*(qof_entity_get_guid(QOF_ENTITY(X))))
|
||||
#define gnc_price_get_book(X) qof_instance_get_book(QOF_INSTANCE(X))
|
||||
|
||||
/* ******************************************************************** */
|
||||
/** GNCPrice lists:
|
||||
|
||||
|
@ -285,6 +285,20 @@ init_from_time(void)
|
||||
return total;
|
||||
}
|
||||
|
||||
static size_t
|
||||
init_from_int(int val)
|
||||
{
|
||||
md5_process_bytes(&val, sizeof(val), &guid_context);
|
||||
return sizeof(int);
|
||||
}
|
||||
|
||||
static size_t
|
||||
init_from_buff(char * buf, size_t buflen)
|
||||
{
|
||||
md5_process_bytes(buf, buflen, &guid_context);
|
||||
return buflen;
|
||||
}
|
||||
|
||||
void
|
||||
guid_init(void)
|
||||
{
|
||||
@ -458,6 +472,20 @@ guid_new(GUID *guid)
|
||||
/* update the global context */
|
||||
init_from_time();
|
||||
|
||||
/* Make it a little extra salty. I think init_from_time was buggy,
|
||||
* or something, since duplicate id's actually happened. Or something
|
||||
* like that. I think this is because init_from_time kept returning
|
||||
* the same values too many times in a row. So we'll do some 'block
|
||||
* chaining', and feed in the old guid as new random data.
|
||||
*
|
||||
* Anyway, I think the whole fact that I saw a bunch of duplicate
|
||||
* id's at one point, but can't reproduce the bug is rather alarming.
|
||||
* Something must be broken somewhere, and merely adding more salt
|
||||
* is just hiding the problem, not fixing it.
|
||||
*/
|
||||
init_from_int (433781*counter);
|
||||
init_from_buff (guid->data, 16);
|
||||
|
||||
if (counter == 0)
|
||||
{
|
||||
FILE *fp;
|
||||
|
@ -99,6 +99,14 @@ void guid_shutdown (void);
|
||||
*
|
||||
* @param guid A pointer to an existing guid data structure. The
|
||||
* existing value will be replaced with a new value.
|
||||
*
|
||||
* This routine uses the md5 algorithm to build strong random guids.
|
||||
* Note that while guid's are generated randomly, the odds of this
|
||||
* routine returning a non-unique id are astronomically small.
|
||||
* (Literally astronomically: If you had Cray's on every solar
|
||||
* system in the universe running for the entire age of teh universe,
|
||||
* you'd still have less than a one-in-a-million chance of coming up
|
||||
* with a duplicate id. 2^128 == 10^38 is a really really big number.)
|
||||
*/
|
||||
void guid_new(GUID *guid);
|
||||
|
||||
|
@ -34,11 +34,11 @@
|
||||
#include "qofbackend.h"
|
||||
#include "qofbook.h"
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
|
||||
struct _QofBook
|
||||
{
|
||||
/* Unique guid for this book. */
|
||||
GUID guid;
|
||||
QofEntity entity; /* Unique guid for this book. */
|
||||
|
||||
/* The KvpFrame provides a place for top-level data associated
|
||||
* with this book. */
|
||||
@ -48,7 +48,7 @@ struct _QofBook
|
||||
* belonging to this book, with their pointers to the respective
|
||||
* objects. This allows a lookup of objects based on thier guid.
|
||||
*/
|
||||
QofEntityTable *entity_table;
|
||||
GHashTable * hash_of_collections;
|
||||
|
||||
/* In order to store arbitrary data, for extensibility, add a table
|
||||
* that will be used to hold arbitrary pointers.
|
||||
@ -87,7 +87,6 @@ struct _QofBook
|
||||
* if the backends should even be doing this much, but for
|
||||
* backwards compatibility, we leave these here.)
|
||||
*/
|
||||
void qof_book_set_guid(QofBook *book, GUID guid);
|
||||
void qof_book_set_schedxactions( QofBook *book, GList *newList );
|
||||
|
||||
void qof_book_set_backend (QofBook *book, QofBackend *be);
|
||||
@ -101,4 +100,8 @@ void qof_book_mark_saved(QofBook *book);
|
||||
/* Register books with the engine */
|
||||
gboolean qof_book_register (void);
|
||||
|
||||
/* deprecated */
|
||||
#define qof_book_set_guid(book,guid) \
|
||||
qof_entity_set_guid(QOF_ENTITY(book), guid)
|
||||
|
||||
#endif /* QOF_BOOK_P_H */
|
||||
|
@ -58,12 +58,13 @@ static short module = MOD_ENGINE;
|
||||
static void
|
||||
qof_book_init (QofBook *book)
|
||||
{
|
||||
QofCollection *col;
|
||||
if (!book) return;
|
||||
|
||||
book->entity_table = qof_entity_new ();
|
||||
book->hash_of_collections = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
qof_entity_guid_new (book->entity_table, &book->guid);
|
||||
qof_entity_store(book->entity_table, book, &book->guid, QOF_ID_BOOK);
|
||||
col = qof_book_get_collection (book, QOF_ID_BOOK);
|
||||
qof_entity_init (&book->entity, QOF_ID_BOOK, col);
|
||||
|
||||
book->kvp_data = kvp_frame_new ();
|
||||
|
||||
@ -84,30 +85,41 @@ qof_book_new (void)
|
||||
qof_book_init(book);
|
||||
qof_object_book_begin (book);
|
||||
|
||||
gnc_engine_generate_event (&book->guid, QOF_ID_BOOK, GNC_EVENT_CREATE);
|
||||
gnc_engine_gen_event (&book->entity, GNC_EVENT_CREATE);
|
||||
LEAVE ("book=%p", book);
|
||||
return book;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
coll_destroy(gpointer key, gpointer value, gpointer not_used)
|
||||
{
|
||||
QofCollection *col = value;
|
||||
qof_collection_destroy (col);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
qof_book_destroy (QofBook *book)
|
||||
{
|
||||
if (!book) return;
|
||||
|
||||
ENTER ("book=%p etable=%p", book, book->entity_table);
|
||||
gnc_engine_force_event (&book->guid, QOF_ID_BOOK, GNC_EVENT_DESTROY);
|
||||
ENTER ("book=%p", book);
|
||||
gnc_engine_force_event (&book->entity.guid, QOF_ID_BOOK, GNC_EVENT_DESTROY);
|
||||
|
||||
qof_object_book_end (book);
|
||||
|
||||
qof_entity_remove (book->entity_table, &book->guid);
|
||||
qof_entity_destroy (book->entity_table);
|
||||
book->entity_table = NULL;
|
||||
|
||||
kvp_frame_delete (book->kvp_data);
|
||||
|
||||
/* FIXME: Make sure the data_table is empty */
|
||||
g_hash_table_destroy (book->data_tables);
|
||||
|
||||
qof_entity_release (&book->entity);
|
||||
|
||||
g_hash_table_foreach_remove (book->hash_of_collections,
|
||||
coll_destroy, NULL);
|
||||
g_hash_table_destroy (book->hash_of_collections);
|
||||
book->hash_of_collections = NULL;
|
||||
|
||||
g_free (book);
|
||||
LEAVE ("book=%p", book);
|
||||
}
|
||||
@ -145,13 +157,6 @@ qof_book_mark_saved(QofBook *book)
|
||||
/* ====================================================================== */
|
||||
/* getters */
|
||||
|
||||
const GUID *
|
||||
qof_book_get_guid (QofBook *book)
|
||||
{
|
||||
if (!book) return NULL;
|
||||
return &book->guid;
|
||||
}
|
||||
|
||||
KvpFrame *
|
||||
qof_book_get_slots (QofBook *book)
|
||||
{
|
||||
@ -159,13 +164,6 @@ qof_book_get_slots (QofBook *book)
|
||||
return book->kvp_data;
|
||||
}
|
||||
|
||||
QofEntityTable *
|
||||
qof_book_get_entity_table (QofBook *book)
|
||||
{
|
||||
if (!book) return NULL;
|
||||
return book->entity_table;
|
||||
}
|
||||
|
||||
QofBackend *
|
||||
qof_book_get_backend (QofBook *book)
|
||||
{
|
||||
@ -176,18 +174,6 @@ qof_book_get_backend (QofBook *book)
|
||||
/* ====================================================================== */
|
||||
/* setters */
|
||||
|
||||
void
|
||||
qof_book_set_guid (QofBook *book, GUID uid)
|
||||
{
|
||||
if (!book) return;
|
||||
|
||||
if (guid_equal (&book->guid, &uid)) return;
|
||||
|
||||
qof_entity_remove(book->entity_table, &book->guid);
|
||||
book->guid = uid;
|
||||
qof_entity_store(book->entity_table, book, &book->guid, QOF_ID_BOOK);
|
||||
}
|
||||
|
||||
void
|
||||
qof_book_set_backend (QofBook *book, QofBackend *be)
|
||||
{
|
||||
@ -230,6 +216,28 @@ qof_book_get_data (QofBook *book, const char *key)
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
QofCollection *
|
||||
qof_book_get_collection (QofBook *book, QofIdType entity_type)
|
||||
{
|
||||
QofCollection *col;
|
||||
|
||||
col = g_hash_table_lookup (book->hash_of_collections, entity_type);
|
||||
if (col) return col;
|
||||
|
||||
col = qof_collection_new (entity_type);
|
||||
|
||||
/* XXX should use string_cache instead of strdup */
|
||||
/* Need strdup because values are sometimes freed */
|
||||
/* this is a memory leak, since malloc'ed value is not freed */
|
||||
/* ??? huh ?? freed where? by whom? */
|
||||
g_hash_table_insert (book->hash_of_collections,
|
||||
(gpointer)g_strdup(entity_type), col);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
||||
gint64
|
||||
qof_book_get_counter (QofBook *book, const char *counter_name)
|
||||
{
|
||||
@ -287,7 +295,7 @@ gboolean qof_book_register (void)
|
||||
{
|
||||
static QofParam params[] = {
|
||||
{ QOF_BOOK_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_book_get_slots, NULL },
|
||||
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_book_get_guid, NULL },
|
||||
{ QOF_QUERY_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,7 @@ typedef struct _QofBook QofBook;
|
||||
/** GList of QofBook */
|
||||
typedef GList QofBookList;
|
||||
|
||||
/** Register the book boject with the QOF object system. */
|
||||
/** Register the book object with the QOF object system. */
|
||||
gboolean qof_book_register (void);
|
||||
|
||||
/** Allocate, initialise and return a new QofBook. Books contain references
|
||||
@ -60,10 +60,7 @@ QofBook * qof_book_new (void);
|
||||
void qof_book_destroy (QofBook *book);
|
||||
|
||||
/** \return The Entity table for the book. */
|
||||
QofEntityTable * qof_book_get_entity_table (QofBook *book);
|
||||
|
||||
/** \return The GUID for the book. */
|
||||
const GUID * qof_book_get_guid (QofBook *book);
|
||||
QofCollection * qof_book_get_collection (QofBook *, QofIdType);
|
||||
|
||||
/** \return The kvp data for the book */
|
||||
KvpFrame * qof_book_get_slots (QofBook *book);
|
||||
@ -113,5 +110,8 @@ gint64 qof_book_get_counter (QofBook *book, const char *counter_name);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** deprecated */
|
||||
#define qof_book_get_guid(X) qof_entity_get_guid (QOF_ENTITY(X))
|
||||
|
||||
#endif /* QOF_BOOK_H */
|
||||
/** @} */
|
||||
|
@ -31,45 +31,16 @@
|
||||
/* This file defines an engine-only API for using gnucash entity
|
||||
* identifiers. */
|
||||
|
||||
/** Set the ID of the entity, over-riding teh previous ID.
|
||||
* Very dangerous, use only for file i/o work.
|
||||
*/
|
||||
void qof_entity_set_guid (QofEntity *ent, const GUID *guid);
|
||||
|
||||
|
||||
/* Create and destroy entity tables */
|
||||
QofEntityTable * qof_entity_new (void);
|
||||
void qof_entity_destroy (QofEntityTable *table);
|
||||
|
||||
/* Generate a new id. This function is guaranteed to return an id that
|
||||
* is unique within the scope of all GnuCash entities being managed by
|
||||
* the current invocation of GnuCash. GnuCash routines should always
|
||||
* use this function and not guid_new!
|
||||
*
|
||||
* When considered over all possible instances of gnucash, the odds of
|
||||
* this routine returning a non-unique id are still astronomically small.
|
||||
* If you had a gazzillion computers computing new ids, for the entire
|
||||
* age of the universe, you'd still have a one-in-a-million chance of
|
||||
* coming up with a duplicate. 2^128 is a really really big number.
|
||||
/** Take entity, remove it from whatever collection its currently
|
||||
* in, and place it in a new collection. To be used only for
|
||||
* moving entity from one book to another.
|
||||
*/
|
||||
void qof_entity_guid_new (QofEntityTable *entity_table, GUID *guid);
|
||||
void qof_collection_insert_entity (QofCollection *, QofEntity *);
|
||||
|
||||
/* Lookup an entity given an id and a type. If there is no entity
|
||||
* associated with the id, or if it has a different type, NULL
|
||||
* is returned. Input: GUID, returns reference (pointer) to object.
|
||||
*/
|
||||
gpointer qof_entity_lookup (QofEntityTable *entity_table,
|
||||
const GUID * guid, QofIdType entity_type);
|
||||
|
||||
/* Store the given entity under the given id with the given type. */
|
||||
/* this routine obsolete, remove asap */
|
||||
void qof_entity_store (QofEntityTable *entity_table,
|
||||
gpointer entity, const GUID * guid,
|
||||
QofIdType entity_type);
|
||||
|
||||
/* Remove any existing association between an entity and the given
|
||||
* id. The entity is not changed in any way. */
|
||||
void qof_entity_remove (QofEntityTable *entity_table, const GUID * guid);
|
||||
|
||||
/* Call a function for each object of type 'type' in the entity table */
|
||||
void qof_entity_foreach (QofEntityTable *entity_table, QofIdType type,
|
||||
QofEntityForeachCB cb_func, gpointer user_data);
|
||||
|
||||
#endif /* QOF_ID_P_H */
|
||||
|
@ -35,58 +35,8 @@
|
||||
#define CACHE_INSERT(str) g_cache_insert(gnc_engine_get_string_cache(), (gpointer)(str));
|
||||
#define CACHE_REMOVE(str) g_cache_remove(gnc_engine_get_string_cache(), (gpointer)(str));
|
||||
|
||||
#define QOFID_DEBUG 0
|
||||
static short module = MOD_ENGINE;
|
||||
|
||||
/* =============================================================== */
|
||||
/* XXX under construction, the entity_store thing can be vastly simplified */
|
||||
|
||||
void
|
||||
qof_entity_init (QofEntity *ent, QofIdType type, QofEntityTable * tab)
|
||||
{
|
||||
ent->e_type = type;
|
||||
|
||||
do
|
||||
{
|
||||
guid_new(&ent->guid);
|
||||
|
||||
if (qof_entity_type (tab, &ent->guid) == QOF_ID_NONE)
|
||||
break;
|
||||
|
||||
PWARN("duplicate id created, trying again");
|
||||
} while(1);
|
||||
|
||||
ent->e_table = tab;
|
||||
|
||||
qof_entity_store (tab, ent, &ent->guid, type);
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_release (QofEntity *ent)
|
||||
{
|
||||
qof_entity_remove (ent->e_table, &ent->guid);
|
||||
ent->e_table = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* This is a restricted function, should be used only during
|
||||
* read from file */
|
||||
void
|
||||
qof_entity_set_guid (QofEntity *ent, const GUID *guid)
|
||||
{
|
||||
if (guid_equal (guid, &ent->guid)) return;
|
||||
qof_entity_remove (ent->e_table, &ent->guid);
|
||||
ent->guid = *guid;
|
||||
qof_entity_store (ent->e_table, ent, &ent->guid, ent->e_type);
|
||||
}
|
||||
|
||||
/* =============================================================== */
|
||||
|
||||
/** a collection of entities */
|
||||
/* XXX this is supposed to be a replacement for GncBookInfo/gncBusinessCreate
|
||||
* when we finish */
|
||||
typedef struct QofCollection_s QofCollection;
|
||||
|
||||
struct QofCollection_s
|
||||
{
|
||||
QofIdType e_type;
|
||||
@ -95,6 +45,71 @@ struct QofCollection_s
|
||||
GHashTable * hash_of_entities;
|
||||
};
|
||||
|
||||
/* =============================================================== */
|
||||
|
||||
static void qof_collection_remove_entity (QofEntity *ent);
|
||||
|
||||
void
|
||||
qof_entity_init (QofEntity *ent, QofIdType type, QofCollection * tab)
|
||||
{
|
||||
g_return_if_fail (NULL != tab);
|
||||
|
||||
/* XXX We passed redundant info to this routine ... but I think that's
|
||||
* OK, it might eliminate programming errors. */
|
||||
if (safe_strcmp(tab->e_type, type))
|
||||
{
|
||||
PERR ("attempt to insert \"%s\" into \"%s\"", type, tab->e_type);
|
||||
return;
|
||||
}
|
||||
ent->e_type = CACHE_INSERT (type);
|
||||
|
||||
do
|
||||
{
|
||||
guid_new(&ent->guid);
|
||||
|
||||
if (NULL == qof_collection_lookup_entity (tab, &ent->guid)) break;
|
||||
|
||||
PWARN("duplicate id created, trying again");
|
||||
} while(1);
|
||||
|
||||
ent->collection = tab;
|
||||
|
||||
qof_collection_insert_entity (tab, ent);
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_release (QofEntity *ent)
|
||||
{
|
||||
if (!ent->collection) return;
|
||||
qof_collection_remove_entity (ent);
|
||||
CACHE_REMOVE (ent->e_type);
|
||||
ent->e_type = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* This is a restricted function, should be used only during
|
||||
* read from file */
|
||||
void
|
||||
qof_entity_set_guid (QofEntity *ent, const GUID *guid)
|
||||
{
|
||||
QofCollection *col;
|
||||
if (guid_equal (guid, &ent->guid)) return;
|
||||
|
||||
col = ent->collection;
|
||||
qof_collection_remove_entity (ent);
|
||||
ent->guid = *guid;
|
||||
qof_collection_insert_entity (col, ent);
|
||||
}
|
||||
|
||||
GUID *
|
||||
qof_entity_get_guid (QofEntity *ent)
|
||||
{
|
||||
if (!ent) return NULL;
|
||||
return &ent->guid;
|
||||
}
|
||||
|
||||
/* =============================================================== */
|
||||
|
||||
static guint
|
||||
id_hash (gconstpointer key)
|
||||
{
|
||||
@ -130,312 +145,94 @@ id_compare(gconstpointer key_1, gconstpointer key_2)
|
||||
return guid_equal (key_1, key_2);
|
||||
}
|
||||
|
||||
QofCollection * qof_collection_new (QofIdType type);
|
||||
QofCollection *
|
||||
qof_collection_new (QofIdType type)
|
||||
{
|
||||
QofCollection *col;
|
||||
col = g_new0(QofCollection, 1);
|
||||
col->e_type = type;
|
||||
col->e_type = CACHE_INSERT (type);
|
||||
col->hash_of_entities = g_hash_table_new (id_hash, id_compare);
|
||||
return col;
|
||||
}
|
||||
|
||||
void qof_collection_destroy (QofCollection *col);
|
||||
void
|
||||
qof_collection_destroy (QofCollection *col)
|
||||
{
|
||||
/* col->e_type = xxx */
|
||||
CACHE_REMOVE (col->e_type);
|
||||
g_hash_table_destroy(col->hash_of_entities);
|
||||
col->e_type = NULL;
|
||||
col->hash_of_entities = NULL;
|
||||
g_free (col);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
coll_destroy(gpointer key, gpointer value, gpointer not_used)
|
||||
/* =============================================================== */
|
||||
/* getters */
|
||||
|
||||
QofIdType
|
||||
qof_collection_get_type (QofCollection *col)
|
||||
{
|
||||
QofCollection *col = value;
|
||||
qof_collection_destroy (col);
|
||||
return TRUE;
|
||||
return col->e_type;
|
||||
}
|
||||
|
||||
|
||||
struct _QofEntityTable
|
||||
{
|
||||
GHashTable * hash_by_guid;
|
||||
GHashTable * hash_of_collections;
|
||||
};
|
||||
|
||||
|
||||
static inline QofCollection *
|
||||
entity_get_collection (QofEntityTable *entity_table, QofIdType entity_type)
|
||||
{
|
||||
QofCollection *col;
|
||||
|
||||
col = g_hash_table_lookup (entity_table->hash_of_collections, entity_type);
|
||||
if (col) return col;
|
||||
|
||||
col = qof_collection_new (entity_type);
|
||||
|
||||
/* XXX should use string_cache instead of strdup */
|
||||
/* Need strdup because values are sometimes freed */
|
||||
/* this is a memory leak, since malloc'ed value is not freed */
|
||||
g_hash_table_insert (entity_table->hash_of_collections,
|
||||
(gpointer)g_strdup(entity_type), col);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
|
||||
/* =============================================================== */
|
||||
/* Almost everything below is obsolete and should be removed */
|
||||
|
||||
/* XXX this structure should be replaced by QofEntity ASAP */
|
||||
typedef struct entity_node
|
||||
static void
|
||||
qof_collection_remove_entity (QofEntity *ent)
|
||||
{
|
||||
QofIdType entity_type;
|
||||
gpointer entity;
|
||||
} EntityNode;
|
||||
|
||||
|
||||
/** Function implementations ****************************************/
|
||||
|
||||
static gboolean
|
||||
entity_node_destroy(gpointer key, gpointer value, gpointer not_used)
|
||||
{
|
||||
GUID *guid = key;
|
||||
EntityNode *e_node = value;
|
||||
|
||||
CACHE_REMOVE (e_node->entity_type);
|
||||
e_node->entity_type = QOF_ID_NONE;
|
||||
e_node->entity = NULL;
|
||||
|
||||
guid_free(guid);
|
||||
g_free(e_node);
|
||||
|
||||
return TRUE;
|
||||
QofCollection *col = ent->collection;
|
||||
if (!col) return;
|
||||
g_hash_table_remove (col->hash_of_entities, &ent->guid);
|
||||
ent->collection = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_destroy (QofEntityTable *entity_table)
|
||||
qof_collection_insert_entity (QofCollection *col, QofEntity *ent)
|
||||
{
|
||||
if (entity_table == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_foreach_remove (entity_table->hash_by_guid, entity_node_destroy,
|
||||
NULL);
|
||||
g_hash_table_destroy (entity_table->hash_by_guid);
|
||||
entity_table->hash_by_guid = NULL;
|
||||
|
||||
g_hash_table_foreach_remove (entity_table->hash_of_collections,
|
||||
coll_destroy, NULL);
|
||||
g_hash_table_destroy (entity_table->hash_of_collections);
|
||||
entity_table->hash_of_collections = NULL;
|
||||
|
||||
g_free (entity_table);
|
||||
if (guid_equal(&ent->guid, guid_null())) return;
|
||||
g_return_if_fail (col->e_type == ent->e_type);
|
||||
qof_collection_remove_entity (ent);
|
||||
g_hash_table_insert (col->hash_of_entities, &ent->guid, ent);
|
||||
ent->collection = col;
|
||||
}
|
||||
|
||||
|
||||
#if QOFID_DEBUG
|
||||
static void
|
||||
print_node(gpointer key, gpointer value, gpointer not_used)
|
||||
QofEntity *
|
||||
qof_collection_lookup_entity (QofCollection *col, const GUID * guid)
|
||||
{
|
||||
GUID *guid = key;
|
||||
EntityNode *node = value;
|
||||
|
||||
fprintf(stderr, "%s %s %p\n",
|
||||
guid_to_string(guid), node->entity_type, node->entity);
|
||||
QofEntity *ent;
|
||||
g_return_val_if_fail (col, NULL);
|
||||
if (guid == NULL) return NULL;
|
||||
ent = g_hash_table_lookup (col->hash_of_entities, guid->data);
|
||||
return ent;
|
||||
}
|
||||
|
||||
static void
|
||||
summarize_table (QofEntityTable *entity_table)
|
||||
{
|
||||
if (entity_table == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_foreach (entity_table->hash_by_guid, print_node, NULL);
|
||||
}
|
||||
#endif /* QOFID_DEBUG */
|
||||
|
||||
QofEntityTable *
|
||||
qof_entity_new (void)
|
||||
{
|
||||
QofEntityTable *entity_table;
|
||||
|
||||
entity_table = g_new0 (QofEntityTable, 1);
|
||||
|
||||
entity_table->hash_by_guid = g_hash_table_new (id_hash, id_compare);
|
||||
entity_table->hash_of_collections = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
qof_entity_store (entity_table, NULL, guid_null(), QOF_ID_NULL);
|
||||
|
||||
return entity_table;
|
||||
}
|
||||
|
||||
/* XXX There should be no need for this after we start
|
||||
* using QofEntity everywhere, and, once we do that, there will be
|
||||
* no need for the hash_by_guid */
|
||||
QofIdType
|
||||
qof_entity_type (QofEntityTable *entity_table, const GUID * guid)
|
||||
{
|
||||
EntityNode *e_node;
|
||||
|
||||
if (guid == NULL)
|
||||
return QOF_ID_NONE;
|
||||
|
||||
g_return_val_if_fail (entity_table, QOF_ID_NONE);
|
||||
|
||||
e_node = g_hash_table_lookup (entity_table->hash_by_guid, guid->data);
|
||||
if (e_node == NULL)
|
||||
return QOF_ID_NONE;
|
||||
|
||||
return e_node->entity_type;
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_guid_new (QofEntityTable *entity_table, GUID *guid)
|
||||
{
|
||||
if (guid == NULL)
|
||||
return;
|
||||
|
||||
g_return_if_fail (entity_table);
|
||||
|
||||
do
|
||||
{
|
||||
guid_new(guid);
|
||||
|
||||
if (qof_entity_type (entity_table, guid) == QOF_ID_NONE)
|
||||
break;
|
||||
|
||||
PWARN("duplicate id created, trying again");
|
||||
} while(1);
|
||||
}
|
||||
|
||||
gpointer
|
||||
qof_entity_lookup (QofEntityTable *entity_table,
|
||||
const GUID * guid, QofIdType entity_type)
|
||||
{
|
||||
QofCollection *col;
|
||||
EntityNode *e_node;
|
||||
|
||||
g_return_val_if_fail (entity_table, NULL);
|
||||
|
||||
if (guid == NULL)
|
||||
return NULL;
|
||||
|
||||
col = entity_get_collection (entity_table, entity_type);
|
||||
|
||||
e_node = g_hash_table_lookup (col->hash_of_entities, guid->data);
|
||||
if (e_node == NULL)
|
||||
return NULL;
|
||||
|
||||
return e_node->entity;
|
||||
}
|
||||
|
||||
static void
|
||||
entity_store_by_type (QofEntityTable *entity_table,
|
||||
GUID *new_guid, EntityNode *e_node)
|
||||
{
|
||||
QofCollection *col;
|
||||
col = entity_get_collection (entity_table, e_node->entity_type);
|
||||
g_hash_table_insert (col->hash_of_entities, new_guid, e_node);
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_store (QofEntityTable *entity_table, gpointer entity,
|
||||
const GUID * guid, QofIdType entity_type)
|
||||
{
|
||||
EntityNode *e_node;
|
||||
GUID *new_guid;
|
||||
|
||||
g_return_if_fail (entity_table);
|
||||
|
||||
if (guid == NULL)
|
||||
return;
|
||||
|
||||
if (!entity_type) return;
|
||||
|
||||
if (guid_equal(guid, guid_null())) return;
|
||||
|
||||
qof_entity_remove (entity_table, guid);
|
||||
|
||||
e_node = g_new(EntityNode, 1);
|
||||
e_node->entity_type = CACHE_INSERT (entity_type);
|
||||
e_node->entity = entity;
|
||||
|
||||
new_guid = guid_malloc ();
|
||||
|
||||
if (!new_guid) return;
|
||||
|
||||
*new_guid = *guid;
|
||||
|
||||
g_hash_table_insert (entity_table->hash_by_guid, new_guid, e_node);
|
||||
entity_store_by_type (entity_table, new_guid, e_node);
|
||||
}
|
||||
|
||||
static void
|
||||
entity_remove_by_type (QofEntityTable *entity_table, GUID *guid, QofIdType type)
|
||||
{
|
||||
QofCollection *col;
|
||||
col = entity_get_collection (entity_table, type);
|
||||
g_hash_table_remove (col->hash_of_entities, guid);
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_remove (QofEntityTable *entity_table, const GUID * guid)
|
||||
{
|
||||
EntityNode *e_node;
|
||||
gpointer old_guid;
|
||||
gpointer node;
|
||||
|
||||
g_return_if_fail (entity_table);
|
||||
|
||||
if (guid == NULL)
|
||||
return;
|
||||
|
||||
if (g_hash_table_lookup_extended(entity_table->hash_by_guid, guid, &old_guid, &node))
|
||||
{
|
||||
e_node = node;
|
||||
|
||||
if (!safe_strcmp (e_node->entity_type, QOF_ID_NULL))
|
||||
return;
|
||||
|
||||
g_hash_table_remove (entity_table->hash_by_guid, old_guid);
|
||||
entity_remove_by_type (entity_table, old_guid, e_node->entity_type);
|
||||
entity_node_destroy (old_guid, node, NULL);
|
||||
}
|
||||
}
|
||||
/* =============================================================== */
|
||||
|
||||
struct _iterate {
|
||||
QofEntityForeachCB fcn;
|
||||
QofEntityForeachCB fcn;
|
||||
gpointer data;
|
||||
QofIdType type;
|
||||
};
|
||||
|
||||
static void foreach_cb (gpointer key, gpointer item, gpointer arg)
|
||||
{
|
||||
struct _iterate *iter = arg;
|
||||
EntityNode *e_node = item;
|
||||
QofEntity *ent = item;
|
||||
|
||||
iter->fcn (e_node->entity, iter->data);
|
||||
iter->fcn (ent, iter->data);
|
||||
}
|
||||
|
||||
void
|
||||
qof_entity_foreach (QofEntityTable *entity_table, QofIdType type,
|
||||
qof_collection_foreach (QofCollection *col,
|
||||
QofEntityForeachCB cb_func, gpointer user_data)
|
||||
{
|
||||
QofCollection *col;
|
||||
struct _iterate iter;
|
||||
|
||||
g_return_if_fail (entity_table);
|
||||
g_return_if_fail (type);
|
||||
g_return_if_fail (*type);
|
||||
g_return_if_fail (col);
|
||||
g_return_if_fail (cb_func);
|
||||
|
||||
iter.fcn = cb_func;
|
||||
iter.data = user_data;
|
||||
iter.type = type;
|
||||
|
||||
/* Iterate over the objects of the particular type */
|
||||
col = entity_get_collection (entity_table, type);
|
||||
g_hash_table_foreach (col->hash_of_entities, foreach_cb, &iter);
|
||||
}
|
||||
|
||||
/* =============================================================== */
|
||||
|
@ -62,31 +62,46 @@ typedef const char * QofIdTypeConst;
|
||||
#define QOF_ID_NULL "null"
|
||||
#define QOF_ID_SESSION "Session"
|
||||
|
||||
/* simple,cheesy cast but holds water for now */
|
||||
#define QOF_ENTITY(object) ((QofEntity *)(object))
|
||||
|
||||
typedef struct QofEntity_s QofEntity;
|
||||
typedef struct _QofEntityTable QofEntityTable;
|
||||
typedef struct QofCollection_s QofCollection;
|
||||
|
||||
struct QofEntity_s
|
||||
{
|
||||
QofIdType e_type;
|
||||
GUID guid;
|
||||
QofEntityTable * e_table;
|
||||
QofCollection * collection;
|
||||
};
|
||||
|
||||
|
||||
/** Initialise the memory associated with an entity */
|
||||
void qof_entity_init (QofEntity *, QofIdType, QofEntityTable *);
|
||||
void qof_entity_init (QofEntity *, QofIdType, QofCollection *);
|
||||
|
||||
/** release the data associated with this entity. Dont actually free
|
||||
/** Release the data associated with this entity. Dont actually free
|
||||
* the memory associated with the instance. */
|
||||
void qof_entity_release (QofEntity *);
|
||||
|
||||
/** The stuff below is obsolete and should be removed ASAP. */
|
||||
/* Return the GUID of this entity */
|
||||
GUID * qof_entity_get_guid (QofEntity *);
|
||||
|
||||
/** Return the type of the indicated guid */
|
||||
QofIdType qof_entity_type (QofEntityTable *entity_table, const GUID * guid);
|
||||
/** collections of entities */
|
||||
QofCollection * qof_collection_new (QofIdType type);
|
||||
void qof_collection_destroy (QofCollection *col);
|
||||
|
||||
/** return the type that the collection stores */
|
||||
QofIdType qof_collection_get_type (QofCollection *);
|
||||
|
||||
/** Find the entity going only from its guid */
|
||||
QofEntity * qof_collection_lookup_entity (QofCollection *, const GUID *);
|
||||
|
||||
/* Callback type for qof_entity_foreach */
|
||||
typedef void (*QofEntityForeachCB) (gpointer object, gpointer user_data);
|
||||
typedef void (*QofEntityForeachCB) (QofEntity *, gpointer user_data);
|
||||
|
||||
void qof_collection_foreach (QofCollection *,
|
||||
QofEntityForeachCB, gpointer user_data);
|
||||
|
||||
|
||||
|
||||
#endif /* QOF_ID_H */
|
||||
/** @} */
|
||||
|
69
src/engine/qofinstance-p.h
Normal file
69
src/engine/qofinstance-p.h
Normal 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 */
|
@ -35,6 +35,7 @@
|
||||
#include "qofid.h"
|
||||
#include "qofid-p.h"
|
||||
#include "qofinstance.h"
|
||||
#include "qofinstance-p.h"
|
||||
|
||||
static short module = MOD_ENGINE;
|
||||
|
||||
@ -43,13 +44,16 @@ static short module = MOD_ENGINE;
|
||||
void
|
||||
qof_instance_init (QofInstance *inst, QofIdType type, QofBook *book)
|
||||
{
|
||||
QofCollection *col;
|
||||
|
||||
inst->book = book;
|
||||
inst->kvp_data = kvp_frame_new();
|
||||
inst->editlevel = 0;
|
||||
inst->do_free = FALSE;
|
||||
inst->dirty = FALSE;
|
||||
|
||||
qof_entity_init (&inst->entity, type, book->entity_table);
|
||||
col = qof_book_get_collection (book, type);
|
||||
qof_entity_init (&inst->entity, type, col);
|
||||
}
|
||||
|
||||
void
|
||||
@ -90,6 +94,29 @@ qof_instance_is_dirty (QofInstance *inst)
|
||||
return inst->dirty;
|
||||
}
|
||||
|
||||
/* ========================================================== */
|
||||
/* setters */
|
||||
|
||||
void
|
||||
qof_instance_mark_clean (QofInstance *inst)
|
||||
{
|
||||
if(!inst) return;
|
||||
inst->dirty = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
qof_instance_set_slots (QofInstance *inst, KvpFrame *frm)
|
||||
{
|
||||
if (!inst) return;
|
||||
if (inst->kvp_data && (inst->kvp_data != frm))
|
||||
{
|
||||
kvp_frame_delete(inst->kvp_data);
|
||||
}
|
||||
|
||||
inst->dirty = TRUE;
|
||||
inst->kvp_data = frm;
|
||||
}
|
||||
|
||||
/* ========================================================== */
|
||||
|
||||
void
|
||||
@ -101,11 +128,11 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
|
||||
/* Make a note of where the copy came from */
|
||||
gnc_kvp_bag_add (to->kvp_data, "gemini", now,
|
||||
"inst_guid", &from->entity.guid,
|
||||
"book_guid", &from->book->guid,
|
||||
"book_guid", &from->book->entity.guid,
|
||||
NULL);
|
||||
gnc_kvp_bag_add (from->kvp_data, "gemini", now,
|
||||
"inst_guid", &to->entity.guid,
|
||||
"book_guid", &to->book->guid,
|
||||
"book_guid", &to->book->entity.guid,
|
||||
NULL);
|
||||
|
||||
to->dirty = TRUE;
|
||||
@ -114,6 +141,7 @@ qof_instance_gemini (QofInstance *to, QofInstance *from)
|
||||
QofInstance *
|
||||
qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
|
||||
{
|
||||
QofCollection *col;
|
||||
KvpFrame *fr;
|
||||
GUID * twin_guid;
|
||||
QofInstance * twin;
|
||||
@ -126,8 +154,8 @@ qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
|
||||
|
||||
twin_guid = kvp_frame_get_guid (fr, "inst_guid");
|
||||
|
||||
twin = qof_entity_lookup (target_book->entity_table,
|
||||
twin_guid, src->entity.e_type);
|
||||
col = qof_book_get_collection (target_book, src->entity.e_type);
|
||||
twin = (QofInstance *) qof_collection_lookup_entity (col, twin_guid);
|
||||
|
||||
LEAVE (" found twin=%p", twin);
|
||||
return twin;
|
||||
|
@ -41,36 +41,6 @@
|
||||
|
||||
typedef struct QofInstance_s QofInstance;
|
||||
|
||||
struct QofInstance_s
|
||||
{
|
||||
/*
|
||||
* UNDER CONSTRUCTION!
|
||||
* This is mostly scaffolding for now,
|
||||
* eventually, it may hold more fields, such as refrence counting...
|
||||
*
|
||||
*/
|
||||
/* Globally unique id identifying this instance */
|
||||
QofEntity entity;
|
||||
|
||||
/* The entity_table in which this instance is stored */
|
||||
QofBook * book;
|
||||
|
||||
/* kvp_data is a key-value pair database for storing arbirtary
|
||||
* information associated with this instance.
|
||||
* See src/engine/kvp_doc.txt for a list and description of the
|
||||
* important keys. */
|
||||
KvpFrame *kvp_data;
|
||||
|
||||
/* Keep track of nesting level of begin/end edit calls */
|
||||
int editlevel;
|
||||
|
||||
/* In process of being destroyed */
|
||||
gboolean do_free;
|
||||
|
||||
/* This instance has not been saved yet */
|
||||
gboolean dirty;
|
||||
};
|
||||
|
||||
/** Initialise the memory associated with an instance */
|
||||
void qof_instance_init (QofInstance *, QofIdType, QofBook *);
|
||||
|
||||
|
@ -84,7 +84,7 @@ gboolean qof_object_is_dirty (QofBook *book)
|
||||
QofObject *obj = l->data;
|
||||
if (obj->is_dirty)
|
||||
if (obj->is_dirty (book))
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -114,7 +114,7 @@ void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
|
||||
}
|
||||
|
||||
void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
|
||||
QofEntityForeachCB cb, gpointer user_data)
|
||||
QofForeachCB cb, gpointer user_data)
|
||||
{
|
||||
const QofObject *obj;
|
||||
|
||||
@ -147,7 +147,7 @@ qof_object_printable (QofIdTypeConst type_name, gpointer obj)
|
||||
if (b_obj->printable)
|
||||
return (b_obj->printable (obj));
|
||||
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * qof_object_get_type_label (QofIdTypeConst type_name)
|
||||
@ -230,15 +230,15 @@ const QofObject * qof_object_lookup (QofIdTypeConst name)
|
||||
|
||||
for (iter = object_modules; iter; iter = iter->next) {
|
||||
obj = iter->data;
|
||||
if (!safe_strcmp (obj->name, name))
|
||||
if (!safe_strcmp (obj->e_type, name))
|
||||
return obj;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean qof_object_register_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name,
|
||||
gpointer be_data)
|
||||
const char *backend_name,
|
||||
gpointer be_data)
|
||||
{
|
||||
GHashTable *ht;
|
||||
g_return_val_if_fail (object_is_initialized, FALSE);
|
||||
@ -263,7 +263,7 @@ gboolean qof_object_register_backend (QofIdTypeConst type_name,
|
||||
}
|
||||
|
||||
gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
|
||||
const char *backend_name)
|
||||
const char *backend_name)
|
||||
{
|
||||
GHashTable *ht;
|
||||
|
||||
@ -279,8 +279,8 @@ gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
|
||||
}
|
||||
|
||||
struct foreach_data {
|
||||
QofForeachBackendTypeCB cb;
|
||||
gpointer user_data;
|
||||
QofForeachBackendTypeCB cb;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
|
||||
@ -295,8 +295,8 @@ static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
|
||||
}
|
||||
|
||||
void qof_object_foreach_backend (const char *backend_name,
|
||||
QofForeachBackendTypeCB cb,
|
||||
gpointer user_data)
|
||||
QofForeachBackendTypeCB cb,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *ht;
|
||||
struct foreach_data cb_data;
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
|
||||
typedef struct _QofObject QofObject;
|
||||
typedef void (*QofForeachCB) (gpointer obj, gpointer user_data);
|
||||
typedef void (*QofForeachTypeCB) (QofObject *type, gpointer user_data);
|
||||
typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
|
||||
gpointer backend_data,
|
||||
@ -49,7 +50,7 @@ typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
|
||||
struct _QofObject
|
||||
{
|
||||
gint interface_version; /* of this object interface */
|
||||
QofIdType name; /* the Object's QOF_ID */
|
||||
QofIdType e_type; /* the Object's QOF_ID */
|
||||
const char * type_label; /* "Printable" type-label string */
|
||||
|
||||
/* book_begin is called from within the Book routines to create
|
||||
@ -69,7 +70,7 @@ struct _QofObject
|
||||
/* foreach() is used to execute a callback over each object
|
||||
* stored in the particular book
|
||||
*/
|
||||
void (*foreach)(QofBook *, QofEntityForeachCB, gpointer);
|
||||
void (*foreach)(QofBook *, QofForeachCB, gpointer);
|
||||
|
||||
/* Given a particular object, return a printable string */
|
||||
/* Argument should really be QofInstance not gpointer.. */
|
||||
@ -86,7 +87,7 @@ void qof_object_shutdown (void);
|
||||
void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data);
|
||||
|
||||
void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
|
||||
QofEntityForeachCB cb, gpointer user_data);
|
||||
QofForeachCB cb, gpointer user_data);
|
||||
|
||||
const char * qof_object_printable (QofIdTypeConst type_name, gpointer obj);
|
||||
|
||||
|
@ -10,11 +10,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "AccountP.h"
|
||||
#include "Group.h"
|
||||
#include "gnc-date.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-engine-util.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
#include "qofquerycore.h"
|
||||
|
||||
#include "test-engine-stuff.h"
|
||||
@ -988,18 +990,15 @@ get_random_transaction_with_currency(QofBook *book,
|
||||
ret = xaccMallocTransaction(book);
|
||||
|
||||
xaccTransBeginEdit(ret);
|
||||
|
||||
xaccTransSetCurrency (ret,
|
||||
currency ? currency :
|
||||
get_random_commodity (book));
|
||||
|
||||
set_tran_random_string(ret, xaccTransSetNum);
|
||||
|
||||
set_tran_random_string(ret, xaccTransSetDescription);
|
||||
trn_add_ran_timespec(ret, xaccTransSetDatePostedTS);
|
||||
trn_add_ran_timespec(ret, xaccTransSetDateEnteredTS);
|
||||
|
||||
set_tran_random_string(ret, xaccTransSetDescription);
|
||||
|
||||
xaccTransSetSlots_nc(ret, get_random_kvp_frame());
|
||||
|
||||
add_random_splits(book, ret);
|
||||
@ -1012,7 +1011,6 @@ get_random_transaction_with_currency(QofBook *book,
|
||||
}
|
||||
|
||||
xaccTransCommitEdit(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1585,7 +1583,6 @@ add_random_transactions_to_book (QofBook *book, gint num_transactions)
|
||||
Split *split;
|
||||
|
||||
com = get_random_commodity_from_table (table);
|
||||
|
||||
trans = get_random_transaction_with_currency (book, com);
|
||||
|
||||
xaccTransBeginEdit (trans);
|
||||
@ -1600,7 +1597,6 @@ add_random_transactions_to_book (QofBook *book, gint num_transactions)
|
||||
|
||||
xaccTransCommitEdit (trans);
|
||||
}
|
||||
|
||||
g_list_free (accounts);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ test-load-engine
|
||||
test-commodities
|
||||
test-date
|
||||
test-freq-spec
|
||||
test-guid
|
||||
test-group-vs-book
|
||||
test-lots
|
||||
test-object
|
||||
|
@ -18,14 +18,18 @@ LDADD = \
|
||||
${GLIB_LIBS} \
|
||||
-lltdl
|
||||
|
||||
# these tests are ordered kind more or less in the order
|
||||
# that they should be executed, with more basic tests coming first.
|
||||
#
|
||||
TESTS = \
|
||||
test-load-engine \
|
||||
test-create-account \
|
||||
test-commodities \
|
||||
test-guid \
|
||||
test-date \
|
||||
test-object \
|
||||
test-commodities \
|
||||
test-create-account \
|
||||
test-group-vs-book \
|
||||
test-lots \
|
||||
test-object \
|
||||
test-period \
|
||||
test-querynew \
|
||||
test-query \
|
||||
@ -53,6 +57,7 @@ noinst_PROGRAMS = \
|
||||
test-commodities \
|
||||
test-date \
|
||||
test-freq-spec \
|
||||
test-guid \
|
||||
test-group-vs-book \
|
||||
test-load-engine \
|
||||
test-lots \
|
||||
|
@ -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'
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <glib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "TransLog.h"
|
||||
#include "gnc-date.h"
|
||||
#include "gnc-module.h"
|
||||
#include "test-stuff.h"
|
||||
|
69
src/engine/test/test-guid.c
Normal file
69
src/engine/test/test-guid.c
Normal 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;
|
||||
}
|
@ -26,22 +26,12 @@ run_test (void)
|
||||
QofBook *book;
|
||||
AccountGroup *grp;
|
||||
|
||||
if(!gnc_module_load("gnucash/engine", 0))
|
||||
{
|
||||
failure("couldn't load gnucash/engine");
|
||||
exit(get_rv());
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
/* In the first test, we will merely try to see if we can run
|
||||
* without crashing. We don't check to see if data is good. */
|
||||
sess = get_random_session ();
|
||||
book = qof_session_get_book (sess);
|
||||
if (!book)
|
||||
{
|
||||
failure("book not created");
|
||||
exit(get_rv());
|
||||
}
|
||||
do_test ((NULL != book), "book not created");
|
||||
|
||||
add_random_transactions_to_book (book, 720);
|
||||
|
||||
@ -60,6 +50,9 @@ run_test (void)
|
||||
static void
|
||||
main_helper (void *closure, int argc, char **argv)
|
||||
{
|
||||
g_log_set_always_fatal( G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING );
|
||||
do_test((NULL!=gnc_module_load("gnucash/engine", 0)), "couldn't load engine");
|
||||
|
||||
run_test ();
|
||||
|
||||
print_test_results();
|
||||
|
@ -13,7 +13,7 @@
|
||||
#define TEST_MODULE_NAME "object-test"
|
||||
#define TEST_MODULE_DESC "Test Object"
|
||||
|
||||
static void foreach (QofBook *, QofEntityForeachCB, gpointer);
|
||||
static void foreach (QofBook *, QofForeachCB, gpointer);
|
||||
static const char * printable (gpointer obj);
|
||||
static void test_printable (const char *name, gpointer obj);
|
||||
static void test_foreach (QofBook *, const char *);
|
||||
@ -52,7 +52,7 @@ static void test_object (void)
|
||||
}
|
||||
|
||||
static void
|
||||
foreach (QofBook *book, QofEntityForeachCB cb, gpointer u_d)
|
||||
foreach (QofBook *book, QofForeachCB cb, gpointer u_d)
|
||||
{
|
||||
int *foo = u_d;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user