[Gnucash-changes] check_data_type, backend configuration and gettext

Neil Williams codehelp at cvs.gnucash.org
Sun Sep 4 12:45:52 EDT 2005


Log Message:
-----------
check_data_type, backend configuration and gettext

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash/src/engine:
        cashobjects.c
        gnc-date.c
        gnc-event.h
        qof-be-utils.h
        qof.h
        qof_book_merge.h
        qofbackend-p.h
        qofbackend.c
        qofbackend.h
        qofchoice.h
        qofid.h
        qofquery-deserial.h
        qofquery-serialize.h
        qofsession.c
        qofsession.h

Revision Data
-------------
Index: qofid.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofid.h,v
retrieving revision 1.2.6.10
retrieving revision 1.2.6.11
diff -Lsrc/engine/qofid.h -Lsrc/engine/qofid.h -u -r1.2.6.10 -r1.2.6.11
--- src/engine/qofid.h
+++ src/engine/qofid.h
@@ -245,7 +245,7 @@
 
 @param type The QofIdType of the QofCollection \b and of 
 	\b all entities in the GList.
- at param list GList of entities of the same QofIdType.
+ at param glist GList of entities of the same QofIdType.
 
 @return NULL if any of the entities fail to match the
 	QofCollection type, else a pointer to the collection
Index: qofquery-serialize.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofquery-serialize.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -Lsrc/engine/qofquery-serialize.h -Lsrc/engine/qofquery-serialize.h -u -r1.1.2.3 -r1.1.2.4
--- src/engine/qofquery-serialize.h
+++ src/engine/qofquery-serialize.h
@@ -20,11 +20,9 @@
  * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
  *                                                                  *
 \********************************************************************/
-/** @addtogroup Query
-   @{ */
-/** @file qofquery-serialize.h
-    @brief Convert QofQuery to XML
-    @author Copyright (C) 2001,2002,2004 Linas Vepstas <linas at linas.org>
+/* qofquery-serialize.h
+   Convert QofQuery to XML
+   Copyright (C) 2001,2002,2004 Linas Vepstas <linas at linas.org>
  */
 
 #ifndef QOF_QUERY_SERIALIZE_H
@@ -33,14 +31,12 @@
 #include "qofquery.h"
 #include <libxml/tree.h>
 
-/** @addtogroup XML Serialize Queries to/from XML */
-/* @{ */
-/** Take the query passed as input, and serialize it into XML.
+/* XML Serialize Queries to/from XML */
+
+/* Take the query passed as input, and serialize it into XML.
  *  The DTD used will be a very qofquery specific DTD
  *  This is NOT the XQuery XML.
  */
 xmlNodePtr qof_query_to_xml (QofQuery *q);
-/* @} */
 
 #endif /* QOF_QUERY_SERIALIZE_H */
-/* @} */
Index: qofquery-deserial.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofquery-deserial.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -Lsrc/engine/qofquery-deserial.h -Lsrc/engine/qofquery-deserial.h -u -r1.1.2.3 -r1.1.2.4
--- src/engine/qofquery-deserial.h
+++ src/engine/qofquery-deserial.h
@@ -20,11 +20,10 @@
  * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
  *                                                                  *
 \********************************************************************/
-/** @addtogroup Query
-    @{ */
-/** @file qofquery-deserial.h
-    @brief Convert Qof-Query XML to QofQuery 
-    @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
+/* 
+ qofquery-deserial.h
+ Convert Qof-Query XML to QofQuery 
+author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
 */
 
 #ifndef QOF_QUERY_DESERIAL_H
@@ -33,18 +32,16 @@
 #include "qofquery.h"
 #include <libxml/tree.h>
 
-/** @addtogroup XML 
+/*
     Qof Queries can be converted to and from XML so that they
     can be sent from here to there. This file implements the
     routine needed to convert the XML back into a C struct.
 
-    \b Unfinished. XXX Why is this easier than reading a text/sql
+    Unfinished. XXX Why is this easier than reading a text/sql
     file? 
 
- @{ */
-/** Given an XML tree, reconstruct and return the equivalent query. */
+ */
+/* Given an XML tree, reconstruct and return the equivalent query. */
 QofQuery *qof_query_from_xml (xmlNodePtr);
-/* @} */
 
 #endif /* QOF_QUERY_DESERIAL_H */
-/* @} */
Index: qofsession.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.c,v
retrieving revision 1.2.4.22
retrieving revision 1.2.4.23
diff -Lsrc/engine/qofsession.c -Lsrc/engine/qofsession.c -u -r1.2.4.22 -r1.2.4.23
--- src/engine/qofsession.c
+++ src/engine/qofsession.c
@@ -19,25 +19,16 @@
  * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
 \********************************************************************/
 
-/*
- * FILE:
- * qofsession.c
- *
- * FUNCTION:
- * Encapsulate a connection to a storage backend.
+/**
+ * @file qofsession.c
+ * @brief Encapsulate a connection to a storage backend.
  *
  * HISTORY:
  * Created by Linas Vepstas December 1998
- * Copyright (c) 1998-2004 Linas Vepstas <linas at linas.org>
- * Copyright (c) 2000 Dave Peticolas
- * Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
- */
 
-  /* TODO: XXX we should probably move this resolve function to the
-   * file backend.  I think the idea would be to open the backend
-   * and then ask it if it can contact it's storage media (disk,
-   * network, server, etc.) and abort if it can't.  Mal-formed
-   * file URL's would be handled the same way!
+ @author Copyright (c) 1998-2004 Linas Vepstas <linas at linas.org>
+ @author Copyright (c) 2000 Dave Peticolas
+ @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
    */
 
 #include "config.h"
@@ -67,9 +58,8 @@
 #include "gnc-module.h"
 #endif /* GNUCASH */
 
-/** \deprecated current_session should not be static */
+/** \deprecated should not be static */
 static QofSession * current_session = NULL;
