[Gnucash-changes] Reference handling improvements
Neil Williams
codehelp at cvs.gnucash.org
Mon Mar 21 09:56:34 EST 2005
Log Message:
-----------
Reference handling improvements
Tags:
----
gnucash-gnome2-dev
Modified Files:
--------------
gnucash:
ChangeLog
gnucash/src/backend/qsf:
qsf-backend.c
qsf-xml.c
qsf-xml.h
gnucash/src/business/business-gnome:
gnc-plugin-business.c
gnucash/src/business/business-gnome/ui:
gnc-plugin-business-ui.xml
gnucash/src/engine:
qofclass.c
qofclass.h
qofsession.c
qofsession.h
gnucash/src/gnome:
dialog-chart-export.c
gnucash/src/gnome/glade:
chart-export.glade
Revision Data
-------------
Index: ChangeLog
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/ChangeLog,v
retrieving revision 1.1487.2.183
retrieving revision 1.1487.2.184
diff -LChangeLog -LChangeLog -u -r1.1487.2.183 -r1.1487.2.184
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,21 @@
+2005-03-21 Neil Williams <linux at codehelp.co.uk>
+ * src/backend/qsf/qsf-backend.c:
+ * src/backend/qsf/qsf-xml.c:
+ * src/backend/qsf/qsf-xml.h: Reference handling improvements.
+ * src/business/business-gnome/gnc-plugin-business.c:
+ * src/business/business-gnome/ui/gnc-plugin-business-ui.xml:
+ Adding export routines for business objects.
+ * src/engine/qofclass.c:
+ * src/engine/qofclass.h:
+ Reference handling: qof_class_get_referenceList
+ * src/engine/qofsession.c:
+ * src/engine/qofsession.h: Reference handling improvements
+ and improved error handling. Also suspending engine events
+ during copy to improve speed.
+ * src/gnome/dialog-chart-export.c:
+ * src/gnome/glade/chart-export.glade: Removing unnecessary
+ file chooser dialog, using a standard box instead.
+
2005-03-13 Joshua Sled <jsled at asynchronous.org>
* GNOME2_STATUS: Updates; removed some incorrectness, updated for
Index: gnc-plugin-business.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-gnome/Attic/gnc-plugin-business.c,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -Lsrc/business/business-gnome/gnc-plugin-business.c -Lsrc/business/business-gnome/gnc-plugin-business.c -u -r1.1.2.4 -r1.1.2.5
--- src/business/business-gnome/gnc-plugin-business.c
+++ src/business/business-gnome/gnc-plugin-business.c
@@ -95,6 +95,20 @@
static void gnc_plugin_business_cmd_bills_due_reminder (EggAction *action,
GncMainWindowActionData *data);
+static void gnc_plugin_business_cmd_export_invoice (EggAction *action,
+ GncMainWindowActionData *data);
+
+static void gnc_plugin_business_cmd_export_customer (EggAction *action,
+ GncMainWindowActionData *data);
+
+static void gnc_plugin_business_cmd_export_vendor (EggAction *action,
+ GncMainWindowActionData *data);
+
+static void gnc_plugin_business_cmd_export_employee (EggAction *action,
+ GncMainWindowActionData *data);
+
+/*static void gnc_plugin_business_cmd_export_report (EggAction *action,
+ GncMainWindowActionData *data);*/
#define PLUGIN_ACTIONS_NAME "gnc-plugin-business-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-business-ui.xml"
@@ -180,6 +194,19 @@
{ "BillsDueReminderOpenAction", N_("Bills Due Reminder"), NULL, NULL,
N_("Open the Bills Due Reminder dialog"),
G_CALLBACK (gnc_plugin_business_cmd_bills_due_reminder) },
+ { "ExportMenuAction", N_("E_xport"), NULL, NULL, NULL, NULL },
+ { "QSFInvoiceAction", N_("QSF _Invoice"), NULL, NULL,
+ N_("Export one or more invoices to QSF"),
+ G_CALLBACK (gnc_plugin_business_cmd_export_invoice) },
+ { "QSFCustomerAction", N_("QSF _Customer"), NULL, NULL,
+ N_("Export one or more customers to QSF"),
+ G_CALLBACK (gnc_plugin_business_cmd_export_customer) },
+ { "QSFVendorAction", N_("QSF _Vendor"), NULL, NULL,
+ N_("Export one or more vendors to QSF"),
+ G_CALLBACK (gnc_plugin_business_cmd_export_vendor) },
+ { "QSFEmployeeAction", N_("QSF _Employee"), NULL, NULL,
+ N_("Export one or more employees to QSF"),
+ G_CALLBACK (gnc_plugin_business_cmd_export_employee) },
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS (gnc_plugin_actions);
@@ -578,3 +605,147 @@
gnc_remind_bills_due gnc_ui_payment_new (priv->last_employee, gnc_get_current_book());
#endif
}
+
+/**************************************************************
+ * QSF export routines
+ **************************************************************/
+
+static void
+gnc_plugin_business_cmd_export_invoice (EggAction *action, GncMainWindowActionData *mw)
+{
+ QofSession *current_session, *chart_session;
+ QofBook *book;
+ QofCollection *coll;
+ gchar *filename;
+ gboolean success;
+ GtkWidget *qsffilechooser;
+
+ current_session = qof_session_get_current_session();
+ book = qof_session_get_book(current_session);
+ chart_session = qof_session_new();
+ success = FALSE;
+ filename = g_strdup("/tmp/qsf-invoices.xml");
+ qsffilechooser = gtk_file_chooser_dialog_new("Export Invoices to XML",
+ (GtkWindow*)mw->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run (GTK_DIALOG (qsffilechooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (qsffilechooser));
+ qof_session_begin(chart_session, filename, TRUE, TRUE);
+ coll = qof_book_get_collection(book, GNC_ID_INVOICE);
+ success = qof_entity_copy_coll(chart_session, coll);
+ if(success)
+ {
+ qof_session_save(chart_session, NULL);
+ }
+ }
+ g_free(filename);
+ qof_session_end(chart_session);
+ gtk_widget_destroy(qsffilechooser);
+ qof_session_set_current_session(current_session);
+}
+
+static void
+gnc_plugin_business_cmd_export_customer (EggAction *action, GncMainWindowActionData *mw)
+{
+ QofSession *current_session, *chart_session;
+ QofBook *book;
+ QofCollection *coll;
+ gchar *filename;
+ gboolean success;
+ GtkWidget *qsffilechooser;
+
+ current_session = qof_session_get_current_session();
+ book = qof_session_get_book(current_session);
+ chart_session = qof_session_new();
+ success = FALSE;
+ filename = g_strdup("/tmp/qsf-customers.xml");
+ qsffilechooser = gtk_file_chooser_dialog_new("Export Customers to XML",
+ (GtkWindow*)mw->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run (GTK_DIALOG (qsffilechooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (qsffilechooser));
+ qof_session_begin(chart_session, filename, TRUE, TRUE);
+ coll = qof_book_get_collection(book, GNC_ID_CUSTOMER);
+ success = qof_entity_copy_coll(chart_session, coll);
+ if(success)
+ {
+ qof_session_save(chart_session, NULL);
+ }
+ }
+ qof_session_end(chart_session);
+ g_free(filename);
+ gtk_widget_destroy(qsffilechooser);
+ qof_session_set_current_session(current_session);
+}
+
+static void
+gnc_plugin_business_cmd_export_vendor (EggAction *action, GncMainWindowActionData *mw)
+{
+ QofSession *current_session, *chart_session;
+ QofBook *book;
+ QofCollection *coll;
+ gchar *filename;
+ gboolean success;
+ GtkWidget *qsffilechooser;
+
+ current_session = qof_session_get_current_session();
+ book = qof_session_get_book(current_session);
+ chart_session = qof_session_new();
+ success = FALSE;
+ filename = g_strdup("/tmp/qsf-vendors.xml");
+ qsffilechooser = gtk_file_chooser_dialog_new("Export Vendors to XML",
+ (GtkWindow*)mw->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run (GTK_DIALOG (qsffilechooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (qsffilechooser));
+ qof_session_begin(chart_session, filename, TRUE, TRUE);
+ coll = qof_book_get_collection(book, GNC_ID_VENDOR);
+ success = qof_entity_copy_coll(chart_session, coll);
+ if(success)
+ {
+ qof_session_save(chart_session, NULL);
+ }
+ }
+ qof_session_end(chart_session);
+ g_free(filename);
+ qof_session_set_current_session(current_session);
+ gtk_widget_destroy(qsffilechooser);
+}
+
+static void
+gnc_plugin_business_cmd_export_employee (EggAction *action, GncMainWindowActionData *mw)
+{
+ QofSession *current_session, *chart_session;
+ QofBook *book;
+ QofCollection *coll;
+ gchar *filename;
+ gboolean success;
+ GtkWidget *qsffilechooser;
+
+ current_session = qof_session_get_current_session();
+ book = qof_session_get_book(current_session);
+ chart_session = qof_session_new();
+ success = FALSE;
+ filename = g_strdup("/tmp/qsf-employee.xml");
+ qsffilechooser = gtk_file_chooser_dialog_new("Export Employees to XML",
+ (GtkWindow*)mw->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run (GTK_DIALOG (qsffilechooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (qsffilechooser));
+ qof_session_begin(chart_session, filename, TRUE, TRUE);
+ coll = qof_book_get_collection(book, GNC_ID_INVOICE);
+ success = qof_entity_copy_coll(chart_session, coll);
+ if(success)
+ {
+ qof_session_save(chart_session, NULL);
+ }
+ }
+ qof_session_end(chart_session);
+ g_free(filename);
+ gtk_widget_destroy(qsffilechooser);
+ qof_session_set_current_session(current_session);
+}
Index: gnc-plugin-business-ui.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/business/business-gnome/ui/Attic/gnc-plugin-business-ui.xml,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/business/business-gnome/ui/gnc-plugin-business-ui.xml -Lsrc/business/business-gnome/ui/gnc-plugin-business-ui.xml -u -r1.1.2.2 -r1.1.2.3
--- src/business/business-gnome/ui/gnc-plugin-business-ui.xml
+++ src/business/business-gnome/ui/gnc-plugin-business-ui.xml
@@ -33,6 +33,13 @@
<menuitem name="TaxTablesOpen" action="TaxTablesOpenAction"/>
<menuitem name="BillingTermsOpen" action="BillingTermsOpenAction"/>
<menuitem name="BillsDueReminderOpen" action="BillsDueReminderOpenAction"/>
+
+ <menu name="ExportMenu" action="ExportMenuAction">
+ <menuitem name="QSFInvoice" action="QSFInvoiceAction"/>
+ <menuitem name="QSFCustomer" action="QSFCustomerAction"/>
+ <menuitem name="QSFVendor" action="QSFVendorAction"/>
+ <menuitem name="QSFEmployee" action="QSFEmployeeAction"/>
+ </menu>
</menu>
</placeholder>
</menubar>
Index: qofsession.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.c,v
retrieving revision 1.2.4.12
retrieving revision 1.2.4.13
diff -Lsrc/engine/qofsession.c -Lsrc/engine/qofsession.c -u -r1.2.4.12 -r1.2.4.13
--- src/engine/qofsession.c
+++ src/engine/qofsession.c
@@ -54,11 +54,11 @@
#include "gnc-engine-util.h"
#include "gnc-event.h"
#include "gnc-trace.h"
+#include "qofsession.h"
#include "qofbackend-p.h"
#include "qofbook.h"
#include "qofbook-p.h"
#include "qofobject.h"
-#include "qofsession.h"
#include "qofsession-p.h"
/* Some gnucash-specific code */
@@ -318,12 +318,40 @@
typedef struct qof_entity_copy_data {
QofEntity *from;
QofEntity *to;
- GHashTable *referenceTable;
+ GList *referenceList;
GSList *param_list;
QofSession *new_session;
gboolean error;
}QofEntityCopyData;
+static gboolean
+qsf_check_error(QofEntityCopyData *qecd)
+{
+ if(qecd->error == TRUE) {
+ qof_entity_release(qecd->to);
+ g_free(qecd->to);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+qof_session_update_reference_list(QofSession *session, QofEntityReference *reference)
+{
+ QofBook *book;
+ GList *book_ref_list;
+ gboolean partial;
+
+ book = qof_session_get_book(session);
+ book_ref_list = (GList*)qof_book_get_data(book, ENTITYREFERENCE);
+ book_ref_list = g_list_append(book_ref_list, reference);
+ qof_book_set_data(book, ENTITYREFERENCE, book_ref_list);
+ partial = (gboolean)qof_book_get_data(book, PARTIAL_QOFBOOK);
+ if(!partial) {
+ qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
+ }
+}
+
static void
qof_entity_param_cb(QofParam *param, gpointer data)
{
@@ -338,6 +366,32 @@
if(g_slist_length(qecd->param_list) == 0) { qecd->error = TRUE; }
}
+QofEntityReference*
+qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
+{
+ QofEntityReference *reference;
+ QofEntity *ref_ent;
+ const GUID *cm_guid;
+ char cm_sa[GUID_ENCODING_LENGTH + 1];
+ gchar *cm_string;
+
+ ref_ent = param->param_getfcn(ent, param);
+ if(ref_ent != NULL) {
+ reference = g_new0(QofEntityReference, 1);
+ reference->type = g_strdup(ent->e_type);
+ reference->ref_guid = g_new(GUID, 1);
+ reference->ent_guid = &ent->guid;
+ reference->param = param;
+ cm_guid = qof_entity_get_guid(ref_ent);
+ guid_to_string_buff(cm_guid, cm_sa);
+ cm_string = g_strdup(cm_sa);
+ if(TRUE == string_to_guid(cm_string, reference->ref_guid)) {
+ return reference;
+ }
+ }
+ return NULL;
+}
+
static void
qof_entity_foreach_copy(gpointer data, gpointer user_data)
{
@@ -349,9 +403,7 @@
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*);
@@ -373,6 +425,9 @@
g_return_if_fail(user_data != NULL);
context = (QofEntityCopyData*) user_data;
+ /* in case of any error, let the process know. */
+ if(context->error == TRUE) { return; }
+ context->error = TRUE;
importEnt = context->from;
targetEnt = context->to;
registered_type = FALSE;
@@ -384,6 +439,7 @@
string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
if(string_setter != NULL) { string_setter(targetEnt, cm_string); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) {
date_getter = (Timespec (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
@@ -391,6 +447,7 @@
date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn;
if(date_setter != NULL) { date_setter(targetEnt, cm_date); }
registered_type = TRUE;
+ context->error = FALSE;
}
if((safe_strcmp(cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
(safe_strcmp(cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) {
@@ -399,12 +456,14 @@
numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn;
if(numeric_setter != NULL) { numeric_setter(targetEnt, cm_numeric); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_GUID) == 0) {
cm_guid = cm_param->param_getfcn(importEnt, cm_param);
guid_setter = (void(*)(QofEntity*, const GUID*))cm_param->param_setfcn;
if(guid_setter != NULL) { guid_setter(targetEnt, cm_guid); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT32) == 0) {
int32_getter = (gint32 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
@@ -412,6 +471,7 @@
i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn;
if(i32_setter != NULL) { i32_setter(targetEnt, cm_i32); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT64) == 0) {
int64_getter = (gint64 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
@@ -419,6 +479,7 @@
i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn;
if(i64_setter != NULL) { i64_setter(targetEnt, cm_i64); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_DOUBLE) == 0) {
double_getter = (double (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
@@ -426,6 +487,7 @@
double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn;
if(double_setter != NULL) { double_setter(targetEnt, cm_double); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_BOOLEAN) == 0){
boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
@@ -433,33 +495,30 @@
boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn;
if(boolean_setter != NULL) { boolean_setter(targetEnt, cm_boolean); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_KVP) == 0) {
cm_kvp = kvp_frame_copy(cm_param->param_getfcn(importEnt,cm_param));
kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn;
if(kvp_frame_setter != NULL) { kvp_frame_setter(targetEnt, cm_kvp); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(safe_strcmp(cm_param->param_type, QOF_TYPE_CHAR) == 0) {
cm_char = cm_param->param_getfcn(importEnt,cm_param);
char_setter = (void(*)(QofEntity*, char*))cm_param->param_setfcn;
if(char_setter != NULL) { char_setter(targetEnt, cm_char); }
registered_type = TRUE;
+ context->error = FALSE;
}
if(registered_type == FALSE) {
- referenceEnt = NULL;
+ PINFO (" cm_param type=%s", cm_param->param_type);
referenceEnt = cm_param->param_getfcn(importEnt, cm_param);
- if(!referenceEnt) { return; }
- reference = g_new(QofEntityReference, 1);
- reference->type = g_strdup(referenceEnt->e_type);
- reference->guid = g_new(GUID, 1);
- cm_guid = qof_entity_get_guid(referenceEnt);
- guid_to_string_buff(cm_guid, cm_sa);
- cm_string = g_strdup(cm_sa);
- if(TRUE == string_to_guid(cm_string, reference->guid)) {
- cm_src_guid = &importEnt->guid;
- g_hash_table_insert(context->referenceTable, cm_src_guid, reference);
+ reference = qof_entity_get_reference_from(importEnt, cm_param);
+ if(reference) {
+ qof_session_update_reference_list(context->new_session, reference);
}
+ context->error = FALSE;
}
}
@@ -505,7 +564,9 @@
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);
+ if(qsf_check_error(qecd)) { return; }
g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
+ qsf_check_error(qecd);
}
static void
@@ -518,6 +579,7 @@
QofEntity *copy;
g_return_if_fail(user_data != NULL);
+ copy = NULL;
qecd = (QofEntityCopyData*)user_data;
targetBook = qof_session_get_book(qecd->new_session);
g = qof_entity_get_guid(original);
@@ -542,9 +604,8 @@
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);
+ qsf_check_error(qecd);
}
gboolean qof_entity_copy_to_session(QofSession* new_session, QofEntity* original)
@@ -555,21 +616,22 @@
const GUID *g;
if(qof_entity_guid_match(new_session, original)) return FALSE;
+ gnc_engine_suspend_events();
qecd.param_list = NULL;
- qecd.referenceTable = g_hash_table_new(NULL, NULL);
+ book = qof_session_get_book(new_session);
qecd.new_session = new_session;
qecd.error = FALSE;
- book = qof_session_get_book(new_session);
inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
qecd.to = &inst->entity;
qecd.from = original;
g = qof_entity_get_guid(original);
qof_entity_set_guid(qecd.to, g);
qof_class_param_foreach(original->e_type, qof_entity_param_cb, &qecd);
+ if(qsf_check_error(&qecd)) { return FALSE; }
g_slist_foreach(qecd.param_list, qof_entity_foreach_copy, &qecd);
+ if(qsf_check_error(&qecd)) { return FALSE; }
g_slist_free(qecd.param_list);
- qof_book_set_data(book, ENTITYREFERENCE, qecd.referenceTable);
- qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
+ gnc_engine_resume_events();
return TRUE;
}
@@ -578,43 +640,38 @@
GList *e;
QofEntity *original;
QofEntityCopyData qecd;
- QofBook *book;
+ gnc_engine_suspend_events();
qecd.param_list = NULL;
qecd.new_session = new_session;
- qecd.referenceTable = g_hash_table_new(NULL, NULL);
qecd.error = FALSE;
for(e=entity_list; e; e=e->next)
{
original = (QofEntity*) e->data;
- /* The GList can contain mixed entity types, it may
- appear slow, but we do need to check the type every time
- because we can't re-use the QofCollection or QofIdType. */
+ /* The GList can contain mixed entity types, it may */
+ /* appear slow, but we do need to check the type every time */
+ /* because we can't re-use the QofCollection or QofIdType. */
if(qof_entity_guid_match(new_session, original)) return FALSE;
}
g_list_foreach(entity_list, qof_entity_list_foreach, &qecd);
- book = qof_session_get_book(qecd.new_session);
- qof_book_set_data(book, ENTITYREFERENCE, qecd.referenceTable);
- qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
+ gnc_engine_resume_events();
return TRUE;
}
gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll)
{
QofEntityCopyData qecd;
- QofBook *book;
+ gnc_engine_suspend_events();
qecd.param_list = NULL;
qecd.new_session = new_session;
- qecd.referenceTable = g_hash_table_new(NULL, NULL);
qecd.error = FALSE;
qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd);
if(qecd.error == TRUE) return FALSE;
+ qof_class_param_foreach(qof_collection_get_type(entity_coll), qof_entity_param_cb, &qecd);
qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd);
- book = qof_session_get_book(qecd.new_session);
- qof_book_set_data(book, ENTITYREFERENCE, qecd.referenceTable);
- qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); }
+ gnc_engine_resume_events();
return TRUE;
}
@@ -742,6 +799,7 @@
GList *node;
QofBackendProvider *prov;
QofBook *book;
+ char *msg;
ENTER (" ");
/* If the provider list is null, try to register the 'well-known'
@@ -775,7 +833,7 @@
}
p = p->next;
}
- msg = g_strdup_printf("failed to load '%s' backend", backend_name);
+ msg = g_strdup_printf("failed to load '%s' using access_method", access_method);
qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
LEAVE (" ");
}
Index: qofclass.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofclass.h,v
retrieving revision 1.1.6.3
retrieving revision 1.1.6.4
diff -Lsrc/engine/qofclass.h -Lsrc/engine/qofclass.h -u -r1.1.6.3 -r1.1.6.4
--- src/engine/qofclass.h
+++ src/engine/qofclass.h
@@ -212,6 +212,13 @@
void qof_class_param_foreach (QofIdTypeConst obj_name,
QofParamForeachCB, gpointer user_data);
+/** \brief List of the parameters that could be references.
+
+Simple check to return a GList of all parameters
+of this object type that are not known QOF data types.
+Used for partial QofBook support, see ::QofEntityReference
+*/
+GList* qof_class_get_referenceList(QofIdTypeConst type);
#endif /* QOF_CLASS_H */
/* @} */
Index: qofclass.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofclass.c,v
retrieving revision 1.1.6.2
retrieving revision 1.1.6.3
diff -Lsrc/engine/qofclass.c -Lsrc/engine/qofclass.c -u -r1.1.6.2 -r1.1.6.3
--- src/engine/qofclass.c
+++ src/engine/qofclass.c
@@ -250,4 +250,33 @@
g_hash_table_foreach (param_ht, param_foreach_cb, &iter);
}
+static void
+find_reference_param(QofParam *param, gpointer user_data)
+{
+ GList *ref_list;
+
+ ref_list = (GList*)user_data;
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_STRING)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_NUMERIC)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_DATE)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_CHAR)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_DEBCRED)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_GUID)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_INT32)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_INT64)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_DOUBLE)) { return; }
+ if(0 == safe_strcmp(param->param_type, QOF_TYPE_KVP)) { return; }
+ ref_list = g_list_append(ref_list, param);
+}
+
+GList*
+qof_class_get_referenceList(QofIdTypeConst type)
+{
+ GList *ref_list;
+
+ ref_list = NULL;
+ qof_class_param_foreach(type, find_reference_param, ref_list);
+ return ref_list;
+}
+
/* ============================= END OF FILE ======================== */
Index: qofsession.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/qofsession.h,v
retrieving revision 1.2.4.5
retrieving revision 1.2.4.6
diff -Lsrc/engine/qofsession.h -Lsrc/engine/qofsession.h -u -r1.2.4.5 -r1.2.4.6
--- src/engine/qofsession.h
+++ src/engine/qofsession.h
@@ -90,6 +90,8 @@
#include "qofbackend.h"
#include "qofbook.h"
+#include "qofclass.h"
+#include "qofobject.h"
/* PROTOTYPES ******************************************************/
@@ -348,23 +350,64 @@
/** \brief External references in a partial QofBook.
-This data is built into a hash table for use by any session that
-deals with partial QofBooks. It is used by the entity copy
-functions and by the QSF backend. The hashtable key is
-the GUID of the known entity and the value is a
-QofEntityReference to the referenced entity.
+For use by any session that deals with partial QofBooks.
+It is used by the entity copy functions and by the QSF backend.
+Creates a GList stored in the Book hashtable to contain
+repeated references for a single entity.
*/
typedef struct qof_entity_reference {
- QofIdType type;
- GUID *guid;
+ QofIdType type; /**< The type of entity */
+ GUID *ref_guid; /**< The GUID of the REFERENCE entity */
+ const QofParam *param; /**< The parameter used to get/set this reference. */
+ const GUID *ent_guid; /**< The GUID of the original entity. */
}QofEntityReference;
+/** \brief Get a reference from this entity to another entity.
+
+Used in the preparation of a partial QofBook when the known entity
+(the one currently being copied into the partial book) refers to
+any other entity, usually as a parent or child.
+The routine calls the param_getfcn of the supplied parameter,
+which must return an object (QofEntity*), not a known QOF data type, to
+retrieve the referenced entity and therefore the GUID. The GUID of
+both entities are stored in the reference which then needs to be added
+to the reference list which is added to the partial book data hash.
+The reference itself is used by the backend to preserve the relationship
+between entities within and outside the partial book.
+
+See also ::qof_class_get_referenceList to obtain the list of
+parameters that provide references to the known entity whilst
+excluding parameters that return known QOF data types.
+
+Note that even if the referenced entity \b exists in the partial
+book (or will exist later), a reference must still be obtained and
+added to the reference list for the book itself. This maintains
+the integrity of the partial book during sequential copy operations.
+
+ at param ent The known entity.
+ at param param The parameter to use to get the referenced entity.
+
+ at return FALSE on error, otherwise a pointer to the QofEntityReference.
+*/
+QofEntityReference*
+qof_entity_get_reference_from(QofEntity *ent, const QofParam *param);
+
+/** \brief Adds a new reference to the partial book data hash.
+
+Retrieves any existing reference list and appends the new reference.
+
+If the book is not already marked as partial, it will be marked as partial.
+*/
+void
+qof_session_update_reference_list(QofSession *session, QofEntityReference *reference);
+
/** 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.
+ * of the original QofBook as well as the parameter data and the
+ * GUID of the original entity.
* */
#define ENTITYREFERENCE "QofEntityReference"
Index: dialog-chart-export.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Attic/dialog-chart-export.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/gnome/dialog-chart-export.c -Lsrc/gnome/dialog-chart-export.c -u -r1.1.2.1 -r1.1.2.2
--- src/gnome/dialog-chart-export.c
+++ src/gnome/dialog-chart-export.c
@@ -32,22 +32,20 @@
#include "dialog-utils.h"
#include "gnc-engine-util.h"
#include "global-options.h"
-#include "gnc-trace.h"
-static short int module = MOD_GUI;
+#include "gnc-event.h"
#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;
+ GList *param_ref_list;
}chart_data;
static void
@@ -77,6 +75,23 @@
}
static void
+chart_reference_cb(QofEntity *ent, gpointer user_data)
+{
+ QofEntityReference *reference;
+ QofParam *ref_param;
+ chart_data *data;
+
+ g_return_if_fail(user_data != NULL);
+ data = (chart_data*)user_data;
+ while(data->param_ref_list != NULL) {
+ ref_param = data->param_ref_list->data;
+ reference = qof_entity_get_reference_from(ent, ref_param);
+ qof_session_update_reference_list(data->chart_session, reference);
+ data->param_ref_list = data->param_ref_list->next;
+ }
+}
+
+static void
chart_entity_cb(QofEntity *ent, gpointer user_data)
{
chart_data *data;
@@ -87,21 +102,18 @@
QofBook *book;
QofCollection *coll;
const GUID *guid;
- gboolean success;
+ time_t trans_time;
- success = FALSE;
g_return_if_fail(user_data != NULL);
data = (chart_data*)user_data;
+ trans_time = data->chart_time_t;
+ data->param_ref_list = NULL;
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");
- }
+ qof_entity_copy_to_session(data->chart_session, ent);
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);
@@ -116,7 +128,8 @@
trans = xaccMallocTransaction (book);
xaccTransBeginEdit (trans);
xaccTransSetCurrency (trans, xaccAccountGetCommodity (acc_ent));
- xaccTransSetDateSecs (trans, data->chart_time_t);
+ xaccTransSetDateSecs (trans, trans_time);
+ xaccTransSetDateEnteredSecs (trans, trans_time);
xaccTransSetDescription (trans, OPENING_BALANCE_DESC);
split = xaccMallocSplit (book);
xaccTransAppendSplit (trans, split);
@@ -135,29 +148,16 @@
}
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;
+ chart_data *data;
xml = gnc_glade_xml_new ("chart-export.glade", "chart-export");
-
- glade_xml_signal_connect(xml, "on_dateok_clicked",
- GTK_SIGNAL_FUNC (on_dateok_clicked));
+ data = g_new0(chart_data, 1);
+ glade_xml_signal_connect_data(xml, "on_dateok_clicked",
+ GTK_SIGNAL_FUNC (on_dateok_clicked), data);
dialog = glade_xml_get_widget (xml, "chart-export");
return dialog;
}
@@ -173,57 +173,74 @@
on_dateok_clicked (GtkButton *button, gpointer user_data)
{
guint year, month, day;
- chart_data data;
+ chart_data *data;
GtkCalendar *calendar;
struct tm *chart_tm;
+ GtkWidget *qsffilechooser;
+ GtkWindow *parent;
+ gchar *filename;
+ QofSession *current_session, *chart_session;
+ QofBook *book;
+ QofCollection *coll;
calendar = (GtkCalendar*)gnc_glade_lookup_widget(chart_export, "chart-calendar");
- data.chart_time_t = time(NULL);
- chart_tm = gmtime(&data.chart_time_t);
+ parent = (GtkWindow*)gtk_widget_get_parent ((GtkWidget*)chart_export);
+ data = (chart_data*)user_data;
+ 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;
+ day = chart_tm->tm_mday;
gtk_calendar_get_date(calendar, &year, &month, &day);
+ if((year + 1900) != chart_tm->tm_year) {
chart_tm->tm_year = year - 1900;
+ }
+ if(month != chart_tm->tm_mon) {
chart_tm->tm_mon = month;
- chart_tm->tm_yday = day - 1;
- data.chart_time_t = mktime(chart_tm);
+ }
+ if(day != chart_tm->tm_yday) {
+ chart_tm->tm_mday = day;
+ }
+ 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);
+ filename = g_strdup("/tmp/qsf-chartofaccounts.xml");
chart_session = qof_session_new();
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chart_filechooserdialog));
+ qsffilechooser = gtk_file_chooser_dialog_new("Export Chart of Accounts to QSF XML",
+ parent, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL, GTK_STOCK_CONVERT, GTK_RESPONSE_ACCEPT, NULL);
+ if (gtk_dialog_run (GTK_DIALOG (qsffilechooser)) == GTK_RESPONSE_ACCEPT)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (qsffilechooser));
+ gnc_engine_suspend_events();
qof_session_begin(chart_session, filename, TRUE, TRUE);
- data.chart_session = chart_session;
- data.equity_account = NULL;
-
+ 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)
+ 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());
+ data->equity_account = xaccMallocAccount (qof_session_get_book(chart_session));
+ xaccAccountBeginEdit (data->equity_account);
+ xaccAccountSetName (data->equity_account, EQUITY_ACCOUNT_NAME);
+ xaccAccountSetDescription(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_object_foreach(GNC_ID_ACCOUNT, book, chart_entity_cb, data);
+ data->param_ref_list = qof_class_get_referenceList(GNC_ID_TRANS);
+ qof_object_foreach(GNC_ID_TRANS, book, chart_reference_cb, data);
+ g_list_free(data->param_ref_list);
+ data->param_ref_list = qof_class_get_referenceList(GNC_ID_SPLIT);
+ qof_object_foreach(GNC_ID_SPLIT, book, chart_reference_cb, data);
+ g_list_free(data->param_ref_list);
qof_session_save(chart_session, NULL);
+ gnc_engine_resume_events();
+ }
qof_session_end(chart_session);
- gtk_widget_destroy(chart_filechooserdialog);
+ gtk_widget_destroy(qsffilechooser);
+ g_free(data);
qof_session_set_current_session(current_session);
}
Index: qsf-xml.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml.h,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/backend/qsf/qsf-xml.h -Lsrc/backend/qsf/qsf-xml.h -u -r1.1.2.2 -r1.1.2.3
--- src/backend/qsf/qsf-xml.h
+++ src/backend/qsf/qsf-xml.h
@@ -135,47 +135,6 @@
#include "qofsession-p.h"
#include "qofbook-p.h"
-/* KVP XML
- *
- * <kvp type="ACCOUNT_KVP", path="/book/accounting-period" value="string">week</kvp>
- * (ACCOUNT_KVP only for clarity here, actual is "kvp"
- *
- * <kvp type="kvp" path="/from-sched-xaction" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
- *
- * The relevance of kvp type won't be evident in GnuCash, they all use "kvp".
- *
- * need switch statement on kvp_value_get_type(val) val = kvp_value* val,
- * itself used by g_hash_table_foreach(kvp_frame_get_hash(frame), add_kvp_slot, ret);
- * xmlNodePtr ret;
- *
- * Then retrieve the kvp_frame as the parameter from the entity. Use that frame to
- * copy the key and value - become slots for this entity.
- *
- * kvp:key == path
- * kvp:value == content converted according to the type of value.
- * kvp:type == QofParam->name
- *
- * Elsewhere:
- * string:type == QofParam->name
- * i.e. <string type="to_do_note"/> == a to_do_note type string
- *
- *
- * Consider wholesale change from type="" to name="" for object parameters?
- * (but name has special meaning in the KVP documentation).
- *
- *
- * <kvp type="kvp" path="/from-sched-xaction" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
- * A kvp type KVP parameter located at $path containing a $value.
- *
- * A non-GnuCash example helps:
- * <kvp type="pilot_addr_kvp" path="/user/name" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
- * A pilot_addr_kvp type KVP parameter located at /user/name containing a guid value.
- *
- *
- *
- * */
-
-
typedef enum {
QSF_UNDEF = 0, /**< Initial undefined value. */
IS_QSF_MAP, /**< A QSF map */
@@ -184,7 +143,7 @@
OUR_QSF_OBJ, /**< A QSF object that can be loaded without a map. */
}qsf_type;
-/** \internal Holds a description of the QofObject.
+/** \brief Holds a description of the QofObject.
Used when converting QOF objects from another application. The incoming,
\b unknown, objects need to be stored prior to conversion. This allows
@@ -214,8 +173,23 @@
#define QSF_BOOK_COUNT "count" /**< Sequential counter of each book in this file */
#define QSF_OBJECT_TAG "object" /**< Second level child: object tag */
#define QSF_OBJECT_TYPE "type" /**< QSF parameter name for object type specifiers */
+
+/** @name Representing KVP as XML
+
+<kvp type="kvp" path="/from-sched-xaction" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
+A kvp type KVP parameter located at $path containing a GUID $value.
+
+The relevance of type="kvp" won't be evident in GnuCash, they all use "kvp".
+
+A non-GnuCash example helps:
+<kvp type="pilot_addr_kvp" path="/user/name" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
+A pilot_addr_kvp type KVP parameter located at /user/name containing a guid value.
+@{ */
+
#define QSF_OBJECT_KVP "path" /**< The path to this KVP value in the entity frame. */
#define QSF_OBJECT_VALUE "value" /**< The KVP Value. */
+/** @} */
+
#define QSF_OBJECT_COUNT "count" /**< Sequential counter for each QSF object in this file */
#define QSF_XML_VERSION "1.0" /**< The current XML version. */
#define MAP_ROOT_TAG "qsf-map" /**< Top level root tag for QSF Maps */
@@ -437,7 +411,7 @@
int count; /**< sequential counter for each object in the book */
GList *qsf_object_list; /**< list of qsf_objects */
GSList *qsf_sequence; /**< Parameter list sorted into QSF order */
- GHashTable *referenceTable; /**< Table of references, ::QofEntityReference. */
+ GList *referenceList; /**< Table of references, ::QofEntityReference. */
GHashTable *qsf_parameter_hash; /**< Hashtable of parameters for each object */
GHashTable *qsf_calculate_hash, *qsf_default_hash, *qsf_define_hash;
GSList *supported_types; /**< The partial list of QOF types currently supported, in QSF order. */
Index: qsf-xml.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml.c,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -Lsrc/backend/qsf/qsf-xml.c -Lsrc/backend/qsf/qsf-xml.c -u -r1.1.2.3 -r1.1.2.4
--- src/backend/qsf/qsf-xml.c
+++ src/backend/qsf/qsf-xml.c
@@ -34,8 +34,8 @@
{
g_hash_table_destroy(params->qsf_calculate_hash);
g_hash_table_destroy(params->qsf_default_hash);
- if(params->referenceTable) {
- g_hash_table_destroy(params->referenceTable);
+ if(params->referenceList) {
+ g_list_free(params->referenceList);
}
g_slist_free(params->supported_types);
xmlFreeDoc(params->output_doc);
Index: qsf-backend.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-backend.c,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -Lsrc/backend/qsf/qsf-backend.c -Lsrc/backend/qsf/qsf-backend.c -u -r1.1.2.4 -r1.1.2.5
--- src/backend/qsf/qsf-backend.c
+++ src/backend/qsf/qsf-backend.c
@@ -28,6 +28,10 @@
#include "qsf-dir.h"
#include <errno.h>
+#define QSF_TYPE_BINARY "binary"
+#define QSF_TYPE_GLIST "glist"
+#define QSF_TYPE_FRAME "frame"
+
static short int module = MOD_BACKEND;
struct QSFBackend_s
@@ -64,7 +68,7 @@
params->qsf_default_hash = g_hash_table_new(g_str_hash, g_str_equal);
params->qsf_define_hash = g_hash_table_new(g_str_hash, g_str_equal);
params->qsf_calculate_hash = g_hash_table_new(g_str_hash, g_str_equal);
- params->referenceTable = NULL;
+ params->referenceList = NULL;
params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_STRING);
params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_GUID);
params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_BOOLEAN);
@@ -226,10 +230,7 @@
qsf_ns = qsf_root->ns;
iter.ns = qsf_ns;
book = params->book;
- params->referenceTable = (GHashTable*)qof_book_get_data(book, ENTITYREFERENCE);
- if(params->referenceTable == NULL) {
- params->referenceTable = g_hash_table_new(NULL, NULL);
- }
+ params->referenceList = (GList*)qof_book_get_data(book, ENTITYREFERENCE);
qsf_node_foreach(qsf_root, qsf_book_node_handler, &iter, params);
object_list = g_list_copy(params->qsf_object_list);
while(object_list != NULL)
@@ -242,7 +243,7 @@
g_hash_table_foreach(params->qsf_parameter_hash, qsf_object_commitCB, params);
object_list = g_list_next(object_list);
}
- qof_book_set_data(book, ENTITYREFERENCE, params->referenceTable);
+ qof_book_set_data(book, ENTITYREFERENCE, params->referenceList);
return TRUE;
}
@@ -250,15 +251,40 @@
qsf_object_sequence(QofParam *qof_param, gpointer data)
{
qsf_param *params;
+ GSList *checklist, *result;
g_return_if_fail(data != NULL);
params = (qsf_param*) data;
+ result = NULL;
+ checklist = NULL;
+ params->knowntype = FALSE;
+ checklist = g_slist_copy(params->supported_types);
+ for(result = checklist; result != NULL; result = result->next)
+ {
+ if(0 == safe_strcmp((QofIdType)result->data, qof_param->param_type))
+ {
+ params->knowntype = TRUE;
+ }
+ }
+ g_slist_free(checklist);
if(0 == safe_strcmp(qof_param->param_type, params->qof_type))
{
params->qsf_sequence = g_slist_append(params->qsf_sequence, qof_param);
+ params->knowntype = TRUE;
+ }
+ /* handle params->qof_type = QOF_TYPE_GUID and qof_param->param_type != known type */
+ if(0 == safe_strcmp(params->qof_type, QOF_TYPE_GUID)
+ && (params->knowntype == FALSE))
+ {
+ params->qsf_sequence = g_slist_append(params->qsf_sequence, qof_param);
+ params->knowntype = TRUE;
}
}
+/* receives each entry from supported_types in sequence
+ type = qof data type from supported list
+ user_data = params. Holds object type
+*/
static void
qsf_supported_parameters(gpointer type, gpointer user_data)
{
@@ -279,50 +305,78 @@
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; }
+ if(0 == safe_strcmp(QSF_TYPE_BINARY, type_string)) { return KVP_TYPE_BINARY; }
+ if(0 == safe_strcmp(QSF_TYPE_GLIST, type_string)) { return KVP_TYPE_GLIST; }
+ if(0 == safe_strcmp(QSF_TYPE_FRAME, type_string)) { return KVP_TYPE_FRAME; }
return 0;
}
static void
-qsf_from_kvp_helper(gpointer key, gpointer value, gpointer data)
+qsf_from_kvp_helper(const char *path, KvpValue *content, gpointer data)
{
qsf_param *params;
QofParam *qof_param;
xmlNodePtr node;
- KvpValue *content;
- gchar *path;
params = (qsf_param*)data;
- qof_param = (QofParam*)params->qof_param;
- node = params->output_node;
- path = (gchar*)key;
- content = (KvpValue*)value;
- xmlNodeAddContent(node, kvp_value_to_bare_string(content));
- xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
- xmlNewProp(node, QSF_OBJECT_KVP, path);
+ qof_param = params->qof_param;
+ g_return_if_fail(params != NULL);
switch(kvp_value_get_type(content))
{
case KVP_TYPE_STRING:
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_STRING);
break;
case KVP_TYPE_GUID:
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_GUID);
break;
case KVP_TYPE_BINARY:
-// xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_STRING);
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
+ xmlNewProp(node, QSF_OBJECT_VALUE, QSF_TYPE_BINARY);
break;
case KVP_TYPE_GLIST:
-// xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_STRING);
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
+ xmlNewProp(node, QSF_OBJECT_VALUE, QSF_TYPE_GLIST);
break;
case KVP_TYPE_FRAME:
-// xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_STRING);
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
+ xmlNewProp(node, QSF_OBJECT_VALUE, QSF_TYPE_FRAME);
break;
case KVP_TYPE_GINT64:
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_INT64);
break;
case KVP_TYPE_DOUBLE:
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_DOUBLE);
break;
case KVP_TYPE_NUMERIC:
+ node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+ xmlNodeAddContent(node, kvp_value_to_bare_string(content));
+ xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_KVP, path);
xmlNewProp(node, QSF_OBJECT_VALUE, QOF_TYPE_NUMERIC);
break;
default:
@@ -330,24 +384,64 @@
}
}
+/******* reference handling ***********/
+
+static gint
+qof_reference_list_cb(gconstpointer a, gconstpointer b)
+{
+ const QofEntityReference *aa;
+ const QofEntityReference *bb;
+
+ aa = (QofEntityReference*)a;
+ bb = (QofEntityReference*) b;
+ g_return_val_if_fail((aa != NULL), 1);
+ g_return_val_if_fail((bb != NULL), 1);
+ g_return_val_if_fail((aa->type != NULL), 1);
+ if((0 == guid_compare(bb->ent_guid, aa->ent_guid))
+ &&(0 == safe_strcmp(bb->type, aa->type)))
+ {
+ return 0;
+ }
+ return 1;
+}
+
+static QofEntityReference*
+qof_reference_lookup(GList *referenceList, QofEntityReference *find)
+{
+ GList *single_ref;
+ QofEntityReference *ent_ref;
+
+ if(referenceList == NULL) { return NULL; }
+ g_return_val_if_fail(find != NULL, NULL);
+ single_ref = NULL;
+ ent_ref = NULL;
+ single_ref = g_list_find_custom(referenceList, find, qof_reference_list_cb);
+ if(single_ref == NULL) { return ent_ref; }
+ ent_ref = (QofEntityReference*)single_ref->data;
+ g_list_free(single_ref);
+ return ent_ref;
+}
+
/*=====================================
Convert QofEntity to QSF XML node
+qof_param holds the parameter sequence.
=======================================*/
static void
qsf_entity_foreach(QofEntity *ent, gpointer data)
{
- QofEntityReference *reference;
+ QofEntityReference *reference, *starter;
qsf_param *params;
- GSList *param_list;
+ GSList *param_list, *supported;
xmlNodePtr node, object_node;
xmlNsPtr ns;
- gchar *string_buffer, qsf_guid[GUID_ENCODING_LENGTH + 1];
+ gchar *string_buffer, qsf_guid[GUID_ENCODING_LENGTH + 1], *ref_name;
GString *buffer;
QofParam *qof_param;
KvpFrame *qsf_kvp;
- GHashTable *kvp_hash;
int param_count;
gboolean own_guid;
+ const GUID *cm_guid;
+ char cm_sa[GUID_ENCODING_LENGTH + 1];
g_return_if_fail(data != NULL);
params = (qsf_param*)data;
@@ -365,46 +459,65 @@
g_return_if_fail(qof_param != NULL);
if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_GUID))
{
- if(!own_guid) {
- node = xmlAddChild(object_node, xmlNewNode(ns, qof_param->param_type));
- string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent));
+ if(!own_guid)
+ {
+ cm_guid = qof_entity_get_guid(ent);
+ node = xmlAddChild(object_node, xmlNewNode(ns, QOF_TYPE_GUID));
+ guid_to_string_buff(cm_guid, cm_sa);
+ string_buffer = g_strdup(cm_sa);
xmlNodeAddContent(node, string_buffer);
- xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
+ xmlNewProp(node, QSF_OBJECT_TYPE , QOF_PARAM_GUID);
own_guid = TRUE;
}
- reference = (QofEntityReference*)g_hash_table_lookup(params->referenceTable,
- qof_entity_get_guid(ent));
+ PINFO (" own_guid=%d ent->e_type=%s qof_param->param_name=%s",
+ own_guid, ent->e_type, qof_param->param_name);
+/* if((qof_param->param_setfcn != NULL) && (qof_param->param_getfcn != NULL))
+ {*/
+ starter = g_new(QofEntityReference, 1);
+ starter->ent_guid = qof_entity_get_guid(ent);
+ /* Reading ent->e_type can seg fault if the above check on get() and set() is removed. */
+ /* Some entities seem to be invalid artefacts. Why? */
+ starter->type = g_strdup(ent->e_type);
+ starter->param = qof_param;
+ starter->ref_guid = NULL;
+ reference = qof_reference_lookup(params->referenceList, starter);
+ g_free(starter);
if(reference != NULL) {
- if(0 == safe_strcmp(reference->type, qof_param->param_name))
- {
- node = xmlAddChild(object_node, xmlNewNode(ns, qof_param->param_type));
- guid_to_string_buff(reference->guid, qsf_guid);
+ ref_name = g_strdup(reference->param->param_name);
+ node = xmlAddChild(object_node, xmlNewNode(ns, QOF_TYPE_GUID));
+ guid_to_string_buff(reference->ref_guid, qsf_guid);
+ PINFO ("reference found=%s %s %s", ref_name, qsf_guid, reference->type);
xmlNodeAddContent(node, qsf_guid);
- xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
- }
+ xmlNewProp(node, QSF_OBJECT_TYPE ,ref_name);
+ g_free(ref_name);
}
+ param_list = g_slist_next(param_list);
+ continue;
+/* }*/
}
if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_KVP))
{
/** Special KVP handling - the book_merge function doesn't render KVP */
qsf_kvp = kvp_frame_copy(qof_param->param_getfcn(ent,qof_param));
- kvp_hash = kvp_frame_get_hash(qsf_kvp);
params->qof_param = qof_param;
- if(kvp_hash)
- {
- node = xmlAddChild(object_node, xmlNewNode(ns, qof_param->param_type));
- params->output_node = node;
- g_hash_table_foreach(kvp_hash, qsf_from_kvp_helper, params);
- }
+ params->output_node = object_node;
+ kvp_frame_for_each_slot(qsf_kvp, qsf_from_kvp_helper, params);
}
if((qof_param->param_setfcn != NULL) && (qof_param->param_getfcn != NULL))
{
+ supported = g_slist_copy(params->supported_types);
+ for( supported = g_slist_copy(params->supported_types);
+ supported != NULL; supported = g_slist_next(supported))
+ {
+ if(0 == safe_strcmp((const char*)supported->data, (const char*)qof_param->param_type))
+ {
node = xmlAddChild(object_node, xmlNewNode(ns, qof_param->param_type));
string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent));
xmlNodeAddContent(node, string_buffer);
xmlNewProp(node, QSF_OBJECT_TYPE ,qof_param->param_name);
}
-
+ }
+ }
param_list = g_slist_next(param_list);
}
}
@@ -448,10 +561,7 @@
params = g_new(qsf_param, 1);
qsf_param_init(params);
params->book = book;
- params->referenceTable = (GHashTable*)qof_book_get_data(book, ENTITYREFERENCE);
- if(params->referenceTable == NULL) {
- params->referenceTable = g_hash_table_new(NULL, NULL);
- }
+ params->referenceList = g_list_copy((GList*)qof_book_get_data(book, ENTITYREFERENCE));
doc = xmlNewDoc(QSF_XML_VERSION);
top_node = xmlNewNode(NULL, QSF_ROOT_TAG);
xmlDocSetRootElement(doc, top_node);
@@ -465,7 +575,6 @@
xmlNewChild(params->book_node, params->qsf_ns, QSF_BOOK_GUID, buffer);
params->output_doc = doc;
params->book_node = node;
-// params->output_node = node;
qof_object_foreach_type(qsf_foreach_obj_type, params);
return params->output_doc;
}
@@ -634,8 +743,6 @@
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;
@@ -644,7 +751,6 @@
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;
@@ -700,20 +806,14 @@
return;
}
reference_type = xmlGetProp(node, QSF_OBJECT_TYPE);
- if(0 == safe_strcmp(qsf_ent->e_type, reference_type))
+ if(0 == safe_strcmp(QOF_PARAM_GUID, reference_type))
{
qof_entity_set_guid(qsf_ent, cm_guid);
}
else {
- reference = g_new(QofEntityReference, 1);
- reference->type = g_strdup(qsf_ent->e_type);
- reference->guid = g_new(GUID, 1);
- cm_const_guid = qof_entity_get_guid(qsf_ent);
- guid_to_string_buff(cm_const_guid, cm_sa);
- cm_string = g_strdup(cm_sa);
- if(TRUE == string_to_guid(cm_string, reference->guid)) {
- cm_guid = &qsf_ent->guid;
- g_hash_table_insert(params->referenceTable, cm_guid, reference);
+ reference = qof_entity_get_reference_from(qsf_ent, cm_param);
+ if(reference) {
+ params->referenceList = g_list_append(params->referenceList, reference);
}
}
}
@@ -763,7 +863,6 @@
if(safe_strcmp(qof_type, QOF_TYPE_CHAR) == 0) {
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: chart-export.glade
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/glade/Attic/chart-export.glade,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/gnome/glade/chart-export.glade -Lsrc/gnome/glade/chart-export.glade -u -r1.1.2.1 -r1.1.2.2
--- src/gnome/glade/chart-export.glade
+++ src/gnome/glade/chart-export.glade
@@ -11,7 +11,6 @@
<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>
@@ -178,7 +177,6 @@
<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>
More information about the gnucash-changes
mailing list