[patch 6/8] [budget-persist.diff] Budget persistence for the file backend

c.shoemaker at cox.net c.shoemaker at cox.net
Sat Oct 15 00:18:33 EDT 2005


 * src/backend/file/Makefile.am
 * src/backend/file/gnc-budget-xml-v2.c
 * src/backend/file/gnc-recurrence-xml-v2.c
 * src/backend/file/gnc-xml.h
 * src/backend/file/io-gncxml-v2.c
 * src/backend/file/io-gncxml-v2.h
 * src/backend/file/sixtp-dom-generators.c
 * src/backend/file/sixtp-dom-generators.h
 * src/backend/file/sixtp-dom-parsers.c
 * src/backend/file/sixtp-dom-parsers.h
 * src/backend/file/sixtp-utils.c
 * src/backend/file/test/Makefile.am
  - add Budget persistence for the file backend

 * src/backend/file/sixtp-dom-generators.c
 * src/backend/file/sixtp-dom-generators.h
  - add 'const' qualifier to GDate pointer in gdate_to_dom_tree()
  - reindent function

 src/backend/file/Makefile.am             |    2 
 src/backend/file/gnc-budget-xml-v2.c     |  227 +++++++++++++++++++++++++++++++
 src/backend/file/gnc-recurrence-xml-v2.c |  129 +++++++++++++++++
 src/backend/file/gnc-xml.h               |    4 
 src/backend/file/io-gncxml-v2.c          |   74 +++++++++-
 src/backend/file/io-gncxml-v2.h          |    3 
 src/backend/file/sixtp-dom-generators.c  |   50 +++---
 src/backend/file/sixtp-dom-generators.h  |    4 
 src/backend/file/sixtp-dom-parsers.c     |   27 +++
 src/backend/file/sixtp-dom-parsers.h     |    6 
 src/backend/file/sixtp-utils.c           |    3 
 src/backend/file/test/Makefile.am        |    8 -
 12 files changed, 500 insertions(+), 37 deletions(-)

Index: gnucash/src/backend/file/Makefile.am
===================================================================
--- gnucash.orig/src/backend/file/Makefile.am
+++ gnucash/src/backend/file/Makefile.am
@@ -18,10 +18,12 @@ libgnc_backend_file_la_SOURCES = \
   gnc-account-xml-v2.c \
   gnc-backend-file.c \
   gnc-book-xml-v2.c \
+  gnc-budget-xml-v2.c \
   gnc-commodity-xml-v2.c \
   gnc-freqspec-xml-v2.c \
   gnc-lot-xml-v2.c \
   gnc-pricedb-xml-v2.c \
+  gnc-recurrence-xml-v2.c \
   gnc-schedxaction-xml-v2.c \
   gnc-transaction-xml-v2.c \
   io-example-account.c \