-
 static GHookList * session_closed_hooks = NULL;
 static short module = MOD_BACKEND;
 static GSList *provider_list = NULL;
@@ -228,8 +218,8 @@
   return session;
 }
 
-/** \deprecated  Use a local context to store
-your current session, NOT a static in the library. */
+/** \deprecated Each application should keep
+their \b own session context. */
 QofSession *
 qof_session_get_current_session (void)
 {
@@ -243,7 +233,6 @@
   return current_session;
 }
 
-/** \deprecated */
 void
 qof_session_set_current_session (QofSession *session)
 {
@@ -429,9 +418,7 @@
 	
 	g_return_if_fail(user_data != NULL);
 	context = (QofEntityCopyData*) user_data;
-	/* in case of any error, let the process know. */
-	if(context->error == TRUE) { return; }
-	context->error = TRUE;
+	ENTER (" ");
 	cm_date.tv_nsec = 0;
 	cm_date.tv_sec =  0;
 	importEnt = context->from;
@@ -514,6 +501,7 @@
 			qof_session_update_reference_list(context->new_session, reference);
 		}
 	}
+	LEAVE (" ");
 }
 
 static gboolean
@@ -561,10 +549,10 @@
 		g_slist_free(qecd->param_list);
 		qecd->param_list = NULL;
 	}
-	qof_begin_edit(inst);
 	qof_class_param_foreach(original->e_type, qof_entity_param_cb, qecd);
-	qof_commit_edit(inst);
+	qof_begin_edit(inst);
 	g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
+	qof_commit_edit(inst);
 }
 
 static void
@@ -638,6 +626,8 @@
 {
 	QofEntityCopyData *qecd;
 
+	if(!new_session || !entity_list) { return FALSE; }
+	ENTER (" list=%d", g_list_length(entity_list));
 	qecd = g_new0(QofEntityCopyData, 1);
 	gnc_engine_suspend_events();
 	qecd->param_list = NULL;
@@ -646,6 +636,7 @@
 	g_list_foreach(entity_list, qof_entity_list_foreach, qecd);
 	gnc_engine_resume_events();
 	g_free(qecd);
+	LEAVE (" ");
 	return TRUE;
 }
 
@@ -801,36 +792,29 @@
 }
 
 
-
 /* ====================================================================== */
 
-/* Specify a library, and a function name. Load the library, 
- * call the function name in the library.  */
-/* Use duplicate calls to cover 
- * the name of the shared library that is .so on
- * GNU/Linux but .dylib on Mac OSX etc. */
-static void
-load_backend_library (const char * libso, const char * loadfn)
-{
-	void (*initfn) (void);
-	void *dl_hand = dlopen (libso, RTLD_LAZY);
-	if (NULL == dl_hand)
-	{
-		const char * err_str = dlerror();
-		PERR("Can't load %s backend, %s\n", libso, err_str);
-		return;
-	}
-	initfn = dlsym (dl_hand, loadfn);
-	if (initfn)
-	{
-		 (*initfn)();
-	}
-	else
-	{
-		const char * err_str = dlerror();
-		PERR("Can't find %s:%s, %s\n", libso, loadfn, err_str);
-	}
-}
+/* Programs that use their own backends also need to call
+the default QOF ones. The backends specified here are
+loaded only by applications that do not have their own. */
+struct backend_providers
+{
+	const char *libdir;
+	const char *filename;
+	const char *init_fcn;
+};
+
+/* All available QOF backends need to be described here
+and the last entry must be three NULL's.
+Remember: Use the libdir from the current build environment
+and use the .la NOT the .so - .so is not portable! */
+struct backend_providers backend_list[] = {
+	{ QOF_LIB_DIR, "libqof-backend-qsf.la", "qsf_provider_init" },
+#ifdef HAVE_DWI
+	{ QOF_LIB_DIR, "libqof_backend_dwi.la", "dwiend_provider_init" },
+#endif
+	{ NULL, NULL, NULL }
+};
 
 #ifdef GNUCASH_MAJOR_VERSION 
 
@@ -847,7 +831,7 @@
 }
 
 /* Gnucash uses its module system to load a backend; other users
- * use traditional dlopen calls.
+ * use traditional dlopen calls. This will change with CashUtil.
  */
 static void
 qof_session_load_backend(QofSession * session, char * backend_name)
@@ -863,15 +847,6 @@
 	mod	= 0;
 	mod_name = g_strdup_printf("gnucash/backend/%s", backend_name);
 	msg = g_strdup_printf(" ");
-	/* FIXME : reinstate better error messages with gnc_module errors */
-	ENTER (" ");
-	/* FIXME: this needs to be smarter with version numbers. */
-	/* FIXME: this should use dlopen(), instead of guile/scheme, 
-	*    to load the modules.  Right now, this requires the engine to
-	*    link to scheme, which is an obvious architecture flaw. 
-	*    XXX this is fixed below, in the non-gnucash version. Cut
-	*    over at some point.
-	*/
 	mod = gnc_module_load(mod_name, 0);
 	if (mod) 
 	{
@@ -917,7 +892,6 @@
 	qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
   }
   g_free(mod_name);
-  LEAVE (" ");
 }
 
 #else /* GNUCASH */
@@ -930,21 +904,23 @@
 	QofBackendProvider *prov;
 	QofBook *book;
 	char *msg;
+	gint num;
+	gboolean prov_type;
+	gboolean (*type_check) (const char*);
 	
