[Gnucash-changes] New dialog to export the Chart of Accounts to QSF XML.

Neil Williams codehelp at cvs.gnucash.org
Mon Mar 7 12:56:45 EST 2005


Log Message:
-----------
New dialog to export the Chart of Accounts to QSF XML.
Enable import of QSF XML.
Fix QSF backend object count and validation; add to KVP read support.
Fix char bug in qof_book_merge.

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash:
        ChangeLog
        HACKING
    gnucash/src/app-file:
        gnc-file.c
    gnucash/src/backend/file:
        gnc-backend-file.c
    gnucash/src/backend/qsf:
        qsf-backend.c
        qsf-xml.c
    gnucash/src/engine:
        qof_book_merge.c
        qofbackend.h
        qofsession.c
        qofsession.h
    gnucash/src/gnome:
        Makefile.am
        druid-merge.c
        druid-merge.h
        gnc-main-window.c
        gnc-plugin-page-account-tree.c
        window-main.c
    gnucash/src/gnome/glade:
        Makefile.am
    gnucash/src/gnome/ui:
        gnc-main-window-ui.xml

Added Files:
-----------
    gnucash/src/gnome:
        dialog-chart-export.c
        dialog-chart-export.h
    gnucash/src/gnome/glade:
        chart-export.glade

Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.180
retrieving revision 1.1487.2.181
diff -LChangeLog -LChangeLog -u -r1.1487.2.180 -r1.1487.2.181
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,42 @@
+2005-03-07  Neil Williams  <linux at codehelp.co.uk>
+	* ./HACKING: Add a tip for using gdb with opt
+	style builds.
+	* ./src/app-file/gnc-file.c: New error message
+	to direct users to merge QSF, not open directly.
+	* ./src/backend/file/gnc-backend-file.c: Debug
+	aids.
+	* ./src/backend/qsf/qsf-backend.c: Fix object 
+	count and validation; add to KVP read support.
+	* ./src/backend/qsf/qsf-xml.c: Fix object count
+	validation bug.
+	* ./src/engine/qof_book_merge.c: Fix char merge
+	bug.
+	* ./src/engine/qofbackend.h: New error message
+	support.
+	* ./src/engine/qofsession.c: Fix entity copy 
+	parameter list handling. Fix library name error.
+	* ./src/engine/qofsession.h: Doxygen update.
+	* ./src/gnome/Makefile.am: New dialog support.
+	* ./src/gnome/dialog-chart-export.c: New dialog
+	to export the Chart of Accounts to QSF XML.
+	* ./src/gnome/dialog-chart-export.h: Header for
+	new dialog.
+	* ./src/gnome/druid-merge.c: Adding code to
+	support the new dialog.
+	* ./src/gnome/druid-merge.h: New dialog.
+	* ./src/gnome/glade/Makefile.am: New glade file.
+	* ./src/gnome/glade/chart-export.glade: New glade
+	file for Chart of Account export dialog.
+	* ./src/gnome/gnc-main-window.c: Menu commands for
+	new dialog.
+	* ./src/gnome/gnc-plugin-page-account-tree.c: 
+	Minor tweak.
+	* ./src/gnome/ui/gnc-main-window-ui.xml: Adding
+	menu option for new dialog.
+	* ./src/gnome/window-main.c: Removing old merge
+	druid commands.
+
+
 2005-02-28  Neil Williams  <linux at codehelp.co.uk>
 	
 	* ./src/app-utils/gnc-ui-util.h:
Index: HACKING
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/HACKING,v
retrieving revision 1.5.4.2
retrieving revision 1.5.4.3
diff -LHACKING -LHACKING -u -r1.5.4.2 -r1.5.4.3
--- HACKING
+++ HACKING
@@ -107,6 +107,12 @@
     [gdb output]
     % gdb> run -e main -s ./src/bin/overrides/gnucash --g-fatal-warnings
 
+To run gdb on an opt-style-install from your build tree:
+
+   $ ./gnucash-env gdb /usr/bin/guile
+   [gdb output]
+   gdb> run -e main -s ../libexec/overrides/gnucash --g-fatal-warning
+
 
 Using Electric Fence with GnuCash
 ---------------------------------
Index: qsf-xml.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/backend/qsf/qsf-xml.c -Lsrc/backend/qsf/qsf-xml.c -u -r1.1.2.2 -r1.1.2.3
--- src/backend/qsf/qsf-xml.c
+++ src/backend/qsf/qsf-xml.c
@@ -27,6 +27,8 @@
 #include "qsf-dir.h"
 #include "qsf-xml.h"
 #include "qofbook-p.h"
+#include "gnc-trace.h"
+static short int module = MOD_BACKEND;
 
 void qsf_free_params(qsf_param *params)
 {
@@ -124,14 +126,18 @@
 {
 	xmlNodePtr cur_node;
 	xmlChar *object_declaration;
+	guint count;
 
+	count = 0;
 	for(cur_node = child->children; cur_node != NULL;
 		cur_node = cur_node->next)
 	{
 		if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) {
 			object_declaration = xmlGetProp(cur_node, QSF_OBJECT_TYPE);
+			count = g_hash_table_size(valid->validation_table);
 			g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node));
-			if(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration))
+			if((g_hash_table_size(valid->validation_table) > count) &&
+				(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration)))
 			{
 				valid->qof_registered_count++;
 			}
@@ -148,6 +154,7 @@
 	gint table_count;
 
 	g_return_val_if_fail((path != NULL),FALSE);
+	ENTER (" ");
 	if(path == NULL) { return FALSE; }
 	doc = xmlParseFile(path);
 	if(doc == NULL)  { return FALSE; }
@@ -164,9 +171,11 @@
 	if(table_count == valid.qof_registered_count)
 	{
 		g_hash_table_destroy(valid.validation_table);
+		LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 		return TRUE;
 	}
 	g_hash_table_destroy(valid.validation_table);
+	LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 	return FALSE;
 }
 
@@ -179,6 +188,7 @@
 	doc = xmlParseFile(path);
 	if(doc == NULL) { return FALSE; }
 	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; }
+	ENTER (" implement a way of finding more than one map");
 	/** \todo implement a way of finding more than one map */
 	/** \todo set the map xmlDocPtr in params for later processing. */
 	return TRUE;
@@ -194,6 +204,7 @@
 	char *path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
+	ENTER (" ");
 	path = g_strdup(params->filepath);
 	if(path == NULL) {
 		qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
@@ -223,10 +234,12 @@
 	{
 		g_hash_table_destroy(valid.validation_table);
 		qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
+		LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 		return TRUE;
 	}
 	g_hash_table_destroy(valid.validation_table);
 	qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
+	LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 	return FALSE;
 }
 
Index: qsf-backend.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-backend.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/backend/qsf/qsf-backend.c -Lsrc/backend/qsf/qsf-backend.c -u -r1.1.2.2 -r1.1.2.3
--- src/backend/qsf/qsf-backend.c
+++ src/backend/qsf/qsf-backend.c
@@ -51,7 +51,7 @@
 	gchar *qsf_time_precision;
 
 	g_return_if_fail(params != NULL);
-	params->count = 1;
+	params->count = 0;
 	params->supported_types = NULL;
 	params->file_type = QSF_UNDEF;
 	params->qsf_ns = NULL;
@@ -148,16 +148,18 @@
 {
 	QofSession *qsf_session;
 	
-	first_session = qof_session_get_current_session();
 	qsf_session = qof_session_new();
 	qof_session_begin(qsf_session, path, FALSE, FALSE);
 	qof_session_load(qsf_session, NULL);
-	return qof_session_get_error(qsf_session);
+	PINFO (" path=%s", path);
+	/* FIXME: This needs to return success and set the open not merge error in file_open */
+	return ERR_QSF_OPEN_NOT_MERGE;
 }
 
 QofBackendError 
 qof_session_load_qsf_object(QofSession *first_session, const char *path)
 {
+	DEBUG (" ERR_QSF_NO_MAP");
 	return ERR_QSF_NO_MAP;
 }
 
@@ -269,6 +271,17 @@
 	qof_class_param_foreach(params->qof_obj_type, qsf_object_sequence, params);
 }
 
