* Plug-in Extensions for backends, so pluggable objects can

provide backend-support without changing the core backend
	implementation.

	* src/engine/gncObject: Add a 'mark_clean' data-type method()
				add backend extension registration.

	* src/engine/gnc-book.c: use mark_clean object interface

	* src/backend/file/io-gncxml-v2: use the backend extensions

	* src/business/business-core/gnc*: add the mark_clean methods
					   add commodities to many objects

	* src/business/business-core/gncInvoice.c: fix GetPaidTxn() bug

	* src/business/business-core/file: the XML backend extensions for
	business objects.

	* src/business/business-gnome/dialog-*: supply default commodities


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@6770 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins 2002-03-04 19:34:52 +00:00
parent 136d8e4bd4
commit cfd8718a42
49 changed files with 4083 additions and 30 deletions

View File

@ -1,3 +1,26 @@
2002-03-04 Derek Atkins <warlord@MIT.EDU>
* Plug-in Extensions for backends, so pluggable objects can
provide backend-support without changing the core backend
implementation.
* src/engine/gncObject: Add a 'mark_clean' data-type method()
add backend extension registration.
* src/engine/gnc-book.c: use mark_clean object interface
* src/backend/file/io-gncxml-v2: use the backend extensions
* src/business/business-core/gnc*: add the mark_clean methods
add commodities to many objects
* src/business/business-core/gncInvoice.c: fix GetPaidTxn() bug
* src/business/business-core/file: the XML backend extensions for
business objects.
* src/business/business-gnome/dialog-*: supply default commodities
2002-02-17 Christian Stimming <stimming@tuhh.de>
* src/report/report-system/html-utilities.scm: Added support for

View File

@ -891,6 +891,7 @@ AC_OUTPUT(
src/business/Makefile
src/business/business-core/Makefile
src/business/business-core/test/Makefile
src/business/business-core/file/Makefile
src/business/business-gnome/Makefile
src/business/business-ledger/Makefile

View File

@ -35,6 +35,7 @@
#include "Scrub.h"
#include "Transaction.h"
#include "TransLog.h"
#include "gncObject.h"
#include "sixtp-dom-parsers.h"
#include "io-gncxml-v2.h"
@ -49,6 +50,16 @@
static short module = MOD_IO;
/* Callback structure */
struct file_backend {
gboolean ok;
gpointer data;
sixtp_gdv2 * gd;
const char * tag;
sixtp * parser;
FILE * out;
GNCBook * book;
};
#define GNC_V2_STRING "gnc-v2"
const gchar *book_version_string;
@ -354,6 +365,24 @@ add_pricedb_local(sixtp_gdv2 *data, GNCPriceDB *db)
return TRUE;
}
static void
do_counter_cb (const char *type, gpointer data_p, gpointer be_data_p)
{
GncXmlDataType_t *data = data_p;
struct file_backend *be_data = be_data_p;
g_return_if_fail (type && data && be_data);
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
if (be_data->ok == TRUE)
return;
if (!safe_strcmp (be_data->tag, data->type_name))
be_data->ok = TRUE;
/* XXX: should we do anything with this counter? */
}
static gboolean
gnc_counter_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
@ -415,10 +444,19 @@ gnc_counter_end_handler(gpointer data_for_children,
}
else
{
PERR("Unknown type: %s",
type ? type : "(null)");
xmlFree (type);
return FALSE;
struct file_backend be_data;
be_data.ok = FALSE;
be_data.tag = type;
gncObjectForeachBackend (GNC_FILE_BACKEND, do_counter_cb, &be_data);
if (be_data.ok == FALSE)
{
PERR("Unknown type: %s", type ? type : "(null)");
xmlFree (type);
return FALSE;
}
}
xmlFree (type);
@ -461,6 +499,26 @@ static const char *TRANSACTION_TAG = "gnc:transaction";
static const char *SCHEDXACTION_TAG = "gnc:schedxaction";
static const char *TEMPLATE_TRANSACTION_TAG = "gnc:template-transactions";
static void
add_item_cb (const char *type, gpointer data_p, gpointer be_data_p)
{
GncXmlDataType_t *data = data_p;
struct file_backend *be_data = be_data_p;
g_return_if_fail (type && data && be_data);
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
if (be_data->ok)
return;
if (!safe_strcmp (be_data->tag, data->type_name)) {
if (data->add_item)
(data->add_item)(be_data->gd, be_data->data);
be_data->ok = TRUE;
}
}
static gboolean
book_callback(const char *tag, gpointer globaldata, gpointer data)
{
@ -492,7 +550,19 @@ book_callback(const char *tag, gpointer globaldata, gpointer data)
}
else
{
PWARN ("unexpected tag %s", tag);
struct file_backend be_data;
be_data.ok = FALSE;
be_data.tag = tag;
be_data.gd = gd;
be_data.data = data;
gncObjectForeachBackend (GNC_FILE_BACKEND, add_item_cb, &be_data);
if (be_data.ok == FALSE)
{
PWARN ("unexpected tag %s", tag);
}
}
return TRUE;
}
@ -515,6 +585,26 @@ generic_callback(const char *tag, gpointer globaldata, gpointer data)
return TRUE;
}
static void
add_parser_cb (const char *type, gpointer data_p, gpointer be_data_p)
{
GncXmlDataType_t *data = data_p;
struct file_backend *be_data = be_data_p;
g_return_if_fail (type && data && be_data);
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
if (be_data->ok == FALSE)
return;
if (data->create_parser)
if(!sixtp_add_some_sub_parsers(
be_data->parser, TRUE,
data->type_name, (data->create_parser)(),
NULL, NULL))
be_data->ok = FALSE;
}
gboolean
gnc_session_load_from_xml_file_v2(
GNCSession *session,
@ -525,6 +615,7 @@ gnc_session_load_from_xml_file_v2(
sixtp *top_parser;
sixtp *main_parser;
sixtp *book_parser;
struct file_backend be_data;
gd = g_new0(sixtp_gdv2, 1);
@ -593,6 +684,12 @@ gnc_session_load_from_xml_file_v2(
return FALSE;
}
be_data.ok = TRUE;
be_data.parser = book_parser;
gncObjectForeachBackend (GNC_FILE_BACKEND, add_parser_cb, &be_data);
if (be_data.ok == FALSE)
return FALSE;
/* stop logging while we load */
xaccLogDisable ();
@ -610,13 +707,8 @@ gnc_session_load_from_xml_file_v2(
if (!gnc_book_get_pricedb (book))
gnc_book_set_pricedb (book, gnc_pricedb_create (book));
/* mark the newly read group as saved, since the act of putting
* it together will have caused it to be marked up as not-saved.
*/
xaccGroupMarkSaved (gnc_book_get_group(book));
/* also mark the pricedb as saved for the same reasons */
gnc_pricedb_mark_clean (gnc_book_get_pricedb (book));
/* Mark the book as saved */
gnc_book_mark_saved (book);
/* Fix account and transaction commodities */
xaccGroupScrubCommodities (gnc_book_get_group(book), book);
@ -703,9 +795,38 @@ static void write_transactions (FILE *out, GNCBook *book);
static void write_template_transaction_data (FILE *out, GNCBook *book);
static void write_schedXactions(FILE *out, GNCBook *book);
static void
write_counts_cb (const char *type, gpointer data_p, gpointer be_data_p)
{
GncXmlDataType_t *data = data_p;
struct file_backend *be_data = be_data_p;
g_return_if_fail (type && data && be_data);
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
if (data->get_count)
write_counts (be_data->out, data->type_name,
(data->get_count) (be_data->book),
NULL);
}
static void
write_data_cb (const char *type, gpointer data_p, gpointer be_data_p)
{
GncXmlDataType_t *data = data_p;
struct file_backend *be_data = be_data_p;
g_return_if_fail (type && data && be_data);
g_return_if_fail (data->version == GNC_FILE_BACKEND_VERS);
if (data->write)
(data->write)(be_data->out, be_data->book);
}
static void
write_book(FILE *out, GNCBook *book)
{
struct file_backend be_data;
#ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
/* We can't just blast out the dom tree, because the dom tree
@ -728,6 +849,9 @@ write_book(FILE *out, GNCBook *book)
xmlFreeNode(node);
#endif
be_data.out = out;
be_data.book = book;
fprintf( out, "<%s version=\"%s\">\n", BOOK_TAG, book_version_string );
write_book_parts (out, book);
@ -743,6 +867,8 @@ write_book(FILE *out, GNCBook *book)
g_list_length( gnc_book_get_schedxactions(book) ),
NULL);
gncObjectForeachBackend (GNC_FILE_BACKEND, write_counts_cb, &be_data);
write_commodities(out, book);
write_pricedb(out, book);
write_accounts(out, book);
@ -750,6 +876,8 @@ write_book(FILE *out, GNCBook *book)
write_template_transaction_data(out, book);
write_schedXactions(out, book);
gncObjectForeachBackend (GNC_FILE_BACKEND, write_data_cb, &be_data);
fprintf( out, "</%s>\n", BOOK_TAG );
}

View File

@ -41,6 +41,8 @@
#include "gnc-pricedb.h"
#include "SchedXaction.h"
#include "sixtp.h"
typedef struct
{
int accounts_total;
@ -69,6 +71,36 @@ typedef struct
void (*countCallback)(const char *type, load_counter counter);
} sixtp_gdv2;
/**
* Struct used to pass in a new data type for XML storage. This contains
* the set of callbacks to read and write XML for new data objects.. New
* types should register an instance of this object with the engine.
*
* The create_parser() method will create a new sixtp parser for this
* data type.
*
* The add_item() method takes a local state and a new object of this type
* and the method implementation should do whatever is necessary to cleanup
* the object and (maybe) add it into the book stored in the local-state.
*
* The get_count() method returns the number of items of this type.
*
* The write() method writes out all the objects of this particular type
* in the book and stores the XML in the FILE.
*/
#define GNC_FILE_BACKEND "gnc:file:2"
#define GNC_FILE_BACKEND_VERS 2
typedef struct
{
int version; /* backend version number */
const char * type_name; /* The XML tag for this type */
sixtp * (*create_parser) (void);
gboolean (*add_item)(sixtp_gdv2 *, gpointer obj);
int (*get_count) (GNCBook *);
void (*write) (FILE*, GNCBook*);
} GncXmlDataType_t;
/**
* Struct used to pass the account group/accounts and trasnactions in
* the <gnc:template-transactions> section between the parser in

View File

@ -1,4 +1,4 @@
SUBDIRS = . test
SUBDIRS = . test file
pkglib_LTLIBRARIES = libgw-business-core.la libgncmod-business-core.la

View File

@ -0,0 +1,6 @@
*.lo
*.la
.deps
.libs
Makefile
Makefile.in

View File

@ -0,0 +1,38 @@
SUBDIRS = .
pkglib_LTLIBRARIES = libgncmod-business-backend-file.la
AM_CFLAGS = \
-I.. -I../../.. \
-I${top_srcdir}/src/backend \
-I${top_srcdir}/src/backend/file \
-I${top_srcdir}/src/engine \
-I${top_srcdir}/src/gnc-module \
${GLIB_CFLAGS}
libgncmod_business_backend_file_la_SOURCES = \
gncmod-business-backend-file.c \
gnc-address-xml-v2.c \
gnc-customer-xml-v2.c \
gnc-employee-xml-v2.c \
gnc-entry-xml-v2.c \
gnc-invoice-xml-v2.c \
gnc-job-xml-v2.c \
gnc-order-xml-v2.c \
gnc-owner-xml-v2.c \
gnc-vendor-xml-v2.c
noinst_HEADERS = \
gnc-address-xml-v2.h \
gnc-customer-xml-v2.h \
gnc-employee-xml-v2.h \
gnc-entry-xml-v2.h \
gnc-invoice-xml-v2.h \
gnc-job-xml-v2.h \
gnc-order-xml-v2.h \
gnc-owner-xml-v2.h \
gnc-vendor-xml-v2.h
libgncmod_business_backend_file_la_LDFLAGS = -module
libgncmod_business_backend_file_la_LIBADD = \
${GLIB_LIBS} ${GNOME_XML_LIB}

View File

@ -0,0 +1,205 @@
/********************************************************************\
* gnc-address-xml-v2.c -- address xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gnc-address-xml-v2.h"
#include "gnc-engine-util.h"
static short module = MOD_IO;
const gchar *address_version_string = "2.0.0";
/* ids */
#define addr_name_string "addr:name"
#define addr_addr1_string "addr:addr1"
#define addr_addr2_string "addr:addr2"
#define addr_addr3_string "addr:addr3"
#define addr_addr4_string "addr:addr4"
#define addr_phone_string "addr:phone"
#define addr_fax_string "addr:fax"
#define addr_email_string "addr:email"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
xmlNodePtr
gnc_address_to_dom_tree (const char *tag, GncAddress *addr)
{
xmlNodePtr ret;
ret = xmlNewNode(NULL, tag);
xmlSetProp(ret, "version", address_version_string);
maybe_add_string (ret, addr_name_string, gncAddressGetName (addr));
maybe_add_string (ret, addr_addr1_string, gncAddressGetAddr1 (addr));
maybe_add_string (ret, addr_addr2_string, gncAddressGetAddr2 (addr));
maybe_add_string (ret, addr_addr3_string, gncAddressGetAddr3 (addr));
maybe_add_string (ret, addr_addr4_string, gncAddressGetAddr4 (addr));
maybe_add_string (ret, addr_phone_string, gncAddressGetPhone (addr));
maybe_add_string (ret, addr_fax_string, gncAddressGetFax (addr));
maybe_add_string (ret, addr_email_string, gncAddressGetEmail (addr));
return ret;
}
/***********************************************************************/
struct address_pdata
{
GncAddress *address;
};
static gboolean
set_string(xmlNodePtr node, GncAddress* addr,
void (*func)(GncAddress *addr, const char *txt))
{
gchar* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(addr, txt);
g_free(txt);
return TRUE;
}
static gboolean
address_name_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetName);
}
static gboolean
address_addr1_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetAddr1);
}
static gboolean
address_addr2_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetAddr2);
}
static gboolean
address_addr3_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetAddr3);
}
static gboolean
address_addr4_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetAddr4);
}
static gboolean
address_phone_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetPhone);
}
static gboolean
address_fax_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetFax);
}
static gboolean
address_email_handler (xmlNodePtr node, gpointer addr_pdata)
{
struct address_pdata *pdata = addr_pdata;
return set_string(node, pdata->address, gncAddressSetEmail);
}
static struct dom_tree_handler address_handlers_v2[] = {
{ addr_name_string, address_name_handler, 0, 0 },
{ addr_addr1_string, address_addr1_handler, 0, 0 },
{ addr_addr2_string, address_addr2_handler, 0, 0 },
{ addr_addr3_string, address_addr3_handler, 0, 0 },
{ addr_addr4_string, address_addr4_handler, 0, 0 },
{ addr_phone_string, address_phone_handler, 0, 0 },
{ addr_fax_string, address_fax_handler, 0, 0 },
{ addr_email_string, address_email_handler, 0, 0 },
{ NULL, 0, 0, 0 }
};
gboolean
gnc_dom_tree_to_address (xmlNodePtr node, GncAddress *address)
{
struct address_pdata addr_pdata;
gboolean successful;
addr_pdata.address = address;
successful = dom_tree_generic_parse (node, address_handlers_v2,
&addr_pdata);
if (!successful)
{
PERR ("failed to parse address tree");
}
return successful;
}

