From c390968d0048754078245c3b508677c5b99f1cc6 Mon Sep 17 00:00:00 2001 From: Dave Peticolas Date: Tue, 13 Mar 2001 06:20:03 +0000 Subject: [PATCH] James LewisMoss's patch. * src/gnome/window-main.c (gnc_ui_xml_v2_cb): new func. (gnc_ui_account_heirarchy_cb): new empty func. (gnc_main_create_menus): add devel menu. * src/engine/io-gncxml-v2.h (struct _load_counter_struct): add counters stuff. * src/engine/io-gncxml-v2.c: mostly complete everything. Writing only partially tested. Reading not tested at all. * src/engine/gnc-xml.h: add pricedb declarations. * src/engine/gnc-transaction-xml-v2.c (split_to_dom_tree): check for NULL return from kvp_frame_to_dom_tree and don't add if we get it. (gnc_transaction_dom_tree_create): same. * src/engine/gnc-commodity.c (gnc_commodity_table_get_size): add func. * src/engine/gnc-account-xml-v2.c (gnc_account_dom_tree_create): check for NULL return from kvp_frame_to_dom_tree and don't do anything if we get it. * src/gnome/gnc-http.c (gnc_http_start_post): cast data to char* (it's const char*) (compile warning) * src/gnome/gnc-html.c: put const on char *ptr (compile warning) * src/doc/xml/io-gncxml-version2.dtd: reorder commodity and prices. Add count data defs. * src/engine/sixtp-dom-generators.c (timespec_to_dom_tree): Only write nanoseconds if > 0. (kvp_frame_to_dom_tree): don't return an xmlNodePtr if the frame is null or contains no data. * src/engine/gnc-commodity-xml-v2.c (gnc_commodity_dom_tree_create): check to see if xcode is > 0 * src/engine/gnc-account-xml-v2.c (gnc_account_dom_tree_create): check for description and code strlen > 0 * src/engine/gnc-pricedb-xml-v1.c (pricedb_v2_end_handler): make this func work in the v2 manner with a callback in the global data. (gnc_pricedb_sixtp_parser_create): change to work in the v2 manner with an end handler that does the final link of the data into the book. (pricedb_after_child_handler): add upping the counter for prices loaded. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3772 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 64 ++++ src/doc/xml/io-gncxml-version2.dtd | 9 +- src/doc/xml/prices-v1.dtd | 22 +- src/engine/gnc-account-xml-v2.c | 14 +- src/engine/gnc-commodity-xml-v2.c | 3 +- src/engine/gnc-commodity.c | 12 + src/engine/gnc-commodity.h | 1 + src/engine/gnc-pricedb-xml-v1.c | 67 ++++- src/engine/gnc-pricedb.c | 2 + src/engine/gnc-pricedb.h | 2 + src/engine/gnc-transaction-xml-v2.c | 24 +- src/engine/gnc-xml.h | 6 +- src/engine/io-gncxml-v2.c | 435 ++++++++++++++++++++++++++-- src/engine/io-gncxml-v2.h | 22 +- src/engine/sixtp-dom-generators.c | 42 ++- src/gnome/gnc-html.c | 2 +- src/gnome/gnc-http.c | 2 +- src/gnome/window-main.c | 45 +++ 18 files changed, 707 insertions(+), 67 deletions(-) diff --git a/ChangeLog b/ChangeLog index a244001dc7..93d4778c65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,56 @@ +2001-03-12 James LewisMoss + + * src/gnome/window-main.c (gnc_ui_xml_v2_cb): new func. + (gnc_ui_account_heirarchy_cb): new empty func. + (gnc_main_create_menus): add devel menu. + + * src/engine/io-gncxml-v2.h (struct _load_counter_struct): add + counters stuff. + + * src/engine/io-gncxml-v2.c: mostly complete everything. Writing + only partially tested. Reading not tested at all. + + * src/engine/gnc-xml.h: add pricedb declarations. + + * src/engine/gnc-transaction-xml-v2.c (split_to_dom_tree): check + for NULL return from kvp_frame_to_dom_tree and don't add if we get + it. + (gnc_transaction_dom_tree_create): same. + + * src/engine/gnc-commodity.c (gnc_commodity_table_get_size): add func. + + * src/engine/gnc-account-xml-v2.c (gnc_account_dom_tree_create): + check for NULL return from kvp_frame_to_dom_tree and don't do + anything if we get it. + + * src/gnome/gnc-http.c (gnc_http_start_post): cast data to char* + (it's const char*) (compile warning) + + * src/gnome/gnc-html.c: put const on char *ptr (compile warning) + + * src/doc/xml/io-gncxml-version2.dtd: reorder commodity and + prices. Add count data defs. + + * src/engine/sixtp-dom-generators.c (timespec_to_dom_tree): Only + write nanoseconds if > 0. + (kvp_frame_to_dom_tree): don't return an xmlNodePtr if the frame + is null or contains no data. + + * src/engine/gnc-commodity-xml-v2.c + (gnc_commodity_dom_tree_create): check to see if xcode is > 0 + + * src/engine/gnc-account-xml-v2.c (gnc_account_dom_tree_create): + check for description and code strlen > 0 + + * src/engine/gnc-pricedb-xml-v1.c (pricedb_v2_end_handler): make + this func work in the v2 manner with a callback in the global + data. + (gnc_pricedb_sixtp_parser_create): change to work in the v2 manner + with an end handler that does the final link of the data into the + book. + (pricedb_after_child_handler): add upping the counter for prices + loaded. + 2001-03-12 Dave Peticolas * src/engine/io-gncxml-r.c (gnc_book_load_from_xml_file): use @@ -58,6 +111,17 @@ 2001-03-09 James LewisMoss + * src/doc/xml/prices-v1.dtd: Add rest of def. + + * src/engine/gnc-pricedb-xml-v1.c (add_child_or_kill_parent): + remove unneeded check since NULL has already been checked. + (xml_add_gnc_pricedb): extract out pricedb xmlNodePtr creation to + func not requiring parent then add that to parent passed into this + func. + (gnc_pricedb_to_dom_tree): new func. + (gnc_pricedb_sixtp_parser_create): new func to call other so names + are standard in v2 parser setup. + * src/engine/Account.c (xaccAccountInsertSplit): Remove unused var oldacc (assigned to once) and the block that went with it. diff --git a/src/doc/xml/io-gncxml-version2.dtd b/src/doc/xml/io-gncxml-version2.dtd index e0cbea88a5..de5c7e15b4 100644 --- a/src/doc/xml/io-gncxml-version2.dtd +++ b/src/doc/xml/io-gncxml-version2.dtd @@ -1,5 +1,6 @@ - + @@ -8,6 +9,10 @@ + + + + %defaults-v1; %prefs-v1; diff --git a/src/doc/xml/prices-v1.dtd b/src/doc/xml/prices-v1.dtd index 3094e643c3..6fb33f9670 100644 --- a/src/doc/xml/prices-v1.dtd +++ b/src/doc/xml/prices-v1.dtd @@ -1 +1,21 @@ - + +%types; + + + + + + + + + + + + + + + + + + diff --git a/src/engine/gnc-account-xml-v2.c b/src/engine/gnc-account-xml-v2.c index 9d6e399ee7..0ba4e84f95 100644 --- a/src/engine/gnc-account-xml-v2.c +++ b/src/engine/gnc-account-xml-v2.c @@ -52,12 +52,14 @@ gnc_account_dom_tree_create(Account *act) xmlAddChild(ret, commodity_ref_to_dom_tree(act_currency_string, xaccAccountGetCurrency(act))); - if(xaccAccountGetCode(act)) + if(xaccAccountGetCode(act) && + strlen(xaccAccountGetCode(act)) > 0) { xmlNewChild(ret, NULL, act_code_string, xaccAccountGetCode(act)); } - if(xaccAccountGetDescription(act)) + if(xaccAccountGetDescription(act) && + strlen(xaccAccountGetDescription(act)) > 0) { xmlNewChild(ret, NULL, act_description_string, xaccAccountGetDescription(act)); @@ -71,8 +73,12 @@ gnc_account_dom_tree_create(Account *act) if(xaccAccountGetSlots(act)) { - xmlAddChild(ret, kvp_frame_to_dom_tree(act_slots_string, - xaccAccountGetSlots(act))); + xmlNodePtr kvpnode = kvp_frame_to_dom_tree(act_slots_string, + xaccAccountGetSlots(act)); + if(kvpnode) + { + xmlAddChild(ret, kvpnode); + } } if(xaccAccountGetParentAccount(act)) diff --git a/src/engine/gnc-commodity-xml-v2.c b/src/engine/gnc-commodity-xml-v2.c index 80616d6bd6..da46406a94 100644 --- a/src/engine/gnc-commodity-xml-v2.c +++ b/src/engine/gnc-commodity-xml-v2.c @@ -40,7 +40,8 @@ gnc_commodity_dom_tree_create(const gnc_commodity *com) xmlNewChild(ret, NULL, "cmdty:name", gnc_commodity_get_fullname(com)); } - if(gnc_commodity_get_exchange_code(com)) + if(gnc_commodity_get_exchange_code(com) && + strlen(gnc_commodity_get_exchange_code(com)) > 0) { xmlNewChild(ret, NULL, "cmdty:xcode", gnc_commodity_get_exchange_code(com)); diff --git a/src/engine/gnc-commodity.c b/src/engine/gnc-commodity.c index f4b3a6600a..6aca80df03 100644 --- a/src/engine/gnc-commodity.c +++ b/src/engine/gnc-commodity.c @@ -295,6 +295,18 @@ gnc_commodity_table_new(void) { return retval; } +/******************************************************************** + * gnc_commodity_get_size + * get the size of the commodity table + ********************************************************************/ + +guint +gnc_commodity_table_get_size(gnc_commodity_table* tbl) +{ + g_return_val_if_fail(tbl, 0); + g_return_val_if_fail(tbl->table, 0); + return g_hash_table_size(tbl->table); +} /******************************************************************** * gnc_commodity_table_lookup diff --git a/src/engine/gnc-commodity.h b/src/engine/gnc-commodity.h index fa3376c3f3..989a20361c 100644 --- a/src/engine/gnc-commodity.h +++ b/src/engine/gnc-commodity.h @@ -80,6 +80,7 @@ gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table * table, int gnc_commodity_table_has_namespace(const gnc_commodity_table * t, const char * namespace); +guint gnc_commodity_table_get_size(gnc_commodity_table* tbl); /* The next two functions return newly allocated lists which should * be freed with g_list_free. */ diff --git a/src/engine/gnc-pricedb-xml-v1.c b/src/engine/gnc-pricedb-xml-v1.c index 96764d0483..65d9b933a6 100644 --- a/src/engine/gnc-pricedb-xml-v1.c +++ b/src/engine/gnc-pricedb-xml-v1.c @@ -34,6 +34,7 @@ #include "sixtp-dom-generators.h" #include "sixtp-writers.h" #include "sixtp-xml-write-utils.h" +#include "io-gncxml-v2.h" #include "gnc-pricedb.h" @@ -246,6 +247,9 @@ pricedb_after_child_handler(gpointer data_for_children, g_return_val_if_fail(p, FALSE); gnc_pricedb_add_price(db, p); + /* can't do this because the v1 parser doesn't use this data + structure as global data */ + /* ((sixtp_gdv2*)global_data)->counter.prices_loaded++; */ return TRUE; } else { return FALSE; @@ -263,6 +267,30 @@ pricedb_cleanup_result_handler(sixtp_child_result *result) } } +static gboolean +pricedb_v2_end_handler( + gpointer data_for_children, GSList* data_from_children, + GSList* sibling_data, gpointer parent_data, gpointer global_data, + gpointer *result, const gchar *tag) +{ + GNCPriceDB *db = (GNCPriceDB*)result; + sixtp_gdv2* globaldata = (sixtp_gdv2*)global_data; + + globaldata->addPriceDBFunc(globaldata, db); + + return TRUE; +} + + +sixtp* +gnc_pricedb_sixtp_parser_create(void) +{ + sixtp *ret; + ret = gnc_pricedb_parser_new(); + sixtp_set_end(ret, pricedb_v2_end_handler); + return ret; +} + sixtp* gnc_pricedb_parser_new(void) { @@ -299,7 +327,6 @@ gnc_pricedb_parser_new(void) static gboolean add_child_or_kill_parent(xmlNodePtr parent, xmlNodePtr child) { - if(!parent) return FALSE; if(!child) { xmlFreeNode(parent); return FALSE; @@ -373,6 +400,33 @@ xml_add_gnc_price_adapter(GNCPrice *p, gpointer data) } } +xmlNodePtr +gnc_pricedb_to_dom_tree(const char *tag, GNCPriceDB *db) +{ + xmlNodePtr db_xml = NULL; + + if(!tag) return NULL; + + db_xml= xmlNewNode(NULL, tag); + if(!db_xml) return NULL; + + xmlSetProp(db_xml, "version", "1"); + + if(!gnc_pricedb_foreach_price(db, xml_add_gnc_price_adapter, db_xml, TRUE)) + { + xmlFreeNode(db_xml); + return NULL; + } + + return db_xml; +} + +xmlNodePtr +gnc_pricedb_dom_tree_create(GNCPriceDB *db) +{ + return gnc_pricedb_to_dom_tree("gnc:pricedb", db); +} + gboolean xml_add_gnc_pricedb(xmlNodePtr p, const char *tag, GNCPriceDB *db) { @@ -381,16 +435,7 @@ xml_add_gnc_pricedb(xmlNodePtr p, const char *tag, GNCPriceDB *db) if(!p || !tag) return FALSE; if(!db) return TRUE; - db_xml= xmlNewTextChild(p, NULL, tag, NULL); - if(!db_xml) return FALSE; - - xmlSetProp(db_xml, "version", "1"); - - if(!gnc_pricedb_foreach_price(db, xml_add_gnc_price_adapter, db_xml, TRUE)) - { - xmlFreeNode(db_xml); - return FALSE; - } + xmlAddChild(p, gnc_pricedb_to_dom_tree(tag, db)); return TRUE; } diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c index 792ebe4f5e..872bac8f44 100644 --- a/src/engine/gnc-pricedb.c +++ b/src/engine/gnc-pricedb.c @@ -86,6 +86,7 @@ gnc_price_unref(GNCPrice *p) } } +#if 0 GNCPrice * gnc_price_clone(GNCPrice* p) { @@ -103,6 +104,7 @@ gnc_price_clone(GNCPrice* p) gnc_price_set_currency(new_p, gnc_price_get_currency(p)); return(new_p); } +#endif /* setters */ void diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h index fdd25d11b6..0eb01648c4 100644 --- a/src/engine/gnc-pricedb.h +++ b/src/engine/gnc-pricedb.h @@ -77,7 +77,9 @@ typedef struct _GNCPrice GNCPrice; /* allocation */ GNCPrice *gnc_price_create(void); /* create and initialize a price */ +#if 0 GNCPrice *gnc_price_clone(GNCPrice* p); +#endif void gnc_price_ref(GNCPrice *p); void gnc_price_unref(GNCPrice *p); diff --git a/src/engine/gnc-transaction-xml-v2.c b/src/engine/gnc-transaction-xml-v2.c index 24bc3b5999..20abd8dbd8 100644 --- a/src/engine/gnc-transaction-xml-v2.c +++ b/src/engine/gnc-transaction-xml-v2.c @@ -94,9 +94,15 @@ split_to_dom_tree(const gchar *tag, Split *spl) xmlAddChild(ret, guid_to_dom_tree( "split:account", xaccSplitGetAccountGUID(spl))); - - xmlAddChild(ret, kvp_frame_to_dom_tree("split:slots", - xaccSplitGetSlots(spl))); + + { + xmlNodePtr kvpnode = kvp_frame_to_dom_tree("split:slots", + xaccSplitGetSlots(spl)); + if(kvpnode) + { + xmlAddChild(ret, kvpnode); + } + } return ret; } @@ -143,9 +149,15 @@ gnc_transaction_dom_tree_create(Transaction *trn) xmlNewTextChild(ret, NULL, "trn:description", xaccTransGetDescription(trn)); } - - xmlAddChild(ret, kvp_frame_to_dom_tree("trn:slots", - xaccTransGetSlots(trn))); + + { + xmlNodePtr kvpnode = kvp_frame_to_dom_tree("trn:slots", + xaccTransGetSlots(trn)); + if(kvpnode) + { + xmlAddChild(ret, kvpnode); + } + } add_trans_splits(ret, trn); diff --git a/src/engine/gnc-xml.h b/src/engine/gnc-xml.h index 9392ddbaf2..faae5e7d14 100644 --- a/src/engine/gnc-xml.h +++ b/src/engine/gnc-xml.h @@ -10,7 +10,7 @@ #include "gnc-commodity.h" #include "sixtp.h" - +#include "gnc-pricedb.h" xmlNodePtr gnc_account_dom_tree_create(Account *act); sixtp* gnc_account_sixtp_parser_create(void); @@ -24,4 +24,8 @@ sixtp* gnc_transaction_sixtp_parser_create(void); xmlNodePtr split_to_dom_tree(const gchar *tag, Split *spl); Split* dom_tree_to_split(xmlNodePtr node); +xmlNodePtr gnc_pricedb_dom_tree_create(GNCPriceDB *db); +sixtp* gnc_pricedb_sixtp_parser_create(void); + + #endif /* __GNC_XML_H__ */ diff --git a/src/engine/io-gncxml-v2.c b/src/engine/io-gncxml-v2.c index 940613f510..fda7016c99 100644 --- a/src/engine/io-gncxml-v2.c +++ b/src/engine/io-gncxml-v2.c @@ -1,57 +1,442 @@ +#include +#include +#include + +#include "gnc-engine.h" +#include "gnc-engine-util.h" + #include "io-gncxml-v2.h" +#include "sixtp.h" +#include "gnc-xml.h" +#include "gnc-book-p.h" +#include "Group.h" -struct _load_counter_struct +static void +clear_up_account_commodity( + GNCBook *book, Account *act, gnc_commodity * (*getter) (Account *account), + void (*setter) (Account *account, gnc_commodity *comm)) { - int accounts_total; - int accounts_loaded; + gnc_commodity *gcom; + gnc_commodity *com = getter(act); - int commodities_total; - int commodities_loaded; + if(!com) + { + return; + } + + gcom = gnc_commodity_table_lookup(gnc_book_get_commodity_table(book), + gnc_commodity_get_namespace(com), + gnc_commodity_get_mnemonic(com)); + if(!gcom) + { + g_warning("unable to find global commodity for %s:%s adding new", + gnc_commodity_get_namespace(com), + gnc_commodity_get_mnemonic(com)); + gnc_commodity_table_insert(gnc_book_get_commodity_table(book), com); + } + else + { + gnc_commodity_destroy(com); + setter(act, gcom); + } +} - int transactions_total; - int transactions_loaded; - - int prices_total; - int prices_loaded; -}; - -typedef struct _load_counter_struct load_counter; - -static load_counter* -make_counter() +static gboolean +add_account_local(sixtp_gdv2 *data, Account *act) { - load_counter *ret; + clear_up_account_commodity(data->book, act, + xaccAccountGetCommodity, + xaccAccountSetCommodity); + clear_up_account_commodity(data->book, act, + xaccAccountGetSecurity, + xaccAccountSetSecurity); + if(!xaccAccountGetParent(act)) + { + xaccGroupInsertAccount(gnc_book_get_group(data->book), act); + } + data->counter.accounts_loaded++; + return FALSE; +} - ret = g_new0(load_counter, 1); +static gboolean +add_commodity_local(sixtp_gdv2 *data, gnc_commodity *com) +{ + gnc_commodity_table_insert(gnc_book_get_commodity_table(data->book), com); + data->counter.commodities_loaded++; + return TRUE; +} - return ret; +static gboolean +add_transaction_local(sixtp_gdv2 *data, Transaction *trn) +{ + int i; + Split *spl; + + for(i = 0, spl = xaccTransGetSplit(trn, i); + spl; + i++, spl = xaccTransGetSplit(trn, i)) + { + xaccAccountInsertSplit(xaccSplitGetAccount(spl), spl); + } + + data->counter.transactions_loaded++; + return TRUE; +} + +static gboolean +add_pricedb_local(sixtp_gdv2 *data, GNCPriceDB *db) +{ + if(!db) + { + db = gnc_pricedb_create(); + } + + if(gnc_book_get_pricedb(data->book)) + { + gnc_pricedb_destroy(gnc_book_get_pricedb(data->book)); + } + + gnc_book_set_pricedb(data->book, db); + + return TRUE; +} + +static sixtp* +gnc_counter_sixtp_parser_create(void) +{ + return NULL; } gboolean gnc_book_load_from_xml_file_v2(GNCBook *book) { sixtp_gdv2 gd; - + sixtp *parser; + gpointer parse_result = NULL; + gd.book = book; - gd.data = (gpointer)make_counter(); - /* gd.addAccountFunc = add_account_local; */ + { + AccountGroup *g = gnc_book_get_group(book); + if(g) xaccFreeAccountGroup(g); + gnc_book_set_group(book, xaccMallocAccountGroup()); + } + gd.addAccountFunc = add_account_local; + gd.addCommodityFunc = add_commodity_local; + gd.addTransactionFunc = add_transaction_local; + gd.addPriceDBFunc = add_pricedb_local; - return FALSE; + parser = sixtp_new(); + + if(!sixtp_add_some_sub_parsers( + parser, TRUE, + "gnc:count-data", gnc_counter_sixtp_parser_create(), + "gnc:pricedb", gnc_pricedb_sixtp_parser_create(), + "gnc:commodity", gnc_commodity_sixtp_parser_create(), + "gnc:accout", gnc_account_sixtp_parser_create(), + "gnc:transactions", gnc_transaction_sixtp_parser_create(), + NULL, NULL)) + { + return FALSE; + } + + if(!sixtp_parse_file(parser, gnc_book_get_file_path(book), + NULL, &gd, &parse_result)) + { + sixtp_destroy(parser); + return FALSE; + } + else + { + } + + return TRUE; } +/***********************************************************************/ + +static const gchar *emacs_trailer = +"\n" +"\n" +"\n"; + +static void +write_counts(FILE* out, ...) +{ + va_list ap; + char *type; + + va_start(ap, out); + + type = va_arg(ap, char *); + + while(type) + { + xmlNodePtr node; + char *val; + int amount = va_arg(ap, int); + + val = g_strdup_printf("%d", amount); + + node = xmlNewNode(NULL, "gnc:count-data"); + xmlSetProp(node, "cd:type", type); + xmlNodeAddContent(node, val); + + xmlElemDump(out, NULL, node); + fprintf(out, "\n"); + + g_free(val); + xmlFreeNode(node); + + type = va_arg(ap, char *); + } + + va_end(ap); +} + +static gint +compare_namespaces(gconstpointer a, gconstpointer b) { + const gchar *sa = (const gchar *) a; + const gchar *sb = (const gchar *) b; + return(safe_strcmp(sa, sb)); +} + +static gint +compare_commodity_ids(gconstpointer a, gconstpointer b) { + const gnc_commodity *ca = (const gnc_commodity *) a; + const gnc_commodity *cb = (const gnc_commodity *) b; + return(safe_strcmp(gnc_commodity_get_mnemonic(ca), + gnc_commodity_get_mnemonic(cb))); +} + +static void +write_commodities(FILE *out, GNCBook *book) +{ + gnc_commodity_table *tbl; + GList *namespaces; + GList *lp; + + tbl = gnc_book_get_commodity_table(book); + + namespaces = g_list_sort(gnc_commodity_table_get_namespaces(tbl), + compare_namespaces); + + for(lp = namespaces; lp; lp = lp->next) { + gchar *space; + + if(!lp->data) { + g_list_free (namespaces); + return; + } + + space = (gchar *) lp->data; + if(strcmp(GNC_COMMODITY_NS_ISO, space) != 0) { + GList *comms = gnc_commodity_table_get_commodities(tbl, space); + GList *lp2; + + comms = g_list_sort(comms, compare_commodity_ids); + + for(lp2 = comms; lp2; lp2 = lp2->next) { + xmlNodePtr comnode = gnc_commodity_dom_tree_create( + (gnc_commodity *) lp2->data); + + xmlElemDump(out, NULL, comnode); + fprintf(out, "\n"); + + xmlFreeNode(comnode); + } + + g_list_free (comms); + } + } + + g_list_free (namespaces); + +} + +static void +write_pricedb(FILE *out, GNCBook *book) +{ + xmlNodePtr node; + + node = gnc_pricedb_dom_tree_create(gnc_book_get_pricedb(book)); + + xmlElemDump(out, NULL, node); + fprintf(out, "\n"); + + xmlFreeNode(node); +} + +static void +write_accounts(FILE *out, GNCBook *book) +{ + GList *list; + GList *node; + + list = xaccGroupGetAccountList (gnc_book_get_group(book)); + + for (node = list; node; node = node->next) { + xmlNodePtr accnode; + + accnode = gnc_account_dom_tree_create((Account*)(node->data)); + + xmlElemDump(out, NULL, accnode); + fprintf(out, "\n"); + + xmlFreeNode(accnode); + } +} + +static gboolean +xml_add_trn_data(Transaction *t, gpointer data) { + xmlNodePtr node; + + node = gnc_transaction_dom_tree_create(t); + + xmlElemDump((FILE*)data, NULL, node); + fprintf((FILE*)data, "\n"); + + xmlFreeNode(node); + return TRUE; +} + +static void +write_transactions(FILE *out, GNCBook *book) +{ + xaccGroupForEachTransaction(gnc_book_get_group(book), + xml_add_trn_data, + (gpointer) out); +} gboolean gnc_book_write_to_xml_file_v2(GNCBook *book, const char *filename) { + FILE *out; + + out = fopen(filename, "w"); + + fprintf(out, "\n"); + fprintf(out, "\n"); + + write_counts(out, + "commodity", + gnc_commodity_table_get_size( + gnc_book_get_commodity_table(book)), + "account", + xaccGroupGetNumAccounts(gnc_book_get_group(book)), + NULL); + + write_commodities(out, book); + + write_pricedb(out, book); + + write_accounts(out, book); + + write_transactions(out, book); + + fprintf(out, "\n\n"); + fprintf(out, emacs_trailer); + + fclose(out); + return FALSE; } +/***********************************************************************/ -gboolean gnc_is_xml_data_file_v2(const gchar *name) +static gboolean +eat_whitespace(char **cursor) { - return FALSE; + while(**cursor && isspace(**cursor)) + { + *cursor++; + } + + if(**cursor == '\0') + { + return FALSE; + } + else + { + return TRUE; + } +} + +static gboolean +search_for(char marker, char **cursor) +{ + while(**cursor && **cursor != marker) + { + *cursor++; + } + + if(**cursor == '\0') + { + return FALSE; + } + else + { + return TRUE; + } +} + +gboolean +gnc_is_xml_data_file_v2(const gchar *name) +{ + FILE *f = NULL; + char first_chunk[256]; + char* cursor = NULL; + ssize_t num_read; + + g_return_val_if_fail(name, FALSE); + + f = fopen(name, "r"); + g_return_val_if_fail(f, FALSE); + + num_read = fread(first_chunk, sizeof(char), sizeof(first_chunk) - 1, f); + fclose(f); + + if(num_read == 0) + { + return FALSE; + } + + first_chunk[num_read] = '\0'; + + cursor = first_chunk; + + if(!eat_whitespace(&cursor)) + { + return FALSE; + } + + if(strncmp(cursor, "', &cursor)) + { + return FALSE; + } + + if(!eat_whitespace(&cursor)) + { + return FALSE; + } + + if(strncmp(cursor, "tv_nsec > 0) { - xmlNewTextChild(ret, NULL, "ts:ns", ns_str); + ns_str = timespec_nsec_to_string(spec); + if(ns_str) + { + xmlNewTextChild(ret, NULL, "ts:ns", ns_str); + } } g_free(date_str); - g_free(ns_str); + if(ns_str) + { + g_free(ns_str); + } return ret; } @@ -310,8 +311,23 @@ kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame) { xmlNodePtr ret; - ret = xmlNewNode(NULL, tag); + if(!frame) + { + return NULL; + } + if(!kvp_frame_get_hash(frame)) + { + return NULL; + } + + if(g_hash_table_size(kvp_frame_get_hash(frame)) == 0) + { + return NULL; + } + + ret = xmlNewNode(NULL, tag); + g_hash_table_foreach(kvp_frame_get_hash(frame), add_kvp_slot, ret); return ret; diff --git a/src/gnome/gnc-html.c b/src/gnome/gnc-html.c index b91985639e..97a1d8647d 100644 --- a/src/gnome/gnc-html.c +++ b/src/gnome/gnc-html.c @@ -1393,7 +1393,7 @@ char * gnc_html_decode_string(const char * str) { static gchar * safe = "$-._!*(),"; /* RFC 1738 */ GString * decoded = g_string_new (""); - gchar * ptr; + const gchar * ptr; guchar c; guint hexval; ptr = str; diff --git a/src/gnome/gnc-http.c b/src/gnome/gnc-http.c index 8dbbda5f3e..f84f18a0e4 100644 --- a/src/gnome/gnc-http.c +++ b/src/gnome/gnc-http.c @@ -232,7 +232,7 @@ gnc_http_start_post(gnc_http * http, const char * uri, ghttp_set_header(info->request, http_hdr_Content_Type, content_type); ghttp_set_sync(info->request, ghttp_async); ghttp_set_type(info->request, ghttp_type_post); - ghttp_set_body(info->request, data, datalen); + ghttp_set_body(info->request, (char*)data, datalen); ghttp_prepare(info->request); ghttp_process(info->request); diff --git a/src/gnome/window-main.c b/src/gnome/window-main.c index ee147f578a..4e59ba4018 100644 --- a/src/gnome/window-main.c +++ b/src/gnome/window-main.c @@ -30,6 +30,7 @@ #include "AccWindow.h" #include "EuroUtils.h" +#include "FileBox.h" #include "FileDialog.h" #include "MainWindow.h" #include "RegWindow.h" @@ -59,6 +60,9 @@ #include "window-register.h" #include "window-report.h" +#include "io-gncxml-v2.h" +#include "gnc-book.h" + /* FIXME get rid of these */ #include "gnc.h" @@ -768,6 +772,25 @@ gnc_ui_options_cb(GtkWidget *widget, gpointer data) gnc_show_options_dialog(); } +static void +gnc_ui_xml_v2_cb(GtkWidget *widget, gpointer menuItem) +{ + const char *filename; + GNCBook *book; + + filename = fileBox(_("Save"), "*.gnc", gnc_history_get_last()); + if (!filename) return; + + book = gncGetCurrentBook (); + + gnc_book_write_to_xml_file_v2(book, filename); +} + +static void +gnc_ui_account_heirarchy_cb(GtkWidget *widget, gpointer menuItem) +{ +} + static void gnc_ui_filemenu_cb(GtkWidget *widget, gpointer menuItem) { @@ -1357,12 +1380,34 @@ gnc_main_create_menus(GnomeApp *app, GtkWidget *account_tree, GNOMEUIINFO_END }; + static GnomeUIInfo developer_menu[] = + { + { + GNOME_APP_UI_ITEM, + N_("_Write V2 XML File"), + N_("Write a version 2 XML file"), + gnc_ui_xml_v2_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + { + GNOME_APP_UI_ITEM, + N_("Write _Account Heirarchy"), + N_("Write just the account heirarchy"), + gnc_ui_account_heirarchy_cb, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, 0, NULL + }, + GNOMEUIINFO_END + }; + static GnomeUIInfo mainmenu[] = { GNOMEUIINFO_MENU_FILE_TREE(filemenu), GNOMEUIINFO_SUBTREE(N_("_Accounts"), accountsmenu), GNOMEUIINFO_SUBTREE(N_("_Tools"), toolsmenu), GNOMEUIINFO_MENU_SETTINGS_TREE(optionsmenu), + GNOMEUIINFO_SUBTREE(N_("_Devel Options"), developer_menu), GNOMEUIINFO_MENU_HELP_TREE(helpmenu), GNOMEUIINFO_END };