+static KvpValueType
+qsf_to_kvp_helper(const char *type_string)
+{
+	if(0 == safe_strcmp(QOF_TYPE_STRING, type_string)) { return KVP_TYPE_STRING; }
+	if(0 == safe_strcmp(QOF_TYPE_GUID, type_string)) { return KVP_TYPE_GUID; }
+	if(0 == safe_strcmp(QOF_TYPE_INT64, type_string)) { return KVP_TYPE_GINT64; }
+	if(0 == safe_strcmp(QOF_TYPE_DOUBLE, type_string)) { return KVP_TYPE_DOUBLE; }
+	if(0 == safe_strcmp(QOF_TYPE_NUMERIC, type_string)) { return KVP_TYPE_NUMERIC; }
+	return 0;
+}
+
 static void
 qsf_from_kvp_helper(gpointer key, gpointer value, gpointer data)
 {
@@ -323,22 +336,22 @@
 static void
 qsf_entity_foreach(QofEntity *ent, gpointer data)
 {
-	qsf_param *params;
-	GSList *param_list;
-	xmlNodePtr node, object_node;
-	xmlNsPtr ns;
-	gchar *string_buffer, qsf_guid[GUID_ENCODING_LENGTH + 1];
-	GString *buffer;
-	QofParam *qof_param;
 	QofEntityReference *reference;
-	KvpFrame 	*qsf_kvp;
+	qsf_param  *params;
+	GSList     *param_list;
+	xmlNodePtr node, object_node;
+	xmlNsPtr   ns;
+	gchar      *string_buffer, qsf_guid[GUID_ENCODING_LENGTH + 1];
+	GString    *buffer;
+	QofParam   *qof_param;
+	KvpFrame   *qsf_kvp;
 	GHashTable *kvp_hash;
-	int param_count;
-	gboolean own_guid;
-	
+	int        param_count;
+	gboolean   own_guid;
+
 	g_return_if_fail(data != NULL);
 	params = (qsf_param*)data;
-	param_count = params->count;
+	param_count = ++params->count;
 	ns = params->qsf_ns;
 	own_guid = FALSE;
 	object_node = xmlNewChild(params->book_node, params->qsf_ns, QSF_OBJECT_TAG, NULL);
@@ -501,7 +514,7 @@
 	fclose(out);
 }
 
-/** \brief QofBackend routine to load from file - needs a map.
+/* QofBackend routine to load from file - needs a map.
 */
 gboolean
 load_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
@@ -517,7 +530,7 @@
 	qsf_root = xmlDocGetRootElement(params->input_doc);
 	params->qsf_ns = qsf_root->ns;
 	params->book = book;
-	/** \todo Create a QofBook from the QSF document <b>using a QSF map</b>.
+	/* Create a QofBook from the QSF document <b>using a QSF map</b>.
 	
 	May seem strange, but I think we can do this by using the map handlers to
 	create the output_doc in memory as OUR_QSF_OBJ, then pass to the same routine!
@@ -609,43 +622,44 @@
 void
 qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
 {
-	qsf_param 		*params;
-	qsf_objects		*object_set;
-	xmlNodePtr		node;
-	QofEntityReference 	*reference;
-	QofEntity		*qsf_ent;
-	GSList			*linkedEntList;
-	QofBook			*targetBook;
-	const char		*qof_type, *parameter_name;
-	QofIdType		obj_type, reference_type;
-	struct tm		qsf_time;
-	time_t			qsf_time_t;
-	char			*tail;
+	qsf_param          *params;
+	qsf_objects        *object_set;
+	xmlNodePtr         node;
+	QofEntityReference *reference;
+	QofEntity          *qsf_ent;
+	QofBook            *targetBook;
+	const char         *qof_type, *parameter_name;
+	QofIdType          obj_type, reference_type;
+	struct tm          qsf_time;
+	time_t             qsf_time_t;
+	char               *tail;
 	/* cm_ prefix used for variables that hold the data to commit */
-	char 		    cm_sa[GUID_ENCODING_LENGTH + 1];
-	gchar 			*cm_string;
-	gnc_numeric 	cm_numeric;
-	double 			cm_double;
-	gboolean 		cm_boolean;
-	gint32 			cm_i32;
-	gint64 			cm_i64;
-	Timespec 		cm_date;
-	gchar 			*cm_char;
-	GUID 			*cm_guid;
-	const GUID      *cm_const_guid;
-//	KvpFrame 		*cm_kvp;
-//	KvpValue        *cm_value;
-	QofSetterFunc 	cm_setter;
-	void	(*string_setter)	(QofEntity*, const char*);
-	void	(*date_setter)		(QofEntity*, Timespec);
-	void	(*numeric_setter)	(QofEntity*, gnc_numeric);
-	void	(*double_setter)	(QofEntity*, double);
-	void	(*boolean_setter)	(QofEntity*, gboolean);
-	void	(*i32_setter)		(QofEntity*, gint32);
-	void	(*i64_setter)		(QofEntity*, gint64);
-	void	(*char_setter)		(QofEntity*, char*);
-//	void	(*kvp_frame_setter)	(QofEntity*, KvpFrame*);
-	
+	char           cm_sa[GUID_ENCODING_LENGTH + 1];
+	gchar          *cm_string;
+	gnc_numeric    cm_numeric;
+	double         cm_double;
+	gboolean       cm_boolean;
+	gint32         cm_i32;
+	gint64         cm_i64;
+	Timespec       cm_date;
+	char           cm_char,    (*char_getter)  (xmlNodePtr);
+	GUID           *cm_guid;
+	const GUID     *cm_const_guid;
+	KvpFrame       *cm_kvp;
+	KvpValue       *cm_value;
+	KvpValueType   cm_type;
+	QofSetterFunc  cm_setter;
+	const QofParam *cm_param;
+	void (*string_setter)    (QofEntity*, const char*);
+	void (*date_setter)      (QofEntity*, Timespec);
+	void (*numeric_setter)   (QofEntity*, gnc_numeric);
+	void (*double_setter)    (QofEntity*, double);
+	void (*boolean_setter)   (QofEntity*, gboolean);
+	void (*i32_setter)       (QofEntity*, gint32);
+	void (*i64_setter)       (QofEntity*, gint64);
+	void (*char_setter)      (QofEntity*, char);
+	void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
+
 	g_return_if_fail(data != NULL);
 	g_return_if_fail(value != NULL);
 	params = (qsf_param*)data;
@@ -654,10 +668,11 @@
 	qof_type = node->name;
 	qsf_ent = params->qsf_ent;
 	targetBook = params->book;
-	linkedEntList = NULL;
 	obj_type = xmlGetProp(node->parent, QSF_OBJECT_TYPE);
+	ENTER (" ");
 	if(0 == safe_strcasecmp(obj_type, parameter_name)) { return; }
 	cm_setter = qof_class_get_parameter_setter(obj_type, parameter_name);
+	cm_param = qof_class_get_parameter(obj_type, parameter_name);
 	object_set = params->object_set;
 	if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0)  { 
 		string_setter = (void(*)(QofEntity*, const char*))cm_setter;
@@ -681,6 +696,7 @@
 		if(TRUE != string_to_guid(xmlNodeGetContent(node), cm_guid))
 		{
 			qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
+			LEAVE (" string to guid failed for %s", xmlNodeGetContent(node));
 			return;
 		}
 		reference_type = xmlGetProp(node, QSF_OBJECT_TYPE);
@@ -736,19 +752,19 @@
 		if(boolean_setter != NULL) { boolean_setter(qsf_ent, cm_boolean); }
 	}
 		if(safe_strcmp(qof_type, QOF_TYPE_KVP) == 0) { 
-			// build the KVP frame from xml <kvp type="" path="">values</kvp>
-			// conditional on "value" and use kvp_value_new.
-			//if(0 == safe_strcmp(
-	
-/*			cm_kvp = kvp_frame_copy(cm_param->param_getfcn(rule->importEnt,cm_param));
-			kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn;
-			if(kvp_frame_setter != NULL) { kvp_frame_setter(rule->targetEnt, cm_kvp); }
-			registered_type = TRUE;*/
+			cm_type = qsf_to_kvp_helper(xmlGetProp(node, QSF_OBJECT_VALUE));
+			if(!cm_type) { return; }
+			cm_value = string_to_kvp_value(xmlNodeGetContent(node), cm_type);
+			cm_kvp = kvp_frame_copy(cm_param->param_getfcn(qsf_ent, cm_param));
+			cm_kvp = kvp_frame_set_value(cm_kvp, xmlGetProp(node, QSF_OBJECT_KVP), cm_value);
+			kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_setter;
+			if(kvp_frame_setter != NULL) { kvp_frame_setter(qsf_ent, cm_kvp); }
 		}
-
 	if(safe_strcmp(qof_type, QOF_TYPE_CHAR) == 0) { 
-		cm_char = xmlNodeGetContent(node);
-		char_setter = (void(*)(QofEntity*, char*))cm_setter;
+		char_getter = (char (*)(xmlNodePtr))xmlNodeGetContent;
+		cm_char = char_getter(node);
+		LEAVE (" cm_char=%c", cm_char);
+		char_setter = (void(*)(QofEntity*, char))cm_setter;
 		if(char_setter != NULL) { char_setter(qsf_ent, cm_char); }
 	}
 }
Index: qof_book_merge.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qof_book_merge.c,v
retrieving revision 1.2.2.3
retrieving revision 1.2.2.4
diff -Lsrc/engine/qof_book_merge.c -Lsrc/engine/qof_book_merge.c -u -r1.2.2.3 -r1.2.2.4
--- src/engine/qof_book_merge.c
+++ src/engine/qof_book_merge.c
@@ -40,10 +40,10 @@
 	a string match will still provide a better target
 	than when other types match and the string does not.
 */
-#define DEFAULT_MERGE_WEIGHT	1
-#define QOF_STRING_WEIGHT		3
-#define QOF_DATE_STRING_LENGTH	31
-#define QOF_UTC_DATE_FORMAT		"%Y-%m-%dT%H:%M:%SZ"
+#define DEFAULT_MERGE_WEIGHT    1
+#define QOF_STRING_WEIGHT       3
+#define QOF_DATE_STRING_LENGTH  31
+#define QOF_UTC_DATE_FORMAT     "%Y-%m-%dT%H:%M:%SZ"
 
 /* ================================================================ */
 /* API functions. */
@@ -97,11 +97,11 @@
 		g_slist_free(currentRule->linkedEntList);
 		g_slist_free(currentRule->mergeParam);
 		g_free(mergeData->mergeList->data);
-	if(currentRule) {
-		g_slist_free(currentRule->linkedEntList);
-		g_slist_free(currentRule->mergeParam);
-		g_free(currentRule);
-	}
+		if(currentRule) {
+			g_slist_free(currentRule->linkedEntList);
+			g_slist_free(currentRule->mergeParam);
+			g_free(currentRule);
+		}
 		mergeData->mergeList = g_list_next(mergeData->mergeList);
 	}
 	g_list_free(mergeData->mergeList);
@@ -112,9 +112,7 @@
 	g_free(mergeData);
 }
 
-/*  Q: This could be a general usage function:
-	qof_param_as_string(QofParam*, QofEntity*);
-	Useful? Worth transferring to qofclass.c?
+/*
 	Need to fix the KVP->string. How?
 
 	The QOF_TYPE_DATE output format from
@@ -130,18 +128,19 @@
 char*
 qof_book_merge_param_as_string(QofParam *qtparam, QofEntity *qtEnt)
 {
-	gchar 		*param_string, param_date[QOF_DATE_STRING_LENGTH];
-	char 		param_sa[GUID_ENCODING_LENGTH + 1];
-	KvpFrame 	*param_kvp;
-	QofType 	paramType;
+	gchar       *param_string, param_date[QOF_DATE_STRING_LENGTH];
+	char        param_sa[GUID_ENCODING_LENGTH + 1];
+	KvpFrame    *param_kvp;
+	QofType     paramType;
 	const GUID *param_guid;
-	time_t 		param_t;
-	gnc_numeric param_numeric, 	(*numeric_getter)	(QofEntity*, QofParam*);
-	Timespec 	param_ts, 		(*date_getter)		(QofEntity*, QofParam*);
-	double 		param_double, 	(*double_getter)	(QofEntity*, QofParam*);
-	gboolean 	param_boolean, 	(*boolean_getter)	(QofEntity*, QofParam*);
-	gint32 		param_i32, 		(*int32_getter)		(QofEntity*, QofParam*);
-	gint64 		param_i64, 		(*int64_getter)		(QofEntity*, QofParam*);
+	time_t      param_t;
+	gnc_numeric param_numeric,  (*numeric_getter) (QofEntity*, QofParam*);
+	Timespec    param_ts,       (*date_getter)    (QofEntity*, QofParam*);
+	double      param_double,   (*double_getter)  (QofEntity*, QofParam*);
+	gboolean    param_boolean,  (*boolean_getter) (QofEntity*, QofParam*);
+	gint32      param_i32,      (*int32_getter)   (QofEntity*, QofParam*);
+	gint64      param_i64,      (*int64_getter)   (QofEntity*, QofParam*);
+	char        param_char,     (*char_getter)    (QofEntity*, QofParam*);
 	
 	param_string = NULL;
 	paramType = qtparam->param_type;
@@ -205,7 +204,9 @@
 			return param_string;
 		}
 		if(safe_strcmp(paramType, QOF_TYPE_CHAR) == 0) { 
-			param_string = g_strdup(qtparam->param_getfcn(qtEnt,qtparam));
+			char_getter = (char (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
+			param_char = char_getter(qtEnt, qtparam);
+			param_string = g_strdup_printf("%c", param_char);
 			return param_string;
 		}
 	return NULL;
@@ -222,7 +223,7 @@
 	g_return_val_if_fail((tag != MERGE_REPORT), NULL);
 	resolved = mergeData->currentRule;
 	g_return_val_if_fail((resolved != NULL), NULL);
-	if((resolved->mergeAbsolute == TRUE)&&(tag == MERGE_DUPLICATE)) 	
+	if((resolved->mergeAbsolute == TRUE)&&(tag == MERGE_DUPLICATE))
 	{ 
 		tag = MERGE_ABSOLUTE; 
 	}
@@ -230,7 +231,7 @@
 	{
 		tag = MERGE_UPDATE; 
 	}
-	if((resolved->mergeAbsolute == FALSE)&&	(tag == MERGE_ABSOLUTE)) 	
+	if((resolved->mergeAbsolute == FALSE)&&	(tag == MERGE_ABSOLUTE))
 	{ 
 		tag = MERGE_DUPLICATE; 
 	}
@@ -238,7 +239,7 @@
 	{ 
 		tag = MERGE_NEW; 
 	}
-	if(resolved->updated == FALSE) { resolved->mergeResult = tag;	}
+	if(resolved->updated == FALSE) { resolved->mergeResult = tag; }
 	resolved->updated = TRUE;
 	if(tag >= MERGE_INVALID) { 
 		mergeData->abort = TRUE;
@@ -350,21 +351,22 @@
 qof_book_mergeCompare( qof_book_mergeData *mergeData ) 
 {
 	qof_book_mergeRule *currentRule;
-	gchar 			*stringImport, *stringTarget, *charImport, *charTarget;
-	QofEntity	 	*mergeEnt, *targetEnt, *referenceEnt;
-	const GUID 		*guidImport, *guidTarget;
-	QofParam 		*qtparam;
-	KvpFrame 		*kvpImport, *kvpTarget;
-	QofIdType 		mergeParamName;
-	QofType 		mergeType;
-	GSList 			*paramList;
-	gboolean	 	absolute, mergeError, knowntype, mergeMatch, booleanImport, booleanTarget,
-													(*boolean_getter)	(QofEntity*, QofParam*);
-	Timespec 		tsImport, tsTarget, 			(*date_getter)		(QofEntity*, QofParam*);
-	gnc_numeric 	numericImport, numericTarget, 	(*numeric_getter)	(QofEntity*, QofParam*);
-	double 			doubleImport, doubleTarget, 	(*double_getter)	(QofEntity*, QofParam*);
-	gint32 			i32Import, i32Target, 			(*int32_getter)		(QofEntity*, QofParam*);
-	gint64 			i64Import, i64Target, 			(*int64_getter)		(QofEntity*, QofParam*);
+
+	gchar      *stringImport, *stringTarget, *charImport, *charTarget;
+	QofEntity  *mergeEnt, *targetEnt, *referenceEnt;
+	const GUID *guidImport, *guidTarget;
+	QofParam   *qtparam;
+	KvpFrame   *kvpImport, *kvpTarget;
+	QofIdType  mergeParamName;
+	QofType    mergeType;
+	GSList    *paramList;
+	gboolean  absolute, mergeError, knowntype, mergeMatch, booleanImport, booleanTarget,
+                                                 (*boolean_getter) (QofEntity*, QofParam*);
+	Timespec      tsImport, tsTarget,            (*date_getter)    (QofEntity*, QofParam*);
+	gnc_numeric   numericImport, numericTarget,  (*numeric_getter) (QofEntity*, QofParam*);
+	double        doubleImport, doubleTarget,    (*double_getter)  (QofEntity*, QofParam*);
+	gint32        i32Import, i32Target,          (*int32_getter)   (QofEntity*, QofParam*);
+	gint64        i64Import, i64Target,          (*int64_getter)   (QofEntity*, QofParam*);
 
 	g_return_val_if_fail((mergeData != NULL), -1);
 	currentRule = mergeData->currentRule;
@@ -456,7 +458,7 @@
 			if(booleanImport != FALSE && booleanImport != TRUE) { booleanImport = FALSE; }
 			if(booleanTarget != FALSE && booleanTarget != TRUE) { booleanTarget = FALSE; }
 			if(booleanImport == booleanTarget) { mergeMatch = TRUE; }
-			currentRule	= qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
+			currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
 			knowntype= TRUE;
 		}
 		if(safe_strcmp(mergeType, QOF_TYPE_KVP) == 0) { 
@@ -481,13 +483,13 @@
 			referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
 			if((referenceEnt != NULL)
 				&&(safe_strcmp(referenceEnt->e_type, mergeType) == 0)) {
-				currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, referenceEnt);
+					currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, referenceEnt);
 					/* Compare the mergeEnt reference with targetEnt reference */
 					if(referenceEnt == qtparam->param_getfcn(targetEnt, qtparam)) { mergeMatch = TRUE; }
 					currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
 			}
 		}