View File

@ -0,0 +1,14 @@
/* gnc-address-xml-v2.h -- Address XML header
*
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_ADDRESS_XML_V2_H
#define GNC_ADDRESS_XML_V2_H
#include "gncAddress.h"
gboolean gnc_dom_tree_to_address (xmlNodePtr node, GncAddress *address);
xmlNodePtr gnc_address_to_dom_tree (const char *tag, GncAddress *addr);
#endif /* GNC_ADDRESS_XML_V2_H */

View File

@ -0,0 +1,428 @@
/********************************************************************\
* gnc-customer-xml-v2.c -- customer xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncCustomerP.h"
#include "gnc-customer-xml-v2.h"
#include "gnc-address-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_CUSTOMER_MODULE_NAME
static short module = MOD_IO;
const gchar *customer_version_string = "2.0.0";
/* ids */
#define gnc_customer_string "gnc:GncCustomer"
#define cust_name_string "cust:name"
#define cust_guid_string "cust:guid"
#define cust_id_string "cust:id"
#define cust_addr_string "cust:addr"
#define cust_shipaddr_string "cust:shipaddr"
#define cust_notes_string "cust:notes"
#define cust_terms_string "cust:terms"
#define cust_taxincluded_string "cust:taxincluded"
#define cust_active_string "cust:active"
#define cust_discount_string "cust:discount"
#define cust_credit_string "cust:credit"
#define cust_commodity_string "cust:commodity"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static xmlNodePtr
customer_dom_tree_create (GncCustomer *cust)
{
xmlNodePtr ret;
gnc_numeric num;
ret = xmlNewNode(NULL, gnc_customer_string);
xmlSetProp(ret, "version", customer_version_string);
xmlAddChild(ret, guid_to_dom_tree(cust_guid_string,
gncCustomerGetGUID (cust)));
xmlAddChild(ret, text_to_dom_tree(cust_name_string,
gncCustomerGetName (cust)));
xmlAddChild(ret, text_to_dom_tree(cust_id_string,
gncCustomerGetID (cust)));
xmlAddChild(ret, gnc_address_to_dom_tree(cust_addr_string,
gncCustomerGetAddr (cust)));
xmlAddChild(ret, gnc_address_to_dom_tree(cust_shipaddr_string,
gncCustomerGetShipAddr (cust)));
maybe_add_string (ret, cust_notes_string, gncCustomerGetNotes (cust));
maybe_add_string (ret, cust_terms_string, gncCustomerGetTerms (cust));
xmlAddChild(ret, int_to_dom_tree(cust_taxincluded_string,
gncCustomerGetTaxIncluded (cust)));
xmlAddChild(ret, int_to_dom_tree(cust_active_string,
gncCustomerGetActive (cust)));
num = gncCustomerGetDiscount (cust);
xmlAddChild(ret, gnc_numeric_to_dom_tree(cust_discount_string, &num));
num = gncCustomerGetCredit (cust);
xmlAddChild(ret, gnc_numeric_to_dom_tree(cust_credit_string, &num));
xmlAddChild
(ret,
commodity_ref_to_dom_tree(cust_commodity_string,
gncCustomerGetCommodity (cust)));
return ret;
}
/***********************************************************************/
struct customer_pdata
{
GncCustomer *customer;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncCustomer* cust,
void (*func)(GncCustomer *cust, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(cust, txt);
g_free(txt);
return TRUE;
}
static gboolean
customer_name_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return set_string(node, pdata->customer, gncCustomerSetName);
}
static gboolean
customer_guid_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
GUID *guid;
GncCustomer *cust;
guid = dom_tree_to_guid(node);
g_return_val_if_fail(guid, FALSE);
cust = gncCustomerLookup (pdata->book, guid);
if (cust) {
gncCustomerDestroy (pdata->customer);
pdata->customer = cust;
} else {
gncCustomerSetGUID(pdata->customer, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
customer_id_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return set_string(node, pdata->customer, gncCustomerSetID);
}
static gboolean
customer_notes_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return set_string(node, pdata->customer, gncCustomerSetNotes);
}
static gboolean
customer_terms_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return set_string(node, pdata->customer, gncCustomerSetTerms);
}
static gboolean
customer_addr_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return gnc_dom_tree_to_address (node, gncCustomerGetAddr(pdata->customer));
}
static gboolean
customer_shipaddr_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
return gnc_dom_tree_to_address (node,
gncCustomerGetShipAddr(pdata->customer));
}
static gboolean
customer_taxincluded_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncCustomerSetTaxIncluded(pdata->customer, (gboolean)val);
return ret;
}
static gboolean
customer_active_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncCustomerSetActive(pdata->customer, (gboolean)val);
return ret;
}
static gboolean
customer_discount_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
gnc_numeric *val;
val = dom_tree_to_gnc_numeric(node);
g_return_val_if_fail(val, FALSE);
gncCustomerSetDiscount(pdata->customer, *val);
g_free (val);
return TRUE;
}
static gboolean
customer_credit_handler (xmlNodePtr node, gpointer cust_pdata)
{
struct customer_pdata *pdata = cust_pdata;
gnc_numeric *val;
val = dom_tree_to_gnc_numeric(node);
g_return_val_if_fail(val, FALSE);
gncCustomerSetCredit(pdata->customer, *val);
g_free (val);
return TRUE;
}
static gboolean
customer_commodity_handler (xmlNodePtr node, gpointer customer_pdata)
{
struct customer_pdata *pdata = customer_pdata;
gnc_commodity *com;
com = dom_tree_to_commodity_ref_no_engine(node, pdata->book);
g_return_val_if_fail (com, FALSE);
gncCustomerSetCommodity (pdata->customer, com);
return TRUE;
}
static struct dom_tree_handler customer_handlers_v2[] = {
{ cust_name_string, customer_name_handler, 1, 0 },
{ cust_guid_string, customer_guid_handler, 1, 0 },
{ cust_id_string, customer_id_handler, 1, 0 },
{ cust_addr_string, customer_addr_handler, 1, 0 },
{ cust_shipaddr_string, customer_shipaddr_handler, 1, 0 },
{ cust_notes_string, customer_notes_handler, 0, 0 },
{ cust_terms_string, customer_terms_handler, 0, 0 },
{ cust_taxincluded_string, customer_taxincluded_handler, 1, 0 },
{ cust_active_string, customer_active_handler, 1, 0 },
{ cust_discount_string, customer_discount_handler, 1, 0 },
{ cust_credit_string, customer_credit_handler, 1, 0 },
{ cust_commodity_string, customer_commodity_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncCustomer*
dom_tree_to_customer (xmlNodePtr node, GNCBook *book)
{
struct customer_pdata cust_pdata;
GncCustomer *custToRet;
gboolean successful;
custToRet = gncCustomerCreate(book);
cust_pdata.customer = custToRet;
cust_pdata.book = book;
successful = dom_tree_generic_parse (node, customer_handlers_v2,
&cust_pdata);
gncCustomerCommitEdit (custToRet);
if (!successful)
{
PERR ("failed to parse customer tree");
gncCustomerDestroy (custToRet);
custToRet = NULL;
}
return custToRet;
}
static gboolean
gnc_customer_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncCustomer *cust;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
cust = dom_tree_to_customer(tree, book);
if(cust != NULL)
{
gdata->cb(tag, gdata->parsedata, cust);
}
xmlFreeNode(tree);
return cust != NULL;
}
static sixtp *
customer_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_customer_end_handler, NULL, NULL);
}
static void
do_count (gpointer cust_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
customer_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_customer (gpointer cust_p, gpointer out_p)
{
xmlNodePtr node;
GncCustomer *cust = cust_p;
FILE *out = out_p;
node = customer_dom_tree_create (cust);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
customer_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_customer, (gpointer) out);
}
void
gnc_customer_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_customer_string,
customer_sixtp_parser_create,
NULL, /* add_item */
customer_get_count,
customer_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-customer-xml-v2.h -- customer xml i/o parser/unparser
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_CUSTOMER_XML_V2_H
#define GNC_CUSTOMER_XML_V2_H
void gnc_customer_xml_initialize (void);
#endif /* GNC_CUSTOMER_XML_V2_H */

View File