-	ENTER (" ");
-	/* If the provider list is null, try to register the 'well-known'
-	 *  backends. Right now, there's only two. */
+	ENTER (" list=%d", g_slist_length(provider_list));
+	prov_type = FALSE;
 	if (NULL == provider_list)
 	{
-		/* hack alert: If you change this, change qof_session_save as well. */
-#ifdef HAVE_DWI
-		load_backend_library ("libqof_backend_dwi.so", "dwiend_provider_init");
-#endif
-#ifdef DARWIN 
-		load_backend_library ("libqof-backend-qsf.dylib", "qsf_provider_init" );
-#else
-		load_backend_library ("libqof-backend-qsf.so", "qsf_provider_init" );
-#endif 
+		for (num = 0; backend_list[num].filename != NULL; num++) {
+			if(!qof_load_backend_library(backend_list[num].libdir,
+				backend_list[num].filename, backend_list[num].init_fcn))
+			{
+				PWARN (" failed to load %s from %s using %s",
+				backend_list[num].filename, backend_list[num].libdir,
+				backend_list[num].init_fcn);
+			}
+		}
 	}
 	p = g_slist_copy(provider_list);
 	while(p != NULL)
@@ -953,7 +929,22 @@
 		/* Does this provider handle the desired access method? */
 		if (0 == strcasecmp (access_method, prov->access_method))
 		{
-			if (NULL == prov->backend_new) continue;
+			/* More than one backend could provide this
+			access method, check file type compatibility. */
+			type_check = (gboolean (*)(const char*)) prov->check_data_type;
+			prov_type = (type_check)(session->book_id);
+			if(!prov_type)
+			{
+				PINFO(" %s not usable", prov->provider_name);
+				p = p->next;
+				continue;
+			}
+			PINFO (" selected %s", prov->provider_name);
+			if (NULL == prov->backend_new) 
+			{
+				p = p->next;
+				continue;
+			}
 			/* Use the providers creation callback */
       	    session->backend = (*(prov->backend_new))();
 			session->backend->provider = prov;
@@ -1219,6 +1210,7 @@
 	GSList *p;
 	QofBook *book, *abook;
 	int err;
+	gint num;
 	char *msg, *book_id;
 	
 	if (!session) return;
@@ -1249,13 +1241,10 @@
 		qof_session_destroy_backend(session);
 		if (NULL == provider_list)
 		{
-#ifdef DARWIN
-			load_backend_library ("libqsf-backend-file.dylib", "qsf_provider_init" );
-#else
-			load_backend_library ("libqof-backend-qsf.so", "qsf_provider_init" );
-#endif
-			qof_load_backend_library (QOF_LIB_DIR "libqof-backend-qsf.la",
-				"qsf_provider_init");
+			for (num = 0; backend_list[num].filename != NULL; num++) {
+				qof_load_backend_library(backend_list[num].libdir,
+					backend_list[num].filename, backend_list[num].init_fcn);
+			}
 		}
 		p = g_slist_copy(provider_list);
 		while(p != NULL)
Index: qofbackend.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend.c,v
retrieving revision 1.2.4.5
retrieving revision 1.2.4.6
diff -Lsrc/engine/qofbackend.c -Lsrc/engine/qofbackend.c -u -r1.2.4.5 -r1.2.4.6
--- src/engine/qofbackend.c
+++ src/engine/qofbackend.c
@@ -33,7 +33,10 @@
 #include <errno.h>
 #include "qofbackend-p.h"
 
-/* static short module = MOD_BACKEND; */
+static short module = MOD_BACKEND;
+
+#define QOF_CONFIG_DESC    "desc"
+#define QOF_CONFIG_TIP     "tip"
 
 /********************************************************************\
  * error handling                                                   *
@@ -148,7 +151,7 @@
 void
 qof_backend_run_begin(QofBackend *be, QofInstance *inst)
 {
-	if(!be | !inst) { return; }
+	if(!be || !inst) { return; }
 	if(!be->begin) { return; }
 	(be->begin) (be, inst);
 }
@@ -163,15 +166,176 @@
 void
 qof_backend_run_commit(QofBackend *be, QofInstance *inst)
 {
-	if(!be | !inst) { return; }
+	if(!be || !inst) { return; }
 	if(!be->commit) { return; }
 	(be->commit) (be, inst);
 }
 
+/* =========== Backend Configuration ================ */
+
+void qof_backend_prepare_frame(QofBackend *be)
+{
+	g_return_if_fail(be);
+	if(!kvp_frame_is_empty(be->backend_configuration)) {
+		kvp_frame_delete(be->backend_configuration);
+		be->backend_configuration = kvp_frame_new();
+	}
+	be->config_count = 0;
+}
+
+void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option)
+{
+	KvpValue *value;
+	gchar *temp;
+	gint count;
+
+	g_return_if_fail(be || option);
+	count = be->config_count;
+	count++;
+	value = NULL;
+	ENTER (" %d", count);
+	switch (option->type)
+	{
+		case KVP_TYPE_GINT64   : {
+			value = kvp_value_new_gint64(*(gint64*)option->value);
+			break; 
+		}
+		case KVP_TYPE_DOUBLE   : { 
+			value = kvp_value_new_double(*(double*)option->value);
+			break; 
+		}
+		case KVP_TYPE_NUMERIC  : {
+			value = kvp_value_new_numeric(*(gnc_numeric*)option->value);
+			break; 
+		}
+		case KVP_TYPE_STRING   : {
+			value = kvp_value_new_string((const char*)option->value);
+			break;
+		}
+		case KVP_TYPE_GUID     : { break; } /* unsupported */
+		case KVP_TYPE_TIMESPEC : {
+			value = kvp_value_new_timespec(*(Timespec*)option->value);
+			break;
+		}
+		case KVP_TYPE_BINARY   : { break; } /* unsupported */
+		case KVP_TYPE_GLIST    : { break; } /* unsupported */
+		case KVP_TYPE_FRAME    : { break; } /* unsupported */
+	}
+	if(value) {
+		temp = g_strdup_printf("/%s", option->option_name);
+		kvp_frame_set_value(be->backend_configuration, temp, value);
+		PINFO (" setting value at %s", temp);
+		g_free(temp);
+		temp = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, option->option_name);
+		PINFO (" setting description %s at %s", option->description, temp);
+		kvp_frame_set_string(be->backend_configuration, temp, option->description);
+		PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp));
+		g_free(temp);
+		temp = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, option->option_name);
+		PINFO (" setting tooltip %s at %s", option->tooltip, temp);
+		kvp_frame_set_string(be->backend_configuration, temp, option->tooltip);
+		PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp));
+		g_free(temp);
+		/* only increment the counter if successful */
+		be->config_count = count;
+	}
+	LEAVE (" ");
+}
+
+KvpFrame* qof_backend_complete_frame(QofBackend *be)
+{
+	g_return_val_if_fail(be, NULL);
+	be->config_count = 0;
+	return be->backend_configuration;
+}
+
+struct config_iterate {
+	QofBackendOptionCB fcn;
+	gpointer           data;
+	gint               count;
+	KvpFrame          *recursive;
+};
+
+static void
+config_foreach_cb (const char *key, KvpValue *value, gpointer data)
+{
+	QofBackendOption option;
+	gint64 int64;
+	double db;
+	gnc_numeric num;
+	Timespec ts;
+	gchar *parent;
+	struct config_iterate *helper;
+
+	g_return_if_fail(key || value || data);
+	helper = (struct config_iterate*)data;
+	if(!helper->recursive) { PERR (" no parent frame"); return;	}
+	// skip the presets.
+	if(0 == safe_strcmp(key, QOF_CONFIG_DESC)) { return; }
+	if(0 == safe_strcmp(key, QOF_CONFIG_TIP)) { return; }
+	ENTER (" key=%s", key);
+	option.option_name = key;
+	option.type = kvp_value_get_type(value);
+	if(!option.type) { return; }
+	switch (option.type)
+	{
+		case KVP_TYPE_GINT64   : {
+			int64 = kvp_value_get_gint64(value);
+			option.value = (gpointer)&int64;
+			break; 
+		}
+		case KVP_TYPE_DOUBLE   : {
+			db = kvp_value_get_double(value);
+			option.value = (gpointer)&db;
+			break; 
+		}
+		case KVP_TYPE_NUMERIC  : {
+			num = kvp_value_get_numeric(value);
+			option.value = (gpointer)&num;
+			break; 
+		}
+		case KVP_TYPE_STRING   : {
+			option.value = (gpointer)kvp_value_get_string(value);
+			break;
+		}
+		case KVP_TYPE_GUID     : { break; } /* unsupported */
+		case KVP_TYPE_TIMESPEC : {
+			ts = kvp_value_get_timespec(value);
+			option.value = (gpointer)&ts;
+			break;
+		}
+		case KVP_TYPE_BINARY   : { break; } /* unsupported */
+		case KVP_TYPE_GLIST    : { break; } /* unsupported */
+		case KVP_TYPE_FRAME    : { break; } /* unsupported */
+	}
+	parent = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, key);
+	option.description = kvp_frame_get_string(helper->recursive, parent);
+	g_free(parent);
+	parent = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, key);
+	option.tooltip = kvp_frame_get_string(helper->recursive, parent);
+	helper->count++;
+	helper->fcn (&option, helper->data);
+	LEAVE (" desc=%s tip=%s", option.description, option.tooltip);
+}
+
+void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data)
+{
+	struct config_iterate helper;
+
+	if(!config || !cb) { return; }
+	ENTER (" ");
+	helper.fcn = cb;
+	helper.count = 1;
+	helper.data = data;
+	helper.recursive = config;
+	kvp_frame_for_each_slot(config, config_foreach_cb, &helper);
+	LEAVE (" ");
+}
+
 void
 qof_backend_load_config(QofBackend *be, KvpFrame *config)
 {
-	if(!be | !config) { return; }
+	if(!be || !config) { return; }
 	if(!be->load_config) { return; }
 	(be->load_config) (be, config);
 }