-	paramList = g_slist_next(paramList);
+		paramList = g_slist_next(paramList);
 	}
 	mergeData->currentRule = currentRule;
 	g_free(kvpImport);
@@ -530,7 +532,7 @@
 void qof_book_mergeCommitForeachCB(gpointer rule, gpointer arg)
 {
 	struct qof_book_mergeRuleIterate *iter;
-	
+
 	g_return_if_fail(arg != NULL);
 	iter = (struct qof_book_mergeRuleIterate*)arg;
 	g_return_if_fail(iter->data != NULL);
@@ -716,7 +718,7 @@
 	g_return_if_fail(user_data != NULL);
 	mergeData = (qof_book_mergeData*)user_data;
 	g_return_if_fail(targetEnt != NULL);
-		mergeData->targetList = g_slist_prepend(mergeData->targetList,targetEnt);
+	mergeData->targetList = g_slist_prepend(mergeData->targetList,targetEnt);
 }
 
 void 
@@ -811,34 +813,35 @@
 						qof_book_mergeRule *rule, 
 						guint remainder) 
 { 
-	QofInstance 	*inst;
-	gboolean		registered_type;
-	QofEntity 		*referenceEnt;
-	GSList 			*linkage;
+	QofInstance *inst;
+	gboolean    registered_type;
+	QofEntity   *referenceEnt;
+	GSList      *linkage;
 	/* cm_ prefix used for variables that hold the data to commit */
-	QofParam 		*cm_param;
-	gchar 			*cm_string, *cm_char;
-	const GUID 		*cm_guid;
-	KvpFrame 		*cm_kvp;
+	QofParam    *cm_param;
+	gchar       *cm_string;
+	const GUID  *cm_guid;
+	KvpFrame    *cm_kvp;
 	/* function pointers and variables for parameter getters that don't use pointers normally */
-	gnc_numeric 	cm_numeric, (*numeric_getter)	(QofEntity*, QofParam*);
-	double 			cm_double, 	(*double_getter)	(QofEntity*, QofParam*);
-	gboolean 		cm_boolean, (*boolean_getter)	(QofEntity*, QofParam*);
-	gint32 			cm_i32, 	(*int32_getter)		(QofEntity*, QofParam*);
-	gint64 			cm_i64, 	(*int64_getter)		(QofEntity*, QofParam*);
-	Timespec 		cm_date, 	(*date_getter)		(QofEntity*, QofParam*);
+	gnc_numeric  cm_numeric, (*numeric_getter)  (QofEntity*, QofParam*);
+	double       cm_double,  (*double_getter)   (QofEntity*, QofParam*);
+	gboolean     cm_boolean, (*boolean_getter)  (QofEntity*, QofParam*);
+	gint32       cm_i32,     (*int32_getter)    (QofEntity*, QofParam*);
+	gint64       cm_i64,     (*int64_getter)    (QofEntity*, QofParam*);
+	Timespec     cm_date,    (*date_getter)     (QofEntity*, QofParam*);
+	char         cm_char,    (*char_getter)     (QofEntity*, QofParam*);
 	/* function pointers to the parameter setters */
-	void	(*string_setter)	(QofEntity*, const char*);
-	void	(*date_setter)		(QofEntity*, Timespec);
-	void	(*numeric_setter)	(QofEntity*, gnc_numeric);
-	void	(*guid_setter)		(QofEntity*, const GUID*);
-	void	(*double_setter)	(QofEntity*, double);
-	void	(*boolean_setter)	(QofEntity*, gboolean);
-	void	(*i32_setter)		(QofEntity*, gint32);
-	void	(*i64_setter)		(QofEntity*, gint64);
-	void	(*char_setter)		(QofEntity*, char*);
-	void	(*kvp_frame_setter)	(QofEntity*, KvpFrame*);
-	void	(*reference_setter)	(QofEntity*, QofEntity*);
+	void (*string_setter)    (QofEntity*, const char*);
+	void (*date_setter)      (QofEntity*, Timespec);
+	void (*numeric_setter)   (QofEntity*, gnc_numeric);
+	void (*guid_setter)      (QofEntity*, const GUID*);
+	void (*double_setter)    (QofEntity*, double);
+	void (*boolean_setter)   (QofEntity*, gboolean);
+	void (*i32_setter)       (QofEntity*, gint32);
+	void (*i64_setter)       (QofEntity*, gint64);
+	void (*char_setter)      (QofEntity*, char);
+	void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
+	void (*reference_setter) (QofEntity*, QofEntity*);
 
 	g_return_if_fail(rule != NULL);
 	g_return_if_fail(mergeData != NULL);
@@ -859,13 +862,13 @@
 	*/
 	while(rule->mergeParam != NULL) {
 		registered_type = FALSE;
-		g_return_if_fail(rule->mergeParam->data);		
+		g_return_if_fail(rule->mergeParam->data);
 		cm_param = rule->mergeParam->data;
 		rule->mergeType = cm_param->param_type;
 		if(safe_strcmp(rule->mergeType, QOF_TYPE_STRING) == 0)  { 
 			cm_string = cm_param->param_getfcn(rule->importEnt, cm_param);
 			string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
-			if(string_setter != NULL) {	string_setter(rule->targetEnt, cm_string); }
+			if(string_setter != NULL) { string_setter(rule->targetEnt, cm_string); }
 			registered_type = TRUE;
 		}
 		if(safe_strcmp(rule->mergeType, QOF_TYPE_DATE) == 0) { 
@@ -924,8 +927,9 @@
 			registered_type = TRUE;
 		}
 		if(safe_strcmp(rule->mergeType, QOF_TYPE_CHAR) == 0) { 
-			cm_char = cm_param->param_getfcn(rule->importEnt,cm_param);
-			char_setter = (void(*)(QofEntity*, char*))cm_param->param_setfcn;
+			char_getter = (char (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
+			cm_char = char_getter(rule->importEnt,cm_param);
+			char_setter = (void(*)(QofEntity*, char))cm_param->param_setfcn;
 			if(char_setter != NULL) { char_setter(rule->targetEnt, cm_char); }
 			registered_type = TRUE;
 		}
Index: qofsession.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.c,v
retrieving revision 1.2.4.9
retrieving revision 1.2.4.10
diff -Lsrc/engine/qofsession.c -Lsrc/engine/qofsession.c -u -r1.2.4.9 -r1.2.4.10
--- src/engine/qofsession.c
+++ src/engine/qofsession.c
@@ -333,7 +333,7 @@
 	qecd = (QofEntityCopyData*)data;
 	g_return_if_fail(qecd != NULL);
 	if((param->param_getfcn != NULL)&&(param->param_setfcn != NULL)) {
-			qecd->param_list = g_slist_append(qecd->param_list, param);
+			qecd->param_list = g_slist_prepend(qecd->param_list, param);
 	}
 	if(g_slist_length(qecd->param_list) == 0) { qecd->error = TRUE; }
 }
@@ -341,47 +341,48 @@
 static void
 qof_entity_foreach_copy(gpointer data, gpointer user_data)
 {
-	QofEntity 		*importEnt, *targetEnt, *referenceEnt;
-	QofEntityCopyData 	*context;
-	QofEntityReference  *reference;
-	gboolean		registered_type;
+	QofEntity          *importEnt, *targetEnt, *referenceEnt;
+	QofEntityCopyData  *context;
+	QofEntityReference *reference;
+	gboolean           registered_type;
 	/* cm_ prefix used for variables that hold the data to commit */
-	QofParam 		*cm_param;
-	gchar 			*cm_string, *cm_char;
-	const GUID 		*cm_guid;
-	GUID            *cm_src_guid;
-	KvpFrame 		*cm_kvp;
-	char 		    cm_sa[GUID_ENCODING_LENGTH + 1];
+	QofParam     *cm_param;
+	gchar        *cm_string, *cm_char;
+	const GUID   *cm_guid;
+	GUID         *cm_src_guid;
+	KvpFrame     *cm_kvp;
+	char         cm_sa[GUID_ENCODING_LENGTH + 1];
 	/* function pointers and variables for parameter getters that don't use pointers normally */
-	gnc_numeric 	cm_numeric, (*numeric_getter)	(QofEntity*, QofParam*);
-	double 			cm_double, 	(*double_getter)	(QofEntity*, QofParam*);
-	gboolean 		cm_boolean, (*boolean_getter)	(QofEntity*, QofParam*);
-	gint32 			cm_i32, 	(*int32_getter)		(QofEntity*, QofParam*);
-	gint64 			cm_i64, 	(*int64_getter)		(QofEntity*, QofParam*);
-	Timespec 		cm_date, 	(*date_getter)		(QofEntity*, QofParam*);
+	gnc_numeric cm_numeric, (*numeric_getter) (QofEntity*, QofParam*);
+	double      cm_double,  (*double_getter)  (QofEntity*, QofParam*);
+	gboolean    cm_boolean, (*boolean_getter) (QofEntity*, QofParam*);
+	gint32      cm_i32,     (*int32_getter)   (QofEntity*, QofParam*);
+	gint64      cm_i64,     (*int64_getter)   (QofEntity*, QofParam*);
+	Timespec    cm_date,    (*date_getter)    (QofEntity*, QofParam*);
 	/* function pointers to the parameter setters */
-	void	(*string_setter)	(QofEntity*, const char*);
-	void	(*date_setter)		(QofEntity*, Timespec);
-	void	(*numeric_setter)	(QofEntity*, gnc_numeric);
-	void	(*guid_setter)		(QofEntity*, const GUID*);
-	void	(*double_setter)	(QofEntity*, double);
-	void	(*boolean_setter)	(QofEntity*, gboolean);
-	void	(*i32_setter)		(QofEntity*, gint32);
-	void	(*i64_setter)		(QofEntity*, gint64);
-	void	(*char_setter)		(QofEntity*, char*);
-	void	(*kvp_frame_setter)	(QofEntity*, KvpFrame*);
+	void (*string_setter)    (QofEntity*, const char*);
+	void (*date_setter)      (QofEntity*, Timespec);
+	void (*numeric_setter)   (QofEntity*, gnc_numeric);
+	void (*guid_setter)      (QofEntity*, const GUID*);
+	void (*double_setter)    (QofEntity*, double);
+	void (*boolean_setter)   (QofEntity*, gboolean);
+	void (*i32_setter)       (QofEntity*, gint32);
+	void (*i64_setter)       (QofEntity*, gint64);
+	void (*char_setter)      (QofEntity*, char*);
+	void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
 	
-	g_return_if_fail(data != NULL);
 	g_return_if_fail(user_data != NULL);
 	context = (QofEntityCopyData*) user_data;
 	importEnt = context->from;
 	targetEnt = context->to;
 	registered_type = FALSE;
 	cm_param = (QofParam*) data;
+	g_return_if_fail(cm_param != NULL);
+	ENTER (" cm_param->param_type=%s\tname=%s", cm_param->param_type, cm_param->param_name);
 	if(safe_strcmp(cm_param->param_type, QOF_TYPE_STRING) == 0)  { 
 		cm_string = g_strdup(cm_param->param_getfcn(importEnt, cm_param));
 		string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
-		if(string_setter != NULL) {	string_setter(targetEnt, cm_string); }
+		if(string_setter != NULL) { string_setter(targetEnt, cm_string); }
 		registered_type = TRUE;
 	}
 	if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) { 
@@ -446,6 +447,7 @@
 		registered_type = TRUE;
 	}
 	if(registered_type == FALSE) {
+		referenceEnt = NULL;
 		referenceEnt = cm_param->param_getfcn(importEnt, cm_param);
 		reference = g_new(QofEntityReference, 1);
 		reference->type = g_strdup(referenceEnt->e_type);
@@ -478,7 +480,7 @@
 	coll = qof_book_get_collection(targetBook, type);
 	copy = qof_collection_lookup_entity(coll, g);
 	if(copy) { return TRUE; }
-	return FALSE;	
+	return FALSE;
 }
 
 static void
@@ -500,6 +502,7 @@
 	qecd->to = &inst->entity;
 	g = qof_entity_get_guid(original);
 	qof_entity_set_guid(qecd->to, g);
+	if(qecd->param_list != NULL) { g_slist_free(qecd->param_list); }
 	qof_class_param_foreach(original->e_type, qof_entity_param_cb, qecd);
 	g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
 	qof_book_set_data(book, ENTITYREFERENCE, qecd->referenceTable);
@@ -540,6 +543,7 @@
 	qecd->from = original;
 	g = qof_entity_get_guid(original);
 	qof_entity_set_guid(qecd->to, g);
+	if(qecd->param_list != NULL) { g_slist_free(qecd->param_list); }
 	qof_class_param_foreach(original->e_type, qof_entity_param_cb, qecd);
 	g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
 	qof_book_set_data(book, ENTITYREFERENCE, qecd->referenceTable);
@@ -568,6 +572,7 @@
 	g_slist_foreach(qecd.param_list, qof_entity_foreach_copy, &qecd);
 	qof_book_set_data(book, ENTITYREFERENCE, qecd.referenceTable);
 	qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
+	g_slist_free(qecd.param_list);
 	return TRUE;
 }
 
@@ -604,6 +609,7 @@
 	qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd);
 	if(qecd.error == TRUE) return FALSE;
 	qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd);