@ -0,0 +1,394 @@
/********************************************************************\
* gnc-employee-xml-v2.c -- employee xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncEmployeeP.h"
#include "gnc-employee-xml-v2.h"
#include "gnc-address-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_EMPLOYEE_MODULE_NAME
static short module = MOD_IO;
const gchar *employee_version_string = "2.0.0";
/* ids */
#define gnc_employee_string "gnc:GncEmployee"
#define employee_username_string "employee:username"
#define employee_guid_string "employee:guid"
#define employee_id_string "employee:id"
#define employee_addr_string "employee:addr"
#define employee_language_string "employee:language"
#define employee_acl_string "employee:acl"
#define employee_active_string "employee:active"
#define employee_workday_string "employee:workday"
#define employee_rate_string "employee:rate"
#define employee_commodity_string "employee:commodity"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static xmlNodePtr
employee_dom_tree_create (GncEmployee *employee)
{
xmlNodePtr ret;
gnc_numeric num;
ret = xmlNewNode(NULL, gnc_employee_string);
xmlSetProp(ret, "version", employee_version_string);
xmlAddChild(ret, guid_to_dom_tree(employee_guid_string,
gncEmployeeGetGUID (employee)));
xmlAddChild(ret, text_to_dom_tree(employee_username_string,
gncEmployeeGetUsername (employee)));
xmlAddChild(ret, text_to_dom_tree(employee_id_string,
gncEmployeeGetID (employee)));
xmlAddChild(ret, gnc_address_to_dom_tree(employee_addr_string,
gncEmployeeGetAddr (employee)));
maybe_add_string (ret, employee_language_string,
gncEmployeeGetLanguage (employee));
maybe_add_string (ret, employee_acl_string, gncEmployeeGetAcl (employee));
xmlAddChild(ret, int_to_dom_tree(employee_active_string,
gncEmployeeGetActive (employee)));
num = gncEmployeeGetWorkday (employee);
xmlAddChild(ret, gnc_numeric_to_dom_tree (employee_workday_string, &num));
num = gncEmployeeGetRate (employee);
xmlAddChild(ret, gnc_numeric_to_dom_tree (employee_rate_string, &num));
xmlAddChild
(ret,
commodity_ref_to_dom_tree(employee_commodity_string,
gncEmployeeGetCommodity (employee)));
return ret;
}
/***********************************************************************/
struct employee_pdata
{
GncEmployee *employee;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncEmployee* employee,
void (*func)(GncEmployee *employee, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(employee, txt);
g_free(txt);
return TRUE;
}
static gboolean
employee_username_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
return set_string(node, pdata->employee, gncEmployeeSetUsername);
}
static gboolean
employee_guid_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
GUID *guid;
GncEmployee *employee;
guid = dom_tree_to_guid(node);
g_return_val_if_fail(guid, FALSE);
/* See if we've already created this one */
employee = gncEmployeeLookup (pdata->book, guid);
if (employee) {
gncEmployeeDestroy (pdata->employee);
pdata->employee = employee;
} else {
gncEmployeeSetGUID(pdata->employee, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
employee_id_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
return set_string(node, pdata->employee, gncEmployeeSetID);
}
static gboolean
employee_language_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
return set_string(node, pdata->employee, gncEmployeeSetLanguage);
}
static gboolean
employee_acl_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
return set_string(node, pdata->employee, gncEmployeeSetAcl);
}
static gboolean
employee_addr_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
return gnc_dom_tree_to_address (node, gncEmployeeGetAddr(pdata->employee));
}
static gboolean
employee_active_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncEmployeeSetActive(pdata->employee, (gboolean)val);
return ret;
}
static gboolean
employee_workday_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
gnc_numeric *val;
val = dom_tree_to_gnc_numeric(node);
g_return_val_if_fail(val, FALSE);
gncEmployeeSetWorkday(pdata->employee, *val);
g_free(val);
return TRUE;
}
static gboolean
employee_rate_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
gnc_numeric *val;
val = dom_tree_to_gnc_numeric(node);
g_return_val_if_fail(val, FALSE);
gncEmployeeSetRate(pdata->employee, *val);
g_free(val);
return TRUE;
}
static gboolean
employee_commodity_handler (xmlNodePtr node, gpointer employee_pdata)
{
struct employee_pdata *pdata = employee_pdata;
gnc_commodity *com;
com = dom_tree_to_commodity_ref_no_engine(node, pdata->book);
g_return_val_if_fail (com, FALSE);
gncEmployeeSetCommodity (pdata->employee, com);
return TRUE;
}
static struct dom_tree_handler employee_handlers_v2[] = {
{ employee_username_string, employee_username_handler, 1, 0 },
{ employee_guid_string, employee_guid_handler, 1, 0 },
{ employee_id_string, employee_id_handler, 1, 0 },
{ employee_addr_string, employee_addr_handler, 1, 0 },
{ employee_language_string, employee_language_handler, 0, 0 },
{ employee_acl_string, employee_acl_handler, 0, 0 },
{ employee_active_string, employee_active_handler, 1, 0 },
{ employee_workday_string, employee_workday_handler, 1, 0 },
{ employee_rate_string, employee_rate_handler, 1, 0 },
{ employee_commodity_string, employee_commodity_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncEmployee*
dom_tree_to_employee (xmlNodePtr node, GNCBook *book)
{
struct employee_pdata employee_pdata;
GncEmployee *employeeToRet;
gboolean successful;
employeeToRet = gncEmployeeCreate(book);
employee_pdata.employee = employeeToRet;
employee_pdata.book = book;
successful = dom_tree_generic_parse (node, employee_handlers_v2,
&employee_pdata);
gncEmployeeCommitEdit (employeeToRet);
if (!successful)
{
PERR ("failed to parse employee tree");
gncEmployeeDestroy (employeeToRet);
employeeToRet = NULL;
}
return employeeToRet;
}
static gboolean
gnc_employee_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncEmployee *employee;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
employee = dom_tree_to_employee(tree, book);
if(employee != NULL)
{
gdata->cb(tag, gdata->parsedata, employee);
}
xmlFreeNode(tree);
return employee != NULL;
}
static sixtp *
employee_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_employee_end_handler, NULL, NULL);
}
static void
do_count (gpointer employee_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
employee_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_employee (gpointer employee_p, gpointer out_p)
{
xmlNodePtr node;
GncEmployee *employee = employee_p;
FILE *out = out_p;
node = employee_dom_tree_create (employee);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
employee_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
}
void
gnc_employee_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_employee_string,
employee_sixtp_parser_create,
NULL, /* add_item */
employee_get_count,
employee_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-employee-xml-v2.h -- employee xml i/o parser/unparser
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_EMPLOYEE_XML_V2_H
#define GNC_EMPLOYEE_XML_V2_H
void gnc_employee_xml_initialize (void);
#endif /* GNC_EMPLOYEE_XML_V2_H */

View File

@ -0,0 +1,521 @@
/********************************************************************\
* gnc-entry-xml-v2.c -- entry xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncEntryP.h"
#include "gncOrderP.h"
#include "gncInvoiceP.h"
#include "gnc-entry-xml-v2.h"
#include "gnc-owner-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_ENTRY_MODULE_NAME
static short module = MOD_IO;
const gchar *entry_version_string = "2.0.0";
/* ids */
#define gnc_entry_string "gnc:GncEntry"
#define entry_guid_string "entry:guid"
#define entry_date_string "entry:date"
#define entry_dateentered_string "entry:entered"
#define entry_description_string "entry:description"
#define entry_action_string "entry:action"
#define entry_qty_string "entry:qty"
#define entry_price_string "entry:price"
#define entry_tax_string "entry:tax"
#define entry_taxtype_string "entry:taxtype"
#define entry_discount_string "entry:discount"
#define entry_disctype_string "entry:disc-type"
#define entry_acct_string "entry:acct"
#define entry_taxacc_string "entry:taxacc"
#define entry_order_string "entry:order"
#define entry_invoice_string "entry:invoice"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static void
maybe_add_numeric (xmlNodePtr ptr, const char *tag, gnc_numeric num)
{
if (!gnc_numeric_zero_p (num))
xmlAddChild (ptr, gnc_numeric_to_dom_tree (tag, &num));
}
static xmlNodePtr
entry_dom_tree_create (GncEntry *entry)
{
xmlNodePtr ret;
Timespec ts;
Account *acc;
GncOrder *order;
GncInvoice *invoice;
ret = xmlNewNode(NULL, gnc_entry_string);
xmlSetProp(ret, "version", entry_version_string);
xmlAddChild(ret, guid_to_dom_tree(entry_guid_string,
gncEntryGetGUID (entry)));
ts = gncEntryGetDate (entry);
xmlAddChild(ret, timespec_to_dom_tree (entry_date_string, &ts));
ts = gncEntryGetDateEntered (entry);
xmlAddChild(ret, timespec_to_dom_tree (entry_dateentered_string, &ts));
maybe_add_string (ret, entry_description_string,
gncEntryGetDescription (entry));
maybe_add_string (ret, entry_action_string, gncEntryGetAction (entry));
maybe_add_numeric (ret, entry_qty_string, gncEntryGetQuantity (entry));
maybe_add_numeric (ret, entry_price_string, gncEntryGetPrice (entry));
maybe_add_numeric (ret, entry_tax_string, gncEntryGetTax (entry));
xmlAddChild(ret, int_to_dom_tree(entry_taxtype_string,
gncEntryGetTaxType (entry)));
maybe_add_numeric (ret, entry_discount_string, gncEntryGetDiscount (entry));
xmlAddChild(ret, int_to_dom_tree(entry_disctype_string,
gncEntryGetDiscountType (entry)));
acc = gncEntryGetAccount (entry);
if (acc)
xmlAddChild (ret, guid_to_dom_tree (entry_acct_string,
xaccAccountGetGUID (acc)));
acc = gncEntryGetTaxAccount (entry);
if (acc)
xmlAddChild (ret, guid_to_dom_tree (entry_taxacc_string,
xaccAccountGetGUID (acc)));
order = gncEntryGetOrder (entry);
if (order)
xmlAddChild (ret, guid_to_dom_tree (entry_order_string,
gncOrderGetGUID (order)));
invoice = gncEntryGetInvoice (entry);
if (invoice)
xmlAddChild (ret, guid_to_dom_tree (entry_invoice_string,
gncInvoiceGetGUID (invoice)));
return ret;
}
/***********************************************************************/
struct entry_pdata
{
GncEntry *entry;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncEntry* entry,
void (*func)(GncEntry *entry, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(entry, txt);
g_free(txt);
return TRUE;
}
static gboolean
set_timespec(xmlNodePtr node, GncEntry* entry,
void (*func)(GncEntry *entry, Timespec ts))
{
Timespec *ts = dom_tree_to_timespec (node);
g_return_val_if_fail(ts, FALSE);
func(entry, *ts);
g_free(ts);
return TRUE;
}
static gboolean
set_numeric(xmlNodePtr node, GncEntry* entry,
void (*func)(GncEntry *entry, gnc_numeric num))
{
gnc_numeric* num = dom_tree_to_gnc_numeric(node);
g_return_val_if_fail(num, FALSE);
func(entry, *num);
g_free(num);
return TRUE;
}
static gboolean
entry_guid_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
GUID *guid;
GncEntry *entry;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
entry = gncEntryLookup (pdata->book, guid);
if (entry) {
gncEntryDestroy (pdata->entry);
pdata->entry = entry;
} else {
gncEntrySetGUID(pdata->entry, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
entry_date_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_timespec(node, pdata->entry, gncEntrySetDate);
}
static gboolean
entry_dateentered_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_timespec(node, pdata->entry, gncEntrySetDateEntered);
}
static gboolean
entry_description_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_string(node, pdata->entry, gncEntrySetDescription);
}
static gboolean
entry_action_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_string(node, pdata->entry, gncEntrySetAction);
}
static gboolean
entry_qty_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_numeric(node, pdata->entry, gncEntrySetQuantity);
}
static gboolean
entry_price_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_numeric(node, pdata->entry, gncEntrySetPrice);
}
static gboolean
entry_tax_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_numeric(node, pdata->entry, gncEntrySetTax);
}
static gboolean
entry_taxtype_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
gint64 val;
dom_tree_to_integer(node, &val);
gncEntrySetTaxType(pdata->entry, (int)val);
return TRUE;
}
static gboolean
entry_discount_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
return set_numeric(node, pdata->entry, gncEntrySetDiscount);
}
static gboolean
entry_disctype_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
gint64 val;
dom_tree_to_integer(node, &val);
gncEntrySetDiscountType(pdata->entry, (gint)val);
return TRUE;
}
static gboolean
entry_acct_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
GUID *guid;
Account * acc;
guid = dom_tree_to_guid (node);
g_return_val_if_fail (guid, FALSE);
acc = xaccAccountLookup (guid, pdata->book);
g_free (guid);
g_return_val_if_fail (acc, FALSE);
gncEntrySetAccount (pdata->entry, acc);
return TRUE;
}
static gboolean
entry_taxacc_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
GUID *guid;
Account * acc;
guid = dom_tree_to_guid (node);
g_return_val_if_fail (guid, FALSE);
acc = xaccAccountLookup (guid, pdata->book);
g_free (guid);
g_return_val_if_fail (acc, FALSE);
gncEntrySetTaxAccount (pdata->entry, acc);
return TRUE;
}
static gboolean
entry_order_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
GUID *guid;
GncOrder *order;
guid = dom_tree_to_guid (node);
g_return_val_if_fail (guid, FALSE);
order = gncOrderLookup (pdata->book, guid);
if (!order) {
order = gncOrderCreate (pdata->book);
gncOrderSetGUID (order, guid);
}
gncOrderAddEntry (order, pdata->entry);
g_free(guid);
return TRUE;
}
static gboolean
entry_invoice_handler (xmlNodePtr node, gpointer entry_pdata)
{
struct entry_pdata *pdata = entry_pdata;
GUID *guid;
GncInvoice *invoice;
guid = dom_tree_to_guid (node);
g_return_val_if_fail (guid, FALSE);
invoice = gncInvoiceLookup (pdata->book, guid);
if (!invoice) {
invoice = gncInvoiceCreate (pdata->book);
gncInvoiceSetGUID (invoice, guid);
}
gncInvoiceAddEntry (invoice, pdata->entry);
g_free(guid);
return TRUE;
}
static struct dom_tree_handler entry_handlers_v2[] = {
{ entry_guid_string, entry_guid_handler, 1, 0 },
{ entry_date_string, entry_date_handler, 1, 0 },
{ entry_dateentered_string, entry_dateentered_handler, 1, 0 },
{ entry_description_string, entry_description_handler, 0, 0 },
{ entry_action_string, entry_action_handler, 0, 0 },
{ entry_qty_string, entry_qty_handler, 0, 0 },
{ entry_price_string, entry_price_handler, 0, 0 },
{ entry_tax_string, entry_tax_handler, 0, 0 },
{ entry_taxtype_string, entry_taxtype_handler, 0, 0 },
{ entry_discount_string, entry_discount_handler, 0, 0 },
{ entry_disctype_string, entry_disctype_handler, 0, 0 },
{ entry_acct_string, entry_acct_handler, 0, 0 },
{ entry_taxacc_string, entry_taxacc_handler, 0, 0 },
{ entry_order_string, entry_order_handler, 0, 0 },
{ entry_invoice_string, entry_invoice_handler, 0, 0 },
{ NULL, 0, 0, 0 }
};
static GncEntry*
dom_tree_to_entry (xmlNodePtr node, GNCBook *book)
{
struct entry_pdata entry_pdata;
GncEntry *entryToRet;
gboolean successful;
entryToRet = gncEntryCreate(book);
entry_pdata.entry = entryToRet;
entry_pdata.book = book;
successful = dom_tree_generic_parse (node, entry_handlers_v2,
&entry_pdata);
gncEntryCommitEdit (entryToRet);
if (!successful)
{
PERR ("failed to parse entry tree");
gncEntryDestroy (entryToRet);
entryToRet = NULL;
}
return entryToRet;
}
static gboolean
gnc_entry_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncEntry *entry;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
entry = dom_tree_to_entry(tree, book);
if(entry != NULL)
{
gdata->cb(tag, gdata->parsedata, entry);
}
xmlFreeNode(tree);
return entry != NULL;
}
static sixtp *
entry_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_entry_end_handler, NULL, NULL);
}
static void
do_count (gpointer entry_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
entry_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_entry (gpointer entry_p, gpointer out_p)
{
xmlNodePtr node;
GncEntry *entry = entry_p;
FILE *out = out_p;
/* Don't save non-attached entries! */
if (!(gncEntryGetOrder (entry) || gncEntryGetInvoice (entry)))
return;
node = entry_dom_tree_create (entry);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
entry_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
}
void
gnc_entry_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_entry_string,
entry_sixtp_parser_create,
NULL, /* add_item */
entry_get_count,
entry_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-entry-xml-v2.h -- entry xml i/o parser/unparsers
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_ENTRY_XML_V2_H
#define GNC_ENTRY_XML_V2_H
void gnc_entry_xml_initialize (void);
#endif /* GNC_ENTRY_XML_V2_H */

View File

@ -0,0 +1,490 @@
/********************************************************************\
* gnc-invoice-xml-v2.c -- invoice xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncInvoiceP.h"
#include "gnc-invoice-xml-v2.h"
#include "gnc-owner-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_INVOICE_MODULE_NAME
static short module = MOD_IO;
const gchar *invoice_version_string = "2.0.0";
/* ids */
#define gnc_invoice_string "gnc:GncInvoice"
#define invoice_guid_string "invoice:guid"
#define invoice_id_string "invoice:id"
#define invoice_owner_string "invoice:owner"
#define invoice_opened_string "invoice:opened"
#define invoice_posted_string "invoice:posted"
#define invoice_due_string "invoice:due"
#define invoice_paid_string "invoice:paid"
#define invoice_terms_string "invoice:terms"
#define invoice_notes_string "invoice:notes"
#define invoice_active_string "invoice:active"
#define invoice_posttxn_string "invoice:posttxn"
#define invoice_paidtxn_string "invoice:paidtxn"
#define invoice_postacc_string "invoice:postacc"
#define invoice_commodity_string "invoice:commodity"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static void
maybe_add_timespec (xmlNodePtr ptr, const char *tag, Timespec ts)
{
if (ts.tv_sec || ts.tv_nsec)
xmlAddChild (ptr, timespec_to_dom_tree (tag, &ts));
}
static xmlNodePtr
invoice_dom_tree_create (GncInvoice *invoice)
{
xmlNodePtr ret;
Timespec ts;
Transaction *txn;
Account *acc;
ret = xmlNewNode(NULL, gnc_invoice_string);
xmlSetProp(ret, "version", invoice_version_string);
xmlAddChild(ret, guid_to_dom_tree(invoice_guid_string,
gncInvoiceGetGUID (invoice)));
xmlAddChild(ret, text_to_dom_tree(invoice_id_string,
gncInvoiceGetID (invoice)));
xmlAddChild(ret, gnc_owner_to_dom_tree (invoice_owner_string,
gncInvoiceGetOwner (invoice)));
ts = gncInvoiceGetDateOpened (invoice);
xmlAddChild(ret, timespec_to_dom_tree (invoice_opened_string, &ts));
maybe_add_timespec (ret, invoice_posted_string,
gncInvoiceGetDatePosted (invoice));
maybe_add_timespec (ret, invoice_due_string,
gncInvoiceGetDateDue (invoice));
maybe_add_timespec (ret, invoice_paid_string,
gncInvoiceGetDatePaid (invoice));
maybe_add_string (ret, invoice_terms_string, gncInvoiceGetTerms (invoice));
maybe_add_string (ret, invoice_notes_string, gncInvoiceGetNotes (invoice));
xmlAddChild(ret, int_to_dom_tree(invoice_active_string,
gncInvoiceGetActive (invoice)));
txn = gncInvoiceGetPostedTxn (invoice);
if (txn)
xmlAddChild (ret, guid_to_dom_tree (invoice_posttxn_string,
xaccTransGetGUID (txn)));
txn = gncInvoiceGetPaidTxn (invoice);
if (txn)
xmlAddChild (ret, guid_to_dom_tree (invoice_paidtxn_string,
xaccTransGetGUID (txn)));
acc = gncInvoiceGetPostedAcc (invoice);
if (acc)
xmlAddChild (ret, guid_to_dom_tree (invoice_postacc_string,
xaccAccountGetGUID (acc)));
xmlAddChild
(ret,
commodity_ref_to_dom_tree(invoice_commodity_string,
gncInvoiceGetCommonCommodity (invoice)));
return ret;
}
/***********************************************************************/
struct invoice_pdata
{
GncInvoice *invoice;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncInvoice* invoice,
void (*func)(GncInvoice *invoice, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(invoice, txt);
g_free(txt);
return TRUE;
}
static gboolean
set_timespec(xmlNodePtr node, GncInvoice* invoice,
void (*func)(GncInvoice *invoice, Timespec ts))
{
Timespec* ts = dom_tree_to_timespec(node);
g_return_val_if_fail(ts, FALSE);
func(invoice, *ts);
g_free(ts);
return TRUE;
}
static gboolean
invoice_guid_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
GUID *guid;
GncInvoice *invoice;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
invoice = gncInvoiceLookup (pdata->book, guid);
if (invoice) {
gncInvoiceDestroy (pdata->invoice);
pdata->invoice = invoice;
} else {
gncInvoiceSetGUID(pdata->invoice, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
invoice_id_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_string(node, pdata->invoice, gncInvoiceSetID);
}
static gboolean
invoice_owner_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
GncOwner owner;
gboolean ret;
ret = gnc_dom_tree_to_owner (node, &owner, pdata->book);
if (ret)
gncInvoiceSetOwner (pdata->invoice, &owner);
return ret;
}
static gboolean
invoice_opened_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_timespec (node, pdata->invoice, gncInvoiceSetDateOpened);
}
static gboolean
invoice_posted_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_timespec (node, pdata->invoice, gncInvoiceSetDatePosted);
}
static gboolean
invoice_due_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_timespec (node, pdata->invoice, gncInvoiceSetDateDue);
}
static gboolean
invoice_paid_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_timespec (node, pdata->invoice, gncInvoiceSetDatePaid);
}
static gboolean
invoice_terms_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_string(node, pdata->invoice, gncInvoiceSetTerms);
}
static gboolean
invoice_notes_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
return set_string(node, pdata->invoice, gncInvoiceSetNotes);
}
static gboolean
invoice_active_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncInvoiceSetActive(pdata->invoice, (gboolean)val);
return ret;
}
static gboolean
invoice_posttxn_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
GUID *guid;
Transaction *txn;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
txn = xaccTransLookup (guid, pdata->book);
g_free (guid);
g_return_val_if_fail (txn, FALSE);
gncInvoiceSetPostedTxn (pdata->invoice, txn);
return TRUE;
}
static gboolean
invoice_paidtxn_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
GUID *guid;
Transaction *txn;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
txn = xaccTransLookup (guid, pdata->book);
g_free (guid);
g_return_val_if_fail (txn, FALSE);
gncInvoiceSetPaidTxn (pdata->invoice, txn);
return TRUE;
}
static gboolean
invoice_postacc_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
GUID *guid;
Account *acc;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
acc = xaccAccountLookup (guid, pdata->book);
g_free (guid);
g_return_val_if_fail (acc, FALSE);
gncInvoiceSetPostedAcc (pdata->invoice, acc);
return TRUE;
}
static gboolean
invoice_commodity_handler (xmlNodePtr node, gpointer invoice_pdata)
{
struct invoice_pdata *pdata = invoice_pdata;
gnc_commodity *com;
com = dom_tree_to_commodity_ref_no_engine(node, pdata->book);
g_return_val_if_fail (com, FALSE);
gncInvoiceSetCommonCommodity (pdata->invoice, com);
return TRUE;
}
static struct dom_tree_handler invoice_handlers_v2[] = {
{ invoice_guid_string, invoice_guid_handler, 1, 0 },
{ invoice_id_string, invoice_id_handler, 1, 0 },
{ invoice_owner_string, invoice_owner_handler, 1, 0 },
{ invoice_opened_string, invoice_opened_handler, 1, 0 },
{ invoice_posted_string, invoice_posted_handler, 0, 0 },
{ invoice_due_string, invoice_due_handler, 0, 0 },
{ invoice_paid_string, invoice_paid_handler, 0, 0 },
{ invoice_terms_string, invoice_terms_handler, 0, 0 },
{ invoice_notes_string, invoice_notes_handler, 0, 0 },
{ invoice_active_string, invoice_active_handler, 1, 0 },
{ invoice_posttxn_string, invoice_posttxn_handler, 0, 0 },
{ invoice_paidtxn_string, invoice_paidtxn_handler, 0, 0 },
{ invoice_postacc_string, invoice_postacc_handler, 0, 0 },
{ invoice_commodity_string, invoice_commodity_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncInvoice*
dom_tree_to_invoice (xmlNodePtr node, GNCBook *book)
{
struct invoice_pdata invoice_pdata;
GncInvoice *invoiceToRet;
gboolean successful;
invoiceToRet = gncInvoiceCreate(book);
invoice_pdata.invoice = invoiceToRet;
invoice_pdata.book = book;
successful = dom_tree_generic_parse (node, invoice_handlers_v2,
&invoice_pdata);
gncInvoiceCommitEdit (invoiceToRet);
if (!successful)
{
PERR ("failed to parse invoice tree");
gncInvoiceDestroy (invoiceToRet);
invoiceToRet = NULL;
}
return invoiceToRet;
}
static gboolean
gnc_invoice_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncInvoice *invoice;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
invoice = dom_tree_to_invoice(tree, book);
if(invoice != NULL)
{
gdata->cb(tag, gdata->parsedata, invoice);
}
xmlFreeNode(tree);
return invoice != NULL;
}
static sixtp *
invoice_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_invoice_end_handler, NULL, NULL);
}
static void
do_count (gpointer invoice_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
invoice_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_invoice (gpointer invoice_p, gpointer out_p)
{
xmlNodePtr node;
GncInvoice *invoice = invoice_p;
FILE *out = out_p;
node = invoice_dom_tree_create (invoice);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
invoice_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_invoice, (gpointer) out);
}
void
gnc_invoice_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_invoice_string,
invoice_sixtp_parser_create,
NULL, /* add_item */
invoice_get_count,
invoice_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-invoice-xml-v2.h -- invoice xml i/o parser/unparsers
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_INVOICE_XML_V2_H
#define GNC_INVOICE_XML_V2_H
void gnc_invoice_xml_initialize (void);
#endif /* GNC_INVOICE_XML_V2_H */