Index: gnucash/src/backend/file/gnc-budget-xml-v2.c
===================================================================
--- /dev/null
+++ gnucash/src/backend/file/gnc-budget-xml-v2.c
@@ -0,0 +1,227 @@
+/********************************************************************\
+ * gnc-budget-xml-v2.c -- budget xml i/o implementation             *
+ *                                                                  *
+ * Copyright (C) 2005 Chris Shoemaker <c.shoemaker at cox.net>         *
+ *                                                                  *
+ * 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 at 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"
+
+static QofLogModule log_module = GNC_MOD_IO;
+
+const gchar *budget_version_string = "2.0.0";
+
+/* ids */
+#define gnc_budget_string       "gnc:budget"
+#define bgt_id_string           "bgt:id"
+#define bgt_name_string         "bgt:name"
+#define bgt_description_string  "bgt:description"
+#define bgt_num_periods_string  "bgt:num-periods"
+#define bgt_recurrence_string   "bgt:recurrence"
+#define bgt_slots_string        "bgt:slots"
+
+xmlNodePtr
+gnc_budget_dom_tree_create(GncBudget *bgt)
+{
+    xmlNodePtr ret;
+    KvpFrame *kf;
+
+    ENTER ("(budget=%p)", bgt);
+
+    ret = xmlNewNode(NULL, gnc_budget_string);
+    xmlSetProp(ret, "version", budget_version_string);
+
+    /* field: GUID */
+    xmlAddChild(ret, guid_to_dom_tree(bgt_id_string,
+                                      gnc_budget_get_guid(bgt)));
+    /* field: char* name */
+    xmlAddChild(ret, text_to_dom_tree(bgt_name_string,
+                                      gnc_budget_get_name(bgt)));
+    /* field: char* description */
+    xmlAddChild(ret, text_to_dom_tree(bgt_description_string,
+				      gnc_budget_get_description(bgt)));
+    /* field: guint num_periods */
+    xmlAddChild(ret, guint_to_dom_tree(bgt_num_periods_string,
+                                       gnc_budget_get_num_periods(bgt)));
+    /* field: Recurrence*  */
+    xmlAddChild(ret, recurrence_to_dom_tree(bgt_recurrence_string,
+                                            gnc_budget_get_recurrence(bgt)));
+    /* slots */
+    kf = qof_instance_get_slots(QOF_INSTANCE(bgt));
+    if (kf) {
+        xmlNodePtr kvpnode = kvp_frame_to_dom_tree(bgt_slots_string, kf);
+        if (kvpnode)
+            xmlAddChild(ret, kvpnode);
+    }
+
+    LEAVE (" ");
+    return ret;
+}
+
+/***********************************************************************/
+static inline gboolean
+set_string(xmlNodePtr node, GncBudget* bgt,
+	       void (*func)(GncBudget *bgt, const gchar *txt))
+{
+    gchar* txt = dom_tree_to_text(node);
+    g_return_val_if_fail(txt, FALSE);
+
+    func(bgt, txt);
+    g_free(txt);
+    return TRUE;
+}
+
+static gboolean
+budget_id_handler (xmlNodePtr node, gpointer bgt)
+{
+    GUID *guid;
+
+    guid = dom_tree_to_guid(node);
+    g_return_val_if_fail(guid, FALSE);
+    qof_entity_set_guid(QOF_ENTITY(bgt), guid);
+    g_free(guid);
+    return TRUE;
+}
+
+static gboolean
+budget_name_handler (xmlNodePtr node, gpointer bgt)
+{
+    return set_string(node, GNC_BUDGET(bgt), gnc_budget_set_name);
+}
+
+static gboolean
+budget_description_handler (xmlNodePtr node, gpointer bgt)
+{
+    return set_string(node, GNC_BUDGET(bgt), gnc_budget_set_description);
+}
+
+static gboolean
+budget_num_periods_handler (xmlNodePtr node, gpointer bgt)
+{
+    guint num_periods;
+
+    if (dom_tree_to_guint(node, &num_periods)) {
+        gnc_budget_set_num_periods(GNC_BUDGET(bgt), num_periods);
+        return TRUE;
+    } else
+        return FALSE;
+}
+
+static gboolean
+budget_recurrence_handler (xmlNodePtr node, gpointer bgt)
+{
+  Recurrence *r;
+
+  if ((r = dom_tree_to_recurrence(node)) == NULL)
+      return FALSE;
+
+  gnc_budget_set_recurrence(GNC_BUDGET(bgt), r);
+  g_free(r);
+  return TRUE;
+}
+
+static gboolean
+budget_slots_handler (xmlNodePtr node, gpointer bgt)
+{
+    return dom_tree_to_kvp_frame_given(
+        node, qof_instance_get_slots(QOF_INSTANCE(bgt)));
+}
+
+static struct dom_tree_handler budget_handlers[] = {
+    { bgt_id_string, budget_id_handler, 1, 0 },
+    { bgt_name_string, budget_name_handler, 0, 0 },
+    { bgt_description_string, budget_description_handler, 0, 0 },
+    { bgt_num_periods_string, budget_num_periods_handler, 1, 0 },
+    { bgt_recurrence_string, budget_recurrence_handler, 1, 0 },
+    { bgt_slots_string, budget_slots_handler, 0, 0},
+    { NULL, 0, 0, 0 }
+};
+
+static gboolean
+gnc_budget_end_handler(gpointer data_for_children,
+                       GSList* data_from_children, GSList* sibling_data,
+                       gpointer parent_data, gpointer global_data,
+                       gpointer *result, const gchar *tag)
+{
+    GncBudget *bgt;
+    xmlNodePtr tree = (xmlNodePtr)data_for_children;
+    gxpf_data *gdata = (gxpf_data*)global_data;
+    QofBook *book = gdata->bookdata;
+
+    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);
+
+    bgt = dom_tree_to_budget(tree, book);
+    xmlFreeNode(tree);
+    if(bgt != NULL) {
+        /* ends up calling book_callback */
+        gdata->cb(tag, gdata->parsedata, bgt);
+    }
+
+    return bgt != NULL;
+}
+
+
+GncBudget*
+dom_tree_to_budget (xmlNodePtr node, QofBook *book)
+{
+    GncBudget *bgt;
+
+    bgt = gnc_budget_new(book);
+    if (!dom_tree_generic_parse (node, budget_handlers, bgt)) {
+        PERR ("failed to parse budget tree");
+        gnc_budget_free(bgt);
+        bgt = NULL;
+    }
+    return bgt;
+}
+
+sixtp*
+gnc_budget_sixtp_parser_create(void)
+{
+    return sixtp_dom_parser_new(gnc_budget_end_handler, NULL, NULL);
+}
+/* ======================  END OF FILE ===================*/
Index: gnucash/src/backend/file/gnc-recurrence-xml-v2.c
===================================================================
--- /dev/null
+++ gnucash/src/backend/file/gnc-recurrence-xml-v2.c
@@ -0,0 +1,129 @@
+/********************************************************************
+ * gnc-recurrence-xml-v2.c -- xml routines for Recurrence           *
+ *                                                                  *
+ * Copyright (C) 2005 Chris Shoemaker <c.shoemaker at cox.net>         *
+ *                                                                  *
+ * 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 at gnu.org                   *
+ *                                                                  *
+ *******************************************************************/
+
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include "gnc-xml.h"
+#include "gnc-xml-helper.h"
+#include "gnc-engine-util.h"
+#include "gnc-trace.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 "io-gncxml-v2.h"
+#include "Recurrence.h"
+
+static QofLogModule log_module = GNC_MOD_IO;
+
+const gchar *recurrence_version_string = "1.0.0";
+#define recurrence_root          "gnc:recurrence"
+#define recurrence_mult          "recurrence:mult"
+#define recurrence_period_type   "recurrence:period_type"
+#define recurrence_start         "recurrence:start"
+
+//TODO: I think three of these functions rightly belong in Recurrence.c.
+
+static gboolean
+recurrence_period_type_handler(xmlNodePtr node, gpointer d)
+{
+    PeriodType pt;
+    char *nodeTxt;
+
+    nodeTxt = dom_tree_to_text(node);
+    g_return_val_if_fail(nodeTxt, FALSE);
+    pt = recurrencePeriodTypeFromString(nodeTxt);
+    ((Recurrence *) d)->ptype = pt;
+    g_free(nodeTxt);
+    return (pt != -1);
+}
+
+static gboolean
+recurrence_start_date_handler(xmlNodePtr node, gpointer r)
+{
+    GDate *d;
+
+    d = dom_tree_to_gdate(node);
+    g_return_val_if_fail(d, FALSE);
+    g_return_val_if_fail(g_date_valid(d), FALSE);
+    ((Recurrence *) r)->start = *d;
+    g_date_free(d);
+    return TRUE;
+}
+
+static gboolean
+recurrence_mult_handler(xmlNodePtr node, gpointer r)
+{
+    return dom_tree_to_guint16(node, &((Recurrence *)r)->mult);
+}
+
+static struct dom_tree_handler recurrence_dom_handlers[] = {
+    { recurrence_mult, recurrence_mult_handler, 1, 0 },
+    { recurrence_period_type, recurrence_period_type_handler, 1, 0 },
+    { recurrence_start, recurrence_start_date_handler, 1, 0 },
+    { NULL, NULL, 0, 0 }
+};
+
+Recurrence *
+dom_tree_to_recurrence(xmlNodePtr node)
+{
+    gboolean successful;
+    Recurrence *r;
+
+    r = g_new(Recurrence, 1);
+    successful = dom_tree_generic_parse (node, recurrence_dom_handlers, r);
+    if (!successful) {
+        PERR ("failed to parse recurrence node");
+        xmlElemDump(stdout, NULL, node);
+        g_free(r);
+        r = NULL;
+    }
+    return r;
+}
+
+xmlNodePtr
+recurrence_to_dom_tree(const gchar *tag, const Recurrence *r)
+{
+    xmlNodePtr n;
+    PeriodType pt;
+    GDate d;
+
+    n = xmlNewNode(NULL, tag);
+    xmlSetProp(n, "version", recurrence_version_string );
+    xmlAddChild(n, guint_to_dom_tree(recurrence_mult,
+                                     recurrenceGetMultiplier(r)));
+    pt = recurrenceGetPeriodType(r);
+    xmlAddChild(n, text_to_dom_tree(recurrence_period_type,
+                                    recurrencePeriodTypeToString(pt)));
+    d = recurrenceGetDate(r);
+    xmlAddChild(n, gdate_to_dom_tree(recurrence_start, &d));
+    return n;
+}
Index: gnucash/src/backend/file/gnc-xml.h
===================================================================
--- gnucash.orig/src/backend/file/gnc-xml.h
+++ gnucash/src/backend/file/gnc-xml.h
@@ -32,6 +32,7 @@
 #include "qofbook.h"
 #include "gnc-engine.h"
 #include "gnc-pricedb.h"