+	if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); }
 	return TRUE;
 }
 
@@ -654,43 +660,43 @@
 static void
 qof_session_load_backend(QofSession * session, char * backend_name)
 {
-  GList *node;
-  QofBook *book;
+	GList     *node;
+	QofBook   *book;
 	GNCModule  mod;
 	GSList    *p;
 	char       *mod_name, *access_method, *msg;
-  QofBackend    *(* be_new_func)(void);
+	QofBackend *(* be_new_func)(void);
 	QofBackendProvider *prov;
 
 	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. 
+	/* 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) 
-  {
-    be_new_func = gnc_module_lookup(mod, "gnc_backend_new");
-    if(be_new_func) 
-    {
-      session->backend = be_new_func();
-      for (node=session->books; node; node=node->next)
-      {
-         book = node->data;
-         qof_book_set_backend (book, session->backend);
-      }
-    }
+	*    over at some point.
+	*/
+	mod = gnc_module_load(mod_name, 0);
+	if (mod) 
+	{
+		be_new_func = gnc_module_lookup(mod, "gnc_backend_new");
+		if(be_new_func) 
+		{
+			session->backend = be_new_func();
+			for (node=session->books; node; node=node->next)
+			{
+				book = node->data;
+				qof_book_set_backend (book, session->backend);
+			}
+		}
 		else { qof_session_int_backend_load_error(session, " can't find backend_new ",""); }
-  }
-  else
-  {
+	}
+	else
+	{
 	/* QSF is built for the QOF version, use that if no module is found.
 	  This allows the GnuCash version to be called with an access method,
 	  as it would be in QOF, instead of a resolved module name.
@@ -704,20 +710,20 @@
 		{
 			if (NULL == prov->backend_new) continue;
 			/* Use the providers creation callback */
-        	session->backend = (*(prov->backend_new))();
+			session->backend = (*(prov->backend_new))();
 			session->backend->provider = prov;
 			/* Tell the books about the backend that they'll be using. */
 			for (node=session->books; node; node=node->next)
-	{
+			{
 				book = node->data;
 				qof_book_set_backend (book, session->backend);
 			}
-		return;
-	}
+			return;
+		}
 	}
 	msg = g_strdup_printf("failed to load '%s' backend", backend_name);
 	qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
-	}
+  }
   g_free(mod_name);
   LEAVE (" ");
 }
@@ -731,7 +737,7 @@
 	GList *node;
 	QofBackendProvider *prov;
 	QofBook *book;
-
+	
 	ENTER (" ");
 	/* If the provider list is null, try to register the 'well-known'
 	 *  backends. Right now, there's only two. */
@@ -752,7 +758,7 @@
 		{
 			if (NULL == prov->backend_new) continue;
 			/* Use the providers creation callback */
-      	session->backend = (*(prov->backend_new))();
+      	    session->backend = (*(prov->backend_new))();
 			session->backend->provider = prov;
 			/* Tell the books about the backend that they'll be using. */
 			for (node=session->books; node; node=node->next)
@@ -877,7 +883,7 @@
           g_free(session->book_id);
           session->book_id = NULL;
           qof_session_push_error (session, err, msg);
-          LEAVE("backend error %d", err);
+          LEAVE(" backend error %d %s", err, msg);
           return;
       }
       if (msg != NULL) 
@@ -898,83 +904,83 @@
                   QofPercentageFunc percentage_func)
 {
 	QofBook *newbook, *ob;
-  QofBookList *oldbooks, *node;
-  QofBackend *be;
-  QofBackendError err;
-
-  if (!session) return;
-  if (!session->book_id) return;
-
-  ENTER ("sess=%p book_id=%s", session, session->book_id
-         ? session->book_id : "(null)");
-
-  /* At this point, we should are supposed to have a valid book 
-   * id and a lock on the file. */
-
-  oldbooks = session->books;
-
-  /* XXX why are we creating a book here? I think the books
-   * need to be handled by the backend ... especially since 
-   * the backend may need to load multiple books ... XXX. FIXME.
-   */
-  newbook = qof_book_new();
-  session->books = g_list_append (NULL, newbook);
-  PINFO ("new book=%p", newbook);
-
-  qof_session_clear_error (session);
-
-  /* This code should be sufficient to initialize *any* backend,
-   * whether http, postgres, or anything else that might come along.
-   * Basically, the idea is that by now, a backend has already been
-   * created & set up.  At this point, we only need to get the
-   * top-level account group out of the backend, and that is a
-   * generic, backend-independent operation.
-   */
-  be = session->backend;
-  qof_book_set_backend(newbook, be);
-
-  /* Starting the session should result in a bunch of accounts
-   * and currencies being downloaded, but probably no transactions;
-   * The GUI will need to do a query for that.
-   */
-  if (be)
-  {
-      be->percentage = percentage_func;
-
-      if (be->load) 
-      {
-          be->load (be, newbook);
-          qof_session_push_error (session, qof_backend_get_error(be), NULL);
-      }
-  }
+	QofBookList *oldbooks, *node;
+	QofBackend *be;
+	QofBackendError err;
+	
+	if (!session) return;
+	if (!session->book_id) return;
+	
+	ENTER ("sess=%p book_id=%s", session, session->book_id
+		 ? session->book_id : "(null)");
+	
+	/* At this point, we should are supposed to have a valid book 
+	* id and a lock on the file. */
+	
+	oldbooks = session->books;
+	
+	/* XXX why are we creating a book here? I think the books
+	* need to be handled by the backend ... especially since 
+	* the backend may need to load multiple books ... XXX. FIXME.
+	*/
+	newbook = qof_book_new();
+	session->books = g_list_append (NULL, newbook);
+	PINFO ("new book=%p", newbook);
+	
+	qof_session_clear_error (session);
+	
+	/* This code should be sufficient to initialize *any* backend,
+	* whether http, postgres, or anything else that might come along.
+	* Basically, the idea is that by now, a backend has already been
+	* created & set up.  At this point, we only need to get the
+	* top-level account group out of the backend, and that is a
+	* generic, backend-independent operation.
+	*/
+	be = session->backend;
+	qof_book_set_backend(newbook, be);
+	
+	/* Starting the session should result in a bunch of accounts
+	* and currencies being downloaded, but probably no transactions;
+	* The GUI will need to do a query for that.
+	*/
+	if (be)
+	{
+		be->percentage = percentage_func;
+		
+		if (be->load) 
+		{
+			be->load (be, newbook);
+			qof_session_push_error (session, qof_backend_get_error(be), NULL);
+		}
+	}
 
-  /* XXX if the load fails, then we try to restore the old set of books;
-   * however, we don't undo the session id (the URL).  Thus if the 
-   * user attempts to save after a failed load, they weill be trying to 
-   * save to some bogus URL.   This is wrong. XXX  FIXME.
-   */
-  err = qof_session_get_error(session);
-  if ((err != ERR_BACKEND_NO_ERR) &&
-      (err != ERR_FILEIO_FILE_TOO_OLD) &&
-      (err != ERR_SQL_DB_TOO_OLD))
-  {
-      /* Something broke, put back the old stuff */
-      qof_book_set_backend (newbook, NULL);
-      qof_book_destroy (newbook);
-      g_list_free (session->books);
-      session->books = oldbooks;
-      LEAVE("error from backend %d", qof_session_get_error(session));
-      return;
-  }
+	/* XXX if the load fails, then we try to restore the old set of books;
+	* however, we don't undo the session id (the URL).  Thus if the 
+	* user attempts to save after a failed load, they weill be trying to 
+	* save to some bogus URL.   This is wrong. XXX  FIXME.
+	*/
+	err = qof_session_get_error(session);
+	if ((err != ERR_BACKEND_NO_ERR) &&
+		(err != ERR_FILEIO_FILE_TOO_OLD) &&
+		(err != ERR_SQL_DB_TOO_OLD))
+	{
+		/* Something broke, put back the old stuff */
+		qof_book_set_backend (newbook, NULL);
+		qof_book_destroy (newbook);
+		g_list_free (session->books);
+		session->books = oldbooks;
+		LEAVE("error from backend %d", qof_session_get_error(session));
+		return;
+	}
 
-  for (node=oldbooks; node; node=node->next)
-  {
+	for (node=oldbooks; node; node=node->next)
+	{
 		ob = node->data;
-     qof_book_set_backend (ob, NULL);
-     qof_book_destroy (ob);
-  }
-
-  LEAVE ("sess = %p, book_id=%s", session, session->book_id
+		qof_book_set_backend (ob, NULL);
+		qof_book_destroy (ob);
+	}
+	
+	LEAVE ("sess = %p, book_id=%s", session, session->book_id
          ? session->book_id : "(null)");
 }
 
@@ -1008,18 +1014,18 @@
 qof_session_save (QofSession *session,
                   QofPercentageFunc percentage_func)
 {
-  GList *node;
-  QofBackend *be;
+	GList *node;
+	QofBackend *be;
 	gboolean partial, change_backend;
 	QofBackendProvider *prov;
 	GSList *p;
 	QofBook *book, *abook;
 	int err;
 	char *msg, *book_id;
-
-  if (!session) return;
-  ENTER ("sess=%p book_id=%s", 
-         session, session->book_id ? session->book_id : "(null)");
+	
+	if (!session) return;
+	ENTER ("sess=%p book_id=%s", 
+		 session, session->book_id ? session->book_id : "(null)");
 	/* Partial book handling. */
 	book = qof_session_get_book(session);
 	partial = (gboolean)qof_book_get_data(book, PARTIAL_QOFBOOK);
@@ -1045,7 +1051,7 @@
 		qof_session_destroy_backend(session);
 		if (NULL == provider_list)
 		{
-			load_backend_library ("libqsf-backend-file.so", "qsf_provider_init" );
+			load_backend_library ("libqof-backend-qsf.so", "qsf_provider_init" );
 		}
 		p = g_slist_copy(provider_list);
 		while(p != NULL)
@@ -1104,43 +1110,43 @@
 			return;
 		}
 	}