View File

@ -0,0 +1,327 @@
/********************************************************************\
* gnc-job-xml-v2.c -- job xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncJobP.h"
#include "gnc-job-xml-v2.h"
#include "gnc-owner-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_JOB_MODULE_NAME
static short module = MOD_IO;
const gchar *job_version_string = "2.0.0";
/* ids */
#define gnc_job_string "gnc:GncJob"
#define job_guid_string "job:guid"
#define job_id_string "job:id"
#define job_name_string "job:name"
#define job_reference_string "job:reference"
#define job_owner_string "job:owner"
#define job_active_string "job:active"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static xmlNodePtr
job_dom_tree_create (GncJob *job)
{
xmlNodePtr ret;
ret = xmlNewNode(NULL, gnc_job_string);
xmlSetProp(ret, "version", job_version_string);
xmlAddChild(ret, guid_to_dom_tree(job_guid_string,
gncJobGetGUID (job)));
xmlAddChild(ret, text_to_dom_tree(job_id_string,
gncJobGetID (job)));
xmlAddChild(ret, text_to_dom_tree(job_name_string,
gncJobGetName (job)));
maybe_add_string (ret, job_reference_string, gncJobGetReference (job));
xmlAddChild(ret, gnc_owner_to_dom_tree (job_owner_string,
gncJobGetOwner (job)));
xmlAddChild(ret, int_to_dom_tree(job_active_string,
gncJobGetActive (job)));
return ret;
}
/***********************************************************************/
struct job_pdata
{
GncJob *job;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncJob* job,
void (*func)(GncJob *job, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(job, txt);
g_free(txt);
return TRUE;
}
static gboolean
job_name_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
return set_string(node, pdata->job, gncJobSetName);
}
static gboolean
job_guid_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
GUID *guid;
GncJob *job;
guid = dom_tree_to_guid(node);
g_return_val_if_fail(guid, FALSE);
job = gncJobLookup (pdata->book, guid);
if (job) {
gncJobDestroy (pdata->job);
pdata->job = job;
} else {
gncJobSetGUID(pdata->job, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
job_id_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
return set_string(node, pdata->job, gncJobSetID);
}
static gboolean
job_reference_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
return set_string(node, pdata->job, gncJobSetReference);
}
static gboolean
job_owner_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
GncOwner owner;
gboolean ret;
ret = gnc_dom_tree_to_owner (node, &owner, pdata->book);
if (ret)
gncJobSetOwner (pdata->job, &owner);
return ret;
}
static gboolean
job_active_handler (xmlNodePtr node, gpointer job_pdata)
{
struct job_pdata *pdata = job_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncJobSetActive(pdata->job, (gboolean)val);
return ret;
}
static struct dom_tree_handler job_handlers_v2[] = {
{ job_guid_string, job_guid_handler, 1, 0 },
{ job_id_string, job_id_handler, 1, 0 },
{ job_name_string, job_name_handler, 1, 0 },
{ job_reference_string, job_reference_handler, 0, 0 },
{ job_owner_string, job_owner_handler, 1, 0 },
{ job_active_string, job_active_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncJob*
dom_tree_to_job (xmlNodePtr node, GNCBook *book)
{
struct job_pdata job_pdata;
GncJob *jobToRet;
gboolean successful;
jobToRet = gncJobCreate(book);
job_pdata.job = jobToRet;
job_pdata.book = book;
successful = dom_tree_generic_parse (node, job_handlers_v2,
&job_pdata);
gncJobCommitEdit (jobToRet);
if (!successful)
{
PERR ("failed to parse job tree");
gncJobDestroy (jobToRet);
jobToRet = NULL;
}
return jobToRet;
}
static gboolean
gnc_job_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncJob *job;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
job = dom_tree_to_job(tree, book);
if(job != NULL)
{
gdata->cb(tag, gdata->parsedata, job);
}
xmlFreeNode(tree);
return job != NULL;
}
static sixtp *
job_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_job_end_handler, NULL, NULL);
}
static void
do_count (gpointer job_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
job_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_job (gpointer job_p, gpointer out_p)
{
xmlNodePtr node;
GncJob *job = job_p;
FILE *out = out_p;
node = job_dom_tree_create (job);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
job_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
}
void
gnc_job_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_job_string,
job_sixtp_parser_create,
NULL, /* add_item */
job_get_count,
job_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-job-xml-v2.h -- job xml i/o parser/unparsers
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_JOB_XML_V2_H
#define GNC_JOB_XML_V2_H
void gnc_job_xml_initialize (void);
#endif /* GNC_JOB_XML_V2_H */

View File

@ -0,0 +1,365 @@
/********************************************************************\
* gnc-order-xml-v2.c -- order xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncOrderP.h"
#include "gnc-order-xml-v2.h"
#include "gnc-owner-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_ORDER_MODULE_NAME
static short module = MOD_IO;
const gchar *order_version_string = "2.0.0";
/* ids */
#define gnc_order_string "gnc:GncOrder"
#define order_guid_string "order:guid"
#define order_id_string "order:id"
#define order_owner_string "order:owner"
#define order_opened_string "order:opened"
#define order_closed_string "order:closed"
#define order_notes_string "order:notes"
#define order_reference_string "order:reference"
#define order_active_string "order:active"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static xmlNodePtr
order_dom_tree_create (GncOrder *order)
{
xmlNodePtr ret;
Timespec ts;
ret = xmlNewNode(NULL, gnc_order_string);
xmlSetProp(ret, "version", order_version_string);
xmlAddChild(ret, guid_to_dom_tree(order_guid_string,
gncOrderGetGUID (order)));
xmlAddChild(ret, text_to_dom_tree(order_id_string,
gncOrderGetID (order)));
xmlAddChild(ret, gnc_owner_to_dom_tree (order_owner_string,
gncOrderGetOwner (order)));
ts = gncOrderGetDateOpened (order);
xmlAddChild(ret, timespec_to_dom_tree (order_opened_string, &ts));
ts = gncOrderGetDateClosed (order);
if (ts.tv_sec || ts.tv_nsec)
xmlAddChild(ret, timespec_to_dom_tree (order_closed_string, &ts));
maybe_add_string (ret, order_notes_string, gncOrderGetNotes (order));
maybe_add_string (ret, order_reference_string, gncOrderGetReference (order));
xmlAddChild(ret, int_to_dom_tree(order_active_string,
gncOrderGetActive (order)));
return ret;
}
/***********************************************************************/
struct order_pdata
{
GncOrder *order;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncOrder* order,
void (*func)(GncOrder *order, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(order, txt);
g_free(txt);
return TRUE;
}
static gboolean
set_timespec(xmlNodePtr node, GncOrder* order,
void (*func)(GncOrder *order, Timespec ts))
{
Timespec* ts = dom_tree_to_timespec(node);
g_return_val_if_fail(ts, FALSE);
func(order, *ts);
g_free(ts);
return TRUE;
}
static gboolean
order_guid_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
GUID *guid;
GncOrder *order;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
order = gncOrderLookup (pdata->book, guid);
if (order) {
gncOrderDestroy (pdata->order);
pdata->order = order;
} else {
gncOrderSetGUID(pdata->order, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
order_id_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
return set_string(node, pdata->order, gncOrderSetID);
}
static gboolean
order_owner_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
GncOwner owner;
gboolean ret;
ret = gnc_dom_tree_to_owner (node, &owner, pdata->book);
if (ret)
gncOrderSetOwner (pdata->order, &owner);
return ret;
}
static gboolean
order_opened_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
return set_timespec (node, pdata->order, gncOrderSetDateOpened);
}
static gboolean
order_closed_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
return set_timespec (node, pdata->order, gncOrderSetDateClosed);
}
static gboolean
order_notes_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
return set_string(node, pdata->order, gncOrderSetNotes);
}
static gboolean
order_reference_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
return set_string(node, pdata->order, gncOrderSetReference);
}
static gboolean
order_active_handler (xmlNodePtr node, gpointer order_pdata)
{
struct order_pdata *pdata = order_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncOrderSetActive(pdata->order, (gboolean)val);
return ret;
}
static struct dom_tree_handler order_handlers_v2[] = {
{ order_guid_string, order_guid_handler, 1, 0 },
{ order_id_string, order_id_handler, 1, 0 },
{ order_owner_string, order_owner_handler, 1, 0 },
{ order_opened_string, order_opened_handler, 1, 0 },
{ order_closed_string, order_closed_handler, 0, 0 },
{ order_notes_string, order_notes_handler, 0, 0 },
{ order_reference_string, order_reference_handler, 0, 0 },
{ order_active_string, order_active_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncOrder*
dom_tree_to_order (xmlNodePtr node, GNCBook *book)
{
struct order_pdata order_pdata;
GncOrder *orderToRet;
gboolean successful;
orderToRet = gncOrderCreate(book);
order_pdata.order = orderToRet;
order_pdata.book = book;
successful = dom_tree_generic_parse (node, order_handlers_v2,
&order_pdata);
gncOrderCommitEdit (orderToRet);
if (!successful)
{
PERR ("failed to parse order tree");
gncOrderDestroy (orderToRet);
orderToRet = NULL;
}
return orderToRet;
}
static gboolean
gnc_order_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncOrder *order;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
order = dom_tree_to_order(tree, book);
if(order != NULL)
{
gdata->cb(tag, gdata->parsedata, order);
}
xmlFreeNode(tree);
return order != NULL;
}
static sixtp *
order_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_order_end_handler, NULL, NULL);
}
static void
do_count (gpointer order_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
order_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_order (gpointer order_p, gpointer out_p)
{
xmlNodePtr node;
GncOrder *order = order_p;
FILE *out = out_p;
node = order_dom_tree_create (order);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
order_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_order, (gpointer) out);
}
void
gnc_order_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_order_string,
order_sixtp_parser_create,
NULL, /* add_item */
order_get_count,
order_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-order-xml-v2.h -- order xml i/o parser/unparsers
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_ORDER_XML_V2_H
#define GNC_ORDER_XML_V2_H
void gnc_order_xml_initialize (void);
#endif /* GNC_ORDER_XML_V2_H */