+#include "gnc-budget.h"
 #include "gnc-xml-helper.h"
 #include "sixtp.h"
 
@@ -58,6 +59,9 @@ sixtp* gnc_pricedb_sixtp_parser_create(v
 xmlNodePtr gnc_schedXaction_dom_tree_create( SchedXaction *sx );
 sixtp* gnc_schedXaction_sixtp_parser_create(void);
 
+xmlNodePtr gnc_budget_dom_tree_create( GncBudget *bgt );
+sixtp* gnc_budget_sixtp_parser_create(void);
+
 xmlNodePtr gnc_transaction_dom_tree_create(Transaction *txn);
 sixtp* gnc_transaction_sixtp_parser_create(void);
 
Index: gnucash/src/backend/file/io-gncxml-v2.c
===================================================================
--- gnucash.orig/src/backend/file/io-gncxml-v2.c
+++ gnucash/src/backend/file/io-gncxml-v2.c
@@ -273,7 +273,7 @@ add_template_transaction_local( sixtp_gd
             xaccGetAccountFromName( acctGroup,
                                     xaccAccountGetName( (Account*)n->data ) );
             if ( tmpAcct != NULL ) {
-/* XXX hack alert FIXME .... Should the be 'Remove', or 'Destroy'?
+/* XXX hack alert FIXME .... Should this be 'Remove', or 'Destroy'?
  * If we just remove, then this seems to be a memory leak to me, since
  * it is never reparented.  Shouldn't it be a Destroy ???
  */
@@ -302,6 +302,16 @@ add_pricedb_local(sixtp_gdv2 *data, GNCP
     return TRUE;
 }
 
+#if 0
+static gboolean
+add_budget_local(sixtp_gdv2 *data, GncBudget *bgt)
+{
+/* CAS:I don't think anything is needed here, because budgets are
+ * automatically added to their book's collections when they are created. */
+  return TRUE;
+}
+#endif
+
 static void
 do_counter_cb (const char *type, gpointer data_p, gpointer be_data_p)
 {
@@ -379,6 +389,10 @@ gnc_counter_end_handler(gpointer data_fo
     {
         sixdata->counter.schedXactions_total = val;
     }
+    else if(safe_strcmp(type, "budget") == 0)
+    {
+        sixdata->counter.budgets_total = val;
+    }
     else
     {
       struct file_backend be_data;
@@ -421,6 +435,8 @@ print_counter_data(load_counter *data)
            data->commodities_total, data->commodities_loaded);
     PINFO("Scheduled Tansactions: Total: %d, Loaded: %d",
            data->schedXactions_total, data->schedXactions_loaded);
+    PINFO("Budgets: Total: %d, Loaded: %d",
+	  data->budgets_total, data->budgets_loaded);
 }
 
 static void
@@ -436,13 +452,15 @@ file_rw_feedback (sixtp_gdv2 *gd, const 
     counter = &gd->counter;
     loaded = counter->transactions_loaded + counter->accounts_loaded +
       counter->books_loaded + counter->commodities_loaded +
-      counter->schedXactions_loaded;
+      counter->schedXactions_loaded + counter->budgets_loaded;
     total = counter->transactions_total + counter->accounts_total +
       counter->books_total + counter->commodities_total +
-      counter->schedXactions_total;
+      counter->schedXactions_total + counter->budgets_total;
 
     percentage = (loaded * 100)/total;
     if (percentage > 100) {
+      /* FIXME: Perhaps the below should be replaced by:
+	 print_counter_data(counter); */
       printf("Transactions: Total: %d, Loaded: %d\n",
              counter->transactions_total, counter->transactions_loaded);
       printf("Accounts: Total: %d, Loaded: %d\n",
@@ -453,6 +471,8 @@ file_rw_feedback (sixtp_gdv2 *gd, const 
              counter->commodities_total, counter->commodities_loaded);
       printf("Scheduled Tansactions: Total: %d, Loaded: %d\n",
              counter->schedXactions_total, counter->schedXactions_loaded);
+      printf("Budgets: Total: %d, Loaded: %d\n",
+	     counter->budgets_total, counter->budgets_loaded);
     }
     percentage = MIN(percentage, 100);
     gd->gui_display_fn(NULL, percentage);
@@ -468,6 +488,7 @@ static const char *COUNT_DATA_TAG = "gnc
 static const char *TRANSACTION_TAG = "gnc:transaction";
 static const char *SCHEDXACTION_TAG = "gnc:schedxaction";
 static const char *TEMPLATE_TRANSACTION_TAG = "gnc:template-transactions";
+static const char *BUDGET_TAG = "gnc:budget";
 
 static void
 add_item_cb (const char *type, gpointer data_p, gpointer be_data_p)
@@ -514,10 +535,15 @@ book_callback(const char *tag, gpointer 
     {
         add_schedXaction_local(gd, (SchedXaction*)data);
     }
-    else if(safe_strcmp(tag, TEMPLATE_TRANSACTION_TAG ) == 0 )
+    else if(safe_strcmp(tag, TEMPLATE_TRANSACTION_TAG) == 0)
     {
         add_template_transaction_local( gd, (gnc_template_xaction_data*)data );
     }
+    else if(safe_strcmp(tag, BUDGET_TAG) == 0)
+    {
+        // What's this for?  Needed?
+        //add_budget_local(gd, (GncBudget *)data);
+    }
     else
     {
       struct file_backend be_data;
@@ -612,6 +638,8 @@ gnc_sixtp_gdv2_new (
     gd->counter.prices_total = 0;
     gd->counter.schedXactions_loaded = 0;
     gd->counter.schedXactions_total = 0;
+    gd->counter.budgets_loaded = 0;
+    gd->counter.budgets_total = 0;
     gd->exporting = exporting;
     gd->countCallback = countcallback;
     gd->gui_display_fn = gui_display_fn;
@@ -670,6 +698,7 @@ qof_session_load_from_xml_file_v2(FileBa
            PRICEDB_TAG, gnc_pricedb_sixtp_parser_create(),
            COMMODITY_TAG, gnc_commodity_sixtp_parser_create(),
            ACCOUNT_TAG, gnc_account_sixtp_parser_create(),
+           BUDGET_TAG, gnc_budget_sixtp_parser_create(),
            TRANSACTION_TAG, gnc_transaction_sixtp_parser_create(),
            SCHEDXACTION_TAG, gnc_schedXaction_sixtp_parser_create(),
            TEMPLATE_TRANSACTION_TAG, gnc_template_transaction_sixtp_parser_create(),
@@ -796,6 +825,7 @@ static void write_pricedb (FILE *out, Qo
 static void write_transactions (FILE *out, QofBook *book, sixtp_gdv2 *gd);
 static void write_template_transaction_data (FILE *out, QofBook *book, sixtp_gdv2 *gd);
 static void write_schedXactions(FILE *out, QofBook *book, sixtp_gdv2 *gd);
+static void write_budgets(FILE *out, QofBook *book, sixtp_gdv2 *gd);
 
 static void
 write_counts_cb (const char *type, gpointer data_p, gpointer be_data_p)
@@ -864,6 +894,9 @@ write_book(FILE *out, QofBook *book, six
 	}
     write_book_parts (out, book);
 
+    /* gd->counter.{foo}_total fields should have all these totals
+       already collected.  I don't know why we're re-calling all these
+       functions.  */
     write_counts(out,
                  "commodity",
                  gnc_commodity_table_get_size(
@@ -874,7 +907,9 @@ write_book(FILE *out, QofBook *book, six
                  gnc_book_count_transactions(book),
                  "schedxaction",
                  g_list_length( gnc_book_get_schedxactions(book) ),
-                 NULL);
+		 "budget",
+		 g_list_length(gnc_book_get_budgets(book)),
+		 NULL);
 
 	qof_object_foreach_backend (GNC_FILE_BACKEND, write_counts_cb, &be_data);
 
@@ -884,7 +919,7 @@ write_book(FILE *out, QofBook *book, six
     write_transactions(out, book, gd);
     write_template_transaction_data(out, book, gd);
     write_schedXactions(out, book, gd);
-
+    write_budgets(out, book, gd);
     qof_object_foreach_backend (GNC_FILE_BACKEND, write_data_cb, &be_data);
 
     if(fprintf( out, "</%s>\n", BOOK_TAG ) < 0) {
@@ -1034,6 +1069,29 @@ write_schedXactions( FILE *out, QofBook 
     } while ( (schedXactions = schedXactions->next) );
 }
 
+static void
+write_budgets( FILE *out, QofBook *book, sixtp_gdv2 *gd)
+{
+    GList *budgetList;
+    GncBudget *tmp;
+    xmlNodePtr node;
+
+    /* get list of budgets from QofBook */
+    budgetList = gnc_book_get_budgets(book);
+
+    g_return_if_fail(budgetList);
+
+    do {
+        tmp = budgetList->data;
+        node = gnc_budget_dom_tree_create( tmp );
+        xmlElemDump( out, NULL, node );
+        fprintf( out, "\n" );
+        xmlFreeNode( node );
+        gd->counter.budgets_loaded++;
+        run_callback(gd, "budgets");
+    } while ((budgetList = budgetList->next));
+}
+
 void
 gnc_xml2_write_namespace_decl (FILE *out, const char *namespace)
 {
@@ -1102,7 +1160,7 @@ gnc_book_write_to_xml_filehandle_v2(QofB
     gd->counter.transactions_total = gnc_book_count_transactions(book);
     gd->counter.schedXactions_total =
       g_list_length( gnc_book_get_schedxactions(book));
-
+    gd->counter.budgets_total = g_list_length(gnc_book_get_budgets(book));
     write_book(out, book, gd);
 
     fprintf(out, "</" GNC_V2_STRING ">\n\n");
@@ -1207,7 +1265,7 @@ gnc_book_write_to_xml_file_v2(
     FILE *out;
 
     out = try_gz_open(filename, "w", compress);
-     if (out == NULL)
+    if (out == NULL)
     {
         return FALSE;
     }
Index: gnucash/src/backend/file/io-gncxml-v2.h
===================================================================
--- gnucash.orig/src/backend/file/io-gncxml-v2.h
+++ gnucash/src/backend/file/io-gncxml-v2.h
@@ -58,6 +58,9 @@ typedef struct
 
     int schedXactions_total;
     int schedXactions_loaded;
+
+    int budgets_total;
+    int budgets_loaded;
 } load_counter;
 
 typedef struct sixtp_gdv2 sixtp_gdv2;
Index: gnucash/src/backend/file/sixtp-dom-generators.c
===================================================================
--- gnucash.orig/src/backend/file/sixtp-dom-generators.c
+++ gnucash/src/backend/file/sixtp-dom-generators.c
@@ -38,14 +38,14 @@ static QofLogModule log_module = GNC_MOD
 xmlNodePtr
 text_to_dom_tree(const char *tag, const char *str)
 {
-  xmlNodePtr result;
+    xmlNodePtr result;
 
-  g_return_val_if_fail(tag, NULL);
-  g_return_val_if_fail(str, NULL);
-  result = xmlNewNode(NULL, BAD_CAST tag);
-  g_return_val_if_fail(result, NULL);
-  xmlNodeAddContent(result, BAD_CAST str);
-  return result;
+    g_return_val_if_fail(tag, NULL);
+    g_return_val_if_fail(str, NULL);
+    result = xmlNewNode(NULL, BAD_CAST tag);
+    g_return_val_if_fail(result, NULL);
+    xmlNodeAddContent(result, BAD_CAST str);
+    return result;
 }
 
 xmlNodePtr
@@ -55,11 +55,26 @@ int_to_dom_tree(const char *tag, gint64 
     xmlNodePtr result;
 
     text = g_strdup_printf("%" G_GINT64_FORMAT, val);
+    g_return_val_if_fail(text, NULL);
     result = text_to_dom_tree(tag, text);
     g_free(text);
     return result;
 }
+
+xmlNodePtr
+guint_to_dom_tree(const char *tag, guint an_int)
+{
+    gchar *text;
+    xmlNodePtr result;
     
+    text = g_strdup_printf("%u", an_int );
+    g_return_val_if_fail(text, NULL);
+    result = text_to_dom_tree(tag, text);
+    g_free(text);
+    return result;
+}
+
+
 xmlNodePtr
 guid_to_dom_tree(const char *tag, const GUID* gid)
 {
@@ -72,7 +87,7 @@ guid_to_dom_tree(const char *tag, const 
 
     if (!guid_to_string_buff(gid, guid_str))
     {
-        PERR("guid_to_string failed\n");
+        PERR("guid_to_string_buff failed\n");
         return NULL;
     }
 
@@ -158,7 +173,7 @@ timespec_to_dom_tree(const char *tag, co
 }
 
 xmlNodePtr
-gdate_to_dom_tree(const char *tag, GDate *date)
+gdate_to_dom_tree(const char *tag, const GDate *date)
 {
 	xmlNodePtr ret;
 	gchar *date_str = NULL;
@@ -275,6 +290,7 @@ add_kvp_value_node(xmlNodePtr node, gcha
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string");
         break;
     case KVP_TYPE_GUID:
+        /* THREAD-UNSAFE */
         add_text_to_node(val_node,"guid",
                          g_strdup(guid_to_string(kvp_value_get_guid(val))));
         break;
@@ -371,19 +387,3 @@ kvp_frame_to_dom_tree(const char *tag, c
     return ret;
 }
 
-xmlNodePtr guint_to_dom_tree(const char *tag, guint an_int)
-{
-    xmlNodePtr ret;
-    gchar *numstr;
-
-    numstr = g_strdup_printf( "%u", an_int );
-    g_return_val_if_fail(numstr, NULL);
-
-    ret = xmlNewNode(NULL, BAD_CAST tag);
-
-    xmlNodeAddContent(ret, BAD_CAST numstr);
-
-    g_free(numstr);
-
-    return ret;
-}
Index: gnucash/src/backend/file/sixtp-dom-generators.h
===================================================================
--- gnucash.orig/src/backend/file/sixtp-dom-generators.h
+++ gnucash/src/backend/file/sixtp-dom-generators.h
@@ -34,6 +34,7 @@
 #include "gnc-commodity.h"
 #include "gnc-date.h"
 #include "gnc-numeric.h"
+#include "Recurrence.h"
 #include "kvp_frame.h"
 #include "qofid.h"
 
@@ -44,10 +45,11 @@ xmlNodePtr commodity_ref_to_dom_tree(con
 xmlNodePtr timespec_to_dom_tree(const char *tag, const Timespec *spec);
 gchar * timespec_nsec_to_string(const Timespec *ts);
 gchar * timespec_sec_to_string(const Timespec *ts);
-xmlNodePtr gdate_to_dom_tree(const char *tag, GDate *spec);
+xmlNodePtr gdate_to_dom_tree(const char *tag, const GDate *spec);
 xmlNodePtr gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num);
 xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame);
 xmlNodePtr guint_to_dom_tree(const char *tag, guint an_int);
+xmlNodePtr recurrence_to_dom_tree(const gchar *tag, const Recurrence *r);
 
 gchar* double_to_string(double value);
 
Index: gnucash/src/backend/file/sixtp-dom-parsers.c
===================================================================
--- gnucash.orig/src/backend/file/sixtp-dom-parsers.c
+++ gnucash/src/backend/file/sixtp-dom-parsers.c
@@ -111,6 +111,33 @@ dom_tree_to_integer(xmlNodePtr node, gin
     return ret;
 }
 
+gboolean
+dom_tree_to_guint16(xmlNodePtr node, guint16 *i)
+{
+    gboolean ret;
+    guint j = 0;
+
+    ret = dom_tree_to_guint(node, &j);
+    *i = (guint16) j;
+    return ret;
+}
+
+gboolean
+dom_tree_to_guint(xmlNodePtr node, guint *i)
+{
+    gchar *text, *endptr;
+    gboolean ret;
+
+    text = dom_tree_to_text(node);
+    /* In spite of the strange string_to_gint64 function, I'm just
+       going to use strtoul here until someone shows me the error of
+       my ways. -CAS */
+    *i = (guint) strtoul(text, &endptr, 0);
+    ret = (endptr != text);
+    g_free(text);
+    return ret;
+}
+
 kvp_value*
 dom_tree_to_double_kvp_value(xmlNodePtr node)
 {
Index: gnucash/src/backend/file/sixtp-dom-parsers.h
===================================================================
--- gnucash.orig/src/backend/file/sixtp-dom-parsers.h
+++ gnucash/src/backend/file/sixtp-dom-parsers.h
@@ -36,7 +36,7 @@
 #include "kvp_frame.h"
 #include "qofbook.h"
 #include "qofid.h"
-
+#include "gnc-budget.h"
 
 GUID* dom_tree_to_guid(xmlNodePtr node);
 
@@ -44,6 +44,7 @@ gnc_commodity* dom_tree_to_commodity_ref
 gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node, QofBook *);
 
 FreqSpec* dom_tree_to_freqSpec( xmlNodePtr node, QofBook *book);
+Recurrence* dom_tree_to_recurrence(xmlNodePtr node);
 
 Timespec dom_tree_to_timespec(xmlNodePtr node);
 #define is_valid_timespec(ts) (ts.tv_sec || ts.tv_nsec)
@@ -67,12 +68,15 @@ kvp_value* dom_tree_to_list_kvp_value(xm
 kvp_value* dom_tree_to_frame_kvp_value(xmlNodePtr node);
 
 gboolean dom_tree_to_integer(xmlNodePtr node, gint64 *daint);
+gboolean dom_tree_to_guint16(xmlNodePtr node, guint16 *i);
+gboolean dom_tree_to_guint(xmlNodePtr node, guint *i);
 
 /* higher level structures */
 Account* dom_tree_to_account(xmlNodePtr node, QofBook *book);
 QofBook* dom_tree_to_book   (xmlNodePtr node, QofBook *book);
 GNCLot*  dom_tree_to_lot    (xmlNodePtr node, QofBook *book);
 Transaction* dom_tree_to_transaction(xmlNodePtr node, QofBook *book);
+GncBudget* dom_tree_to_budget(xmlNodePtr node, QofBook *book);
 
 struct dom_tree_handler
 {
Index: gnucash/src/backend/file/sixtp-utils.c
===================================================================
--- gnucash.orig/src/backend/file/sixtp-utils.c
+++ gnucash/src/backend/file/sixtp-utils.c
@@ -211,7 +211,8 @@ string_to_double(const char *str, double
 /*********/
 /* gint64
  */
-
+/* Maybe there should be a comment here explaining why this function
+   doesn't call g_ascii_strtoull, because it's not so obvious. -CAS */
 gboolean
 string_to_gint64(const gchar *str, gint64 *v)
 {
Index: gnucash/src/backend/file/test/Makefile.am
===================================================================
--- gnucash.orig/src/backend/file/test/Makefile.am
+++ gnucash/src/backend/file/test/Makefile.am
@@ -39,11 +39,13 @@ test_load_example_account_SOURCES = \
   ${top_srcdir}/src/backend/file/sixtp-stack.c \
   ${top_srcdir}/src/backend/file/sixtp-to-dom-parser.c \
   ${top_srcdir}/src/backend/file/io-example-account.c \
-  ${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
   ${top_srcdir}/src/backend/file/io-gncxml-gen.c \
   ${top_srcdir}/src/backend/file/io-gncxml-v2.c \
   ${top_srcdir}/src/backend/file/io-utils.c \
+  ${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-budget-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \
@@ -124,9 +126,11 @@ test_xml_transaction_SOURCES = \
   ${top_srcdir}/src/backend/file/sixtp-to-dom-parser.c \
   ${top_srcdir}/src/backend/file/io-gncxml-gen.c \
   ${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-budget-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-commodity-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-book-xml-v2.c \
@@ -143,7 +147,9 @@ test_xml2_is_file_SOURCES = \
   ${top_srcdir}/src/backend/file/sixtp-stack.c \
   ${top_srcdir}/src/backend/file/sixtp-to-dom-parser.c \
   ${top_srcdir}/src/backend/file/gnc-account-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-budget-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-lot-xml-v2.c \
+  ${top_srcdir}/src/backend/file/gnc-recurrence-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-schedxaction-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-freqspec-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-transaction-xml-v2.c \

--


More information about the gnucash-patches mailing list