-	g_free(book_id);
-  /* If there is a backend, and the backend is reachable
-   * (i.e. we can communicate with it), then synchronize with 
-   * the backend.  If we cannot contact the backend (e.g.
-   * because we've gone offline, the network has crashed, etc.)
-   * then give the user the option to save to the local disk. 
-   *
-   * hack alert -- FIXME -- XXX the code below no longer
-   * does what the words above say.  This needs fixing.
-   */
-  be = session->backend;
-  if (be)
-  {
-    for (node = session->books; node; node=node->next)
-    {
+	/* If there is a backend, and the backend is reachable
+	* (i.e. we can communicate with it), then synchronize with 
+	* the backend.  If we cannot contact the backend (e.g.
+	* because we've gone offline, the network has crashed, etc.)
+	* then give the user the option to save to the local disk. 
+	*
+	* hack alert -- FIXME -- XXX the code below no longer
+	* does what the words above say.  This needs fixing.
+	*/
+	be = session->backend;
+	if (be)
+	{
+		for (node = session->books; node; node=node->next)
+		{
 			abook = node->data;
-      /* if invoked as SaveAs(), then backend not yet set */
-      qof_book_set_backend (abook, be);
-      be->percentage = percentage_func;
-      if (be->sync)
-      {
-        (be->sync)(be, abook);
-        if (save_error_handler(be, session)) return;
-      }
-    }
-    /* If we got to here, then the backend saved everything 
-     * just fine, and we are done. So return. */
-    qof_session_clear_error (session);
-    LEAVE("Success");
-    return;
-  } 
+			/* if invoked as SaveAs(), then backend not yet set */
+			qof_book_set_backend (abook, be);
+			be->percentage = percentage_func;
+			if (be->sync)
+			{
+				(be->sync)(be, abook);
+				if (save_error_handler(be, session)) return;
+			}
+		}
+		/* If we got to here, then the backend saved everything 
+		* just fine, and we are done. So return. */
+		/* Return the book_id to previous value. */
+		qof_session_clear_error (session);
+		LEAVE("Success");
+		return;
+	}
 	else
 	{
 		msg = g_strdup_printf("failed to load backend");
 		qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
 	}
-  LEAVE("error -- No backend!");
+	LEAVE("error -- No backend!");
 }
 
 /* ====================================================================== */
Index: qofbackend.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofbackend.h,v
retrieving revision 1.3.4.4
retrieving revision 1.3.4.5
diff -Lsrc/engine/qofbackend.h -Lsrc/engine/qofbackend.h -u -r1.3.4.4 -r1.3.4.5
--- src/engine/qofbackend.h
+++ src/engine/qofbackend.h
@@ -65,7 +65,7 @@
   ERR_BACKEND_MOD_DESTROY,  /**< commit of object update failed because 
                                another user has deleted the object */
   ERR_BACKEND_MISC,         /**< undetermined error */
-  
+
   /* QSF add-ons */
   ERR_QSF_INVALID_OBJ, 		/**< The QSF object failed to validate against the QSF object schema */
   ERR_QSF_INVALID_MAP, 		/**< The QSF map failed to validate against the QSF map schema */
@@ -87,11 +87,16 @@
   */
   ERR_QSF_MAP_NOT_OBJ,		/**< Selected file is a QSF map and cannot be opened as a QSF object */
   ERR_QSF_OVERFLOW,			/**< EOVERFLOW - generated by strtol or strtoll.
-  
+
   When converting XML strings into numbers, an overflow has been detected. The XML file
   contains invalid data in a field that is meant to hold a signed long integer or signed long long
   integer.
   */
+  ERR_QSF_OPEN_NOT_MERGE,	/** QSF files cannot be opened alone. The data must be merged.
+
+  This error is more of a warning that can be ignored by any routine
+  that uses qof_book_merge on the new session.
+  */
   /* fileio errors */
   ERR_FILEIO_FILE_BAD_READ = 1000,  /**< read failed or file prematurely truncated */
   ERR_FILEIO_FILE_EMPTY,     /**< file exists, is readable, but is empty */
Index: qofsession.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.h,v
retrieving revision 1.2.4.4
retrieving revision 1.2.4.5
diff -Lsrc/engine/qofsession.h -Lsrc/engine/qofsession.h -u -r1.2.4.4 -r1.2.4.5
--- src/engine/qofsession.h
+++ src/engine/qofsession.h
@@ -272,15 +272,6 @@
 
 */
 
-/** Used as the key value for the QofBook data hash.
-
-Retrieved later by QSF (or any other suitable backend) to
-rebuild the references from the QofEntityReference struct
-that contains the QofIdType and GUID of the referenced entity
-of the original QofBook.
-*/
-#define ENTITYREFERENCE "QofEntityReference"
-
 /** \brief Copy a single QofEntity to another session
  
 Checks first that no entity in the session book contains
@@ -368,6 +359,15 @@
 	GUID      *guid;
 }QofEntityReference;
 
+/** Used as the key value for the QofBook data hash.
+ *
+ * Retrieved later by QSF (or any other suitable backend) to
+ * rebuild the references from the QofEntityReference struct
+ * that contains the QofIdType and GUID of the referenced entity
+ * of the original QofBook.
+ * */
+#define ENTITYREFERENCE "QofEntityReference"
+
 /** \brief Flag indicating a partial QofBook.
 
 When set in the book data with a gboolean value of TRUE,
@@ -399,7 +399,7 @@
 
 /** @name Event Handling
 
- @{ */
+  @{ */
 /** The qof_session_events_pending() method will return TRUE if the backend
  *    has pending events which must be processed to bring the engine
  *    up to date with the backend.
Index: gnc-backend-file.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/gnc-backend-file.c,v
retrieving revision 1.23.4.5
retrieving revision 1.23.4.6
diff -Lsrc/backend/file/gnc-backend-file.c -Lsrc/backend/file/gnc-backend-file.c -u -r1.23.4.5 -r1.23.4.6
--- src/backend/file/gnc-backend-file.c
+++ src/backend/file/gnc-backend-file.c
@@ -391,7 +391,7 @@
 static QofBookFileType
 gnc_file_be_determine_file_type(const char *path)
 {
-    if(gnc_is_xml_data_file_v2(path)) {
+	if(gnc_is_xml_data_file_v2(path)) {
         return GNC_BOOK_XML2_FILE;
     } else if(gnc_is_xml_data_file(path)) {
         return GNC_BOOK_XML1_FILE;
@@ -399,10 +399,10 @@
         return GNC_BOOK_XML2_FILE;
     } else if(is_our_qsf_object(path)) {
         return QSF_GNC_OBJECT;  /**< QSF object file using only GnuCash QOF objects */
-	} else if(is_qsf_object(path)) {
-		return QSF_OBJECT;  	/**< QSF object file that needs a QSF map */
-	} else if(is_qsf_map(path)) {
-		return QSF_MAP;  		/**< QSF map file */
+    } else if(is_qsf_object(path)) {
+		return QSF_OBJECT;   /**< QSF object file that needs a QSF map */
+    } else if(is_qsf_map(path)) {
+		return QSF_MAP;      /**< QSF map file */
     } else {
         return GNC_BOOK_BIN_FILE;
     }
@@ -832,17 +832,20 @@
         if (FALSE == rc) error = ERR_FILEIO_PARSE_ERROR;
         break;
 
-	case QSF_GNC_OBJECT:
+    case QSF_GNC_OBJECT:
 		error = qof_session_load_our_qsf_object(qof_session_get_current_session(), be->fullpath);
+		PINFO (" QSF_GNC_OBJECT error=%d", error);
 		break;
 
-	case QSF_OBJECT:
+    case QSF_OBJECT:
 		/* a QSF object file needs a QSF map to convert external objects */
 		error = qof_session_load_qsf_object(qof_session_get_current_session(), be->fullpath);
+		PINFO (" QSF_OBJECT error=%d", error);
 		break;
 
-	case QSF_MAP:
+    case QSF_MAP:
 		error = ERR_QSF_MAP_NOT_OBJ;
+		PINFO (" QSF_MAP error=%d", error);
 		break;
 
     case GNC_BOOK_BIN_FILE:
Index: druid-merge.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/druid-merge.h,v
retrieving revision 1.2.2.1
retrieving revision 1.2.2.2
diff -Lsrc/gnome/druid-merge.h -Lsrc/gnome/druid-merge.h -u -r1.2.2.1 -r1.2.2.2
--- src/gnome/druid-merge.h
+++ src/gnome/druid-merge.h
@@ -23,6 +23,8 @@
 
 #ifndef DRUID_MERGE_H
 #define DRUID_MERGE_H
+#include "qofsession.h"
+
 /** @addtogroup GUI
 	@{ */
 /** @addtogroup NewHierarchy Merging a new account tree into an existing file
@@ -73,6 +75,9 @@
 */
 
 void gnc_ui_qof_book_merge_druid (void);
+
+void gnc_ui_qsf_import_merge_druid(QofSession *original, QofSession *import);
+
 GtkWidget* qof_book_merge_running (void);
 
 /** \brief 	gncCommodity is not QOF enabled, need to set a default commodity before the merge */
Index: window-main.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/window-main.c,v
retrieving revision 1.180.4.14
retrieving revision 1.180.4.15
diff -Lsrc/gnome/window-main.c -Lsrc/gnome/window-main.c -u -r1.180.4.14 -r1.180.4.15
--- src/gnome/window-main.c
+++ src/gnome/window-main.c
@@ -44,7 +44,6 @@
 #include "dialog-utils.h"
 #include "druid-acct-period.h"
 #include "druid-loan.h"
-#include "druid-merge.h"
 #include "gfec.h"
 #include "global-options.h"
 #include "gnc-engine.h"
@@ -67,6 +66,7 @@
 #include "messages.h"
 #include "guile-mappings.h"
 
+
 /* static short module = MOD_GUI; */
 
 #if INCLUDE_GNOME1_BASED_ROUTINES
@@ -766,12 +766,6 @@
 }
 
 static void
-gnc_main_window_file_hierarchy_merge_cb(GtkWidget *w, gpointer data)
-{
-	gnc_ui_qof_book_merge_druid();
-}
-
-static void
 gnc_main_window_file_new_account_tree_cb(GtkWidget * w, gpointer data)
 {
 }
@@ -815,13 +809,6 @@
       gnc_main_window_file_new_account_tree_cb, NULL, NULL, 
       GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL
     },    