View File

@ -0,0 +1,195 @@
/********************************************************************\
* gnc-owner-xml-v2.c -- owner xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gnc-owner-xml-v2.h"
#include "gncCustomerP.h"
#include "gncJobP.h"
#include "gncVendorP.h"
#include "gnc-engine-util.h"
static short module = MOD_IO;
const gchar *owner_version_string = "2.0.0";
/* ids */
#define owner_type_string "owner:type"
#define owner_id_string "owner:id"
xmlNodePtr
gnc_owner_to_dom_tree (const char *tag, GncOwner *owner)
{
xmlNodePtr ret;
const char *type_str;
switch (gncOwnerGetType (owner)) {
case GNC_OWNER_CUSTOMER:
type_str = GNC_CUSTOMER_MODULE_NAME;
break;
case GNC_OWNER_JOB:
type_str = GNC_JOB_MODULE_NAME;
break;
case GNC_OWNER_VENDOR:
type_str = GNC_VENDOR_MODULE_NAME;
break;
default:
PWARN ("Invalid owner type: %d", gncOwnerGetType (owner));
return NULL;
}
ret = xmlNewNode(NULL, tag);
xmlSetProp(ret, "version", owner_version_string);
xmlAddChild (ret, text_to_dom_tree (owner_type_string, type_str));
xmlAddChild (ret, guid_to_dom_tree (owner_id_string,
gncOwnerGetGUID (owner)));
return ret;
}
/***********************************************************************/
struct owner_pdata
{
GncOwner *owner;
GNCBook *book;
};
static gboolean
owner_type_handler (xmlNodePtr node, gpointer owner_pdata)
{
struct owner_pdata *pdata = owner_pdata;
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
if (!safe_strcmp (txt, GNC_CUSTOMER_MODULE_NAME))
gncOwnerInitCustomer (pdata->owner, NULL);
else if (!safe_strcmp (txt, GNC_JOB_MODULE_NAME))
gncOwnerInitJob (pdata->owner, NULL);
else if (!safe_strcmp (txt, GNC_VENDOR_MODULE_NAME))
gncOwnerInitVendor (pdata->owner, NULL);
else {
PWARN ("Unknown owner type: %s", txt);
g_free(txt);
return FALSE;
}
g_free(txt);
return TRUE;
}
static gboolean
owner_id_handler (xmlNodePtr node, gpointer owner_pdata)
{
struct owner_pdata *pdata = owner_pdata;
GUID *guid;
guid = dom_tree_to_guid(node);
g_return_val_if_fail (guid, FALSE);
switch (gncOwnerGetType (pdata->owner)) {
case GNC_OWNER_CUSTOMER:
{
GncCustomer *cust = gncCustomerLookup (pdata->book, guid);
if (!cust) {
cust = gncCustomerCreate (pdata->book);
gncCustomerSetGUID (cust, guid);
}
gncOwnerInitCustomer (pdata->owner, cust);
break;
}
case GNC_OWNER_JOB:
{
GncJob *job = gncJobLookup (pdata->book, guid);
if (!job) {
job = gncJobCreate (pdata->book);
gncJobSetGUID (job, guid);
}
gncOwnerInitJob (pdata->owner, job);
break;
}
case GNC_OWNER_VENDOR:
{
GncVendor *vendor = gncVendorLookup (pdata->book, guid);
if (!vendor) {
vendor = gncVendorCreate (pdata->book);
gncVendorSetGUID (vendor, guid);
}
gncOwnerInitVendor (pdata->owner, vendor);
break;
}
default:
PWARN ("Invalid owner type: %d\n", gncOwnerGetType (pdata->owner));
g_free (guid);
return FALSE;
}
g_free (guid);
return TRUE;
}
static struct dom_tree_handler owner_handlers_v2[] = {
{ owner_type_string, owner_type_handler, 1, 0 },
{ owner_id_string, owner_id_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
gboolean
gnc_dom_tree_to_owner (xmlNodePtr node, GncOwner *owner, GNCBook *book)
{
struct owner_pdata owner_pdata;
gboolean successful;
owner_pdata.owner = owner;
owner_pdata.book = book;
successful = dom_tree_generic_parse (node, owner_handlers_v2,
&owner_pdata);
if (!successful)
{
PERR ("failed to parse owner tree");
}
return successful;
}

View File

@ -0,0 +1,16 @@
/* gnc-owner-xml-v2.h -- Owner XML header
*
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_OWNER_XML_V2_H
#define GNC_OWNER_XML_V2_H
#include "gncOwner.h"
#include "gnc-book.h"
gboolean gnc_dom_tree_to_owner (xmlNodePtr node, GncOwner *owner,
GNCBook *book);
xmlNodePtr gnc_owner_to_dom_tree (const char *tag, GncOwner *addr);
#endif /* GNC_OWNER_XML_V2_H */

View File

@ -0,0 +1,372 @@
/********************************************************************\
* gnc-vendor-xml-v2.c -- vendor xml i/o implementation *
* *
* Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
#include "io-gncxml-v2.h"
#include "gncVendorP.h"
#include "gnc-vendor-xml-v2.h"
#include "gnc-address-xml-v2.h"
#include "gnc-engine-util.h"
#include "gncObject.h"
#define _GNC_MOD_NAME GNC_VENDOR_MODULE_NAME
static short module = MOD_IO;
const gchar *vendor_version_string = "2.0.0";
/* ids */
#define gnc_vendor_string "gnc:GncVendor"
#define vendor_name_string "vendor:name"
#define vendor_guid_string "vendor:guid"
#define vendor_id_string "vendor:id"
#define vendor_addr_string "vendor:addr"
#define vendor_notes_string "vendor:notes"
#define vendor_terms_string "vendor:terms"
#define vendor_taxincluded_string "vendor:taxincluded"
#define vendor_active_string "vendor:active"
#define vendor_commodity_string "vendor:commodity"
static void
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
{
if (str && strlen(str) > 0)
xmlAddChild (ptr, text_to_dom_tree (tag, str));
}
static xmlNodePtr
vendor_dom_tree_create (GncVendor *vendor)
{
xmlNodePtr ret;
ret = xmlNewNode(NULL, gnc_vendor_string);
xmlSetProp(ret, "version", vendor_version_string);
xmlAddChild(ret, guid_to_dom_tree(vendor_guid_string,
gncVendorGetGUID (vendor)));
xmlAddChild(ret, text_to_dom_tree(vendor_name_string,
gncVendorGetName (vendor)));
xmlAddChild(ret, text_to_dom_tree(vendor_id_string,
gncVendorGetID (vendor)));
xmlAddChild(ret, gnc_address_to_dom_tree(vendor_addr_string,
gncVendorGetAddr (vendor)));
maybe_add_string (ret, vendor_notes_string, gncVendorGetNotes (vendor));
maybe_add_string (ret, vendor_terms_string, gncVendorGetTerms (vendor));
xmlAddChild(ret, int_to_dom_tree(vendor_taxincluded_string,
gncVendorGetTaxIncluded (vendor)));
xmlAddChild(ret, int_to_dom_tree(vendor_active_string,
gncVendorGetActive (vendor)));
xmlAddChild
(ret,
commodity_ref_to_dom_tree(vendor_commodity_string,
gncVendorGetCommodity (vendor)));
return ret;
}
/***********************************************************************/
struct vendor_pdata
{
GncVendor *vendor;
GNCBook *book;
};
static gboolean
set_string(xmlNodePtr node, GncVendor* vendor,
void (*func)(GncVendor *vendor, const char *txt))
{
char* txt = dom_tree_to_text(node);
g_return_val_if_fail(txt, FALSE);
func(vendor, txt);
g_free(txt);
return TRUE;
}
static gboolean
vendor_name_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
return set_string(node, pdata->vendor, gncVendorSetName);
}
static gboolean
vendor_guid_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
GUID *guid;
GncVendor *vendor;
guid = dom_tree_to_guid(node);
g_return_val_if_fail(guid, FALSE);
vendor = gncVendorLookup (pdata->book, guid);
if (vendor) {
gncVendorDestroy (pdata->vendor);
pdata->vendor = vendor;
} else {
gncVendorSetGUID(pdata->vendor, guid);
}
g_free(guid);
return TRUE;
}
static gboolean
vendor_id_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
return set_string(node, pdata->vendor, gncVendorSetID);
}
static gboolean
vendor_notes_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
return set_string(node, pdata->vendor, gncVendorSetNotes);
}
static gboolean
vendor_terms_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
return set_string(node, pdata->vendor, gncVendorSetTerms);
}
static gboolean
vendor_addr_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
return gnc_dom_tree_to_address (node, gncVendorGetAddr(pdata->vendor));
}
static gboolean
vendor_taxincluded_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncVendorSetTaxIncluded(pdata->vendor, (gboolean)val);
return ret;
}
static gboolean
vendor_active_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
gint64 val;
gboolean ret;
ret = dom_tree_to_integer(node, &val);
if (ret)
gncVendorSetActive(pdata->vendor, (gboolean)val);
return ret;
}
static gboolean
vendor_commodity_handler (xmlNodePtr node, gpointer vendor_pdata)
{
struct vendor_pdata *pdata = vendor_pdata;
gnc_commodity *com;
com = dom_tree_to_commodity_ref_no_engine(node, pdata->book);
g_return_val_if_fail (com, FALSE);
gncVendorSetCommodity (pdata->vendor, com);
return TRUE;
}
static struct dom_tree_handler vendor_handlers_v2[] = {
{ vendor_name_string, vendor_name_handler, 1, 0 },
{ vendor_guid_string, vendor_guid_handler, 1, 0 },
{ vendor_id_string, vendor_id_handler, 1, 0 },
{ vendor_addr_string, vendor_addr_handler, 1, 0 },
{ vendor_notes_string, vendor_notes_handler, 0, 0 },
{ vendor_terms_string, vendor_terms_handler, 0, 0 },
{ vendor_taxincluded_string, vendor_taxincluded_handler, 1, 0 },
{ vendor_active_string, vendor_active_handler, 1, 0 },
{ vendor_commodity_string, vendor_commodity_handler, 1, 0 },
{ NULL, 0, 0, 0 }
};
static GncVendor*
dom_tree_to_vendor (xmlNodePtr node, GNCBook *book)
{
struct vendor_pdata vendor_pdata;
GncVendor *vendorToRet;
gboolean successful;
vendorToRet = gncVendorCreate(book);
vendor_pdata.vendor = vendorToRet;
vendor_pdata.book = book;
successful = dom_tree_generic_parse (node, vendor_handlers_v2,
&vendor_pdata);
gncVendorCommitEdit (vendorToRet);
if (!successful)
{
PERR ("failed to parse vendor tree");
gncVendorDestroy (vendorToRet);
vendorToRet = NULL;
}
return vendorToRet;
}
static gboolean
gnc_vendor_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
int successful;
GncVendor *vendor;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data *gdata = (gxpf_data*)global_data;
GNCBook *book = gdata->bookdata;
successful = TRUE;
if(parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if(!tag)
{
return TRUE;
}
g_return_val_if_fail(tree, FALSE);
vendor = dom_tree_to_vendor(tree, book);
if(vendor != NULL)
{
gdata->cb(tag, gdata->parsedata, vendor);
}
xmlFreeNode(tree);
return vendor != NULL;
}
static sixtp *
vendor_sixtp_parser_create(void)
{
return sixtp_dom_parser_new(gnc_vendor_end_handler, NULL, NULL);
}
static void
do_count (gpointer vendor_p, gpointer count_p)
{
int *count = count_p;
(*count)++;
}
static int
vendor_get_count (GNCBook *book)
{
int count = 0;
gncObjectForeach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
return count;
}
static void
xml_add_vendor (gpointer vendor_p, gpointer out_p)
{
xmlNodePtr node;
GncVendor *vendor = vendor_p;
FILE *out = out_p;
node = vendor_dom_tree_create (vendor);
xmlElemDump(out, NULL, node);
fprintf(out, "\n");
xmlFreeNode (node);
}
static void
vendor_write (FILE *out, GNCBook *book)
{
gncObjectForeach (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
}
void
gnc_vendor_xml_initialize (void)
{
static GncXmlDataType_t be_data = {
GNC_FILE_BACKEND_VERS,
gnc_vendor_string,
vendor_sixtp_parser_create,
NULL, /* add_item */
vendor_get_count,
vendor_write,
};
gncObjectRegisterBackend (_GNC_MOD_NAME,
GNC_FILE_BACKEND,
&be_data);
}

View File

@ -0,0 +1,12 @@
/*
* gnc-vendor-xml-v2.h -- vendor xml i/o parser/unparsers
*
* Copyright (C) 2000 Derek Atkins <warlord@MIT.EDU>
*/
#ifndef GNC_VENDOR_XML_V2_H
#define GNC_VENDOR_XML_V2_H
void gnc_vendor_xml_initialize (void);
#endif /* GNC_VENDOR_XML_V2_H */

View File

@ -0,0 +1,88 @@
/*********************************************************************
* gncmod-business-backend-file.c
* module definition/initialization for the file backend module
*
* Copyright (c) 2002 Derek Atkins <warlord@MIT.EDU>
*********************************************************************/
#include <stdio.h>
#include <glib.h>
#include "gnc-module.h"
#include "gnc-module-api.h"
#include "gnc-customer-xml-v2.h"
#include "gnc-employee-xml-v2.h"
#include "gnc-entry-xml-v2.h"
#include "gnc-invoice-xml-v2.h"
#include "gnc-job-xml-v2.h"
#include "gnc-order-xml-v2.h"
#include "gnc-vendor-xml-v2.h"
/* version of the gnc module system interface we require */
int gnc_module_system_interface = 0;
/* module versioning uses libtool semantics. */
int gnc_module_current = 0;
int gnc_module_revision = 0;
int gnc_module_age = 0;
static GNCModule bus_core;
static GNCModule file;
char *
gnc_module_path(void)
{
return g_strdup("gnucash/business-core-file");
}
char *
gnc_module_description(void)
{
return g_strdup("The XML (v2) parsers for Gnucash business objects");
}
int
gnc_module_init(int refcount)
{
bus_core = gnc_module_load("gnucash/business-core", 0);
if(!bus_core) return FALSE;
file = gnc_module_load("gnucash/backend/file", 0);
if(!file) {
gnc_module_unload (bus_core);
return FALSE;
}
if (refcount == 0) {
/* Initialize our pointers into the backend subsystem */
gnc_customer_xml_initialize ();
gnc_employee_xml_initialize ();
gnc_entry_xml_initialize ();
gnc_invoice_xml_initialize ();
gnc_job_xml_initialize ();
gnc_order_xml_initialize ();
gnc_vendor_xml_initialize ();
}
return TRUE;
}
int
gnc_module_end(int refcount)
{
int unload = TRUE;
if (bus_core)
unload = gnc_module_unload(bus_core);
if (file)
unload = gnc_module_unload(file);
if (refcount == 0) {
bus_core = NULL;
file = NULL;
}
return unload;
}

View File

@ -72,6 +72,17 @@ gboolean gncBusinessIsDirty (GNCBook *book, GNCIdType mod_name)
return bi->is_dirty;
}
void gncBusinessSetDirtyFlag (GNCBook *book, GNCIdType mod_name,
gboolean is_dirty)
{
GncBookInfo *bi;
if (!book) return;
bi = gnc_book_get_data (book, mod_name);
bi->is_dirty = is_dirty;
}
void gncBusinessAddObject (GNCBook *book, GNCIdType mod_name,
gpointer obj, const GUID *guid)
{

View File

@ -21,6 +21,8 @@ void gncBusinessForeach (GNCBook *book, GNCIdType mod_name,
void gncBusinessCreate (GNCBook *book, GNCIdType mod_name);
void gncBusinessDestroy (GNCBook *book, GNCIdType mod_name);
gboolean gncBusinessIsDirty (GNCBook *book, GNCIdType mod_name);
void gncBusinessSetDirtyFlag (GNCBook *book, GNCIdType mod_name,
gboolean is_dirty);
void gncBusinessAddObject (GNCBook *book, GNCIdType mod_name,
gpointer obj, const GUID *guid);
void gncBusinessRemoveObject (GNCBook *book, GNCIdType mod_name,

View File

@ -32,6 +32,7 @@ struct _gncCustomer {
char * terms;
GncAddress * addr;
GncAddress * shipaddr;
gnc_commodity * commodity;
gnc_numeric discount;
gnc_numeric credit;
gboolean taxincluded;
@ -191,6 +192,13 @@ void gncCustomerSetCredit (GncCustomer *cust, gnc_numeric credit)
mark_customer (cust);
}
void gncCustomerSetCommodity (GncCustomer *cust, gnc_commodity *com)
{
if (!cust || !com) return;
cust->commodity = com;
mark_customer (cust);
}
/* Note that JobList changes do not affect the "dirtiness" of the customer */
void gncCustomerAddJob (GncCustomer *cust, GncJob *job)
{
@ -223,8 +231,14 @@ void gncCustomerRemoveJob (GncCustomer *cust, GncJob *job)
void gncCustomerCommitEdit (GncCustomer *cust)
{
if (!cust) return;
/* XXX COMMIT TO DATABASE */
if (cust->dirty)
gncBusinessSetDirtyFlag (cust->book, _GNC_MOD_NAME, TRUE);
cust->dirty = FALSE;
gncAddressClearDirty (cust->addr);
gncAddressClearDirty (cust->shipaddr);
}
/* Get Functions */
@ -283,6 +297,12 @@ gboolean gncCustomerGetTaxIncluded (GncCustomer *cust)
return cust->taxincluded;
}
gnc_commodity * gncCustomerGetCommodity (GncCustomer *cust)
{
if (!cust) return NULL;
return cust->commodity;
}
gboolean gncCustomerGetActive (GncCustomer *cust)
{
if (!cust) return FALSE;
@ -371,6 +391,11 @@ static gboolean _gncCustomerIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncCustomerMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncCustomerForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -394,6 +419,7 @@ static GncObject_t gncCustomerDesc = {
_gncCustomerCreate,
_gncCustomerDestroy,
_gncCustomerIsDirty,
_gncCustomerMarkClean,
_gncCustomerForeach,
_gncCustomerPrintable,
};

View File

@ -32,6 +32,7 @@ void gncCustomerSetTaxIncluded (GncCustomer *customer, gboolean taxincl);
void gncCustomerSetActive (GncCustomer *customer, gboolean active);
void gncCustomerSetDiscount (GncCustomer *customer, gnc_numeric discount);
void gncCustomerSetCredit (GncCustomer *customer, gnc_numeric credit);
void gncCustomerSetCommodity (GncCustomer *customer, gnc_commodity *com);
void gncCustomerAddJob (GncCustomer *customer, GncJob *job);
void gncCustomerRemoveJob (GncCustomer *customer, GncJob *job);
@ -52,6 +53,7 @@ gboolean gncCustomerGetTaxIncluded (GncCustomer *customer);
gboolean gncCustomerGetActive (GncCustomer *customer);
gnc_numeric gncCustomerGetDiscount (GncCustomer *customer);
gnc_numeric gncCustomerGetCredit (GncCustomer *customer);
gnc_commodity * gncCustomerGetCommodity (GncCustomer *customer);
GList * gncCustomerGetJoblist (GncCustomer *customer, gboolean show_all);

View File

@ -31,6 +31,7 @@ struct _gncEmployee {
char * language;
char * acl;
GncAddress * addr;
gnc_commodity * commodity;
gnc_numeric workday;
gnc_numeric rate;
gboolean active;
@ -167,6 +168,13 @@ void gncEmployeeSetRate (GncEmployee *employee, gnc_numeric rate)
mark_employee (employee);
}
void gncEmployeeSetCommodity (GncEmployee *employee, gnc_commodity *com)
{
if (!employee || !com) return;
employee->commodity = com;
mark_employee (employee);
}
void gncEmployeeSetActive (GncEmployee *employee, gboolean active)
{
if (!employee) return;
@ -231,6 +239,12 @@ gnc_numeric gncEmployeeGetRate (GncEmployee *employee)
return employee->rate;
}
gnc_commodity * gncEmployeeGetCommodity (GncEmployee *employee)
{
if (!employee) return NULL;
return employee->commodity;
}
gboolean gncEmployeeGetActive (GncEmployee *employee)
{
if (!employee) return FALSE;
@ -252,9 +266,13 @@ gboolean gncEmployeeIsDirty (GncEmployee *employee)
void gncEmployeeCommitEdit (GncEmployee *employee)
{
if (!employee) return;
/* XXX COMMIT TO DATABASE */
if (employee->dirty)
gncBusinessSetDirtyFlag (employee->book, _GNC_MOD_NAME, TRUE);
employee->dirty = FALSE;
gncAddressClearDirty (employee->addr);
}
/* Other functions */
@ -296,6 +314,11 @@ static gboolean _gncEmployeeIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncEmployeeMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncEmployeeForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -319,6 +342,7 @@ static GncObject_t gncEmployeeDesc = {
_gncEmployeeCreate,
_gncEmployeeDestroy,
_gncEmployeeIsDirty,
_gncEmployeeMarkClean,
_gncEmployeeForeach,
_gncEmployeePrintable
};

View File

@ -27,6 +27,7 @@ void gncEmployeeSetLanguage (GncEmployee *employee, const char *language);
void gncEmployeeSetAcl (GncEmployee *employee, const char *acl);
void gncEmployeeSetWorkday (GncEmployee *employee, gnc_numeric workday);
void gncEmployeeSetRate (GncEmployee *employee, gnc_numeric rate);
void gncEmployeeSetCommodity (GncEmployee *employee, gnc_commodity * com);
void gncEmployeeSetActive (GncEmployee *employee, gboolean active);
/* Get Functions */
@ -40,6 +41,7 @@ const char * gncEmployeeGetLanguage (GncEmployee *employee);
const char * gncEmployeeGetAcl (GncEmployee *employee);
gnc_numeric gncEmployeeGetWorkday (GncEmployee *employee);
gnc_numeric gncEmployeeGetRate (GncEmployee *employee);
gnc_commodity * gncEmployeeGetCommodity (GncEmployee *employee);
gboolean gncEmployeeGetActive (GncEmployee *employee);
GncEmployee * gncEmployeeLookup (GNCBook *book, const GUID *guid);

View File

@ -450,6 +450,9 @@ void gncEntryCommitEdit (GncEntry *entry)
{
if (!entry) return;
/* XXX */
if (entry->dirty)
gncBusinessSetDirtyFlag (entry->book, _GNC_MOD_NAME, TRUE);
entry->dirty = FALSE;
}
int gncEntryCompare (GncEntry *a, GncEntry *b)
@ -502,6 +505,11 @@ static gboolean _gncEntryIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncEntryMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncEntryForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -515,6 +523,7 @@ static GncObject_t gncEntryDesc = {
_gncEntryCreate,
_gncEntryDestroy,
_gncEntryIsDirty,
_gncEntryMarkClean,
_gncEntryForeach,
NULL /* printable */
};

View File

@ -41,6 +41,8 @@ struct _gncInvoice {
Timespec date_due;
Timespec date_paid;
gnc_commodity * common_commodity;
Account * posted_acc;
Transaction * posted_txn;
Transaction * paid_txn;
@ -195,6 +197,13 @@ void gncInvoiceSetActive (GncInvoice *invoice, gboolean active)
mark_invoice (invoice);
}
void gncInvoiceSetCommonCommodity (GncInvoice *invoice, gnc_commodity *com)
{
if (!invoice || !com) return;
invoice->common_commodity = com;
mark_invoice (invoice);
}
void gncInvoiceSetDirty (GncInvoice *invoice, gboolean dirty)
{
if (!invoice) return;
@ -316,6 +325,12 @@ const char * gncInvoiceGetNotes (GncInvoice *invoice)
return invoice->notes;
}
gnc_commodity * gncInvoiceGetCommonCommodity (GncInvoice *invoice)
{
if (!invoice) return NULL;
return invoice->common_commodity;
}
Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice)
{
if (!invoice) return NULL;
@ -325,7 +340,7 @@ Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice)
Transaction * gncInvoiceGetPaidTxn (GncInvoice *invoice)
{
if (!invoice) return NULL;
return invoice->posted_txn;
return invoice->paid_txn;
}
Account * gncInvoiceGetPostedAcc (GncInvoice *invoice)
@ -407,7 +422,6 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
GList *iter;
GList *splitinfo = NULL;
gnc_numeric total;
gnc_commodity *commonCommodity = NULL; /* XXX: FIXME */
struct acct_val {
Account * acc;
gnc_numeric val;
@ -415,8 +429,6 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
if (!invoice || !acc) return NULL;
/* XXX: Figure out the common currency */
txn = xaccMallocTransaction (invoice->book);
xaccTransBeginEdit (txn);
@ -425,7 +437,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
(txn, gncOwnerGetName (gncInvoiceGetOwner (invoice)));
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
xaccTransSetCurrency (txn, commonCommodity);
xaccTransSetCurrency (txn, invoice->common_commodity);
/* Entered and Posted at date */
if (date) {
@ -484,7 +496,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
xaccSplitSetBaseValue (split, (reverse ? gnc_numeric_neg (acc_val->val)
: acc_val->val),
commonCommodity);
invoice->common_commodity);
xaccAccountBeginEdit (acc_val->acc);
xaccAccountInsertSplit (acc_val->acc, split);
xaccAccountCommitEdit (acc_val->acc);
@ -496,7 +508,7 @@ Transaction * gncInvoicePostToAccount (GncInvoice *invoice, Account *acc,
Split *split = xaccMallocSplit (invoice->book);
/* Set action/memo */
xaccSplitSetBaseValue (split, (reverse ? total : gnc_numeric_neg (total)),
commonCommodity);
invoice->common_commodity);
xaccAccountBeginEdit (acc);
xaccAccountInsertSplit (acc, split);
xaccAccountCommitEdit (acc);
@ -518,7 +530,6 @@ gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
{
Transaction *txn;
gnc_numeric total;
gnc_commodity *commonCommodity = NULL; /* XXX: FIXME */
Account *acct;
if (!invoice || !acc) return NULL;
@ -548,8 +559,6 @@ gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
g_return_val_if_fail (l, NULL);
}
/* XXX: Figure out the common currency */
txn = xaccMallocTransaction (invoice->book);
xaccTransBeginEdit (txn);
@ -558,7 +567,7 @@ gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
(txn, gncOwnerGetName (gncInvoiceGetOwner (invoice)));
xaccTransSetNum (txn, gncInvoiceGetID (invoice));
xaccTransSetCurrency (txn, commonCommodity);
xaccTransSetCurrency (txn, invoice->common_commodity);
/* Entered and Posted at date */
if (paid_date) {
@ -571,7 +580,7 @@ gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
{
Split *split = xaccMallocSplit (invoice->book);
/* Set action/memo */
xaccSplitSetBaseValue (split, total, commonCommodity);
xaccSplitSetBaseValue (split, total, invoice->common_commodity);
xaccAccountBeginEdit (acc);
xaccAccountInsertSplit (acc, split);
xaccAccountCommitEdit (acc);
@ -583,7 +592,8 @@ gncInvoicePayToAccount (GncInvoice *invoice, Account *acc,
Split *split = xaccMallocSplit (invoice->book);
/* Set action/memo */
xaccSplitSetBaseValue (split, gnc_numeric_neg (total), commonCommodity);
xaccSplitSetBaseValue (split, gnc_numeric_neg (total),
invoice->common_commodity);
xaccAccountBeginEdit (acct);
xaccAccountInsertSplit (acct, split);
xaccAccountCommitEdit (acct);
@ -651,6 +661,9 @@ void gncInvoiceBeginEdit (GncInvoice *invoice)
void gncInvoiceCommitEdit (GncInvoice *invoice)
{
if (!invoice) return;
if (invoice->dirty)
gncBusinessSetDirtyFlag (invoice->book, _GNC_MOD_NAME, TRUE);
invoice->dirty = FALSE;
}
int gncInvoiceCompare (GncInvoice *a, GncInvoice *b)
@ -703,6 +716,11 @@ static gboolean _gncInvoiceIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncInvoiceMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncInvoiceForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -734,6 +752,7 @@ static GncObject_t gncInvoiceDesc = {
_gncInvoiceCreate,
_gncInvoiceDestroy,
_gncInvoiceIsDirty,
_gncInvoiceMarkClean,
_gncInvoiceForeach,
_gncInvoicePrintable,
};

View File

@ -30,6 +30,7 @@ void gncInvoiceSetDateDue (GncInvoice *invoice, Timespec date);
void gncInvoiceSetDatePaid (GncInvoice *invoice, Timespec date);
void gncInvoiceSetTerms (GncInvoice *invoice, const char *terms);
void gncInvoiceSetNotes (GncInvoice *invoice, const char *notes);
void gncInvoiceSetCommonCommodity (GncInvoice *invoice, gnc_commodity *com);
void gncInvoiceSetActive (GncInvoice *invoice, gboolean active);
void gncInvoiceAddEntry (GncInvoice *invoice, GncEntry *entry);
@ -47,6 +48,7 @@ Timespec gncInvoiceGetDateDue (GncInvoice *invoice);
Timespec gncInvoiceGetDatePaid (GncInvoice *invoice);
const char * gncInvoiceGetTerms (GncInvoice *invoice);
const char * gncInvoiceGetNotes (GncInvoice *invoice);
gnc_commodity * gncInvoiceGetCommonCommodity (GncInvoice *invoice);
gboolean gncInvoiceGetActive (GncInvoice *invoice);
Transaction * gncInvoiceGetPostedTxn (GncInvoice *invoice);

View File

@ -186,7 +186,11 @@ void gncJobSetActive (GncJob *job, gboolean active)
void gncJobCommitEdit (GncJob *job)
{
if (!job) return;
/* XXX: COMMIT TO DATABASE */
if (job->dirty)
gncBusinessSetDirtyFlag (job->book, _GNC_MOD_NAME, TRUE);
job->dirty = FALSE;
}
@ -285,6 +289,11 @@ static gboolean _gncJobIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncJobMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncJobForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -308,6 +317,7 @@ static GncObject_t gncJobDesc = {
_gncJobCreate,
_gncJobDestroy,
_gncJobIsDirty,
_gncJobMarkClean,
_gncJobForeach,
_gncJobPrintable
};

View File

@ -298,6 +298,10 @@ void gncOrderBeginEdit (GncOrder *order)
void gncOrderCommitEdit (GncOrder *order)
{
if (!order) return;
if (order->dirty)
gncBusinessSetDirtyFlag (order->book, _GNC_MOD_NAME, TRUE);
order->dirty = FALSE;
}
int gncOrderCompare (GncOrder *a, GncOrder *b)
@ -347,6 +351,11 @@ static gboolean _gncOrderIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncOrderMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncOrderForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -377,6 +386,7 @@ static GncObject_t gncOrderDesc = {
_gncOrderCreate,
_gncOrderDestroy,
_gncOrderIsDirty,
_gncOrderMarkClean,
_gncOrderForeach,
_gncOrderPrintable,
};

View File

@ -30,6 +30,7 @@ struct _gncVendor {
char * notes;
char * terms;
GncAddress * addr;
gnc_commodity * commodity;
gboolean taxincluded;
gboolean active;
GList * jobs;
@ -158,6 +159,13 @@ void gncVendorSetTaxIncluded (GncVendor *vendor, gboolean taxincl)
mark_vendor (vendor);
}
void gncVendorSetCommodity (GncVendor *vendor, gnc_commodity *com)
{
if (!vendor || !com) return;
vendor->commodity = com;
mark_vendor (vendor);
}
void gncVendorSetActive (GncVendor *vendor, gboolean active)
{
if (!vendor) return;
@ -216,6 +224,12 @@ gboolean gncVendorGetTaxIncluded (GncVendor *vendor)
return vendor->taxincluded;
}
gnc_commodity * gncVendorGetCommodity (GncVendor *vendor)
{
if (!vendor) return NULL;
return vendor->commodity;
}
gboolean gncVendorGetActive (GncVendor *vendor)
{
if (!vendor) return FALSE;
@ -255,9 +269,13 @@ void gncVendorRemoveJob (GncVendor *vendor, GncJob *job)
void gncVendorCommitEdit (GncVendor *vendor)
{
if (!vendor) return;
/* XXX COMMIT TO DATABASE */
if (vendor->dirty)
gncBusinessSetDirtyFlag (vendor->book, _GNC_MOD_NAME, TRUE);
vendor->dirty = FALSE;
gncAddressClearDirty (vendor->addr);
}
/* Other functions */
@ -328,6 +346,11 @@ static gboolean _gncVendorIsDirty (GNCBook *book)
return gncBusinessIsDirty (book, _GNC_MOD_NAME);
}
static void _gncVendorMarkClean (GNCBook *book)
{
gncBusinessSetDirtyFlag (book, _GNC_MOD_NAME, FALSE);
}
static void _gncVendorForeach (GNCBook *book, foreachObjectCB cb,
gpointer user_data)
{
@ -351,6 +374,7 @@ static GncObject_t gncVendorDesc = {
_gncVendorCreate,
_gncVendorDestroy,
_gncVendorIsDirty,
_gncVendorMarkClean,
_gncVendorForeach,
_gncVendorPrintable
};

View File

@ -27,6 +27,7 @@ void gncVendorSetName (GncVendor *vendor, const char *name);
void gncVendorSetNotes (GncVendor *vendor, const char *notes);
void gncVendorSetTerms (GncVendor *vendor, const char *terms);
void gncVendorSetTaxIncluded (GncVendor *vendor, gboolean taxincl);
void gncVendorSetCommodity (GncVendor *vendor, gnc_commodity *com);
void gncVendorSetActive (GncVendor *vendor, gboolean active);
void gncVendorAddJob (GncVendor *vendor, GncJob *job);
@ -44,6 +45,7 @@ GncAddress * gncVendorGetAddr (GncVendor *vendor);
const char * gncVendorGetNotes (GncVendor *vendor);
const char * gncVendorGetTerms (GncVendor *vendor);
gboolean gncVendorGetTaxIncluded (GncVendor *vendor);
gnc_commodity * gncVendorGetCommodity (GncVendor *vendor);
gboolean gncVendorGetActive (GncVendor *vendor);
GList * gncVendorGetJoblist (GncVendor *vendor, gboolean show_all);

View File

@ -213,6 +213,14 @@
'((<gnc:GncCustomer*> customer) ((<gw:mchars> callee-owned const) name))
"Set the customer Name")
(gw:wrap-function
ws
'gnc:customer-set-commodity
'<gw:void>
"gncCustomerSetCommodity"
'((<gnc:GncCustomer*> customer) (<gnc:commodity*> commodity))
"Set the Customer Commodity")
; Get Functions
(gw:wrap-function
@ -255,6 +263,14 @@
'((<gnc:GncCustomer*> customer))
"Return the Customer's Notes")
(gw:wrap-function
ws
'gnc:customer-get-commodity
'<gnc:commodity*>
"gncCustomerGetCommodity"
'((<gnc:GncCustomer*> customer))
"Get the Customer Commodity")
;;
;; gncEmployee.h
;;
@ -429,6 +445,14 @@
'((<gnc:GncInvoice*> invoice) ((<gw:mchars> callee-owned const) id))
"Set the Invoice Terms")
(gw:wrap-function
ws
'gnc:invoice-set-common-commodity
'<gw:void>
"gncInvoiceSetCommonCommodity"
'((<gnc:GncInvoice*> invoice) (<gnc:commodity*> commodity))
"Set the Invoice Commodity")
; Get Functions
(gw:wrap-function
@ -503,6 +527,14 @@
'((<gnc:GncInvoice*> invoice))
"Return the invoice's Notes")
(gw:wrap-function
ws
'gnc:invoice-get-common-commodity
'<gnc:commodity*>
"gncInvoiceGetCommonCommodity"
'((<gnc:GncInvoice*> invoice))
"Return the invoice's commodity")
(gw:wrap-function
ws
'gnc:invoice-get-entries

View File

@ -5,6 +5,7 @@
(gnc:module-load "gnucash/gnome-utils" 0)
(gnc:module-load "gnucash/business-core" 0)
(gnc:module-load "gnucash/gnome-search" 0)
(gnc:module-load "gnucash/business-core-file" 0)
(define (add-customer-extensions)
(let ((last-cust (gnc:owner-create)))
@ -244,6 +245,8 @@
;; Create Customer
(gnc:customer-set-id customer "000001")
(gnc:customer-set-name customer "Test Customer")
(gnc:customer-set-commodity customer
(gnc:default-currency))
(gnc:address-set-name address "Contact Person")
(gnc:address-set-addr1 address
"20 Customer Lane")
@ -259,6 +262,8 @@
(gnc:invoice-set-terms invoice "Net-30")
(gnc:invoice-set-date-opened
invoice (cons (current-time) 0))
(gnc:invoice-set-common-commodity
invoice (gnc:default-currency))
;; Create the Job
(gnc:job-set-id job "000025")

View File

@ -548,6 +548,7 @@ gnc_customer_new_window (GtkWidget *parent, GNCBook *bookp,
cw);
} else {
cust = gncCustomerCreate (bookp);
gncCustomerSetCommodity (cust, commodity);
cw->customer_guid = *gncCustomerGetGUID (cust);
cw->dialog_type = NEW_CUSTOMER;

View File

@ -463,6 +463,7 @@ gnc_employee_new_window (GtkWidget *parent, GNCBook *bookp,
ew);
} else {
employee = gncEmployeeCreate (bookp);
gncEmployeeSetCommodity (employee, commodity);
ew->employee_guid = *gncEmployeeGetGUID (employee);
ew->dialog_type = NEW_EMPLOYEE;

View File

@ -670,6 +670,7 @@ gnc_invoice_new_window (GtkWidget *parent, GNCBook *bookp,
if (type == NEW_INVOICE) {
invoice = gncInvoiceCreate (bookp);
gncInvoiceSetCommonCommodity (invoice, gnc_default_currency ()); /* XXX */
gncInvoiceSetOwner (invoice, owner);
}

View File

@ -417,6 +417,7 @@ gnc_vendor_new_window (GtkWidget *parent, GNCBook *bookp,
vw);
} else {
vendor = gncVendorCreate (bookp);
gncVendorSetCommodity (vendor, gnc_default_currency ());
vw->vendor_guid = *gncVendorGetGUID (vendor);
vw->dialog_type = NEW_VENDOR;

View File

@ -334,6 +334,9 @@ gnc_book_mark_saved(GNCBook *book)
xaccGroupMarkSaved(gnc_book_get_template_group(book));
book_sxns_mark_saved(book);
/* Mark everything as clean */
gncObjectMarkClean (book);
}
static gboolean

View File

@ -16,6 +16,7 @@
static gboolean object_is_initialized = FALSE;
static GList *object_modules = NULL;
static GList *book_list = NULL;
static GHashTable *backend_data = NULL;
void gncObjectBookBegin (GNCBook *book)
{
@ -61,6 +62,30 @@ gboolean gncObjectIsDirty (GNCBook *book)
return FALSE;
}
void gncObjectMarkClean (GNCBook *book)
{
GList *l;
if (!book) return;
for (l = object_modules; l; l = l->next) {
GncObject_t *obj = l->data;
if (obj->mark_clean)
(obj->mark_clean) (book);
}
}
void gncObjectForeachType (foreachTypeCB cb, gpointer user_data)
{
GList *l;
if (!cb) return;
for (l = object_modules; l; l = l->next) {
GncObject_t *obj = l->data;
(cb) (obj, user_data);
}
}
void gncObjectForeach (GNCIdTypeConst type_name, GNCBook *book,
foreachObjectCB cb, gpointer user_data)
{
@ -105,17 +130,29 @@ const char * gncObjectGetTypeLabel (GNCIdTypeConst type_name)
return _(obj->type_label);
}
static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
{
g_hash_table_destroy (value);
return TRUE;
}
/* INITIALIZATION and PRIVATE FUNCTIONS */
void gncObjectInitialize (void)
{
if (object_is_initialized) return;
backend_data = g_hash_table_new (g_str_hash, g_str_equal);
object_is_initialized = TRUE;
}
void gncObjectShutdown (void)
{
g_return_if_fail (object_is_initialized == TRUE);
g_hash_table_foreach_remove (backend_data, clear_table, NULL);
g_hash_table_destroy (backend_data);
backend_data = NULL;
g_list_free (object_modules);
object_modules = NULL;
g_list_free (book_list);
@ -130,9 +167,10 @@ void gncObjectShutdown (void)
*/
gboolean gncObjectRegister (const GncObject_t *object)
{
g_return_val_if_fail (object_is_initialized, FALSE);
if (!object) return FALSE;
if (object->version != GNC_OBJECT_VERSION) return FALSE;
if (!object_is_initialized) return FALSE;
g_return_val_if_fail (object->version == GNC_OBJECT_VERSION, FALSE);
if (g_list_index (object_modules, (gpointer)object) == -1)
object_modules = g_list_prepend (object_modules, (gpointer)object);
@ -165,3 +203,81 @@ const GncObject_t * gncObjectLookup (GNCIdTypeConst name)
}
return NULL;
}
gboolean gncObjectRegisterBackend (GNCIdTypeConst type_name,
const char *backend_name,
gpointer be_data)
{
GHashTable *ht;
g_return_val_if_fail (object_is_initialized, FALSE);
if (!type_name || *type_name == '\0' ||
!backend_name || *backend_name == '\0' ||
!be_data)
return FALSE;
ht = g_hash_table_lookup (backend_data, backend_name);
/* If it doesn't already exist, create a new table for this backend */
if (!ht) {
ht = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (backend_data, (char *)backend_name, ht);
}
/* Now insert the data */
g_hash_table_insert (ht, (char *)type_name, be_data);
return TRUE;
}
gpointer gncObjectLookupBackend (GNCIdTypeConst type_name,
const char *backend_name)
{
GHashTable *ht;
if (!type_name || *type_name == '\0' ||
!backend_name || *backend_name == '\0')
return NULL;
ht = g_hash_table_lookup (backend_data, (char *)backend_name);
if (!ht)
return NULL;
return g_hash_table_lookup (ht, (char *)type_name);
}
struct foreach_data {
foreachBackendTypeCB cb;
gpointer user_data;
};
static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
{
char *data_type = key;
struct foreach_data *cb_data = arg;
g_return_if_fail (key && be_item && arg);
/* Call the callback for this data type */
(cb_data->cb) (data_type, be_item, cb_data->user_data);
}
void gncObjectForeachBackend (const char *backend_name,
foreachBackendTypeCB cb,
gpointer user_data)
{
GHashTable *ht;
struct foreach_data cb_data;
if (!backend_name || *backend_name == '\0' || !cb)
return;
ht = g_hash_table_lookup (backend_data, (char *)backend_name);
if (!ht)
return;
cb_data.cb = cb;
cb_data.user_data = user_data;
g_hash_table_foreach (ht, foreach_backend, &cb_data);
}

View File

@ -16,10 +16,15 @@
*/
#define GNC_OBJECT_VERSION 1
typedef struct _gncObjectDef GncObject_t;
typedef void (*foreachObjectCB) (gpointer object, gpointer user_data);
typedef void (*foreachTypeCB) (GncObject_t *type, gpointer user_data);
typedef void (*foreachBackendTypeCB) (GNCIdTypeConst type,
gpointer backend_data,
gpointer user_data);
/* This is the Object Object descriptor */
typedef struct _gncObjectDef {
struct _gncObjectDef {
gint version; /* of the object interface */
GNCIdType name; /* the Object's GNC_ID */
const char * type_label; /* "Printable" type-label string */
@ -35,6 +40,9 @@ typedef struct _gncObjectDef {
/* Determine if there are any dirty items in this book */
gboolean (*is_dirty)(GNCBook *);
/* Mark this object's book clean (for after a load) */
void (*mark_clean)(GNCBook *);
/* foreach() is used to execute a callback over each object
* stored in the particular book
*/
@ -43,7 +51,9 @@ typedef struct _gncObjectDef {
/* Given a particular object, return a printable string */
const char * (*printable)(gpointer obj);
} GncObject_t;
};
void gncObjectForeachType (foreachTypeCB cb, gpointer user_data);
void gncObjectForeach (GNCIdTypeConst type_name, GNCBook *book,
foreachObjectCB cb, gpointer user_data);
@ -63,4 +73,16 @@ const char * gncObjectGetTypeLabel (GNCIdTypeConst type_name);
const GncObject_t * gncObjectLookup (GNCIdTypeConst type_name);
/* Register and lookup backend-specific data for this particular object */
gboolean gncObjectRegisterBackend (GNCIdTypeConst type_name,
const char *backend_name,
gpointer be_data);
gpointer gncObjectLookupBackend (GNCIdTypeConst type_name,
const char *backend_name);
void gncObjectForeachBackend (const char *backend_name,
foreachBackendTypeCB cb,
gpointer user_data);
#endif /* GNC_OBJECT_H_ */

View File

@ -18,5 +18,6 @@ void gncObjectBookBegin (GNCBook *book);
void gncObjectBookEnd (GNCBook *book);
gboolean gncObjectIsDirty (GNCBook *book);
void gncObjectMarkClean (GNCBook *book);
#endif /* GNC_OBJECTP_H_ */