@@ -192,16 +356,6 @@
 	else { return FALSE; }
 }
 
-#if 0
-gboolean
-qof_backend_check_type (QofBackend *be, const char *path)
-{
-	if(!be) { return FALSE; }
-	if(!be->check_data_type) { return FALSE; }
-	return (gboolean)(be->check_data_type) (be, path);
-}
-#endif
-
 void 
 qof_begin_edit(QofInstance *inst)
 {
@@ -239,7 +393,8 @@
 #define STR_LIBDIR     "libdir="
 
 gboolean
-qof_load_backend_library (const char* filename, const char* init_fcn)
+qof_load_backend_library (const char *directory, 
+				const char* filename, const char* init_fcn)
 {
 	FILE *filehandle;
 	void (*initfn) (void);
@@ -260,10 +415,20 @@
 	tempstr = NULL;
 	libdirpath = NULL;
 	g_return_val_if_fail((filename || init_fcn), FALSE); 
+  if(directory)
+	{
+		if(!g_str_has_suffix(directory, "/")) {
+			tempstr = g_strconcat(directory, "/", filename, NULL);
+		}
+		else {
+			tempstr = g_strconcat(directory, filename, NULL);
+		}
+		filename = tempstr;
+	}
 	g_return_val_if_fail(g_str_has_suffix (filename, ".la"), FALSE);
 	/* now we have a filename ending in .la, see if we can open it. */
 	n = (guint)strlen(STR_DLNAME);
-	g_return_val_if_fail((stat(filename, &sbuf) <0), FALSE);
+	g_return_val_if_fail((stat(filename, &sbuf) == 0), FALSE);
 	filehandle = fopen(filename, "r");
 	g_return_val_if_fail((filehandle), FALSE);
 #ifndef HAVE_GETLINE
@@ -273,6 +438,7 @@
 	while (0 < getline(&lineptr, &n, filehandle))
 #endif
 	{
+		n = (guint)strlen(STR_DLNAME);
 		if (strncmp (lineptr, STR_DLNAME, n - 1) == 0)
 		{
 			/* obtain substring from dlname='.*'\n
@@ -301,7 +467,6 @@
 				tempstr = g_strndup(libdirpath, end - 1);
 				libdirpath = tempstr;
 			}
-			break;
 		}
 	}
 	fclose(filehandle);
Index: qofbackend-p.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend-p.h,v
retrieving revision 1.2.4.5
retrieving revision 1.2.4.6
diff -Lsrc/engine/qofbackend-p.h -Lsrc/engine/qofbackend-p.h -u -r1.2.4.5 -r1.2.4.6
--- src/engine/qofbackend-p.h
+++ src/engine/qofbackend-p.h
@@ -279,6 +279,22 @@
   */
   const char* provider_config;
   
+/** \brief Distinguish two providers with same access method.
+  
+  More than 1 backend can be registered under the same access_method,
+  so each one is passed the path to the data (e.g. a file) and
+  should return TRUE only:
+-# if the backend recognises the type as one that it can load and write or 
+-#if the path contains no data but can be used (e.g. a new session).
+  
+  \note If the backend can cope with more than one type, the backend
+  should not try to store or cache the sub-type for this data.
+  It is sufficient only to return TRUE if any ONE of the supported
+  types match the incoming data. The backend should not assume that
+  returning TRUE will mean that the data will naturally follow.
+  */
+  gboolean (*check_data_type) (const char*);
+  
   /** Free this structure, unregister this backend handler. */
   void (*provider_free) (QofBackendProvider *);
 };
@@ -322,26 +338,12 @@
   char * error_msg;
 
   KvpFrame* backend_configuration;
+  gint config_count;
   /** Each backend resolves a fully-qualified file path.
    * This holds the filepath and communicates it to the frontends.
    */
   char * fullpath;
 
-  /** \brief Distinguish two providers with same access method.
-  
-  When more than 1 backend is registered under the same access_method,
-  each one is passed the path to the data (usually a file) and
-  should return TRUE only if the backend recognises the type 
-  as one that it can load and write.
-  
-  \note If the backend can cope with more than one type, the backend
-  should not try to store or cache the sub-type for this data.
-  It is sufficient only to return TRUE if any ONE of the supported
-  types match the incoming data. The backend should not assume that
-  returning TRUE will mean that the data will naturally follow.
-  */
-  gboolean (*check_data_type) (QofBackend *, const char*);
-
 #ifdef GNUCASH_MAJOR_VERSION
   /** XXX price_lookup should be removed during the redesign
    * of the SQL backend... prices can now be queried using
Index: qofbackend.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend.h,v
retrieving revision 1.3.4.8
retrieving revision 1.3.4.9
diff -Lsrc/engine/qofbackend.h -Lsrc/engine/qofbackend.h -u -r1.3.4.8 -r1.3.4.9
--- src/engine/qofbackend.h
+++ src/engine/qofbackend.h
@@ -18,8 +18,6 @@
  * Boston, MA  02111-1307,  USA       gnu at gnu.org                   *
  *                                                                  *
 \********************************************************************/
-/** @addtogroup Object
-    @{ */
 /** @addtogroup Backend
 
     The QOF Backend is a pseudo-object providing an interface between the
@@ -32,7 +30,8 @@
     the GUI & other front-end users.  This file defines these errors.
    
     Backends are used to save and restore Entities in a Book.
-    @{ */
+    @{ 
+*/
 /** @file qofbackend.h
     @brief API for data storage Backend
     @author Copyright (C) 2000-2001 Linas Vepstas <linas at linas.org>
@@ -152,47 +151,112 @@
 /** \brief DOCUMENT ME! */
 typedef void (*QofBePercentageFunc) (const char *message, double percent);
 
-/** \name Allow access to the begin routine for this backend.
+/** @name Allow access to the begin routine for this backend.
 
 QOF_BEGIN_EDIT and QOF_COMMIT_EDIT_PART1 and part2 rely on 
 calling QofBackend *be->begin and be->commit. This means the
 QofBackend struct becomes part of the public API.
 These function replaces those calls to allow the macros to be
-used when QOF is built as a library.
+used when QOF is built as a library. */
+//@{
+
+void qof_backend_run_begin(QofBackend *be, QofInstance *inst);
+
+gboolean qof_backend_begin_exists(QofBackend *be);
+
+void qof_backend_run_commit(QofBackend *be, QofInstance *inst);
+
+gboolean qof_backend_commit_exists(QofBackend *be);
+//@}
+
+/** @name Backend Configuration using KVP
+
+The backend uses qof_backend_get_config to pass back a KvpFrame of QofBackendOption
+that includes the \b translated strings that serve as description and
+tooltip for that option. i.e. backends need to run gettext in the init function.
+
+qof_backend_prepare_frame, qof_backend_prepare_option and qof_backend_complete_frame
+are intended to be used by the backend itself to create the options.
+
+qof_backend_get_config, qof_backend_option_foreach and qof_backend_load_config
+are intended for either the backend or the frontend to retrieve the option data
+from the frame or set new data.
+
 @{
 */
 
+/** A single Backend Configuration Option. */
+typedef struct QofBackendOption_s {
+	KvpValueType type;        /**< Only GINT64, DOUBLE, NUMERIC, STRING and TIMESPEC supported. */
+	const char *option_name;  /**< non-translated, key. */
+	const char *description;  /**< translatable description. */
+	const char *tooltip;      /**< translatable tooltip */
+	gpointer value;           /**< The value of the option. */
+}QofBackendOption;
+
+/** Initialise the backend_configuration */
+void qof_backend_prepare_frame(QofBackend *be);
+
+/** Add an option to the backend_configuration. Repeat for more. */
+void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option);
+
+/** Complete the backend_configuration and return the frame. */
+KvpFrame* qof_backend_complete_frame(QofBackend *be);
+
+/** Backend configuration option foreach callback prototype. */
+typedef void (*QofBackendOptionCB)(QofBackendOption*, gpointer data);
+
+/** Iterate over the frame and process each option. */
+void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data);
+
 /** \brief Load configuration options specific to this backend.
 
 @param be The backend to configure.
- at param config A hash table with specific keys that this backend
+ at param config A KvpFrame of QofBackendOptions that this backend
 will recognise. Each backend needs to document their own config
-keys and acceptable values.
+types and acceptable values.
 
-The hash table remains the property of the caller and should
-be freed / destroyed once loaded in the backend.
 */
 void qof_backend_load_config (QofBackend *be, KvpFrame *config);
 
-KvpFrame* qof_backend_get_config(QofBackend *be);
+/** \brief Get the available configuration options
 
-void qof_backend_run_begin(QofBackend *be, QofInstance *inst);
+To retrieve the options from the returned KvpFrame, the caller
+needs to parse the XML file that documents the option names and
+data types. The XML file itself is part of the backend and is
+installed in a directory determined by the backend. Therefore,
+loading a new backend requires two paths: the path to the .la file
+and the path to the xml. Both paths are available by including a
+generated header file, e.g. gncla-dir.h defines GNC_LIB_DIR for
+the location of the .la file and GNC_XML_DIR for the xml.
 
-gboolean qof_backend_begin_exists(QofBackend *be);
+ at param be The QofBackend to be configured.
 
-void qof_backend_run_commit(QofBackend *be, QofInstance *inst);
+ at return A new KvpFrame containing the available options or
+NULL on failure.
 
-gboolean qof_backend_commit_exists(QofBackend *be);
+*/
+KvpFrame* qof_backend_get_config(QofBackend *be);
+//@}
+
+/** \brief Load a QOF-compatible backend shared library.
+
+\param directory Can be NULL if filename is a complete path.
+\param filename  Name of the .la file that describes the
+	shared library. This provides platform independence,
+	courtesy of libtool.
+\param init_fcn  The QofBackendProvider init function.
 
+\return FALSE in case or error, otherwise TRUE.
+*/
 gboolean
-qof_load_backend_library (const char* filename, const char* init_fcn);
+qof_load_backend_library (const char *directory, 
+			const char* filename, const char* init_fcn);
 
-/** @} */
 /** \brief Retrieve the backend used by this book */
 QofBackend* qof_book_get_backend (QofBook *book);
 
 void qof_book_set_backend (QofBook *book, QofBackend *);
 
 #endif /* QOF_BACKEND_H */
-/**@}*/
-/**@}*/
+/** @} */
Index: gnc-event.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-event.h,v
retrieving revision 1.8.6.3
retrieving revision 1.8.6.4
diff -Lsrc/engine/gnc-event.h -Lsrc/engine/gnc-event.h -u -r1.8.6.3 -r1.8.6.4
--- src/engine/gnc-event.h
+++ src/engine/gnc-event.h
@@ -21,6 +21,14 @@
  *                                                                  *
  ********************************************************************/
 
+/** @addtogroup Event
+@{
+*/
+/** @file gnc-event.h
+    @brief engine event handling interface
+	@author Copyright 2000 Dave Peticolas <dave at krondo.com>
+*/
+
 #ifndef GNC_EVENT_H
 #define GNC_EVENT_H
 
@@ -41,37 +49,41 @@
 } GNCEngineEventType;
 
 
-/* GNCEngineEventHandler
+/** GNCEngineEventHandler
+
  *   Handler invoked when an engine event occurs.
  *
- * entity:      GUID of entity generating event
- * type:	QofIdType of the entity generating the event
- * event_type:  one of the single-bit GNCEngineEventTypes, not a combination
- * user_data:   user_data supplied when handler was registered.
+ * @param entity:      GUID of entity generating event
+ * @param type:	QofIdType of the entity generating the event
+ * @param event_type:  one of the single-bit GNCEngineEventTypes, not a combination
+ * @param user_data:   user_data supplied when handler was registered.
  */
 typedef void (*GNCEngineEventHandler) (GUID *entity, QofIdType type,
                                        GNCEngineEventType event_type,
                                        gpointer user_data);
 
-/* gnc_engine_register_event_handler
+/** gnc_engine_register_event_handler
+
  *   Register a handler for engine events.
  *
- * handler:   handler to register
- * user_data: data provided when handler is invoked
+ * @param handler:   handler to register
+ * @param user_data: data provided when handler is invoked
  *
- * Returns: id identifying handler
+ * @return id identifying handler
  */
 gint gnc_engine_register_event_handler (GNCEngineEventHandler handler,
                                         gpointer user_data);
 
-/* gnc_engine_unregister_event_handler
+/** gnc_engine_unregister_event_handler
+
  *   Unregister an engine event handler.
  *
- * handler_id: the id of the handler to unregister
+ * @param handler_id: the id of the handler to unregister
  */
 void gnc_engine_unregister_event_handler (gint handler_id);
 
-/* gnc_engine_generate_event
+/** gnc_engine_generate_event
+
  *   Invoke all registered event handlers using the given arguments.
  *
  *   GNC_EVENT_CREATE events should be generated after the object
@@ -81,13 +93,14 @@
  *   GNC_EVENT_DESTROY events should be called before the object
  *     has been destroyed or removed from the entity table.
  *
- * entity:     the GUID of the entity generating the event
- * event_type: the type of event -- this should be one of the
+ * @param entity:     the GUID of the entity generating the event
+ * @param event_type: the type of event -- this should be one of the
  *             single-bit GNCEngineEventType values, not a combination.
  */
 void gnc_engine_gen_event (QofEntity *entity,
                                 GNCEngineEventType event_type);
-/* gnc_engine_suspend_events
+/** gnc_engine_suspend_events
+
  *   Suspend all engine events. This function may be
  *   called multiple times. To resume event generation,
  *   an equal number of calls to gnc_engine_resume_events
@@ -95,9 +108,11 @@
  */
 void gnc_engine_suspend_events (void);
 
-/* gnc_engine_resume_events
+/** gnc_engine_resume_events
+
  *   Resume engine event generation.
  */
 void gnc_engine_resume_events (void);
 
 #endif
+/** @} */
Index: qof.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qof.h,v
retrieving revision 1.2.4.6
retrieving revision 1.2.4.7
diff -Lsrc/engine/qof.h -Lsrc/engine/qof.h -u -r1.2.4.6 -r1.2.4.7
--- src/engine/qof.h
+++ src/engine/qof.h
@@ -22,7 +22,8 @@
 #ifndef QOF_H_
 #define QOF_H_
 /** @defgroup QOF Query Object Framework 
- @{ */
+ @{
+*/
 
 /**
     @addtogroup Date Date:  Date and Time Printing, Parsing and Manipulation
@@ -60,6 +61,12 @@
     @addtogroup Trace Trace: Error Reporting and Debugging
     @ingroup QOF
 */
+/** @addtogroup BookMerge Merging QofBook structures
+	@ingroup QOF
+*/
+/** @addtogroup Event Event: QOF event handlers.
+	@ingroup QOF
+*/
 /**
     @addtogroup Utilities Misc Utilities
     @ingroup QOF
Index: qof_book_merge.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qof_book_merge.h,v
retrieving revision 1.2.2.5
retrieving revision 1.2.2.6
diff -Lsrc/engine/qof_book_merge.h -Lsrc/engine/qof_book_merge.h -u -r1.2.2.5 -r1.2.2.6
--- src/engine/qof_book_merge.h
+++ src/engine/qof_book_merge.h
@@ -25,9 +25,7 @@
 #ifndef QOFBOOKMERGE_H
 #define QOFBOOKMERGE_H
 
-/** @addtogroup QOF
-	@{ */
-/** @addtogroup BookMerge Merging QofBook structures.
+/** @addtogroup BookMerge
 
 <b>Collision handling principles.</b>\n
 \n
@@ -66,7 +64,8 @@
 pointer to the ::qof_book_mergeData struct - the calling process needs to
 make sure this is non-NULL to know that the Init has been successful.
 
- @{ */
+ @{
+*/
 /** @file  qof_book_merge.h
     @brief API for merging two \c QofBook structures with collision handling
     @author Copyright (c) 2004-2005 Neil Williams <linux at codehelp.co.uk>
@@ -135,7 +134,7 @@
 If the ::GUID matches it's the always same semantic object,
 regardless of whether other data fields are changed.
 \n	
-The boolean value mergeAbsolute defaults to \c FALSE\n
+The boolean value mergeAbsolute defaults to \c FALSE
 
 NOTE 1: if mergeAbsolute == \c TRUE, ::qof_book_mergeResult will still be set to 
 ::MERGE_UPDATE if parameters within this entity have been modified.
@@ -310,9 +309,9 @@
 return the two specific entities.
 
 */
-void qof_book_mergeRuleForeach( qof_book_mergeData*,
-                                qof_book_mergeRuleForeachCB, 
-                                qof_book_mergeResult );
+void qof_book_mergeRuleForeach( qof_book_mergeData* mergeData,
+                                qof_book_mergeRuleForeachCB callback , 
+                                qof_book_mergeResult mergeResult);
 
 /** \brief provides easy string access to parameter data for dialog use
 
@@ -401,7 +400,6 @@
 ::qof_book_merge_abort(mergeData) if non-zero.
 
 @param	mergeData	the merge context, ::qof_book_mergeData*
- at param	resolved	the current rule, ::qof_book_mergeRule*
 @param	tag			the result to attempt to set, ::qof_book_mergeResult
 
 \return -1 if supplied parameters are invalid or NULL, 0 on success.
@@ -454,8 +452,6 @@
 void
 qof_book_merge_abort(qof_book_mergeData *mergeData);
 
-/** @} */
-
+#endif // QOFBOOKMERGE_H
 /** @} */
 /** @} */
-#endif // QOFBOOKMERGE_H
Index: gnc-date.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-date.c,v
retrieving revision 1.6.2.6
retrieving revision 1.6.2.7
diff -Lsrc/engine/gnc-date.c -Lsrc/engine/gnc-date.c -u -r1.6.2.6 -r1.6.2.7
--- src/engine/gnc-date.c
+++ src/engine/gnc-date.c
@@ -463,21 +463,6 @@
     case QOF_DATE_FORMAT_CE:
       flen = g_snprintf (buff, len, "%2d.%2d.%-4d", day, month, year);
       break;
- /*
-    case QOF_DATE_FORMAT_UTC:
-    // Is there any reason to go through strftime() here when we're using
-    // the same format as with ISO?  The output is the same either way.
-	{
-		struct tm tm_str;
-
-		tm_str.tm_mday = day;
-		tm_str.tm_mon = month - 1;
-		tm_str.tm_year = year - 1900;
-
-		flen = strftime(buff, MAX_DATE_LENGTH, "%Y-%m-%d", &tm_str);
-		break;
-	}
- */
     case QOF_DATE_FORMAT_LOCALE:
       {
         struct tm tm_str;
Index: qofchoice.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Attic/qofchoice.h,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/engine/qofchoice.h -Lsrc/engine/qofchoice.h -u -r1.1.2.1 -r1.1.2.2
--- src/engine/qofchoice.h
+++ src/engine/qofchoice.h
@@ -14,7 +14,7 @@
  *  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 Library General Public License for more details.
+ *  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, write to the Free Software
@@ -116,7 +116,7 @@
 
 @param choice The choice object.
 @param add  The object to be added as an option.
- at param param The parameter that will be used to get or set options.
+ at param param_name The parameter that will be used to get or set options.
 
 @return FALSE if object is not a choice object or on error
 	otherwise TRUE.
@@ -126,7 +126,7 @@
 /** \brief Return the list of all object types usable with this parameter.
 
 @param type The choice object type.
- at param param_name The name of the parameter that will be used to
+ at param param The name of the parameter that will be used to
 	get or set options.
 
 @return NULL on error or if no options exist for this parameter,
Index: qof-be-utils.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qof-be-utils.h,v
retrieving revision 1.3.2.5
retrieving revision 1.3.2.6
diff -Lsrc/engine/qof-be-utils.h -Lsrc/engine/qof-be-utils.h -u -r1.3.2.5 -r1.3.2.6
--- src/engine/qof-be-utils.h
+++ src/engine/qof-be-utils.h
@@ -42,8 +42,7 @@
 
 /** begin_edit helper
  *
- * @args:
- *        inst: an instance of QofInstance
+ * @param  inst: an instance of QofInstance
  *
  * The caller should use this macro first and then perform any other operations.
 
@@ -92,8 +91,7 @@
 /**
  * part1 -- deal with the editlevel
  * 
- * @args:
- *        inst: an instance of QofInstance
+ * @param inst: an instance of QofInstance
  */
 
 #define QOF_COMMIT_EDIT_PART1(inst) {                            \
@@ -133,15 +131,14 @@
 /**
  * part2 -- deal with the backend
  * 
- * @args:
- *        inst: an instance of QofInstance
- *        on_error: a function called if there is a backend error.
+ * @param inst: an instance of QofInstance
+ * @param on_error: a function called if there is a backend error.
  *                void (*on_error)(inst, QofBackendError)
- *        on_done: a function called after the commit is complete 
+ * @param 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. 
+ * @param on_free: a function called if inst->do_free is TRUE. 
  *                void (*on_free)(inst)
  */
 #define QOF_COMMIT_EDIT_PART2(inst,on_error,on_done,on_free) {   \
Index: cashobjects.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Attic/cashobjects.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/engine/cashobjects.c -Lsrc/engine/cashobjects.c -u -r1.1.2.1 -r1.1.2.2
--- src/engine/cashobjects.c
+++ src/engine/cashobjects.c
@@ -35,7 +35,12 @@
 #include "gncTaxTableP.h"
 #include "gncOrderP.h"
 #include "AccountP.h"
+#include "GroupP.h"
 #include "TransactionP.h"
+#include "FreqSpec.h"
+#include "SchedXaction.h"
+#include "SX-book-p.h"
+
 
 gboolean
 cashobjects_register(void)
@@ -51,9 +56,14 @@
 	g_return_val_if_fail (gncVendorRegister (), FALSE);
 	g_return_val_if_fail(gncTaxTableRegister(), FALSE);
 	g_return_val_if_fail ( gncOrderRegister (), FALSE);
+	g_return_val_if_fail(gnc_commodity_table_register(), FALSE);
 #endif
 	g_return_val_if_fail(xaccAccountRegister(), FALSE);
 	g_return_val_if_fail ( xaccTransRegister(), FALSE);
 	g_return_val_if_fail ( xaccSplitRegister(), FALSE);
+	g_return_val_if_fail ( xaccGroupRegister(), FALSE);
+	g_return_val_if_fail ( FreqSpecRegister(),  FALSE);
+	g_return_val_if_fail ( SXRegister (),       FALSE);
+	g_return_val_if_fail ( gnc_sxtt_register(), FALSE);
 	return TRUE;
 }
Index: qofsession.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.h,v
retrieving revision 1.2.4.9
retrieving revision 1.2.4.10
diff -Lsrc/engine/qofsession.h -Lsrc/engine/qofsession.h -u -r1.2.4.9 -r1.2.4.10
--- src/engine/qofsession.h
+++ src/engine/qofsession.h
@@ -75,7 +75,15 @@
  * make that assumption, in order to store the different accounting
  * periods in a clump so that one can be found, given another.
  *
- *  @{ 
+
+   The session now calls QofBackendProvider->check_data_type
+   to check that the incoming path contains data that the
+   backend provider can open. The backend provider should
+   also check if it can contact it's storage media (disk,
+   network, server, etc.) and abort if it can't.  Malformed
+   file URL's would be handled the same way.
+  
+ @{ 
  */
 
 /** @file qofsession.h
@@ -99,15 +107,7 @@
 
 QofSession * qof_session_new (void);
 void         qof_session_destroy (QofSession *session);
-
-/** \deprecated Use a local context, not this static!
-
-Applications must not use 'current_session' in new code.
-
-Use a local context and store your session data there.
-*/
 QofSession * qof_session_get_current_session (void);
-/** \deprecated do not use! */
 void	       qof_session_set_current_session (QofSession *session);
 
 /** The qof_session_swap_data () method swaps the book of
@@ -191,13 +191,13 @@
  *    See qofbackend.h for a listing of returned errors.
  */
 QofBackendError qof_session_pop_error (QofSession *session);
-/* @} */
+/** @} */
 
 /** The qof_session_add_book() allows additional books to be added to
  *    a session. 
  * XXX Under construction, clarify the following when done:
  * XXX There must already be an open book in the session already!?
- * XXX Only one open bok at a time per session is alowed!?
+ * XXX Only one open book at a time per session is allowed!?
  * XXX each book gets its own unique backend ???
  */
 void qof_session_add_book (QofSession *session, QofBook *book);
@@ -356,7 +356,7 @@
 @param coll A QofCollection of entities that may or may not have 
 references.
 
- at param session The QofSession to receive the copied entities.
+ at param new_session The QofSession to receive the copied entities.
 
 @return TRUE on success; if any individual copy fails, returns FALSE.
 <b>Note</b> : Some entities may have been copied successfully even if
@@ -379,7 +379,7 @@
 
 @param ent A single entity that may or may not have references.
 
- at param session The QofSession to receive the copied entities.
+ at param new_session The QofSession to receive the copied entities.
 
 @return TRUE on success; if any individual copy fails, returns FALSE.
 <b>Note</b> : Some entities may have been copied successfully even if
@@ -521,7 +521,7 @@
  *    engine was modified while engine events were suspended.
  */
 gboolean qof_session_process_events (QofSession *session);
-/* @} */
+/** @} */
 
 #ifdef GNUCASH_MAJOR_VERSION
 /** Run the RPC Server 


More information about the gnucash-changes mailing list