-	{
-		GNOME_APP_UI_ITEM,
-		N_("Add New Account Hierarchy"),
-		N_("Extend the current book by merging with new account type categories"),
-		gnc_main_window_file_hierarchy_merge_cb, NULL, NULL,
-		GNOME_APP_PIXMAP_NONE, NULL, 0, 0, NULL
-	},
     GNOMEUIINFO_SEPARATOR,
     GNOMEUIINFO_MENU_OPEN_ITEM(gnc_main_window_file_open_cb, NULL),
     {
Index: gnc-plugin-page-account-tree.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Attic/gnc-plugin-page-account-tree.c,v
retrieving revision 1.1.2.34
retrieving revision 1.1.2.35
diff -Lsrc/gnome/gnc-plugin-page-account-tree.c -Lsrc/gnome/gnc-plugin-page-account-tree.c -u -r1.1.2.34 -r1.1.2.35
--- src/gnome/gnc-plugin-page-account-tree.c
+++ src/gnome/gnc-plugin-page-account-tree.c
@@ -127,7 +127,7 @@
 	{ "FileNewAccountAction", N_("New Account..."), GNC_STOCK_NEW_ACCOUNT, NULL,
 	  N_("Create a new Account"),
 	  G_CALLBACK (gnc_plugin_page_account_tree_cmd_new_account) },
-	{ "FileAddAccountHierarchyDruidAction", N_("Add New Account Hierarchy..."), NULL, NULL,
+	{ "FileAddAccountHierarchyDruidAction", N_("Add New Account _Hierarchy..."), NULL, NULL,
 	  N_("Extend the current book by merging with new account type categories"),
 	  G_CALLBACK (gnc_plugin_page_account_tree_cmd_file_hierarchy_merge) },
 	{ "FileOpenAccountAction", N_("Open Account"), GNC_STOCK_OPEN_ACCOUNT, "<control>o",
--- /dev/null
+++ src/gnome/dialog-chart-export.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ *            dialog-chart-export.h
+ *
+ *  Sun Feb 27 14:19:21 2005
+ *  Copyright  2005  Neil Williams
+ *  linux at codehelp.co.uk
+ ****************************************************************************/
+
+/*
+ *  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 Library 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
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+ 
+#ifndef _DIALOG_CHART_EXPORT_H
+#define _DIALOG_CHART_EXPORT_H
+
+#include <gnome.h>
+
+#define _GNU_SOURCE
+
+
+/** @addtogroup Import_Export
+	@{
+*/
+/** @addtogroup ChartExport Export a chart of accounts.
+
+Remember to use qof_entity_copy routines
+like ::qof_entity_copy_to_session so that the QofBook is marked
+as \a partial. 
+
+\par guidelines Guidelines for partial book export
+-# When exporting GnuCash accounts into QSF, remember that there is no
+   AccountGroup in the partial book, not even a root. Some account functions
+   that you have used in full books will \b not work within a partial book.
+-# Take special care with the book pointer. It is \b very easy to use a
+   QofBook* pointer to a book in a different QofSession. Certain API functions
+   also make assumptions about the current book - \b check carefully.
+-# Remember that just because the function does not use books or AccountGroup
+   itself, it does \b not follow that other functions called by the routine
+   are also suitable. You may have to reimplement the body of certain functions.
+-# Commodities are \b not supported. Most Account functions will use the 
+   commodity of the account, so be sure to set at least the ::gnc_default_currency().
+
+	@{
+*/
+/** @file dialog-chart-export.h
+    @brief  Chart Export - Routines to export Chart of Accounts to file
+    @author Copyright (C) 2005 Neil Williams <linux at codehelp.co.uk>
+*/
+
+/** \brief Export the Chart of Accounts to QSF
+
+Write out the Chart of Accounts \b with balances as of a
+specific date, as QSF.
+
+The function iterates over each account in the current book and 
+gets the balance as of the specified date. The account is copied to
+the export session, setting the export session book as partial.
+The function then looks up the new entity in the export session
+book and sets the opening balance of the copied account.
+*/
+void
+gnc_main_window_chart_export(void);
+
+/** @} */
+/** @} */
+
+#endif /* _DIALOG_CHART_EXPORT_H */
--- /dev/null
+++ src/gnome/dialog-chart-export.c
@@ -0,0 +1,229 @@
+/***************************************************************************
+ *            dialog-chart-export.c
+ *
+ *  Sun Feb 27 14:19:12 2005
+ *  Copyright  2005  Neil Williams
+ *  linux at codehelp.co.uk
+ ****************************************************************************/
+
+/*
+ *  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 Library 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
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+ 
+#include <time.h>
+#include "qofsession.h"
+#include "AccountP.h"
+#include "Transaction.h"
+#include "qofobject.h"
+#include "dialog-chart-export.h"
+#include "gnc-ui-util.h"
+#include "dialog-utils.h"
+#include "gnc-engine-util.h"
+#include "global-options.h"
+#include "gnc-trace.h"
+static short int module = MOD_GUI;
+
+#define EQUITY_ACCOUNT_NAME  _("Opening Balances")
+#define OPENING_BALANCE_DESC _("Opening Balance")
+
+static GtkWidget *chart_export;
+static GtkWidget *chart_filechooserdialog;
+void on_dateok_clicked (GtkButton *button, gpointer user_data);
+void on_exportok_clicked (GtkButton *button, gpointer user_data);
+
+typedef struct chart_data_s
+{
+	time_t chart_time_t;
+	QofSession *chart_session;
+	Account *equity_account;
+}chart_data;
+
+static void
+chart_collection_cb(QofEntity *ent, gpointer user_data)
+{
+	chart_data *data;
+	Account *acc;
+	gboolean success;
+	const GUID *guid;
+	QofCollection *copy_coll;
+	QofBook *book;
+
+	g_return_if_fail(user_data != NULL);
+	data = (chart_data*)user_data;
+	acc = (Account*)ent;
+	if(0 == safe_strcmp(EQUITY_ACCOUNT_NAME, xaccAccountGetName(acc)) 
+		&& (xaccAccountGetType(acc) == EQUITY))
+	{
+		success = qof_entity_copy_to_session(data->chart_session, ent);
+		if(!success) { return; }
+		guid = qof_entity_get_guid(ent);
+		book = qof_session_get_book(data->chart_session);
+		copy_coll = qof_book_get_collection(book, GNC_ID_ACCOUNT);
+		data->equity_account = (Account*)qof_collection_lookup_entity(copy_coll, guid);
+		return;
+	}
+}
+
+static void
+chart_entity_cb(QofEntity *ent, gpointer user_data)
+{
+	chart_data *data;
+	Account *acc_ent, *equity_account;
+	Transaction *trans;
+	Split *split;
+	gnc_numeric balance;
+	QofBook *book;
+	QofCollection *coll;
+	const GUID *guid;
+	gboolean success;
+	
+	success = FALSE;
+	g_return_if_fail(user_data != NULL);
+	data = (chart_data*)user_data;
+	guid = qof_entity_get_guid(ent);
+	acc_ent = (Account*)ent;
+	equity_account = data->equity_account;
+	g_return_if_fail(equity_account != NULL);
+	ENTER (" Acc=%p\tEquity=%p ", acc_ent, equity_account);
+	balance = xaccAccountGetBalanceAsOfDate(acc_ent, data->chart_time_t);
+	success = qof_entity_copy_to_session(data->chart_session, ent);
+	if(!success) {
+		PWARN("%s - %s",  "ERR_BACKEND_MISC" , "entity already exists");
+	}
+	book = qof_session_get_book(data->chart_session);
+	coll = qof_book_get_collection(book, GNC_ID_ACCOUNT);
+	acc_ent = (Account*)qof_collection_lookup_entity(coll, guid);
+	if(xaccAccountGetCommodity(acc_ent) == NULL)
+	{
+		xaccAccountSetCommodity(acc_ent, gnc_default_currency());
+	}
+	/* can't use gnc_account_create_opening_balance directly - the partial 
+	QofBook doesn't have an AccountGroup that is used to locate the Equity Account. */
+	xaccAccountBeginEdit (acc_ent);
+	xaccAccountBeginEdit (equity_account);
+	trans = xaccMallocTransaction (book);
+	xaccTransBeginEdit (trans);
+	xaccTransSetCurrency (trans, xaccAccountGetCommodity (acc_ent));
+	xaccTransSetDateSecs (trans, data->chart_time_t);
+	xaccTransSetDescription (trans, OPENING_BALANCE_DESC);
+	split = xaccMallocSplit (book);
+	xaccTransAppendSplit (trans, split);
+	xaccAccountInsertSplit (acc_ent, split);
+	xaccSplitSetAmount (split, balance);
+	xaccSplitSetValue (split, balance);
+	balance = gnc_numeric_neg (balance);
+	split = xaccMallocSplit (book);
+	xaccTransAppendSplit (trans, split);
+	xaccAccountInsertSplit (equity_account, split);
+	xaccSplitSetAmount (split, balance);
+	xaccSplitSetValue (split, balance);
+	xaccTransCommitEdit (trans);
+	xaccAccountCommitEdit (equity_account);
+	xaccAccountCommitEdit (acc_ent);
+}
+
+static GtkWidget *
+create_chartfilechooserdialog ( void )
+{
+	GtkWidget *dialog;
+	GladeXML *xml;
+	
+	xml = gnc_glade_xml_new ("chart-export.glade", "chartfilechooserdialog");
+	glade_xml_signal_connect(xml, "on_exportok_clicked",
+		GTK_SIGNAL_FUNC (on_exportok_clicked));
+	dialog = glade_xml_get_widget (xml, "chartfilechooserdialog");
+	return dialog;
+}
+
+
+static GtkWidget *
+create_chart_export ( void )
+{
+  GtkWidget *dialog;
+  GladeXML *xml;
+
+	xml = gnc_glade_xml_new ("chart-export.glade", "chart-export");
+
+	glade_xml_signal_connect(xml, "on_dateok_clicked",
+		GTK_SIGNAL_FUNC	(on_dateok_clicked));
+	dialog = glade_xml_get_widget (xml, "chart-export");
+	return dialog;	
+}
+
+void
+gnc_main_window_chart_export(void)
+{
+	chart_export = create_chart_export ();
+	gtk_widget_show (chart_export);
+}
+
+void
+on_dateok_clicked (GtkButton *button, gpointer user_data)
+{
+	guint year, month, day;
+	chart_data data;
+	GtkCalendar *calendar;
+	struct tm *chart_tm;
+
+	calendar = (GtkCalendar*)gnc_glade_lookup_widget(chart_export, "chart-calendar");
+	data.chart_time_t = time(NULL);
+	chart_tm = gmtime(&data.chart_time_t);
+	/* set today - calendar will omit any zero/NULL values */
+	year = chart_tm->tm_year + 1900;
+	month = chart_tm->tm_mon + 1;
+	day = chart_tm->tm_yday + 1;
+	gtk_calendar_get_date(calendar, &year, &month, &day);
+	chart_tm->tm_year = year - 1900;
+	chart_tm->tm_mon = month;
+	chart_tm->tm_yday = day - 1;
+	data.chart_time_t = mktime(chart_tm);
+	gtk_widget_destroy(chart_export);
+	chart_filechooserdialog = create_chartfilechooserdialog ();
+	gtk_widget_show (chart_filechooserdialog);
+}
+
+void
+on_exportok_clicked (GtkButton *button, gpointer user_data)
+{
+	QofSession *current_session, *chart_session;
+	QofBook *book;
+	QofCollection *coll;
+	const char *filename;
+	chart_data data;
+
+	current_session = qof_session_get_current_session();
+	book = qof_session_get_book(current_session);
+	chart_session = qof_session_new();
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chart_filechooserdialog));
+	qof_session_begin(chart_session, filename, TRUE, TRUE);
+	data.chart_session = chart_session;
+	data.equity_account = NULL;
+
+	coll = qof_book_get_collection(book, GNC_ID_ACCOUNT);
+	qof_collection_foreach(coll, chart_collection_cb, &data);
+	if(data.equity_account == NULL)
+	{
+		data.equity_account = xaccMallocAccount (qof_session_get_book(chart_session));
+		xaccAccountBeginEdit (data.equity_account);
+		xaccAccountSetName (data.equity_account, EQUITY_ACCOUNT_NAME);
+		xaccAccountSetType (data.equity_account, EQUITY);
+		xaccAccountSetCommodity (data.equity_account, gnc_default_currency());
+	}
+	qof_object_foreach(GNC_ID_ACCOUNT, book, chart_entity_cb, &data);
+	qof_session_save(chart_session, NULL);
+	qof_session_end(chart_session);
+	gtk_widget_destroy(chart_filechooserdialog);
+	qof_session_set_current_session(current_session);
+}
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Makefile.am,v
retrieving revision 1.107.4.16
retrieving revision 1.107.4.17
diff -Lsrc/gnome/Makefile.am -Lsrc/gnome/Makefile.am -u -r1.107.4.16 -r1.107.4.17
--- src/gnome/Makefile.am
+++ src/gnome/Makefile.am
@@ -27,6 +27,7 @@
   dialog-budget-category.c \
   dialog-budget-list.c \
   dialog-budget-workbench.c \
