Incomplete engine registration in gnc_budget

Neil Williams linux at codehelp.co.uk
Mon Aug 9 09:09:36 EDT 2004


In working on the QofBook merge operation, I'm tidying up the getter and 
setter functions that will be used by the engine, not only for merge 
operations but also for the SQL backend on which Linas is working.

qof_book_merge is not in the main tree yet but it's close. You can see my work 
so far at:
www.codehelp.co.uk/code/

So far it can merge simple QofBooks and a QOF test routine is working. 
However, GnuCash also needs small adjustments to allow a merge to operate. 
I've already submitted two patches to HEAD to cover this:
http://lists.gnucash.org/pipermail/gnucash-patches/2004-July/015693.html

More will be needed, including some new functions for existing objects.

The aim is to have a 100% generic interface to all GnuCash objects, via QOF, 
so that any two QofBooks can be merged.

I've just been able to get hold of gnc_budget from the gnucash-gnome2-dev 
branch and I noticed something that I thought I'd seen with the first patch - 
there's no QOF class data for budget. I'm hoping that we can work together on 
the registration, following the example in engine/Account.c

This will be essential when the SQL backend is in use and leaving it NULL 
would also mean that NO budgets would ever get merged during qof_book_merge. 
I would assume that budgets, like other components of QofBook, would be 
merged when the book itself is merged - if the import book contains a budget 
and the target doesn't, you'd expect the budget to be imported into the 
resulting merged book.

The QofAccessFunc and QofSetterFunc pair details across the engine are in need 
of a little work at the moment and I'm trying to bring them all into a 
standard mechanism. My idea for a standard format is:
parameter name (as a define)
QOF type - if you have a new type, talk to Linas and let me know
accessfunc - this is the get function but it must have a standard prototype. 
setterfunc - this is the set function, again with a standard prototype.

AFAICT, all get and set functions using the same QOF_TYPE MUST use the same 
function parameters. If one uses const gchar* and one uses gchar*, the merge 
code will have no way to know how to retrieve the parameter value. Equally, a 
get function MUST return the same type as the set function requires - it 
can't work with a char* being returned and a const char* being required or 
vice versa. i.e. I should be able to take the return value of get() and put 
it straight into the set() for the corresponding entity in the other book.

This is a sample of how budget could be defined to QOF:

/* Register ourselves with the engine. */
gboolean gnc_budget_register (void)
{
  static QofParam params[] = {
	{ BUDGET_NAME, QOF_TYPE_STRING, (QofAccessFunc)gnc_budget_get_name, 
(QofSetterFunc)gnc_budget_set_name },
	{ BUDGET_DESCRIPTION, QOF_TYPE_STRING, 
(QofAccessFunc)gnc_budget_get_description, 
		(QofSetterFunc)gnc_budget_set_description },
	{ BUDGET_PERIOD_FREQ, QOF_TYPE_NUMERIC /*see later, this won't work*/, 
(QofAccessFunc)gnc_budget_get_period_frequency, 
		(QofSetterFunc)gnc_budget_set_period_frequency },
	{ BUDGET_START, QOF_TYPE_DATE, (QofAccessFunc)gnc_budget_get_start_date, 
		(QofSetterFunc)gnc_budget_set_start_date },
	{ BUDGET_LENGTH_MTH, QOF_TYPE_INT32, 
(QofAccessFunc)gnc_budget_get_length_months,
		(QofSetterFunc)gnc_budget_set_length_months },
	{ BUDGET_LENGTH_YRS, QOF_TYPE_INT32, 
(QofAccessFunc)gnc_budget_get_length_years,
		(QofSetterFunc)gnc_budget_set_length_years },
    { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, 
NULL },
    { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, 
NULL },
	{ NULL },
  }
    qof_class_register (GNC_ID_BUDGET, NULL, params);

    return qof_object_register (&budget_object_def);
}

Each of the parameter names would have to be described earlier in the file (or 
header) using #define - the actual values will simply be used to describe the 
parameter to the user in the event of a conflict in the merge.

However, there are problems here - as there are in other parts of the engine.

1. Budget uses GDate when other engine functions use Timespec - there are a 
few options there.
2. Your set_name and set_description use a different pointer type to the 
get_name and get_description functions - this is more serious for me:
void gnc_budget_set_name(GncBudget* budget, const gchar* name);
gchar* gnc_budget_get_name(GncBudget* budget);
Compare with Account:
const char *   xaccAccountGetName (Account *account);
void xaccAccountSetName (Account *account, const char *name);
This would make it difficult for me to retrieve the parameter value as I'd 
need to lose some of the generic code and set a different variable just for 
your version of the QOF_TYPE_STRING.
3. Period frequency (FreqSpec) is unknown to QOF(unless I've just missed it?). 
We'd either need to come up with a new QOF type or have a secondary function 
that can accept an existing QOF_TYPE. I've used an example of 
QOF_TYPE_NUMERIC above but that is just a placeholder, I would not expect 
gnc_numeric to be suitable. A similar problem (for me) occurs elsewhere in 
the engine too - a possible set function may want a struct but the get 
function is repeated to allow retrieval of each struct member directly - some 
minor tweaks are likely.
4. categories. I'm lazy too, I haven't gone through all your budget code, but 
these would, presumably, need to be part of any budget object. If we think of 
these as Transaction is to Account, these could be described separately - 
with their own QOF class registration.

I've checked with Linas that a simple rule should be adequate for QOF class 
registrations:
If a parameter must be set, define a standard get and set pair - parameter 
will be merged (and later stored in SQL).
If a parameter must be calculated, define either a get or set or none, NOT 
both. Parameter will be ignored by merge and SQL backend - it doesn't make 
sense to define a set function for a calculated value anyway.

So account balances only have a get function - the set function is NULL 
because the Transactions are summed to create the balance so setting an 
account balance independently of Transaction would corrupt the data.

I'm currently working on how to create new objects from the import data, 
without the program having to know anything about specialised Init functions. 
This may not work and the QOF class registration might need to have an extra 
field specified for a QofCreateFunc but that's a long way off. (Does anyone 
have ideas about how this can be done? is qof_instance_init sufficient? Do we 
need a QofCreateFunc? I'm getting seg faults again (but that's not unusual 
and I'm probably missing something obvious.)

I hope you can help me sort out a standard way of dealing with budget objects 
- it will bring enormous benefits to the user when QofBooks can be merged and 
the SQL backend is available.

-- 

Neil Williams
=============
http://www.codehelp.co.uk/
http://www.dclug.org.uk/
http://www.isbn.org.uk/
http://sourceforge.net/projects/isbnsearch/

http://www.biglumber.com/x/web?qs=0x8801094A28BCB3E3
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: signature
Url : http://lists.gnucash.org/pipermail/gnucash-devel/attachments/20040809/6cc67b5d/attachment.bin


More information about the gnucash-devel mailing list