+  dialog-chart-export.c  \
   dialog-commodities.c \
   dialog-fincalc.c \
   dialog-find-transactions.c \
Index: gnc-main-window.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Attic/gnc-main-window.c,v
retrieving revision 1.1.2.34
retrieving revision 1.1.2.35
diff -Lsrc/gnome/gnc-main-window.c -Lsrc/gnome/gnc-main-window.c -u -r1.1.2.34 -r1.1.2.35
--- src/gnome/gnc-main-window.c
+++ src/gnome/gnc-main-window.c
@@ -61,7 +61,8 @@
 #include "window-main.h"
 #include "window-main-summarybar.h"
 #include "messages.h"
-
+#include "druid-merge.h"
+#include "dialog-chart-export.h"
 // +JSLED
 #include "gnc-html.h"
 
@@ -98,7 +99,9 @@
 static void gnc_main_window_cmd_file_open_new_window (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_save (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_save_as (EggAction *action, GncMainWindow *window);
+static void gnc_main_window_cmd_file_qsf_import (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_export_accounts (EggAction *action, GncMainWindow *window);
+static void gnc_main_window_cmd_chart_export (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_print (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_properties (EggAction *action, GncMainWindow *window);
 static void gnc_main_window_cmd_file_close (EggAction *action, GncMainWindow *window);
@@ -135,8 +138,8 @@
 	GtkWidget *notebook;
 	GtkWidget *statusbar;
 	GtkWidget *progressbar;
-
-        GtkWidget *gncSummaryBar;
+	
+	GtkWidget *gncSummaryBar;
 
 	EggActionGroup *action_group;
 
@@ -183,10 +186,19 @@
 	  NULL,
 	  G_CALLBACK (gnc_main_window_cmd_file_save_as) },
 	{ "FileImportAction", N_("_Import"), NULL, NULL, NULL, NULL },
+	{ "FileImportQSFAction", N_("_QSF Import"),
+		GTK_STOCK_CONVERT, NULL,
+		N_("Import a QSF object file"),
+		G_CALLBACK (gnc_main_window_cmd_file_qsf_import) },
 	{ "FileExportAction", N_("_Export"), NULL, NULL, NULL, NULL },
-	{ "FileExportAccountsAction", N_("Export _Accounts..."), NULL, NULL,
-	   N_("Export the account hierarchy to a new file"),
-	   G_CALLBACK (gnc_main_window_cmd_file_export_accounts) },
+	{ "FileExportAccountsAction", N_("Export _Accounts"), 
+		GTK_STOCK_CONVERT, NULL,
+		N_("Export the account hierarchy to a new file"),
+		G_CALLBACK (gnc_main_window_cmd_file_export_accounts) },
+	{ "FileExportChartAction", N_("Export _Chart of Accounts"), 
+		GTK_STOCK_CONVERT, NULL,
+		N_("Export the chart of accounts for a date with balances"),
+		G_CALLBACK (gnc_main_window_cmd_chart_export) },
 	{ "FilePrintAction", N_("_Print..."), GTK_STOCK_PRINT, "<control>p",
 	  NULL,
 	  G_CALLBACK (gnc_main_window_cmd_file_print) },
@@ -770,7 +782,7 @@
 	priv->statusbar = gtk_statusbar_new ();
 	gtk_widget_show (priv->statusbar);
 	gtk_box_pack_start (GTK_BOX (main_vbox), priv->statusbar,
-			    FALSE, TRUE, 0);
+	                           FALSE, TRUE, 0);
         gtk_statusbar_set_has_resize_grip( GTK_STATUSBAR(priv->statusbar), TRUE );
 
         priv->gncSummaryBar = gnc_main_window_summary_new();
@@ -1026,6 +1038,42 @@
 }
 
 static void
+qsf_file_select_ok(GtkWidget *w, GtkFileSelection *fs )
+{
+	QofSession *qsf_session, *first_session;
+	const gchar *filename;
+	QofBook *original;
+
+	ENTER (" ");
+	gnc_engine_suspend_events();
+	filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs));
+	gtk_widget_destroy((GtkWidget*) fs);
+	first_session = qof_session_get_current_session();
+	original = qof_session_get_book(first_session);
+	qsf_session = qof_session_new();
+	qof_session_begin(qsf_session, filename, TRUE, FALSE);
+	qof_session_load(qsf_session, NULL);
+	gnc_engine_resume_events();
+	gnc_ui_qsf_import_merge_druid(first_session, qsf_session);
+	LEAVE (" ");
+}
+
+static void
+gnc_main_window_cmd_file_qsf_import (EggAction *action, GncMainWindow *window)
+{
+	GtkWidget *file_select;
+
+	gnc_window_set_progressbar_window(GNC_WINDOW(window));
+	file_select = gtk_file_selection_new("Select the QSF file to import into GnuCash");
+	g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (file_select)->ok_button),
+		"clicked", G_CALLBACK (qsf_file_select_ok), (gpointer) file_select);
+	g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (file_select)->cancel_button),
+		"clicked", G_CALLBACK (gtk_widget_destroy), G_OBJECT (file_select));
+	gtk_widget_show (file_select);
+	gnc_window_set_progressbar_window(NULL);
+}
+
+static void
 gnc_main_window_cmd_file_export_accounts (EggAction *action, GncMainWindow *window)
 {
 	gnc_window_set_progressbar_window (GNC_WINDOW(window));
@@ -1036,6 +1084,16 @@
 }
 
 static void
+gnc_main_window_cmd_chart_export (EggAction *action, GncMainWindow *window)
+{
+	gnc_window_set_progressbar_window (GNC_WINDOW(window));
+	gnc_main_window_chart_export();
+	gnc_window_set_progressbar_window (NULL);
+	/* FIXME GNOME 2 Port (update the title etc.) */
+	/* gnc_refresh_main_window_info (); */
+}
+
+static void
 gnc_main_window_cmd_file_print (EggAction *action, GncMainWindow *window)
 {
 }
Index: druid-merge.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/druid-merge.c,v
retrieving revision 1.2.2.2
retrieving revision 1.2.2.3
diff -Lsrc/gnome/druid-merge.c -Lsrc/gnome/druid-merge.c -u -r1.2.2.2 -r1.2.2.3
--- src/gnome/druid-merge.c
+++ src/gnome/druid-merge.c
@@ -42,17 +42,20 @@
 #include "gnc-trace.h"
 #include "Group.h"
 
-static GtkWidget			*qof_book_merge_window = NULL;
+static GtkWidget	*qof_book_merge_window = NULL;
 GtkWidget			*druid_hierarchy_window = NULL;
+static GtkWidget	*qsf_import_merge_window = NULL;
 QofSession			*previous_session = NULL;
-gint					count = 0;
+gint				count = 0;
 qof_book_mergeData	*mergeData = NULL;
 QofSession 			*merge_session = NULL;
 QofBook				*mergeBook = NULL;
 QofBook				*targetBook = NULL;
 gchar 				*buffer = "";
 
-void collision_rule_loop	( qof_book_mergeData*, qof_book_mergeRule*, 	guint );
+static short int module = MOD_GUI;
+
+void collision_rule_loop ( qof_book_mergeData*, qof_book_mergeRule*, guint );
 
 static GtkWidget*
 merge_get_widget (const char *name)
@@ -65,10 +68,10 @@
 static void
 delete_merge_window (void)
 {
-  if (!qof_book_merge_window) return;
-
-  gtk_widget_destroy (qof_book_merge_window);
-  qof_book_merge_window = NULL;
+	if (!qof_book_merge_window) return;
+	
+	gtk_widget_destroy (qof_book_merge_window);
+	qof_book_merge_window = NULL;
 }
 
 static void
@@ -77,6 +80,17 @@
 }
 
 static gboolean
+on_import_start_page_next(GnomeDruidPage  *gnomedruidpage,
+                       gpointer         arg1,
+                       gpointer         user_data)
+{
+
+	return FALSE;
+}
+
+
+
+static gboolean
 on_qof_start_page_next(GnomeDruidPage  *gnomedruidpage,
                        gpointer         arg1,
                        gpointer         user_data)
@@ -91,6 +105,7 @@
               		    gpointer         user_data)
 {
 	g_return_if_fail(mergeData != NULL);
+	ENTER (" ");
 	mergeData = qof_book_mergeUpdateResult(mergeData, MERGE_UPDATE); 
 	count = 0;
  	qof_book_mergeRuleForeach(mergeData, collision_rule_loop, MERGE_REPORT);
@@ -103,6 +118,7 @@
 	qof_book_mergeRule *currentRule;
 	
 	g_return_if_fail(mergeData != NULL);
+	ENTER (" ");
 	currentRule = mergeData->currentRule;
 	if(currentRule->mergeAbsolute == FALSE) { 
 		mergeData = qof_book_mergeUpdateResult(mergeData, MERGE_DUPLICATE); 
@@ -120,7 +136,8 @@
               		gpointer         user_data)
 {
 	qof_book_mergeRule *currentRule;
-	
+
+	ENTER (" ");
 	g_return_if_fail(mergeData != NULL);
 	currentRule = mergeData->currentRule;
 	g_return_if_fail(currentRule != NULL);
@@ -132,30 +149,34 @@
 }
 
 static gboolean
+on_import_next (GnomeDruidPage  *gnomedruidpage,
+                       gpointer         arg1,
+                       gpointer         user_data)
+{
+	return FALSE;
+}
+
+static gboolean
 on_qof_book_merge_next (GnomeDruidPage  *gnomedruidpage,
                        gpointer         arg1,
                        gpointer         user_data)
 {
     GtkWidget *top;
-	GtkLabel *output;
     const char *message = _("You must resolve all collisions.");
 
+	ENTER (" count=%d", count);
 	if(count > 0) {
 		top = gtk_widget_get_toplevel (GTK_WIDGET (gnomedruidpage));
 	    gnc_error_dialog(top, message);
 		return TRUE;
 	}
 	buffer = "";
-	gnc_suspend_gui_refresh ();
-	output = GTK_LABEL(merge_get_widget("OutPut"));
-	gtk_label_set_text(output, buffer);
-	gtk_widget_show(GTK_WIDGET(output));
-	gnc_resume_gui_refresh ();
+	LEAVE (" ");
 	return FALSE;
 }
 
 static void
-on_cancel (	GnomeDruid      *gnomedruid,
+on_merge_cancel (	GnomeDruid      *gnomedruid,
 			gpointer         user_data)
 {
 	gnc_suspend_gui_refresh ();
@@ -184,14 +205,15 @@
 }
 
 static void
-on_finish (GnomeDruidPage  *gnomedruidpage,
+on_merge_finish (GnomeDruidPage  *gnomedruidpage,
            gpointer         arg1,
            gpointer         user_data)
 {
 	gint result;
-    GtkWidget *top;
+    GtkWidget *top;	
     const char *message;
 
+	ENTER (" ");
 	message = _("Error: the Commit operation failed.");
 	g_return_if_fail(mergeData != NULL);
 	gnc_suspend_gui_refresh ();
@@ -211,13 +233,14 @@
 }
 
 static void
-on_qof_book_merge_prepare (GnomeDruidPage  *gnomedruidpage,
+on_merge_prepare (GnomeDruidPage  *gnomedruidpage,
                             gpointer         arg1,
                             gpointer         user_data)
 {
 	GtkLabel *progress;
 
-    gnc_suspend_gui_refresh ();
+	gnc_suspend_gui_refresh ();
+	ENTER (" ");
 	progress = GTK_LABEL (merge_get_widget("ResultsBox"));
 	/* blank out old data */
 	gtk_label_set_text(progress, "");
@@ -230,6 +253,50 @@
 }
 
 static GtkWidget *
+gnc_create_import_druid ( void )
+{
+  GtkWidget *dialog;
+  GtkWidget *druid;
+  GladeXML *xml;
+
+	xml = gnc_glade_xml_new ("merge.glade", "Merge Druid");
+
+	glade_xml_signal_connect(xml, "on_start_page_next",
+		GTK_SIGNAL_FUNC (on_import_start_page_next));
+	
+	glade_xml_signal_connect(xml, "on_qof_book_merge_prepare",
+		GTK_SIGNAL_FUNC (on_merge_prepare));
+
+	glade_xml_signal_connect(xml, "on_qof_book_merge_next",
+		GTK_SIGNAL_FUNC (on_import_next));
+
+	glade_xml_signal_connect (xml, "on_finish", 
+		GTK_SIGNAL_FUNC (on_merge_finish));
+
+	glade_xml_signal_connect (xml, "on_cancel", 
+		GTK_SIGNAL_FUNC (on_merge_cancel));
+	
+	glade_xml_signal_connect (xml, "on_MergeUpdate_clicked",
+		GTK_SIGNAL_FUNC (on_MergeUpdate_clicked));
+		
+	glade_xml_signal_connect (xml, "on_MergeDuplicate_clicked",
+		GTK_SIGNAL_FUNC (on_MergeDuplicate_clicked));
+		
+	glade_xml_signal_connect (xml, "on_MergeNew_clicked",
+		GTK_SIGNAL_FUNC (on_MergeNew_clicked));
+
+	dialog = glade_xml_get_widget (xml, "Merge Druid");
+	gnome_window_icon_set_from_default (GTK_WINDOW (dialog));
+
+	druid = glade_xml_get_widget (xml, "merge_druid");
+	gnc_druid_set_colors (GNOME_DRUID (druid));
+
+	gtk_signal_connect (GTK_OBJECT(dialog), "destroy",
+                      GTK_SIGNAL_FUNC(qof_book_merge_destroy_cb), NULL);
+	return dialog;
+}
+
+static GtkWidget *
 gnc_create_merge_druid ( void )
 {
   GtkWidget *dialog;
@@ -242,16 +309,16 @@
 		GTK_SIGNAL_FUNC (on_qof_start_page_next));
 	
 	glade_xml_signal_connect(xml, "on_qof_book_merge_prepare",
-		GTK_SIGNAL_FUNC (on_qof_book_merge_prepare));
+		GTK_SIGNAL_FUNC (on_merge_prepare));
 
 	glade_xml_signal_connect(xml, "on_qof_book_merge_next",
 		GTK_SIGNAL_FUNC (on_qof_book_merge_next));
 
 	glade_xml_signal_connect (xml, "on_finish", 
-		GTK_SIGNAL_FUNC (on_finish));
+		GTK_SIGNAL_FUNC (on_merge_finish));
 
 	glade_xml_signal_connect (xml, "on_cancel", 
-		GTK_SIGNAL_FUNC (on_cancel));
+		GTK_SIGNAL_FUNC (on_merge_cancel));
 	
 	glade_xml_signal_connect (xml, "on_MergeUpdate_clicked",
 		GTK_SIGNAL_FUNC (on_MergeUpdate_clicked));
@@ -281,6 +348,7 @@
 	GtkLabel *output;
 	
 	g_return_if_fail(rule != NULL);
+	ENTER (" count=%d", count);
 	buffer = "";
 	/* there is a rule awaiting resolution, don't print any more */
 	if(count > 0) return;
@@ -328,13 +396,26 @@
 	return NULL;
 }
 
+void
+gnc_ui_qsf_import_merge_druid (QofSession *original, QofSession *import)
+{
+	if (qsf_import_merge_window) { return; }
+	gnc_engine_suspend_events ();
+	qsf_import_merge_window = gnc_create_import_druid();
+	g_return_if_fail(qsf_import_merge_window != NULL);
+	previous_session = original;
+	targetBook = qof_session_get_book(previous_session);
+	merge_session = import;
+	mergeBook = qof_session_get_book(merge_session);
+	gtk_widget_show(qsf_import_merge_window);
+}
 
 void
 gnc_ui_qof_book_merge_druid (void)
 {
-	if (qof_book_merge_window) return;
+	if (qof_book_merge_window) { return; }
 	/*	QofSession changes to avoid using current book */
-    gnc_engine_suspend_events ();
+	gnc_engine_suspend_events ();
 	previous_session = qof_session_get_current_session();
 	targetBook = qof_session_get_book(previous_session);
 	merge_session = qof_session_new();
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/glade/Makefile.am,v
retrieving revision 1.21.4.7
retrieving revision 1.21.4.8
diff -Lsrc/gnome/glade/Makefile.am -Lsrc/gnome/glade/Makefile.am -u -r1.21.4.7 -r1.21.4.8
--- src/gnome/glade/Makefile.am
+++ src/gnome/glade/Makefile.am
@@ -3,6 +3,7 @@
 	account.glade \
 	acctperiod.glade \
 	budget.glade \
+	chart-export.glade \
 	commodities.glade \
 	fincalc.glade \
 	lots.glade \
--- /dev/null
+++ src/gnome/glade/chart-export.glade
@@ -0,0 +1,299 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="chart-export">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Export Chart of Accounts</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="icon">gnucash-icon.png</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+
+	  <child>
+	    <widget class="GtkButton" id="cancelbutton1">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="dateok">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Click to choose the filename and location.</property>
+	      <property name="can_default">True</property>
+	      <property name="has_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="has_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-5</property>
+	      <signal name="clicked" handler="on_dateok_clicked" last_modification_time="Mon, 28 Feb 2005 10:40:01 GMT"/>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkFixed" id="fixed1">
+	  <property name="visible">True</property>
+
+	  <child>
+	    <widget class="GtkCalendar" id="chart-calendar">
+	      <property name="width_request">215</property>
+	      <property name="height_request">180</property>
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Future dates are not supported</property>
+	      <property name="can_focus">True</property>
+	      <property name="display_options">GTK_CALENDAR_SHOW_HEADING|GTK_CALENDAR_SHOW_DAY_NAMES</property>
+	    </widget>
+	    <packing>
+	      <property name="x">40</property>
+	      <property name="y">184</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="chartlabel">
+	      <property name="width_request">304</property>
+	      <property name="height_request">56</property>
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">You can export the Chart of Accounts to a QSF XML file that can be imported into another GnuCash file or used in other programs.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_FILL</property>
+	      <property name="wrap">True</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.519999980927</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <accessibility>
+		<atkproperty name="AtkObject::accessible_name" translatable="yes" comments="QSF is QOF Serialization Format">You can export the Chart of Accounts to a QSF XML file that can be imported into another GnuCash file or used in other programs.</atkproperty>
+	      </accessibility>
+	    </widget>
+	    <packing>
+	      <property name="x">8</property>
+	      <property name="y">8</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="processlabel">
+	      <property name="width_request">296</property>
+	      <property name="height_request">48</property>
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Select the date to use and click Next to choose the filename and location.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_FILL</property>
+	      <property name="wrap">True</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="x">8</property>
+	      <property name="y">128</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="chartnote">
+	      <property name="width_request">304</property>
+	      <property name="height_request">56</property>
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">The Chart of Accounts includes the balance for each account, on the date specified.  Note that future dates are not supported.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_FILL</property>
+	      <property name="wrap">True</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="x">8</property>
+	      <property name="y">64</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkFileChooserDialog" id="chartfilechooserdialog">
+  <property name="visible">True</property>
+  <property name="tooltip" translatable="yes">The extension .xml is optional</property>
+  <property name="action">GTK_FILE_CHOOSER_ACTION_SAVE</property>
+  <property name="local_only">True</property>
+  <property name="select_multiple">False</property>
+  <property name="show_hidden">False</property>
+  <property name="title" translatable="yes">Filename for exported XML</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="icon">gnucash-icon.png</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox2">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">24</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area2">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button1">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="exportok">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="has_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-5</property>
+	      <accessibility>
+		<atkproperty name="AtkObject::accessible_name" translatable="yes">Export</atkproperty>
+	      </accessibility>
+	      <signal name="clicked" handler="on_exportok_clicked" last_modification_time="Mon, 28 Feb 2005 11:26:59 GMT"/>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment1">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">0</property>
+		  <property name="yscale">0</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">0</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox1">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">2</property>
+
+		      <child>
+			<widget class="GtkImage" id="image1">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-convert</property>
+			  <property name="icon_size">4</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label3">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Export</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
Index: gnc-file.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/app-file/gnc-file.c,v
retrieving revision 1.25.4.9
retrieving revision 1.25.4.10
diff -Lsrc/app-file/gnc-file.c -Lsrc/app-file/gnc-file.c -u -r1.25.4.9 -r1.25.4.10
--- src/app-file/gnc-file.c
+++ src/app-file/gnc-file.c
@@ -99,7 +99,7 @@
     case ERR_BACKEND_NO_ERR:
       uh_oh = FALSE;
       break;
-
+	
 	case ERR_BACKEND_NO_HANDLER: {
 		fmt = _("No suitable backend was found for\n%s.");
 		gnc_error_dialog(parent, fmt, newfile);
@@ -243,6 +243,17 @@
 			"has been detected. The QSF object file\n%s\n contains invalid "
 			"data in a field that is meant to hold a number.");
 		gnc_error_dialog(parent, fmt, newfile);
+		break;
+	}
+	case ERR_QSF_OPEN_NOT_MERGE : {
+		fmt = _("The QSF object file\n%s\nis valid and contains GnuCash "
+			"objects. However, GnuCash cannot open the file directly because "
+			"the data needs to be merged into an existing GnuCash data book. "
+			"Please open a GnuCash file or create a new one, then import "
+			"this QSF object file so that the data can be merged into the "
+			"main data book.");
+		gnc_error_dialog(parent, fmt, newfile);
+		break;
 	}
     case ERR_FILEIO_FILE_BAD_READ:
       fmt = _("There was an error reading the file.\n"
@@ -461,7 +472,6 @@
 
   qof_session_begin (new_session, newfile, FALSE, FALSE);
   io_err = qof_session_get_error (new_session);
-
   /* if file appears to be locked, ask the user ... */
   if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
   {
@@ -509,7 +519,10 @@
       gnc_file_new ();
     }
   }
-
+  if(ERR_QSF_OPEN_NOT_MERGE == io_err)
+  {
+	uh_oh = TRUE;
+  }
   /* if the database doesn't exist, ask the user ... */
   else if ((ERR_BACKEND_NO_SUCH_DB == io_err) ||
            (ERR_SQL_DB_TOO_OLD == io_err))
Index: gnc-main-window-ui.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/ui/Attic/gnc-main-window-ui.xml,v
retrieving revision 1.1.2.9
retrieving revision 1.1.2.10
diff -Lsrc/gnome/ui/gnc-main-window-ui.xml -Lsrc/gnome/ui/gnc-main-window-ui.xml -u -r1.1.2.9 -r1.1.2.10
--- src/gnome/ui/gnc-main-window-ui.xml
+++ src/gnome/ui/gnc-main-window-ui.xml
@@ -14,11 +14,13 @@
       <placeholder name="FileSavePlaceholder"/>
       <separator name="FileSep3"/>
       <menu name="FileImport" action="FileImportAction">
-      	<placeholder name="FileImportPlaceholder"/>
+        <menuitem name="FileImportQSF" action="FileImportQSFAction"/>
+        <placeholder name="FileImportPlaceholder"/>
       </menu>
       <menu name="FileExport" action="FileExportAction">
-      	<menuitem name="FileExportAccounts" action="FileExportAccountsAction"/>
-      	<placeholder name="FileExportPlaceholder"/>
+        <menuitem name="FileExportAccounts" action="FileExportAccountsAction"/>
+        <menuitem name="FileExportChart" action="FileExportChartAction"/>
+        <placeholder name="FileExportPlaceholder"/>
       </menu>
       <separator name="FileSep4"/>
       <menuitem name="FilePrint" action="FilePrintAction"/>


More information about the gnucash-changes mailing list