[Gnucash-changes] Files that are changed somewhat with the addition of Chris Shoemaker's

David Hampton hampton at cvs.gnucash.org
Thu Oct 27 20:41:46 EDT 2005


Log Message:
-----------
Files that are changed somewhat with the addition of Chris Shoemaker's
budgeting functionality rewrite.  A changed include file here, a
single function there, etc. etc.

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash/src/app-utils:
        app-utils.scm
        options.scm
    gnucash/src/backend/file:
        Makefile.am
        gnc-xml.h
        io-gncxml-v2.c
        io-gncxml-v2.h
        sixtp-dom-generators.c
        sixtp-dom-generators.h
        sixtp-dom-parsers.c
        sixtp-dom-parsers.h
        sixtp-utils.c
    gnucash/src/backend/file/test:
        Makefile.am
    gnucash/src/engine:
        Makefile.am
        cashobjects.c
        gnc-budget.c
        gnc-budget.h
        gnc-engine.c
        gnc-engine.h
        gw-engine-spec.scm
    gnucash/src/gnome:
        Makefile.am
        gnc-plugin-basic-commands.c
        top-level.c
    gnucash/src/gnome/glade:
        budget.glade
    gnucash/src/gnome/ui:
        Makefile.am
        gnc-plugin-basic-commands-ui.xml
    gnucash/src/gnome-utils:
        Makefile.am
        dialog-options.c
        gnc-html.c
        gnc-html.h
        gnc-icons.h
    gnucash/src/gnome-utils/test:
        Makefile.am
    gnucash/src/report/report-system:
        html-utilities.scm
        report-system.scm
    gnucash/src/report/standard-reports:
        Makefile.am
        standard-reports.scm

Revision Data
-------------
Index: app-utils.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/app-utils/app-utils.scm,v
retrieving revision 1.22.4.5
retrieving revision 1.22.4.6
diff -Lsrc/app-utils/app-utils.scm -Lsrc/app-utils/app-utils.scm -u -r1.22.4.5 -r1.22.4.6
--- src/app-utils/app-utils.scm
+++ src/app-utils/app-utils.scm
@@ -15,6 +15,7 @@
 (export-syntax N_)
 (export gnc:make-string-database)
 
+;; options.scm
 (export gnc:make-option)
 (export gnc:option-section)
 (export gnc:option-name)
@@ -52,6 +53,7 @@
 (export gnc:make-complex-boolean-option)
 (export gnc:make-pixmap-option)
 (export gnc:make-date-option)
+(export gnc:make-budget-option)
 (export gnc:get-rd-option-data-subtype)
 (export gnc:get-rd-option-data-show-time)
 (export gnc:get-rd-option-data-rd-list)
Index: options.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/app-utils/options.scm,v
retrieving revision 1.11.4.3
retrieving revision 1.11.4.4
diff -Lsrc/app-utils/options.scm -Lsrc/app-utils/options.scm -u -r1.11.4.3 -r1.11.4.4
--- src/app-utils/options.scm
+++ src/app-utils/options.scm
@@ -121,7 +121,7 @@
 (define (gnc:option-value-validator option)  
   (vector-ref option 11))
 (define (gnc:option-data option)
-    (vector-ref option 12))
+  (vector-ref option 12))
 (define (gnc:option-data-fns option)
   (vector-ref option 13))
 
@@ -301,6 +301,55 @@
       (lambda (x) (list #t x))
       #f #f #f #f)))
 
+;; budget option
+;; TODO: need to double-check this proc
+(define (gnc:make-budget-option
+	 section
+	 name
+	 sort-tag
+         documentation-string)
+
+  (define (budget->guid budget)
+    (if (string? budget)
+        budget
+        (gnc:budget-get-guid budget)))
+
+  (define (guid->budget budget)
+    (if (string? budget)
+        (gnc:budget-lookup budget (gnc:get-current-book))
+        budget))
+
+  (let* ((default-value (gnc:budget-get-default (gnc:get-current-book)))
+         (value (budget->guid default-value))
+         (option-set #f)
+         (value->string (lambda ()
+                          (string-append
+                           "'" (gnc:value->string (if option-set option #f)))))
+
+         )
+    (gnc:make-option
+     section name sort-tag 'budget documentation-string
+     ;; the getter should always return a budget pointer
+     (lambda () (guid->budget  ;; getter
+                 (if option-set
+                     value
+                     default-value))
+             )
+
+     (lambda (x) (set! value (budget->guid x))
+             (set! option-set #t)) ;; setter
+     (lambda ()
+       (guid->budget
+        (gnc:budget-get-default (gnc:get-current-book)))) ;; default-getter
+     (gnc:restore-form-generator value->string) ;; ??
+     (lambda (f p) (gnc:kvp-frame-set-slot-path f value p))
+     (lambda (f p)
+       (let ((v (gnc:kvp-frame-get-slot-path f p)))
+         (if (and v (string? v))
+             (set! value v))))
+     (lambda (x) (list #t x)) ;; value-validator
+     #f #f #f #f)))
+
 ;; commodity options use a specialized widget for entering commodities
 ;; in the GUI implementation.
 (define (gnc:make-commodity-option
Index: gnc-xml.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/gnc-xml.h,v
retrieving revision 1.8.4.5
retrieving revision 1.8.4.6
diff -Lsrc/backend/file/gnc-xml.h -Lsrc/backend/file/gnc-xml.h -u -r1.8.4.5 -r1.8.4.6
--- src/backend/file/gnc-xml.h
+++ 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 @@
 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: io-gncxml-v2.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/io-gncxml-v2.c,v
retrieving revision 1.24.4.13
retrieving revision 1.24.4.14
diff -Lsrc/backend/file/io-gncxml-v2.c -Lsrc/backend/file/io-gncxml-v2.c -u -r1.24.4.13 -r1.24.4.14
--- src/backend/file/io-gncxml-v2.c
+++ src/backend/file/io-gncxml-v2.c
@@ -273,7 +273,7 @@
             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 ???
  */
@@ -379,6 +379,10 @@
     {
         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 +425,8 @@
            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 +442,15 @@
     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 +461,8 @@
              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 +478,7 @@
 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 +525,14 @@
     {
         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)
+    {
+        // Nothing needed here.
+    }
     else
     {
       struct file_backend be_data;
@@ -612,6 +627,8 @@
     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 +687,7 @@
            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 +814,7 @@
 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_budget (QofEntity *ent, gpointer data);
 
 static void
 write_counts_cb (const char *type, gpointer data_p, gpointer be_data_p)
@@ -857,6 +876,7 @@
 
     be_data.out = out;
     be_data.book = book;
+    be_data.gd = gd;
     if(fprintf( out, "<%s version=\"%s\">\n", BOOK_TAG, gnc_v2_book_version_string) < 0)
 	{
 		qof_backend_set_error(qof_book_get_backend(book), ERR_FILEIO_WRITE_ERROR);
@@ -864,6 +884,9 @@
 	}
     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,9 +897,11 @@
                  gnc_book_count_transactions(book),
                  "schedxaction",
                  g_list_length( gnc_book_get_schedxactions(book) ),
-                 NULL);
+		 "budget", qof_collection_count(
+                     qof_book_get_collection(book, GNC_ID_BUDGET)),
+		 NULL);
 
-	qof_object_foreach_backend (GNC_FILE_BACKEND, write_counts_cb, &be_data);
+    qof_object_foreach_backend (GNC_FILE_BACKEND, write_counts_cb, &be_data);
 
     write_commodities(out, book, gd);
     write_pricedb(out, book, gd);
@@ -885,6 +910,9 @@
     write_template_transaction_data(out, book, gd);
     write_schedXactions(out, book, gd);
 
+    qof_collection_foreach(qof_book_get_collection(book, GNC_ID_BUDGET), 
+        write_budget, &be_data);
+
     qof_object_foreach_backend (GNC_FILE_BACKEND, write_data_cb, &be_data);
 
     if(fprintf( out, "</%s>\n", BOOK_TAG ) < 0) {
@@ -1034,6 +1062,22 @@
     } while ( (schedXactions = schedXactions->next) );
 }
 
+static void
+write_budget (QofEntity *ent, gpointer data)
+{
+    xmlNodePtr node;
+    struct file_backend* be = data;
+
+    GncBudget *bgt = GNC_BUDGET(ent);
+    node = gnc_budget_dom_tree_create(bgt);
+    xmlElemDump( be->out, NULL, node );
+    fprintf( be->out, "\n" );
+    xmlFreeNode( node );
+    
+    be->gd->counter.budgets_loaded++;
+    run_callback(be->gd, "budgets");    
+}
+
 void
 gnc_xml2_write_namespace_decl (FILE *out, const char *namespace)
 {
@@ -1102,6 +1146,8 @@
     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 = qof_collection_count(
+        qof_book_get_collection(book, GNC_ID_BUDGET));
 
     write_book(out, book, gd);
 
@@ -1207,7 +1253,7 @@
     FILE *out;
 
     out = try_gz_open(filename, "w", compress);
-     if (out == NULL)
+    if (out == NULL)
     {
         return FALSE;
     }
Index: sixtp-dom-parsers.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/sixtp-dom-parsers.h,v
retrieving revision 1.9.4.3
retrieving revision 1.9.4.4
diff -Lsrc/backend/file/sixtp-dom-parsers.h -Lsrc/backend/file/sixtp-dom-parsers.h -u -r1.9.4.3 -r1.9.4.4
--- src/backend/file/sixtp-dom-parsers.h
+++ 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_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_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: sixtp-utils.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/sixtp-utils.c,v
retrieving revision 1.7.4.9
retrieving revision 1.7.4.10
diff -Lsrc/backend/file/sixtp-utils.c -Lsrc/backend/file/sixtp-utils.c -u -r1.7.4.9 -r1.7.4.10
--- src/backend/file/sixtp-utils.c
+++ src/backend/file/sixtp-utils.c
@@ -211,7 +211,8 @@
 /*********/
 /* 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: sixtp-dom-generators.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/sixtp-dom-generators.c,v
retrieving revision 1.5.4.7
retrieving revision 1.5.4.8
diff -Lsrc/backend/file/sixtp-dom-generators.c -Lsrc/backend/file/sixtp-dom-generators.c -u -r1.5.4.7 -r1.5.4.8
--- src/backend/file/sixtp-dom-generators.c
+++ src/backend/file/sixtp-dom-generators.c
@@ -38,14 +38,14 @@
 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 @@
     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 @@
 
     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 @@
 }
 
 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 @@
         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 @@
     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: io-gncxml-v2.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/io-gncxml-v2.h,v
retrieving revision 1.11.4.5
retrieving revision 1.11.4.6
diff -Lsrc/backend/file/io-gncxml-v2.h -Lsrc/backend/file/io-gncxml-v2.h -u -r1.11.4.5 -r1.11.4.6
--- src/backend/file/io-gncxml-v2.h
+++ src/backend/file/io-gncxml-v2.h
@@ -58,6 +58,9 @@
 
     int schedXactions_total;
     int schedXactions_loaded;
+
+    int budgets_total;
+    int budgets_loaded;
 } load_counter;
 
 typedef struct sixtp_gdv2 sixtp_gdv2;
Index: sixtp-dom-parsers.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/sixtp-dom-parsers.c,v
retrieving revision 1.12.4.9
retrieving revision 1.12.4.10
diff -Lsrc/backend/file/sixtp-dom-parsers.c -Lsrc/backend/file/sixtp-dom-parsers.c -u -r1.12.4.9 -r1.12.4.10
--- src/backend/file/sixtp-dom-parsers.c
+++ src/backend/file/sixtp-dom-parsers.c
@@ -111,6 +111,33 @@
     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: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/Makefile.am,v
retrieving revision 1.16.4.7
retrieving revision 1.16.4.8
diff -Lsrc/backend/file/Makefile.am -Lsrc/backend/file/Makefile.am -u -r1.16.4.7 -r1.16.4.8
--- src/backend/file/Makefile.am
+++ src/backend/file/Makefile.am
@@ -19,10 +19,12 @@
   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: sixtp-dom-generators.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/sixtp-dom-generators.h,v
retrieving revision 1.2.6.2
retrieving revision 1.2.6.3
diff -Lsrc/backend/file/sixtp-dom-generators.h -Lsrc/backend/file/sixtp-dom-generators.h -u -r1.2.6.2 -r1.2.6.3
--- src/backend/file/sixtp-dom-generators.h
+++ 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 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: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/file/test/Makefile.am,v
retrieving revision 1.28.4.6
retrieving revision 1.28.4.7
diff -Lsrc/backend/file/test/Makefile.am -Lsrc/backend/file/test/Makefile.am -u -r1.28.4.6 -r1.28.4.7
--- src/backend/file/test/Makefile.am
+++ src/backend/file/test/Makefile.am
@@ -39,11 +39,13 @@
   ${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 @@
   ${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 @@
   ${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 \
Index: gw-engine-spec.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gw-engine-spec.scm,v
retrieving revision 1.53.4.12
retrieving revision 1.53.4.13
diff -Lsrc/engine/gw-engine-spec.scm -Lsrc/engine/gw-engine-spec.scm -u -r1.53.4.12 -r1.53.4.13
--- src/engine/gw-engine-spec.scm
+++ src/engine/gw-engine-spec.scm
@@ -26,6 +26,7 @@
     "#include <guid.h>\n"
     "#include <Group.h>\n"
     "#include <Query.h>\n"
+    "#include <gnc-budget.h>\n"
     "#include <gnc-commodity.h>\n"
     "#include <gnc-date.h>\n"
     "#include <gnc-engine.h>\n"
@@ -260,6 +261,7 @@
 ;
 (gw:wrap-value ws 'gnc:id-account '<gnc:id-type> "GNC_ID_ACCOUNT")
 (gw:wrap-value ws 'gnc:id-book '<gnc:id-type> "GNC_ID_BOOK")
+(gw:wrap-value ws 'gnc:id-budget '<gnc:id-type> "GNC_ID_BUDGET")
 (gw:wrap-value ws 'gnc:id-lot '<gnc:id-type> "GNC_ID_LOT")
 (gw:wrap-value ws 'gnc:id-price '<gnc:id-type> "GNC_ID_PRICE")
 (gw:wrap-value ws 'gnc:id-split '<gnc:id-type> "GNC_ID_SPLIT")
@@ -2491,6 +2493,87 @@
  '(((gw:glist-of (<gw:mchars> callee-owned) callee-owned) choices))
  "Takes a list of installed Finance::Quote souces and records it internally.")
 
+
+;; Budget functions
+
+(gw:wrap-as-wct ws '<gnc:Budget*> "GncBudget *" "const GncBudget *")
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-guid
+ '<gnc:guid-scm>
+ "gnc_budget_return_guid"
+ '((<gnc:Budget*> budget))
+ "Gets the guid of the budget")
+
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-lookup
+ '<gnc:Budget*>
+ "gnc_budget_lookup_direct"
+ '((<gnc:guid-scm> guid)
+   (<gnc:Book*> book))
+ "Lookup a budget from its GUID.")
+
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-default
+ '<gnc:Budget*>
+ "gnc_budget_get_default"
+ '((<gnc:Book*> book))
+ "Get the default budget for the book.")
+
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-name
+ '(<gw:mchars> callee-owned const)
+ "gnc_budget_get_name"
+ '((<gnc:Budget*> budget))
+ "Get the brief name for the budget.")
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-num-periods
+ '<gw:unsigned-int>
+ "gnc_budget_get_num_periods"
+ '((<gnc:Budget*> budget))
+ "Get the number of periods in a budget.")
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-account-period-value
+ '<gnc:numeric>
+ "gnc_budget_get_account_period_value"
+ '((<gnc:Budget*> budget)
+   (<gnc:Account*> acct)
+   (<gw:unsigned-int> period_num)
+   )
+ "Get the budgeted value for the given account and budget period.")
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-account-period-actual-value
+ '<gnc:numeric>
+ "gnc_budget_get_account_period_actual_value"
+ '((<gnc:Budget*> budget)
+   (<gnc:Account*> acct)
+   (<gw:unsigned-int> period_num)
+   )
+ "Get the actual account value for the given account and budget period.")
+
+(gw:wrap-function
+ ws
+ 'gnc:budget-get-period-start-date
+ '<gnc:time-pair>
+ "gnc_budget_get_period_start_date"
+ '((<gnc:Budget*> budget)
+   (<gw:unsigned-int> period_num)
+   )
+ "Get the date that the given period begins.")
+
 ;;
 ;; gnc-hooks-scm.h
 ;;   (and gnc-hooks.h)
Index: gnc-budget.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Attic/gnc-budget.h,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/engine/gnc-budget.h -Lsrc/engine/gnc-budget.h -u -r1.1.2.2 -r1.1.2.3
--- src/engine/gnc-budget.h
+++ src/engine/gnc-budget.h
@@ -1,6 +1,7 @@
 /********************************************************************\
- * gnc-budget.h -- Budget public handling routines.                     *
+ * gnc-budget.h -- Budget public handling routines.                 *
  * Copyright (C) 04 sep 2003    Darin Willits <darin at willits.ca>    *
+ * 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   *
@@ -21,39 +22,58 @@
  *                                                                  *
 \********************************************************************/
 
-
-/** @addtogroup Engine
- *     @{ */
-/** @addtogroup Budget Budget objects
- * A budget object contains a list of budget_categories each of 
- * which define an individual budgetable item.  When a budget is first
- * created these catagories will be initialized based on the existing 
- * account hierarchy.
- *     @{ */
-/** @file gnc-budget.h
- *  @brief Public interface for budget objects.
- *  @author Created by Darin Willits 04 sep 2003 
- *  @author Copyright (c) 04 Darin Willits <darin at willits.ca>
- *
- * This file contains the public methods to interact with a budgeting
- * object. 
- * This is pre-alpha code right now.  User beware.
+/*  Design decisions:
+ *
+ *  - The budget values that the user enters (and that are stored) for
+ *  each account are inclusive of any sub-accounts.
+ *
+ *     - Reason: This allows the user to budget an amount for a
+ *     "parent" account, while tracking (e.g.) expenses with more
+ *     detail in sub-accounts.
+ *
+ *     - Implication: when reporting budgeted values for parent
+ *     accounts, just show the stored value, not a sum.
+ *
+ *  - Budget values are always in the account's commodity.
+ *
+ *
+ *
+ *  Accounts with sub-accounts can have a value budgeted.  For those
+ *  accounts,
+ *
+ *    Option 1: when setting or getting budgeted values, the value is
+ *    *always* exclusive of sub-account values.  Pro: consistent
+ *    values in all contexts.  Con: no summary behavior.
+ *
+ *    Option 2: make setting only for account proper, but always
+ *    report summaries. Con: value can change as soon as it is
+ *    entered; forces entry from bottom-up.
+ *
+ *    * Option 3: value is always *inclusive* of sub-accounts, although
+ *    potentially in a different commodity.  Pro: allows top-down
+ *    entry; no auto value update. Con: ?  [ This option was selected. ]
+ *
  */
 
-
 #ifndef __GNC_BUDGET_H__
 #define __GNC_BUDGET_H__
 
 #include <glib.h>
 
 /** The budget data.*/
-typedef struct gncp_budget GncBudget;
+typedef struct gnc_budget_private GncBudget;
 
 #include "guid.h"
 #include "qofbook.h"
-#include "gnc-budget-cat.h"
-#include "FreqSpec.h"
+#include "Account.h"
+#include "Recurrence.h"
+
+#define GNC_IS_BUDGET(obj)  (QOF_CHECK_TYPE((obj), GNC_ID_BUDGET))
+#define GNC_BUDGET(obj)     (QOF_CHECK_CAST((obj), GNC_ID_BUDGET, GncBudget))
 
+#define GNC_BUDGET_MAX_NUM_PERIODS_DIGITS 3 // max num periods == 999
+
+gboolean gnc_budget_register(void);
 
 /**
  * Creates and initializes a Budget.
@@ -61,130 +81,53 @@
 GncBudget *gnc_budget_new(QofBook *book);
 
 /** Deletes the given budget object.*/
-void gnc_budget_delete(GncBudget* budget);
-
+void gnc_budget_free(GncBudget* budget);
 
+const GUID* gnc_budget_get_guid(GncBudget* budget);
+#define gnc_budget_return_guid(X) \
+  (X ? *(qof_entity_get_guid(QOF_ENTITY(X))) : *(guid_null()))
 
-/**  Set the Name of the Budget.
- */
+/** Set/Get the name of the Budget */
 void gnc_budget_set_name(GncBudget* budget, const gchar* name);
+const gchar* gnc_budget_get_name(GncBudget* budget);
 
-/**  Retieve the Name of the Budget.
- */
-gchar* gnc_budget_get_name(GncBudget* budget);
-
-
-
-/**  Set the Description of the Budget.
- */
+/** Set/Get the description of the Budget */
 void gnc_budget_set_description(GncBudget* budget, const gchar* description);
+const gchar* gnc_budget_get_description(GncBudget* budget);
 
-/**  Retieve the Description of the Budget.
- */
-gchar* gnc_budget_get_description(GncBudget* budget);
-
-
-
-/** Set the period frequency.
- */
-void gnc_budget_set_period_frequency(GncBudget* budget, FreqSpec* period);
-
-/** Get the period frequency.
- */
-FreqSpec* gnc_budget_get_period_frequency(GncBudget* budget);
-
-
-
-/** Set the start date*/
-void gnc_budget_set_start_date(GncBudget* budget, GDate* date);
-
-/** Return the start date */
-GDate* gnc_budget_get_start_date(GncBudget* budget);
-
-
-/** Set the Length for this budget in terms of a number of months.
- */
-void gnc_budget_set_length_months(GncBudget* budget, gint months);
+/** Set/Get the number of periods in the Budget */
+void gnc_budget_set_num_periods(GncBudget* budget, guint num_periods);
+guint gnc_budget_get_num_periods(GncBudget* budget);
+
+void gnc_budget_set_recurrence(GncBudget *budget, const Recurrence *r);
+const Recurrence * gnc_budget_get_recurrence(GncBudget *budget);
+
+/** Set/Get the starting date of the Budget */
+void gnc_budget_set_start_date(GncBudget* budget, Timespec date);
+Timespec gnc_budget_get_start_date(GncBudget* budget);
+Timespec gnc_budget_get_period_start_date(GncBudget* budget, guint period_num);
+
+/* Period indices are zero-based. */
+void gnc_budget_set_account_period_value(
+    GncBudget* budget, Account* account, guint period_num, gnc_numeric val);
+
+gnc_numeric gnc_budget_get_account_period_value(
+    GncBudget *budget, Account *account, guint period_num);
+gnc_numeric gnc_budget_get_account_period_actual_value(
+    GncBudget *budget, Account *account, guint period_num);
 
-/** Set the Length for this budget in terms of a number of months.
- */
-void gnc_budget_set_length_years(GncBudget* budget, gint years);
-
-/** Retrieve the Length for this budget in number of months.
- */
-gint gnc_budget_get_length_months(GncBudget* budget);
-
-/** Retrieve the Length for this budget in number of years.
- */
-gint gnc_budget_get_length_years(GncBudget* budget);
-
-
-
-/* Add the inflow category for this budget.  
- * This is a wrapper function to make it easier to add a category
- * as a child of the inflow category.  It's here cause I'm a lazy ass.
- */
-void gnc_budget_add_inflow_category(GncBudget* budget, GncBudgetCategory* inflow);
-
-/* Remove the inflow category for this budget.  
- */
-void gnc_budget_remove_inflow_category(GncBudget* budget, GncBudgetCategory* category);
-
-/* Set the inflow category for this budget.  
- */
-void gnc_budget_set_inflow_category(GncBudget* budget, GncBudgetCategory* inflow);
-
-/** Retrieve the inflow category for this budget. 
- */
-GncBudgetCategory* gnc_budget_get_inflow_category(GncBudget* budget);
-
-
-
-
-/* Add the outflow category for this budget.  
- */
-void gnc_budget_add_outflow_category(GncBudget* budget, GncBudgetCategory* outflow);
-
-/* Remove the outflow category for this budget.  
- */
-void gnc_budget_remove_outflow_category(GncBudget* budget, GncBudgetCategory* inflow);
-
-/* Set the outflow category for this budget.  
- */
-void gnc_budget_set_outflow_category(GncBudget* budget, GncBudgetCategory* category);
-
-/** Retrieve the outflow category for this budget. 
- */
-GncBudgetCategory* gnc_budget_get_outflow_category(GncBudget* budget);
-
-
-
-/** Retrieve the book that this budget is associated with.*/
+/** Get the book that this budget is associated with. */
 QofBook* gnc_budget_get_book(GncBudget* budget);
 
+/* Caller owns the list of all budgets in the book. */
+GList* gnc_book_get_budgets(QofBook* book);
 
-/** Generate the list of periods.
- * This function will use the start date and budget length to generate a 
- * list of budget periods.  The periods are represented by a list of start
- * dates for each period.
- * As well this function regenerates the list of values for each
- * category.
- * */
-void gnc_budget_generate_periods(GncBudget* budget);
-
-/** Get the number of periods.
- */
-gint gnc_budget_get_num_periods(GncBudget* budget);
-
-/* Return the list of periods.
- */
-GList* gnc_budget_get_period_list(GncBudget* budget);
-
+/* Returns some budget in the book, or NULL. */
+GncBudget* gnc_budget_get_default(QofBook *book);
 
-/** Retrieve the budget object associated with the given GUID from 
- * the given book.
- */
+/* Get the budget associated with the given GUID from the given book. */
 GncBudget* gnc_budget_lookup (const GUID *guid, QofBook *book);
+#define  gnc_budget_lookup_direct(g,b) gnc_budget_lookup(&(g),(b))
 
 #endif // __BUDGET_H__
 
Index: gnc-engine.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-engine.c,v
retrieving revision 1.17.4.9
retrieving revision 1.17.4.10
diff -Lsrc/engine/gnc-engine.c -Lsrc/engine/gnc-engine.c -u -r1.17.4.9 -r1.17.4.10
--- src/engine/gnc-engine.c
+++ src/engine/gnc-engine.c
@@ -31,7 +31,7 @@
 #include "AccountP.h"
 #include "GroupP.h"
 #include "SX-book-p.h"
-#include "gnc-budget-book-p.h"
+#include "gnc-budget.h"
 #include "TransactionP.h"
 #include "gnc-commodity.h"
 #include "gnc-lot-p.h"
Index: gnc-budget.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Attic/gnc-budget.c,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/engine/gnc-budget.c -Lsrc/engine/gnc-budget.c -u -r1.1.2.2 -r1.1.2.3
--- src/engine/gnc-budget.c
+++ src/engine/gnc-budget.c
@@ -1,6 +1,7 @@
 /********************************************************************\
- * gnc-budget.c -- Implementation of the top level Budgeting API's.     *
+ * gnc-budget.c -- Implementation of the top level Budgeting API's. *
  * Copyright (C) 04 sep 2003    Darin Willits <darin at willits.ca>    *
+ * 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   *
@@ -21,492 +22,370 @@
  *                                                                  *
 \********************************************************************/
 
-/** @file gnc-budget.c
- *  @brief Implementation of the top level budgeting API's.
- *  @author Created by Darin Willits 04 sep 2003 
- *  @author Copyright (c) 2003 Darin Willits <darin at willits.ca>
- *
- *
- */
-
-// Includes
-#include "config.h"
-#include <stdio.h>
-
-#include "gnc-budget-p.h"
-#include "qofbook.h"
-#include "qofbook-p.h"
-#include "qofid-p.h"
-#include "gnc-engine.h"
-#include "gnc-engine-util.h"
-#include "gnc-event-p.h"
-#include "Group.h"
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include "qof.h"
+
 #include "Account.h"
-#include "gnc-budget-period.h"
+#include "Group.h"
 
+#include "gnc-budget.h"
+#include "gnc-event-p.h"
+#include "gnc-commodity.h"
+#include "gnc-trace.h"
+#include "gnc-gdate-utils.h"
+
+static QofLogModule log_module = GNC_MOD_ENGINE;
 
-static void budget_fill_categories(GncBudget* budget);
+struct gnc_budget_private{
+    QofInstance inst;
+
+    gchar* name;
+    gchar* description;
+    Recurrence recurrence;
+    guint  num_periods;
+};
 
-GncBudget* gnc_budget_new(QofBook *book)
+GncBudget*
+gnc_budget_new(QofBook *book)
 {
     GncBudget* budget;
-    GDate date;
-    GString* freqStr;
 
     g_return_val_if_fail(book, NULL);
 
+    ENTER(" ");
     budget = g_new0(GncBudget, 1);
-    
-    
     qof_instance_init (&budget->inst, GNC_ID_BUDGET, book);
-    //budget->entity_table = qof_book_get_entity_table (book);
-    //qof_entity_guid_new (budget->entity_table, &budget->guid);
-    //qof_entity_store( budget->entity_table, budget,
-    //                &budget->guid, GNC_ID_BUDGET );
-    
-    budget->book = book;
-
-    /* Create the default period frequency.*/
-    budget->period_freq = xaccFreqSpecMalloc(book);
-    
-    g_date_clear(&date, 1);
-    g_date_set_time(&date, time(NULL));
-    xaccFreqSpecSetMonthly(budget->period_freq, &date, 1);
-    xaccFreqSpecSetUIType(budget->period_freq, UIFREQ_MONTHLY);
-
-    freqStr = g_string_sized_new(16);
-    xaccFreqSpecGetFreqStr(budget->period_freq, freqStr);
-    //printf("Category Freq: %s\n", freqStr->str);
-
-    
-    
-    /* fill the categories based on the current account hierarchy. 
-     * FIXME: This should probably not be here but rather be a separate 
-     * operation with a public interface.  For now it is convienent.*/
-    budget_fill_categories(budget);
 
+    recurrenceSet(&budget->recurrence, 1, PERIOD_MONTH, NULL);
+
+    gnc_budget_set_name(budget, "Unnamed Budget");
+    gnc_budget_set_description(budget, "");
+    gnc_budget_set_num_periods(budget, 12);
 
     gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_CREATE );
 
+    LEAVE(" ");
     return budget;
 }
 
-void gnc_budget_delete(GncBudget* budget)
+static void
+remove_bgt_line_items(QofEntity *act, gpointer bgt)
+{
+    KvpFrame *frame;
+    const GUID *guid;
+    gchar guidbuf[GUID_ENCODING_LENGTH+1];
+
+    frame = qof_instance_get_slots(QOF_INSTANCE(bgt));
+    guid = qof_entity_get_guid(QOF_ENTITY(act));
+    guid_to_string_buff(guid, guidbuf);
+    kvp_frame_delete(kvp_frame_get_frame(frame, guidbuf));
+}
+
+static void
+gnc_budget_remove_all_line_items(GncBudget *budget)
 {
-    if(budget == NULL){
+    QofBook *book;
+    QofCollection *col;
+
+    g_return_if_fail(GNC_IS_BUDGET(budget));
+
+    book = qof_instance_get_book(QOF_INSTANCE(budget));
+    col = qof_book_get_collection(book, GNC_ID_ACCOUNT);
+    qof_collection_foreach(col, remove_bgt_line_items, (gpointer) budget);
+}
+
+void
+gnc_budget_free(GncBudget* budget)
+{
+    if (budget == NULL)
         return;
-    }
-    
+
+    g_return_if_fail(GNC_IS_BUDGET(budget));
+    gnc_budget_remove_all_line_items(budget);
+
     /* We first send the message that this object is about to be
      * destroyed so that any GUI elements can remove it before it is
-     * actually gone.
-     */
+     * actually gone. */
     gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_DESTROY);
-    
-    //qof_entity_remove(budget->entity_table, &budget->guid);
 
-    if(budget->name){
+    if (budget->name)
         g_free(budget->name);
-    }
-    
-    if(budget->description){
+
+    if (budget->description)
         g_free(budget->description);
-    }
 
     qof_instance_release (&budget->inst);
     g_free(budget);
 }
 
-void gnc_budget_set_name(GncBudget* budget, const gchar* name)
+void
+gnc_budget_set_name(GncBudget* budget, const gchar* name)
 {
-    g_return_if_fail( name != NULL );
-    if ( budget->name != NULL ) {
-        g_free( budget->name );
-        budget->name = NULL;
-    }
-    budget->name = g_strdup( name );
+    g_return_if_fail(GNC_IS_BUDGET(budget));
+    g_return_if_fail(name);
+
+    if (budget->name)
+        g_free(budget->name);
+    budget->name = g_strdup(name);
+    gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_MODIFY);
 }
 
-gchar* gnc_budget_get_name(GncBudget* budget)
+const gchar*
+gnc_budget_get_name(GncBudget* budget)
 {
-    if(budget == NULL){
-        return NULL;
-    }
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
     return budget->name;
 }
 
-void gnc_budget_set_description(GncBudget* budget, const gchar* description)
+void
+gnc_budget_set_description(GncBudget* budget, const gchar* description)
 {
-    g_return_if_fail( description != NULL );
-    if ( budget->description != NULL ) {
+    g_return_if_fail(GNC_IS_BUDGET(budget));
+    g_return_if_fail(description);
+
+    if (budget->description)
         g_free( budget->description);
-        budget->description = NULL;
-    }
     budget->description = g_strdup(description);
+    gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_MODIFY);
 }
 
-gchar* gnc_budget_get_description(GncBudget* budget)
+const gchar*
+gnc_budget_get_description(GncBudget* budget)
 {
-    if(budget == NULL){
-        return NULL;
-    }
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
     return budget->description;
 }
 
-
-
-
-void gnc_budget_set_period_frequency(GncBudget* budget, FreqSpec* period)
+void
+gnc_budget_set_recurrence(GncBudget *budget, const Recurrence *r)
 {
-    if(budget == NULL){
-        return;
-    }
-    
-    if((budget->period_freq == period) || (period == NULL)){
-        return;
-    }
-
-    if(budget->period_freq != NULL){
-        /* Delete the existing object before setting the new one. */
-        xaccFreqSpecFree(budget->period_freq);
-    }
-
-    budget->period_freq = period;
+    g_return_if_fail(budget && r);
+    budget->recurrence = *r;
+    gnc_engine_gen_event(&budget->inst.entity, GNC_EVENT_MODIFY);
 }
 
-FreqSpec* gnc_budget_get_period_frequency(GncBudget* budget)
+const Recurrence *
+gnc_budget_get_recurrence(GncBudget *budget)
 {
-    if(budget == NULL){
-        return NULL;
-    }
-
-    return budget->period_freq;
+    g_return_val_if_fail(budget, NULL);
+    return (&budget->recurrence);
 }
 
-
-
-
-void gnc_budget_set_start_date(GncBudget* budget, GDate* date)
+const GUID*
+gnc_budget_get_guid(GncBudget* budget)
 {
-    if(budget == NULL){
-        return;
-    }
-    budget->start_date = *date;
+    g_return_val_if_fail(budget, NULL);
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
+    return qof_entity_get_guid(QOF_ENTITY(budget));
 }
 
-GDate* gnc_budget_get_start_date(GncBudget* budget)
+void
+gnc_budget_set_num_periods(GncBudget* budget, guint num_periods)
 {
-    if(budget == NULL){
-        return NULL;
-    }
-    return &budget->start_date;
+    g_return_if_fail(GNC_IS_BUDGET(budget));
+    budget->num_periods = num_periods;
+    gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_MODIFY);
 }
 
-
-
-
-
-
-void gnc_budget_set_length_months(GncBudget* budget, gint months)
+guint
+gnc_budget_get_num_periods(GncBudget* budget)
 {
-    if(budget == NULL){
-        return;
-    }
-
-    budget->length = months;
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), 0);
+    return budget->num_periods;
 }
 
-void gnc_budget_set_length_years(GncBudget* budget, gint years)
-{
-    if(budget == NULL){
-        return;
-    }
-
-    budget->length = years * 12;
-}
+#define BUF_SIZE (10 + GUID_ENCODING_LENGTH + \
+   GNC_BUDGET_MAX_NUM_PERIODS_DIGITS)
 
-gint gnc_budget_get_length_months(GncBudget* budget)
+/* period_num is zero-based */
+/* What happens when account is deleted, after we have an entry for it? */
+void
+gnc_budget_set_account_period_value(GncBudget *budget, Account *account,
+                                    guint period_num, gnc_numeric val)
 {
-    if(budget == NULL){
-        return 0;
-    }
+    const GUID *guid;
+    KvpFrame *frame;
+    gchar path[BUF_SIZE];
+    gchar *bufend;
 
-    return budget->length;
-}
+    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
+    guid = xaccAccountGetGUID(account);
+    bufend = guid_to_string_buff(guid, path);
+    g_sprintf(bufend, "/%d", period_num);
 
-gint gnc_budget_get_length_years(GncBudget* budget)
-{
-    if(budget == NULL){
-        return 0;
-    }
+    kvp_frame_set_numeric(frame, path, val);
+    gnc_engine_gen_event( &budget->inst.entity, GNC_EVENT_MODIFY);
 
-    return budget->length / 12;
 }
 
+/* We don't need these here, but maybe they're useful somewhere else?
+   Maybe this should move to Account.h */
+#if 0
+static gpointer
+is_same_commodity(Account *a, gpointer data)
+{
+    gnc_commodity *acct_comm;
+    gnc_commodity *comm;
 
+    g_return_val_if_fail(data, NULL);
+    // What? No type-checking macro?
+    comm = (gnc_commodity *) data;
+    acct_comm = xaccAccountGetCommodity(a);
 
-
-
-
-void gnc_budget_add_inflow_category(GncBudget* budget, GncBudgetCategory* category)
-{
-    if(budget == NULL){
-        return;
-    }
-    gnc_budget_category_add_child(budget->inflow_category, category);
+    return gnc_commodity_equal(comm, acct_comm) ? NULL : data;
 }
 
-void gnc_budget_remove_inflow_category(GncBudget* budget, GncBudgetCategory* category)
+static gboolean
+xaccAccountChildrenHaveSameCommodity(Account *account)
 {
-    if(budget == NULL){
-        return;
-    }
-    gnc_budget_category_remove_child(budget->inflow_category, category);
-}
+    AccountGroup *grp;
+    gpointer different;
+    gnc_commodity *comm;
 
-void gnc_budget_set_inflow_category(GncBudget* budget, GncBudgetCategory* inflow)
-{
-    if(budget == NULL){
-        return;
-    }
-    budget->inflow_category = inflow;
+    comm = xaccAccountGetCommodity(account);
+    grp = xaccAccountGetChildren(account);
+    different = xaccGroupForEachAccount(
+        grp, is_same_commodity, comm, TRUE);
+    return (different == NULL);
 }
+#endif
 
-GncBudgetCategory* gnc_budget_get_inflow_category(GncBudget* budget)
-{
-    if(budget == NULL){
-        return NULL;
-    }
-    return budget->inflow_category;
-}
 
-void gnc_budget_set_outflow_category(GncBudget* budget, GncBudgetCategory* outflow)
+/* In order to distinguish between a value of zero and an unset value,
+   this function can return a gnc_numeric with GNC_ERROR_ARG set.
+   Currently, it only does so for placeholder accounts with
+   mixed-commodity subaccounts. */
+gnc_numeric
+gnc_budget_get_account_period_value(GncBudget *budget, Account *account,
+                                    guint period_num)
 {
-    if(budget == NULL){
-        return;
-    }
-    budget->outflow_category = outflow;
-}
+    gnc_numeric numeric;
+    gchar path[BUF_SIZE];
+    gchar *bufend;
+    const GUID *guid;
+    KvpFrame *frame;
 
-GncBudgetCategory* gnc_budget_get_outflow_category(GncBudget* budget)
-{
-    if(budget == NULL){
-        return NULL;
-    }
-    return budget->outflow_category;
-}
+    numeric = gnc_numeric_zero();
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), numeric);
+    g_return_val_if_fail(account, numeric);
 
-void gnc_budget_add_outflow_category(GncBudget* budget, GncBudgetCategory* category)
-{
-    if(budget == NULL){
-        return;
-    }
-    gnc_budget_category_add_child(budget->outflow_category, category);
+    /* FIXME? check for unset?  Right now, returns zero on unset. */
+    frame = qof_instance_get_slots(QOF_INSTANCE(budget));
+    guid = xaccAccountGetGUID(account);
+    bufend = guid_to_string_buff(guid, path);
+    g_sprintf(bufend, "/%d", period_num);
+    numeric = kvp_frame_get_numeric(frame, path);
+    return numeric;
 }
 
-void gnc_budget_remove_outflow_category(GncBudget* budget, GncBudgetCategory* category)
+/* If 'end' is true, then get a time just before the beginning of the
+   next period */
+static time_t
+gnc_budget_get_period_time(GncBudget *budget, guint period_num, gboolean end)
 {
-    if(budget == NULL){
-        return;
+    GDate date;
+    recurrenceNthInstance(&(budget->recurrence),
+                          period_num + (end ? 1 : 0), &date);
+    if (end) {
+        g_date_subtract_days(&date, 1);
+        return gnc_timet_get_day_end_gdate(&date);
+    } else {
+        return gnc_timet_get_day_start_gdate(&date);
     }
-    gnc_budget_category_remove_child(budget->inflow_category, category);
-}
 
-QofBook* gnc_budget_get_book(GncBudget* budget)
-{
-    if(budget == NULL){
-        return NULL;
-    }
-    return budget->book;
 }
 
-static void free_budget_period(gpointer data, gpointer user_data)
+Timespec
+gnc_budget_get_period_start_date(GncBudget *budget, guint period_num)
 {
-    GncBudgetPeriod* period = data;
-    g_free(period);
+    Timespec ts;
+    timespecFromTime_t(
+        &ts,  gnc_budget_get_period_time(budget, period_num, FALSE));
+    return ts;
 }
 
-void gnc_budget_generate_periods(GncBudget* budget)
+gnc_numeric
+gnc_budget_get_account_period_actual_value(
+    GncBudget *budget, Account *account, guint period_num)
 {
-    GDate currentPeriod, outDate;
-    GDate endDate;
-    GDate periodStartDate;
-    GncBudgetPeriod* budgetPeriod;
+    gnc_numeric numeric, num1, num2;
+    time_t t1, t2;
 
-    if(budget == NULL){
-        return;
-    }
-
-    /* TODO: Add in some error checking such that we don't regenerate
-     * the periods if they are the same as before.  We may still need
-     * to recalculate the values however.
-     */
-    if(budget->period_list != NULL){
-        g_list_foreach(budget->period_list, free_budget_period, NULL);
-        g_list_free(budget->period_list);
-        budget->period_list = NULL;
-    }
-    
-    /* Add the starting period.  Every budget should have at least
-     * one period. */
-    g_date_set_dmy(&periodStartDate, g_date_get_day(&budget->start_date),
-                                     g_date_get_month(&budget->start_date),
-                                     g_date_get_year(&budget->start_date));
-    budgetPeriod = gnc_budget_period_new();
-    gnc_budget_period_set_start_date(budgetPeriod, &periodStartDate);
-    budget->period_list = g_list_append(budget->period_list, budgetPeriod);
- 
-    
-    /* Setup the end Date */
-    g_date_set_dmy(&endDate, g_date_get_day(&budget->start_date),
-                             g_date_get_month(&budget->start_date),
-                             g_date_get_year(&budget->start_date));
-    g_date_add_months(&endDate, budget->length);
-    
-
-    g_date_set_dmy(&currentPeriod, g_date_get_day(&budget->start_date),
-                                  g_date_get_month(&budget->start_date),
-                                  g_date_get_year(&budget->start_date));
-    do{
-        xaccFreqSpecGetNextInstance(budget->period_freq, &currentPeriod, &outDate);
-        if(g_date_valid(&outDate) == FALSE){
-            break;
-        }
-        
-        if(g_date_compare(&outDate, &endDate) >= 0){
-            break;
-        }
-        else{
-            /* Set the end date of the previous period. */
-            gnc_budget_period_set_end_date(budgetPeriod, &outDate);
-
-            /* Create the new period. */
-            budgetPeriod = gnc_budget_period_new();
-            gnc_budget_period_set_start_date(budgetPeriod, &outDate);
-            
-            budget->period_list = g_list_append(budget->period_list, budgetPeriod);
-            g_date_set_dmy(&currentPeriod, g_date_get_day(&outDate),
-                            g_date_get_month(&outDate),
-                            g_date_get_year(&outDate));
-        }
-    }while(1);
-
-    gnc_budget_period_set_end_date(budgetPeriod, &endDate);
-    
-    /* Now we should generate the list of values for each category.*/
-    gnc_budget_category_generate_values(budget->inflow_category);
-    gnc_budget_category_generate_values(budget->outflow_category);
-}
+    // FIXME: maybe zero is not best error return val.
+    g_return_val_if_fail(GNC_IS_BUDGET(budget) && account, gnc_numeric_zero());
+    t1 = gnc_budget_get_period_time(budget, period_num, FALSE);
+    t2 = gnc_budget_get_period_time(budget, period_num, TRUE);
 
+    num1 = xaccAccountGetBalanceAsOfDateInCurrency(
+        account, t1, NULL, TRUE);
+    num2 = xaccAccountGetBalanceAsOfDateInCurrency(
+        account, t2, NULL, TRUE);
 
-gint gnc_budget_get_num_periods(GncBudget* budget)
-{
-    if(budget == NULL){
-        return 0;
-    }
-    return g_list_length(budget->period_list);
+    numeric = gnc_numeric_sub(num2, num1, GNC_DENOM_AUTO,
+                              GNC_HOW_DENOM_FIXED);
+    return numeric;
 }
 
-GList* gnc_budget_get_period_list(GncBudget* budget)
+QofBook*
+gnc_budget_get_book(GncBudget* budget)
 {
-    if(budget == NULL){
-        return NULL;
-    }
-    return budget->period_list;
+    g_return_val_if_fail(GNC_IS_BUDGET(budget), NULL);
+    return qof_instance_get_book(&budget->inst);
 }
 
-
-
-/* ==================================================================== */
-/* Private member functions.
- *
- * ==================================================================== */
-
-static void add_category_from_account(gpointer data, gpointer userdata)
+GncBudget*
+gnc_budget_lookup (const GUID *guid, QofBook *book)
 {
-    GncBudget* budget;
-    Account* account;
-    AccountList* children;
-    GncBudgetCategory* category = NULL;
-    gchar* name;
-    AccountGroup* group;
-    int numChildren;
-    GNCAccountType accountType;
-
-    account = data;
-    budget = userdata;
-    
-    if(account == NULL){
-        return;
-    }
-
-    //printf("Adding Category from account\n");
-    //printf("Account: %s\n", xaccAccountGetName(account));
-    group  = xaccAccountGetChildren(account);
-    children = xaccGroupGetAccountList(group);
-    numChildren = xaccGroupGetNumAccounts(group);
-    //printf("NumChildren: %d\n", numChildren);
-
-    if(numChildren == 0){
-        name = xaccAccountGetFullName(account, ':');
-        accountType = xaccAccountGetType(account);
-        
-        category = gnc_budget_category_new(budget->book, budget);
-        gnc_budget_category_set_name(category, name);
-        gnc_budget_category_add_account(category, account);
-                
-        if(accountType == INCOME){
-            //printf("Inflow Category: %s\n", gnc_budget_category_get_name(category));
-            gnc_budget_category_set_type(category, BUDGET_CATEGORY_INFLOW);
-            gnc_budget_category_add_child(budget->inflow_category, category);
-        }
-        else{
-            //printf("Outflow Category: %s\n", gnc_budget_category_get_name(category));
-            gnc_budget_category_set_type(category, BUDGET_CATEGORY_OUTFLOW);
-            gnc_budget_category_add_child(budget->outflow_category, category);
-        }
-        
-        g_free(name);
-    }
+    QofCollection *col;
 
+    g_return_val_if_fail(guid, NULL);
+    g_return_val_if_fail(book, NULL);
+    col = qof_book_get_collection (book, GNC_ID_BUDGET);
+    return GNC_BUDGET(qof_collection_lookup_entity (col, guid));
 }
 
-static void budget_fill_categories(GncBudget* budget)
+static void just_get_one(QofEntity *ent, gpointer data)
 {
-    AccountList* children;
-    if(budget == NULL){
-        return;
-    }
-    
-    //printf("Creating top level budget categories.\n");
-
-    budget->inflow_category = gnc_budget_category_new(budget->book, budget);
-    gnc_budget_category_set_name(budget->inflow_category, "Inflow");
-
-    
-    budget->outflow_category = gnc_budget_category_new(budget->book, budget);
-    gnc_budget_category_set_name(budget->outflow_category, "Outflow");
-
-    
-    //printf("Filing budget Categories.\n");
-    //children = xaccGroupGetAccountList(gnc_book_get_group(budget->book));
-    children = xaccGroupGetSubAccounts(gnc_book_get_group(budget->book));
-    g_list_foreach(children, add_category_from_account, budget);
-
-    //printf("Number of inflow categories: %d\n", 
-            //gnc_budget_category_get_num_children(budget->inflow_category));
-    //printf("Number of outflow categories: %d\n", 
-            //gnc_budget_category_get_num_children(budget->outflow_category));
+    GncBudget **bgt = (GncBudget**)data;
+    if (bgt && !*bgt) *bgt = GNC_BUDGET(ent);
 }
 
-GncBudget* gnc_budget_lookup (const GUID *guid, QofBook *book)
+GncBudget*
+gnc_budget_get_default (QofBook *book)
 {
     QofCollection *col;
-    
-    if (!guid || !book){
-        return NULL;
-    }
-        
-    col = qof_book_get_collection (book, GNC_ID_BUDGET);
-    return (GncBudget*)qof_collection_lookup_entity (col, guid);
+    GncBudget *bgt = NULL;
+
+    g_return_val_if_fail(book, NULL);
+    col = qof_book_get_collection(book, GNC_ID_BUDGET);
+    if (qof_collection_count(col) > 0) {
+        qof_collection_foreach(col, just_get_one, &bgt);
+    }
+    return bgt;
+}
+
+/* Define the QofObject. */
+/* TODO: Eventually, I'm think I'm going to have to check if this struct is
+   complete.  Also, do we need one of those QofParam thingys? */
+static QofObject budget_object_def =
+{
+    interface_version: QOF_OBJECT_VERSION,
+    e_type:            GNC_ID_BUDGET,
+    type_label:        "BUDGET",
+    create:            (gpointer (*)(QofBook *)) gnc_budget_new,
+    book_begin:        NULL,
+    book_end:          NULL,
+    is_dirty:          NULL,
+    mark_clean:        NULL,
+    foreach:           qof_collection_foreach,
+    printable:         NULL,
+    version_cmp:       (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
+};
+
+/* Register ourselves with the engine. */
+gboolean gnc_budget_register (void)
+{
+    return qof_object_register (&budget_object_def);
 }
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Makefile.am,v
retrieving revision 1.94.2.20
retrieving revision 1.94.2.21
diff -Lsrc/engine/Makefile.am -Lsrc/engine/Makefile.am -u -r1.94.2.20 -r1.94.2.21
--- src/engine/Makefile.am
+++ src/engine/Makefile.am
@@ -5,6 +5,7 @@
 
 AM_CFLAGS = \
 	-I${top_srcdir}/lib/libc \
+	-I${top_srcdir}/src/core-utils \
 	-I${top_srcdir}/src \
 	-I${top_srcdir}/src/gnc-module \
 	-I${top_srcdir}/src/business/business-core/ \
@@ -125,10 +126,6 @@
   cap-gains.c \
   cashobjects.c \
   gnc-associate-account.c \
-  gnc-budget-book.c \
-  gnc-budget-cat.c \
-  gnc-budget-period-value.c \
-  gnc-budget-period.c \
   gnc-budget.c \
   gnc-commodity.c \
   gnc-engine.c \
@@ -169,10 +166,6 @@
   glib-helpers.h \
   gnc-associate-account.h \
   gnc-book.h \
-  gnc-budget-book.h \
-  gnc-budget-cat.h \
-  gnc-budget-period-value.h \
-  gnc-budget-period.h \
   gnc-budget.h \
   gnc-commodity.h \
   gnc-engine.h \
@@ -196,11 +189,6 @@
   SX-book.h \
   SX-ttinfo.h \
   TransactionP.h \
-  gnc-budget-book-p.h \
-  gnc-budget-cat-p.h \
-  gnc-budget-period-value-p.h \
-  gnc-budget-period-p.h \
-  gnc-budget-p.h \
   gnc-hooks-scm.h \
   gnc-lot.h \
   gnc-lot-p.h \
Index: cashobjects.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Attic/cashobjects.c,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -Lsrc/engine/cashobjects.c -Lsrc/engine/cashobjects.c -u -r1.1.2.4 -r1.1.2.5
--- src/engine/cashobjects.c
+++ src/engine/cashobjects.c
@@ -32,7 +32,7 @@
 #include "SX-book-p.h"
 #include "gnc-pricedb-p.h"
 #include "gnc-lot-p.h"
-#include "gnc-budget-book-p.h"
+#include "gnc-budget.h"
 
 gboolean
 cashobjects_register(void)
Index: gnc-engine.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-engine.h,v
retrieving revision 1.16.4.10
retrieving revision 1.16.4.11
diff -Lsrc/engine/gnc-engine.h -Lsrc/engine/gnc-engine.h -u -r1.16.4.10 -r1.16.4.11
--- src/engine/gnc-engine.h
+++ src/engine/gnc-engine.h
@@ -62,6 +62,7 @@
 #define GNC_MOD_IMPORT    "gnucash-import-export"
 #define GNC_MOD_DRUID     "gnucash-druids"
 #define GNC_MOD_TEST      "gnucash-tests"
+#define GNC_MOD_BUDGET    "gnucash-budget"
 //@}
 
 /** @brief IDENTIFIERS
@@ -99,13 +100,29 @@
 #define GNC_ID_SPLIT          "Split"
 #define GNC_ID_SCHEDXACTION   "SchedXaction"
 #define GNC_ID_BUDGET         "Budget"
-#define GNC_ID_BUDGET_CATEGORY "BudgetCategory"
 #define GNC_ID_SXTG           "SXTGroup"
 #define GNC_ID_SXTT           "SXTTrans"
 #define GNC_ID_TRANS          "Trans"
                                                                                 
 /* TYPES **********************************************************/
 
+/* CAS: ISTM, it would make more sense to put the typedefs in their
+   corresponding header files, (e.g. Account.h), and to #include all
+   the engine API header files right here.  After all, when I jump to
+   the definition "Account", I want to end up in Account.h, not this
+   file, like I do now.
+
+   Also, as it is now, if I want to use the engine api, I need to
+   include this header, plus all the other engine headers for the
+   types whose functions I call, so this header is providing almost no
+   benefit of aggregation.  But, if it included all the headers I
+   could just include this file.  Or would that cause a massive
+   recompile everytime one engine header changed?
+   Even if including all the headers here doesn't make sense, I think
+   distributing the stuff in the "Types" section does.
+*/
+
+
 /** @brief Account in Gnucash. 
  * This is the typename for an account. The actual structure is
  * defined in the private header AccountP.h, but no one outside the
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Makefile.am,v
retrieving revision 1.107.4.29
retrieving revision 1.107.4.30
diff -Lsrc/gnome/Makefile.am -Lsrc/gnome/Makefile.am -u -r1.107.4.29 -r1.107.4.30
--- src/gnome/Makefile.am
+++ src/gnome/Makefile.am
@@ -21,9 +21,6 @@
 libgw_gnc_la_LIBADD = libgncgnome.la
 
 libgncgnome_la_SOURCES = \
-  dialog-budget-category.c \
-  dialog-budget-list.c \
-  dialog-budget-workbench.c \
   dialog-chart-export.c  \
   dialog-commodities.c \
   dialog-fincalc.c \
@@ -39,16 +36,17 @@
   dialog-totd.c \
   dialog-userpass.c \
   dialog-scheduledxaction.c \
-  druid-budget-create.c \
   druid-acct-period.c \
   druid-hierarchy.c \
   druid-merge.c \
   druid-loan.c \
   druid-stock-split.c \
-  gnc-plugin-basic-commands.c \
   gnc-plugin-account-tree.c \
+  gnc-plugin-basic-commands.c \
+  gnc-plugin-budget.c \
   gnc-plugin-register.c \
   gnc-plugin-page-account-tree.c \
+  gnc-plugin-page-budget.c \
   gnc-plugin-page-register.c \
   gnc-split-reg.c \
   lot-viewer.c \
@@ -63,18 +61,20 @@
   ${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 \
   ${top_srcdir}/src/backend/file/gnc-commodity-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-book-xml-v2.c \
   ${top_srcdir}/src/backend/file/gnc-pricedb-xml-v2.c
-  
+
 
 gnomeappdir = ${datadir}/gnome/apps/Applications
 
@@ -88,9 +88,6 @@
 mime_DATA = gnucash.keys gnucash.mime
 
 noinst_HEADERS = \
-  dialog-budget-category.h \
-  dialog-budget-list.h \
-  dialog-budget-workbench.h \
   dialog-chart-export.h \
   dialog-fincalc.h \
   dialog-find-transactions.h \
@@ -101,17 +98,17 @@
   dialog-sxsincelast.h \
   dialog-totd.h \
   dialog-scheduledxaction.h \
-  druid-budget-create.h \
   druid-acct-period.h \
   druid-hierarchy.h \
   druid-merge.h \
   druid-loan.h \
   druid-stock-split.h \
-  gnc-budget-gui.h \
   gnc-plugin-account-tree.h \
   gnc-plugin-basic-commands.h \
+  gnc-plugin-budget.h \
   gnc-plugin-register.h \
   gnc-plugin-page-account-tree.h \
+  gnc-plugin-page-budget.h \
   gnc-plugin-page-register.h \
   gnc-split-reg.h \
   gw-gnc.h \
Index: gnc-plugin-basic-commands.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/Attic/gnc-plugin-basic-commands.c,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -Lsrc/gnome/gnc-plugin-basic-commands.c -Lsrc/gnome/gnc-plugin-basic-commands.c -u -r1.1.2.7 -r1.1.2.8
--- src/gnome/gnc-plugin-basic-commands.c
+++ src/gnome/gnc-plugin-basic-commands.c
@@ -26,7 +26,6 @@
 
 #include "gnc-plugin-basic-commands.h"
 
-#include "dialog-budget-list.h"
 #include "dialog-chart-export.h"
 #include "dialog-fincalc.h"
 #include "dialog-find-transactions.h"
@@ -61,7 +60,6 @@
 static void gnc_main_window_cmd_edit_tax_options (GtkAction *action, GncMainWindowActionData *data);
 static void gnc_main_window_cmd_actions_mortgage_loan (GtkAction *action, GncMainWindowActionData *data);
 static void gnc_main_window_cmd_actions_scheduled_transaction_editor (GtkAction *action, GncMainWindowActionData *data);
-static void gnc_main_window_cmd_actions_budget_workbench(GtkAction *action, GncMainWindowActionData *data);
 static void gnc_main_window_cmd_actions_since_last_run (GtkAction *action, GncMainWindowActionData *data);
 static void gnc_main_window_cmd_actions_close_books (GtkAction *action, GncMainWindowActionData *data);
 static void gnc_main_window_cmd_tools_financial_calculator (GtkAction *action, GncMainWindowActionData *data);
@@ -125,9 +123,6 @@
   { "ActionsMortgageLoanAction", NULL, N_("_Mortgage & Loan Repayment..."), NULL,
     N_("Setup scheduled transactions for repayment of a loan"),
     G_CALLBACK (gnc_main_window_cmd_actions_mortgage_loan) },
-  { "ActionsBudgetWorkbenchAction", NULL, N_("Budget _Workbench (Experimental)"), NULL, 
-    N_("Create, Manage, and Monitor Budgets." ),
-    G_CALLBACK(gnc_main_window_cmd_actions_budget_workbench) },
   { "ActionsCloseBooksAction", NULL, N_("Close _Books"), NULL,
     N_("Archive old data using accounting periods"),
     G_CALLBACK (gnc_main_window_cmd_actions_close_books) },
@@ -397,12 +392,6 @@
   gnc_ui_sx_loan_druid_create ();
 }
 
-static void 
-gnc_main_window_cmd_actions_budget_workbench(GtkAction *action, GncMainWindowActionData *data)
-{
-  gnc_budget_list_dialog_create();
-}
-
 static void
 gnc_main_window_cmd_actions_close_books (GtkAction *action, GncMainWindowActionData *data)
 {
Index: top-level.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/top-level.c,v
retrieving revision 1.140.4.32
retrieving revision 1.140.4.33
diff -Lsrc/gnome/top-level.c -Lsrc/gnome/top-level.c -u -r1.140.4.32 -r1.140.4.33
--- src/gnome/top-level.c
+++ src/gnome/top-level.c
@@ -54,6 +54,7 @@
 #include "gnc-plugin-basic-commands.h" /* FIXME Remove this line*/
 #include "gnc-plugin-file-history.h" /* FIXME Remove this line*/
 #include "gnc-plugin-register.h" /* FIXME Remove this line*/
+#include "gnc-plugin-budget.h"
 #include "gnc-plugin-page-register.h"
 #include "gnc-plugin-manager.h" /* FIXME Remove this line*/
 #include "gnc-icons.h" /* FIXME Remove this line*/
@@ -308,6 +309,11 @@
     gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), gnc_plugin_file_history_new ());
     gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), gnc_plugin_menu_additions_new ());
     gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (), gnc_plugin_register_new ());
+    /* I'm not sure why the FIXME note says to remove this.  Maybe
+       each module should be adding its own plugin to the manager?
+       Anyway... Oh, maybe... nah */
+    gnc_plugin_manager_add_plugin (gnc_plugin_manager_get (),
+                                   gnc_plugin_budget_new ());
     gnc_load_stock_icons ();
     gnc_ui_hierarchy_druid_initialize();
 
Index: budget.glade
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/glade/Attic/budget.glade,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/gnome/glade/budget.glade -Lsrc/gnome/glade/budget.glade -u -r1.1.2.2 -r1.1.2.3
--- src/gnome/glade/budget.glade
+++ src/gnome/glade/budget.glade
@@ -2259,4 +2259,918 @@
   </child>
 </widget>
 
+<widget class="GtkDialog" id="OptionsContainer">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Options</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">True</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox5">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area5">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkNotebook" id="BudgetOptions">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="show_tabs">True</property>
+	  <property name="show_border">True</property>
+	  <property name="tab_pos">GTK_POS_TOP</property>
+	  <property name="scrollable">False</property>
+	  <property name="enable_popup">False</property>
+
+	  <child>
+	    <widget class="GtkTable" id="table5">
+	      <property name="visible">True</property>
+	      <property name="n_rows">5</property>
+	      <property name="n_columns">3</property>
+	      <property name="homogeneous">False</property>
+	      <property name="row_spacing">3</property>
+	      <property name="column_spacing">3</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label85">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Name:</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">1</property>
+		  <property name="yalign">0</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">0</property>
+		  <property name="bottom_attach">1</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkEntry" id="BudgetName">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="editable">True</property>
+		  <property name="visibility">True</property>
+		  <property name="max_length">0</property>
+		  <property name="text" translatable="yes"></property>
+		  <property name="has_frame">True</property>
+		  <property name="invisible_char" translatable="yes">*</property>
+		  <property name="activates_default">False</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">0</property>
+		  <property name="bottom_attach">1</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="label86">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Description:</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">1</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">1</property>
+		  <property name="bottom_attach">2</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow16">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTextView" id="BudgetDescription">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="editable">True</property>
+		      <property name="overwrite">False</property>
+		      <property name="accepts_tab">True</property>
+		      <property name="justification">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap_mode">GTK_WRAP_NONE</property>
+		      <property name="cursor_visible">True</property>
+		      <property name="pixels_above_lines">0</property>
+		      <property name="pixels_below_lines">0</property>
+		      <property name="pixels_inside_wrap">0</property>
+		      <property name="left_margin">0</property>
+		      <property name="right_margin">0</property>
+		      <property name="indent">0</property>
+		      <property name="text" translatable="yes"></property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">1</property>
+		  <property name="bottom_attach">2</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options">fill</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkHBox" id="hbox23">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">0</property>
+
+		  <child>
+		    <widget class="Custom" id="BudgetRecurrenceEntry">
+		      <property name="visible">True</property>
+		      <property name="creation_function">gnc_recurrence_new</property>
+		      <property name="int1">0</property>
+		      <property name="int2">0</property>
+		      <property name="last_modification_time">Tue, 25 Jan 2005 02:09:41 GMT</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">2</property>
+		  <property name="bottom_attach">3</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options">fill</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="label87">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Number of Periods:</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">1</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">3</property>
+		  <property name="bottom_attach">4</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkSpinButton" id="BudgetNumPeriods">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="climb_rate">1</property>
+		  <property name="digits">0</property>
+		  <property name="numeric">True</property>
+		  <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+		  <property name="snap_to_ticks">False</property>
+		  <property name="wrap">False</property>
+		  <property name="adjustment">1 1 60 1 12 12</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">3</property>
+		  <property name="bottom_attach">4</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="label94">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Budget Periods</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">2</property>
+		  <property name="bottom_attach">3</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label83">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Budget</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkTable" id="table6">
+	      <property name="visible">True</property>
+	      <property name="n_rows">3</property>
+	      <property name="n_columns">3</property>
+	      <property name="homogeneous">False</property>
+	      <property name="row_spacing">0</property>
+	      <property name="column_spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label93">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Account Types to Show</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">0</property>
+		  <property name="bottom_attach">1</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkScrolledWindow" id="scrolledwindow17">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="shadow_type">GTK_SHADOW_NONE</property>
+		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+		  <child>
+		    <widget class="GtkTreeView" id="AccountTypesTreeView">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="headers_visible">True</property>
+		      <property name="rules_hint">False</property>
+		      <property name="reorderable">False</property>
+		      <property name="enable_search">True</property>
+		    </widget>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">1</property>
+		  <property name="bottom_attach">2</property>
+		  <property name="x_options">fill</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="tab_expand">False</property>
+	      <property name="tab_fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label92">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Budget View</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="type">tab</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkWindow" id="GncRecurrenceEntry">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes"></property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+  <child>
+    <widget class="GtkVBox" id="RecurrenceEntryVBox">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+	<widget class="GtkHBox" id="hbox218">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label90">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Every </property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkSpinButton" id="GSB_Mult">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Number of calendar units in the recurrence:  E.g. Biweekly = every 2 weeks; Quarterly = every 3 month</property>
+	      <property name="can_focus">True</property>
+	      <property name="climb_rate">1</property>
+	      <property name="digits">0</property>
+	      <property name="numeric">True</property>
+	      <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+	      <property name="snap_to_ticks">False</property>
+	      <property name="wrap">False</property>
+	      <property name="adjustment">1 1 250 1 10 10</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkComboBox" id="GCB_PeriodType">
+	      <property name="visible">True</property>
+	      <property name="items" translatable="yes">day(s)
+week(s)
+month(s)
+year(s)</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHBox" id="hbox219">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label89">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">beginning on: </property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GnomeDateEdit" id="GDE_StartDate">
+	      <property name="visible">True</property>
+	      <property name="dateedit_flags">GNOME_DATE_EDIT_24_HR</property>
+	      <property name="lower_hour">7</property>
+	      <property name="upper_hour">19</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHBox" id="hbox220">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkCheckButton" id="GCB_EndOfMonth">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Always use the last day (or day of week) in the month?</property>
+	      <property name="can_focus">True</property>
+	      <property name="label" translatable="yes">last of month</property>
+	      <property name="use_underline">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="active">False</property>
+	      <property name="inconsistent">False</property>
+	      <property name="draw_indicator">True</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkCheckButton" id="GCB_NthWeekday">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Match the &quot;day of week&quot; and &quot;week of month&quot;?  (for example, the &quot;second Tuesday&quot; of every month)</property>
+	      <property name="can_focus">True</property>
+	      <property name="label" translatable="yes">same week &amp; day</property>
+	      <property name="use_underline">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="active">False</property>
+	      <property name="inconsistent">False</property>
+	      <property name="draw_indicator">True</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkWindow" id="sample">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">window1</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+  <child>
+    <widget class="GtkVBox" id="SampleOptions">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child>
+	<widget class="GtkLabel" id="SampleLabel">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">label91</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0.5</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkEntry" id="SampleEntry">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="editable">True</property>
+	  <property name="visibility">True</property>
+	  <property name="max_length">0</property>
+	  <property name="text" translatable="yes"></property>
+	  <property name="has_frame">True</property>
+	  <property name="invisible_char" translatable="yes">*</property>
+	  <property name="activates_default">False</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkComboBoxEntry" id="SampleComboBoxEntry">
+	  <property name="visible">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkScrolledWindow" id="SampleScrolledWindow">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	  <property name="shadow_type">GTK_SHADOW_NONE</property>
+	  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+	  <child>
+	    <widget class="GtkTextView" id="SampleTextView">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="editable">True</property>
+	      <property name="overwrite">False</property>
+	      <property name="accepts_tab">True</property>
+	      <property name="justification">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap_mode">GTK_WRAP_NONE</property>
+	      <property name="cursor_visible">True</property>
+	      <property name="pixels_above_lines">0</property>
+	      <property name="pixels_below_lines">0</property>
+	      <property name="pixels_inside_wrap">0</property>
+	      <property name="left_margin">0</property>
+	      <property name="right_margin">0</property>
+	      <property name="indent">0</property>
+	      <property name="text" translatable="yes"></property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkButton" id="SampleButton">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="label" translatable="yes">button1</property>
+	  <property name="use_underline">True</property>
+	  <property name="relief">GTK_RELIEF_NORMAL</property>
+	  <property name="focus_on_click">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkToggleButton" id="SampleToggleButton">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="label" translatable="yes">togglebutton1</property>
+	  <property name="use_underline">True</property>
+	  <property name="relief">GTK_RELIEF_NORMAL</property>
+	  <property name="focus_on_click">True</property>
+	  <property name="active">False</property>
+	  <property name="inconsistent">False</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkCheckButton" id="SampleCheckButton">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="label" translatable="yes">checkbutton1</property>
+	  <property name="use_underline">True</property>
+	  <property name="relief">GTK_RELIEF_NORMAL</property>
+	  <property name="focus_on_click">True</property>
+	  <property name="active">False</property>
+	  <property name="inconsistent">False</property>
+	  <property name="draw_indicator">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkRadioButton" id="SampleRadioButton">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="label" translatable="yes">radiobutton1</property>
+	  <property name="use_underline">True</property>
+	  <property name="relief">GTK_RELIEF_NORMAL</property>
+	  <property name="focus_on_click">True</property>
+	  <property name="active">False</property>
+	  <property name="inconsistent">False</property>
+	  <property name="draw_indicator">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkComboBox" id="SampleComboBox">
+	  <property name="visible">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkSpinButton" id="SampleSpinButton">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="climb_rate">1</property>
+	  <property name="digits">0</property>
+	  <property name="numeric">False</property>
+	  <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+	  <property name="snap_to_ticks">False</property>
+	  <property name="wrap">False</property>
+	  <property name="adjustment">1 0 100 1 10 10</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkScrolledWindow" id="SampleScrolledWindow2">
+	  <property name="visible">True</property>
+	  <property name="can_focus">True</property>
+	  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	  <property name="shadow_type">GTK_SHADOW_NONE</property>
+	  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+	  <child>
+	    <widget class="GtkTreeView" id="SampleTreeView">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="headers_visible">True</property>
+	      <property name="rules_hint">False</property>
+	      <property name="reorderable">False</property>
+	      <property name="enable_search">True</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHBox" id="GncRecurrencePlaceholderSampleRecurrence">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <placeholder/>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="Custom" id="SampleCustomGncRecurrence">
+	  <property name="visible">True</property>
+	  <property name="creation_function">gnc_recurrence_new</property>
+	  <property name="int1">0</property>
+	  <property name="int2">0</property>
+	  <property name="last_modification_time">Wed, 19 Jan 2005 02:17:22 GMT</property>
+	</widget>
+	<packing>
+	  <property name="padding">9</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="Custom" id="SampleCustomTreeViewAccount">
+	  <property name="visible">True</property>
+	  <property name="creation_function">gnc_tree_view_account_new</property>
+	  <property name="int1">0</property>
+	  <property name="int2">0</property>
+	  <property name="last_modification_time">Wed, 19 Jan 2005 04:02:13 GMT</property>
+	</widget>
+	<packing>
+	  <property name="padding">10</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="PluginSampleSample2">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <placeholder/>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<placeholder/>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkWindow" id="Sample2">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">window1</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+
+  <child>
+    <widget class="GtkLabel" id="label91">
+      <property name="visible">True</property>
+      <property name="label" translatable="yes">This is Sample2.</property>
+      <property name="use_underline">False</property>
+      <property name="use_markup">False</property>
+      <property name="justify">GTK_JUSTIFY_LEFT</property>
+      <property name="wrap">False</property>
+      <property name="selectable">False</property>
+      <property name="xalign">0.5</property>
+      <property name="yalign">0.5</property>
+      <property name="xpad">0</property>
+      <property name="ypad">0</property>
+    </widget>
+  </child>
+</widget>
+
 </glade-interface>
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/ui/Attic/Makefile.am,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lsrc/gnome/ui/Makefile.am -Lsrc/gnome/ui/Makefile.am -u -r1.1.2.5 -r1.1.2.6
--- src/gnome/ui/Makefile.am
+++ src/gnome/ui/Makefile.am
@@ -1,5 +1,7 @@
 uidir = $(GNC_UI_DIR)
 ui_DATA = \
+	gnc-plugin-budget-ui.xml \
+	gnc-plugin-page-budget-ui.xml \
 	gnc-plugin-account-tree-ui.xml \
 	gnc-plugin-basic-commands-ui.xml \
 	gnc-plugin-page-account-tree-ui.xml \
Index: gnc-plugin-basic-commands-ui.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome/ui/Attic/gnc-plugin-basic-commands-ui.xml,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -Lsrc/gnome/ui/gnc-plugin-basic-commands-ui.xml -Lsrc/gnome/ui/gnc-plugin-basic-commands-ui.xml -u -r1.1.2.4 -r1.1.2.5
--- src/gnome/ui/gnc-plugin-basic-commands-ui.xml
+++ src/gnome/ui/gnc-plugin-basic-commands-ui.xml
@@ -48,7 +48,6 @@
           <menuitem name="ActionsSinceLastRun" action="ActionsSinceLastRunAction"/>
           <menuitem name="ActionsMortgageLoan" action="ActionsMortgageLoanAction"/>
         </menu>
-        <menuitem name="ActionsBudgetWorkbenchAction" action="ActionsBudgetWorkbenchAction"/>
         <menuitem name="ActionsCloseBooks" action="ActionsCloseBooksAction"/>
       </placeholder>
     </menu>
Index: gnc-html.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/gnc-html.h,v
retrieving revision 1.7.4.5
retrieving revision 1.7.4.6
diff -Lsrc/gnome-utils/gnc-html.h -Lsrc/gnome-utils/gnc-html.h -u -r1.7.4.5 -r1.7.4.6
--- src/gnome-utils/gnc-html.h
+++ src/gnome-utils/gnc-html.h
@@ -44,6 +44,7 @@
 #define URL_TYPE_XMLDATA	"xmldata"    /* links to gnucash XML data files */ 
 #define URL_TYPE_PRICE	"price"      /* for price editor popups */
 #define URL_TYPE_OTHER	"other"
+#define URL_TYPE_BUDGET "budget"
 
 #include "gnc-html-history.h"
 
Index: gnc-html.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/gnc-html.c,v
retrieving revision 1.23.4.15
retrieving revision 1.23.4.16
diff -Lsrc/gnome-utils/gnc-html.c -Lsrc/gnome-utils/gnc-html.c -u -r1.23.4.15 -r1.23.4.16
--- src/gnome-utils/gnc-html.c
+++ src/gnome-utils/gnc-html.c
@@ -376,6 +376,7 @@
     { URL_TYPE_HELP, "gnc-help" },
     { URL_TYPE_XMLDATA, "gnc-xml" },
     { URL_TYPE_PRICE, "gnc-price" },
+    { URL_TYPE_BUDGET, "gnc-budget" },
     { URL_TYPE_OTHER, "" },
     { NULL, NULL }};
 
Index: dialog-options.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/dialog-options.c,v
retrieving revision 1.22.2.27
retrieving revision 1.22.2.28
diff -Lsrc/gnome-utils/dialog-options.c -Lsrc/gnome-utils/dialog-options.c -u -r1.22.2.27 -r1.22.2.28
--- src/gnome-utils/dialog-options.c
+++ src/gnome-utils/dialog-options.c
@@ -25,6 +25,9 @@
 #include <gnome.h>
 #include <g-wrap-wct.h>
 
+#include "gnc-tree-model-budget.h" //FIXME?
+#include "gnc-budget.h"
+
 #include "dialog-options.h"
 #include "dialog-utils.h"
 #include "engine-helpers.h"
@@ -48,6 +51,9 @@
 #include "gnc-date-format.h"
 #include "misc-gnome-utils.h"
 
+/* TODO: clean up "register-stocks" junk
+ */
+
 
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = GNC_MOD_GUI;
@@ -58,6 +64,7 @@
  */
 #define MAX_TAB_COUNT 4
 
+/* A Hash-table of GNCOptionDef_t keyed with option names. */
 static GHashTable *optionTable = NULL;
 
 struct gnc_option_win
@@ -93,9 +100,11 @@
 static GNCOptionWinCallback global_help_cb = NULL;
 gpointer global_help_cb_data = NULL;
 
-void gnc_options_dialog_response_cb(GtkDialog *dialog, gint response, GNCOptionWin *window);
+void gnc_options_dialog_response_cb(GtkDialog *dialog, gint response,
+				    GNCOptionWin *window);
 static void gnc_options_dialog_reset_cb(GtkWidget * w, gpointer data);
-void gnc_options_dialog_list_select_cb(GtkWidget * list, GtkWidget * item, gpointer data);
+void gnc_options_dialog_list_select_cb(GtkWidget * list, GtkWidget * item,
+				       gpointer data);
 
 
 static void
@@ -229,17 +238,16 @@
   if (option_def && option_def->set_value)
   {
     bad_value = option_def->set_value (option, use_default, widget, value);
+    if (bad_value)
+    {
+      PERR("bad value\n");
+    }
   }
   else
   {
     PERR("Unknown type. Ignoring.\n");
   }
 
-  if (bad_value)
-  {
-    PERR("bad value\n");
-  }
-
   free(type);
 }
 
@@ -434,6 +442,23 @@
   }
 }
 
+static GtkWidget *
+gnc_option_create_budget_widget(GNCOption *option)
+{
+    GtkTreeModel *tm;
+    GtkComboBox *cb;
+    GtkCellRenderer *cr;
+
+    tm = gnc_tree_model_budget_new(gnc_get_current_book());
+    cb = GTK_COMBO_BOX(gtk_combo_box_new_with_model(tm));
+    g_object_unref(tm);
+    cr = gtk_cell_renderer_text_new();
+    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cb), cr, TRUE);
+
+    gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cb), cr, "text",
+                                   BUDGET_NAME_COLUMN, NULL);
+    return GTK_WIDGET(cb);
+}
 
 static GtkWidget *
 gnc_option_create_multichoice_widget(GNCOption *option)
@@ -524,6 +549,7 @@
   return frame;
 }
 
+
 static void
 gnc_option_account_cb(GtkTreeSelection *selection, gpointer data)
 {
@@ -1120,7 +1146,14 @@
 #endif
 }
 
-
+/* gnc_options_dialog_new:
+ *
+ *   - Opens the preferences glade file
+ *   - Connects signals specified in the glade file
+ *   - Sets the window's title
+ *   - Initializes a new GtkNotebook, and adds it to the window
+ *
+ */
 GNCOptionWin *
 gnc_options_dialog_new(gchar *title)
 {
@@ -1149,6 +1182,8 @@
   return retval;
 }
 
+/* Creates a new GNCOptionWin structure, but assumes you have your own
+   dialog widget you want to plugin */
 GNCOptionWin *
 gnc_options_dialog_new_w_dialog(gchar *title, GtkWidget *dialog)
 {
@@ -1191,6 +1226,7 @@
   global_help_cb_data = cb_data;
 }
 
+/* This is for global program preferences. */
 void
 gnc_options_dialog_destroy(GNCOptionWin * win)
 {
@@ -1215,8 +1251,40 @@
 /*****************************************************************/
 /* Option Registration                                           */
 
-/* SET WIDGET */
-
+/*************************
+ *       SET WIDGET      *
+ *************************
+ *
+ * gnc_option_set_ui_widget_<type>():
+ *
+ * You should create the widget representation for the option type,
+ * and set the top-level container widget for your control in
+ * *enclosing.  If you want to pack the widget into the page yourself,
+ * then you may -- just set *packed to TRUE.  Otherwise, the widget
+ * you return in *enclosing will be packed for you.  (*packed is
+ * initialized to FALSE, so if you're not setting it to TRUE, you
+ * don't have to touch it at all.)
+ *
+ * If you need to initialize the state of your control or to connect
+ * any signals to you widgets, then you should do so in this function.
+ * If you want to create a label for the widget you should use 'name'
+ * for the label text.
+ *
+ * Somewhere in this function, you should also call
+ * gnc_option_set_widget(option, value); where 'value' is the
+ * GtkWidget you will actually store the value in.
+ *
+ * Also call gnc_option_set_ui_value(option, FALSE);
+ *
+ * You probably want to end with something like:
+ *   gtk_widget_show_all(*enclosing);
+ *
+ * If you can can detect state changes for your widget's value, you should also
+ * gnc_option_changed_widget_cb() upon changes.
+ *
+ * The widget you return from this function should be the widget in
+ * which you're storing the option value.
+ */
 static GtkWidget *
 gnc_option_set_ui_widget_boolean (GNCOption *option, GtkBox *page_box,
 				  GtkTooltips *tooltips,
@@ -1487,7 +1555,7 @@
   GtkWidget *value;
   GtkWidget *label;
   GList *acct_type_list;
-  char * colon_name;
+  gchar *colon_name;
 
   colon_name = g_strconcat(name, ":", NULL);
   label = gtk_label_new(colon_name);
@@ -1503,6 +1571,8 @@
 		   G_CALLBACK(gnc_option_changed_widget_cb), option);
 
   gnc_option_set_widget (option, value);
+  /* DOCUMENT ME: Why is the only option type that sets use_default to
+     TRUE? */
   gnc_option_set_ui_value(option, TRUE);
 
   *enclosing = gtk_hbox_new(FALSE, 5);
@@ -1780,7 +1850,43 @@
   return *enclosing;
 }
 
-/* SET VALUE */
+static GtkWidget *
+gnc_option_set_ui_widget_budget (GNCOption *option, GtkBox *page_box,
+                                 GtkTooltips *tooltips,
+                                 char *name, char *documentation,
+                                 /* Return values */
+                                 GtkWidget **enclosing, gboolean *packed)
+{
+  GtkWidget *value;
+
+  *enclosing = gtk_hbox_new(FALSE, 5);
+
+  value = gnc_option_create_budget_widget(option);
+
+  gnc_option_set_widget (option, value);
+  gnc_option_set_ui_value(option, FALSE);
+
+  /* Maybe connect destroy handler for tree model here? */
+  g_signal_connect(G_OBJECT(value), "changed",
+		   G_CALLBACK(gnc_option_changed_widget_cb), option);
+
+  gtk_box_pack_start(GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
+  gtk_widget_show_all(*enclosing);
+  return value;
+}
+
+/*************************
+ *       SET VALUE       *
+ *************************
+ *
+ * gnc_option_set_ui_value_<type>():
+ *
+ *   In this function you should set the state of the gui widget to
+ * correspond to the value provided in 'value'.  You should return
+ * TRUE if there was an error, FALSE otherwise.
+ *
+ *
+ */
 
 static gboolean
 gnc_option_set_ui_value_boolean (GNCOption *option, gboolean use_default,
@@ -1989,7 +2095,7 @@
 
   if (value != SCM_BOOL_F) {
     if (!gw_wcp_p(value))
-      scm_misc_error("gnc_optoin_set_ui_value_account_sel",
+      scm_misc_error("gnc_option_set_ui_value_account_sel",
 		     "Option Value not a gw:wcp.", value);
       
     acc = gw_wcp_get_ptr(value);
@@ -2116,6 +2222,31 @@
   return TRUE;
 }
 
+static gboolean gnc_option_set_ui_value_budget(
+    GNCOption *option, gboolean use_default, GtkWidget *widget, SCM value)
+{
+    GncBudget *bgt;
+    GtkComboBox *cb;
+    GtkTreeModel *tm;
+    GtkTreeIter iter;
+
+    if (value != SCM_BOOL_F) {
+        if (!gw_wcp_p(value))
+            scm_misc_error("gnc_option_set_ui_value_budget",
+                           "Option Value not a gw:wcp.", value);
+
+        bgt = gw_wcp_get_ptr(value);
+        cb = GTK_COMBO_BOX(widget);
+        tm = gtk_combo_box_get_model(cb);
+        gnc_tree_model_budget_get_iter_for_budget(tm, &iter, bgt);
+        gtk_combo_box_set_active_iter(cb, &iter);
+    }
+
+
+    //FIXME: Unimplemented.
+    return FALSE;
+}
+
 static gboolean
 gnc_option_set_ui_value_radiobutton (GNCOption *option, gboolean use_default,
 				     GtkWidget *widget, SCM value)
@@ -2176,7 +2307,19 @@
   return FALSE;
 }
 
-/* GET VALUE */
+/*************************
+ *       GET VALUE       *
+ *************************
+ *
+ * gnc_option_get_ui_value_<type>():
+ *
+ * 'widget' will be the widget returned from the
+ * gnc_option_set_ui_widget_<type>() function.
+ *
+ * You should return a SCM value corresponding to the current state of the
+ * gui widget.
+ *
+ */
 
 static SCM
 gnc_option_get_ui_value_boolean (GNCOption *option, GtkWidget *widget)
@@ -2328,6 +2471,26 @@
 }
 
 static SCM
+gnc_option_get_ui_value_budget(GNCOption *option, GtkWidget *widget)
+{
+    GncBudget *bgt;
+    GtkComboBox *cb;
+    GtkTreeModel *tm;
+    GtkTreeIter iter;
+    gboolean success;
+
+    cb = GTK_COMBO_BOX(widget);
+    success = gtk_combo_box_get_active_iter(cb, &iter);
+    tm = gtk_combo_box_get_model(cb);
+    bgt = gnc_tree_model_budget_get_budget(tm, &iter);
+
+    if (!bgt)
+        return SCM_BOOL_F;
+
+    return gw_wcp_assimilate_ptr(bgt, scm_c_eval_string("<gnc:Budget*>"));
+}
+
+static SCM
 gnc_option_get_ui_value_list (GNCOption *option, GtkWidget *widget)
 {
   SCM result;
@@ -2471,6 +2634,8 @@
       gnc_option_set_ui_value_radiobutton, gnc_option_get_ui_value_radiobutton },
     { "dateformat", gnc_option_set_ui_widget_dateformat,
       gnc_option_set_ui_value_dateformat, gnc_option_get_ui_value_dateformat },
+    { "budget", gnc_option_set_ui_widget_budget,
+      gnc_option_set_ui_value_budget, gnc_option_get_ui_value_budget },
     { NULL, NULL, NULL, NULL }
   };
   int i;
@@ -2485,15 +2650,21 @@
   g_return_if_fail (optionTable);
   g_return_if_fail (option);
 
+  /* FIXME: should protect against repeat insertion. */
   g_hash_table_insert (optionTable, (gpointer)(option->option_name), option);
 }
 
 GNCOptionDef_t * gnc_options_ui_get_option (const char *option_name)
 {
+  GNCOptionDef_t *retval;
   g_return_val_if_fail (optionTable, NULL);
   g_return_val_if_fail (option_name, NULL);
 
-  return g_hash_table_lookup (optionTable, option_name);
+  retval = g_hash_table_lookup (optionTable, option_name);
+  if (!retval) {
+      PERR("Option lookup for type '%s' failed!", option_name);
+  }
+  return retval;
 }
 
 void gnc_options_ui_initialize (void)
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Makefile.am,v
retrieving revision 1.48.2.42
retrieving revision 1.48.2.43
diff -Lsrc/gnome-utils/Makefile.am -Lsrc/gnome-utils/Makefile.am -u -r1.48.2.42 -r1.48.2.43
--- src/gnome-utils/Makefile.am
+++ src/gnome-utils/Makefile.am
@@ -73,8 +73,6 @@
   druid-gconf-setup.c \
   gnc-account-sel.c \
   gnc-amount-edit.c \
-  gnc-budget-list-tree-model.c \
-  gnc-budget-tree-model.c \
   gnc-commodity-edit.c \
   gnc-currency-edit.c \
   gnc-date-delta.c \
@@ -88,6 +86,7 @@
   gnc-embedded-window.c \
   gnc-file.c \
   gnc-frequency.c \
+  gnc-recurrence.c \
   gnc-general-select.c \
   gnc-gnome-utils.c \
   gnc-gui-query.c \
@@ -121,7 +120,9 @@
   gncmod-gnome-utils.c \
   misc-gnome-utils.c \
   print-session.c \
-  search-param.c
+  search-param.c \
+  gnc-dialog.c \
+  gnc-tree-model-budget.c
 
 gncincludedir = ${GNC_INCLUDE_DIR}
 gncinclude_HEADERS = \
@@ -139,8 +140,6 @@
   druid-gconf-setup.h \
   gnc-account-sel.h \
   gnc-amount-edit.h \
-  gnc-budget-list-tree-model.h \
-  gnc-budget-tree-model.h \
   gnc-commodity-edit.h \
   gnc-currency-edit.h \
   gnc-date-delta.h \
@@ -151,6 +150,7 @@
   gnc-embedded-window.h \
   gnc-file.h \
   gnc-frequency.h \
+  gnc-recurrence.h \
   gnc-general-select.h \
   gnc-gnome-utils.h \
   gnc-gui-query.h \
@@ -182,7 +182,9 @@
   gnc-tree-view.h \
   gnc-window.h \
   misc-gnome-utils.h \
-  print-session.h
+  print-session.h \
+  gnc-dialog.h \
+  gnc-tree-model-budget.h
 
 noinst_HEADERS = \
   argv-list-converters.h \
Index: gnc-icons.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/Attic/gnc-icons.h,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -Lsrc/gnome-utils/gnc-icons.h -Lsrc/gnome-utils/gnc-icons.h -u -r1.1.2.2 -r1.1.2.3
--- src/gnome-utils/gnc-icons.h
+++ src/gnome-utils/gnc-icons.h
@@ -15,6 +15,14 @@
 #define GNC_STOCK_NEW_ACCOUNT "gnc-new-account"
 #define GNC_STOCK_OPEN_ACCOUNT "gnc-open-account"
 
+//FIXME: use own budget icons?
+#define GNC_STOCK_BUDGET "gnc-budget"
+#define GNC_STOCK_NEW_BUDGET "gnc-account"
+#define GNC_STOCK_OPEN_BUDGET "gnc-open-account"
+//#define GNC_STOCK_CLOSE_BUDGET "gnc-close-account"
+//#define GNC_STOCK_EDIT_BUDGET "gnc-edit-account"
+#define GNC_STOCK_DELETE_BUDGET "gnc-delete-account"
+
 void gnc_load_stock_icons (void);
 
 G_END_DECLS
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/gnome-utils/test/Makefile.am,v
retrieving revision 1.15.4.1
retrieving revision 1.15.4.2
diff -Lsrc/gnome-utils/test/Makefile.am -Lsrc/gnome-utils/test/Makefile.am -u -r1.15.4.1 -r1.15.4.2
--- src/gnome-utils/test/Makefile.am
+++ src/gnome-utils/test/Makefile.am
@@ -1,5 +1,9 @@
 TESTS =  \
-  test-link-module test-load-module 
+  test-link-module test-load-module test-gnc-recurrence test-gnc-dialog
+
+##lib_LTLIBRARIES = libgncgnome.la
+
+
 
 GNC_TEST_DEPS := @GNC_TEST_SRFI_LOAD_CMD@ \
   --gnc-module-dir ${top_builddir}/src/gnc-module \
@@ -23,12 +27,23 @@
   $(shell ${top_srcdir}/src/gnc-test-env --no-exports ${GNC_TEST_DEPS})
 
 noinst_PROGRAMS = \
-  test-link-module
+  test-link-module test-gnc-recurrence test-gnc-dialog
 
 INCLUDES= \
   -I${top_srcdir}/src \
+  -I${top_srcdir}/src/engine \
+  -I${top_srcdir}/src/gnome-utils \
   -I${top_srcdir}/src/gnc-module \
-  ${GLIB_CFLAGS} ${GUILE_INCS}
+  -I${top_srcdir}/src/app-utils \
+  ${GLIB_CFLAGS} ${GUILE_INCS} ${GNOME_CFLAGS} ${GLADE_CFLAGS}
+
+test_gnc_recurrence_SOURCES=test-gnc-recurrence.c
+test_gnc_recurrence_LDADD = ${GNOME_LIBS} \
+  ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la
+
+test_gnc_dialog_LDADD = ${GNOME_LIBS} \
+  ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
+  ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la
 
 test_link_module_SOURCES=test-link-module.c
 test_link_module_LDADD= \
Index: report-system.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/report-system.scm,v
retrieving revision 1.20.4.4
retrieving revision 1.20.4.5
diff -Lsrc/report/report-system/report-system.scm -Lsrc/report/report-system/report-system.scm -u -r1.20.4.4 -r1.20.4.5
--- src/report/report-system/report-system.scm
+++ src/report/report-system/report-system.scm
@@ -89,6 +89,7 @@
 (export gnc:first-html-build-acct-table)
 (export gnc:html-make-exchangerates)
 (export gnc:html-make-no-account-warning)
+(export gnc:html-make-generic-options-warning)
 (export gnc:html-make-empty-data-warning)
 
 ;; report.scm
@@ -435,7 +436,7 @@
 (export gnc:account-code-less-p)
 (export gnc:account-name-less-p)
 (export gnc:account-path-less-p)
-(export gnc:identity)
+;;(export gnc:identity)
 (export gnc:html-table-add-labeled-amount-line!)
 (export gnc:html-table-add-account-balances)
 (export gnc:second-html-build-acct-table)
Index: html-utilities.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/report-system/html-utilities.scm,v
retrieving revision 1.8.4.2
retrieving revision 1.8.4.3
diff -Lsrc/report/report-system/html-utilities.scm -Lsrc/report/report-system/html-utilities.scm -u -r1.8.4.2 -r1.8.4.3
--- src/report/report-system/html-utilities.scm
+++ src/report/report-system/html-utilities.scm
@@ -784,6 +784,34 @@
     
     table))
 
+
+;; TODO: How 'bout factoring the "Edit report options" stuff out of
+;; these 3 functions?
+
+(define (gnc:html-make-generic-options-warning
+	 report-title-string report-id)
+  (let ((p (gnc:make-html-text)))
+    (gnc:html-text-append!
+     p
+     (gnc:html-markup-h2 (string-append
+			  report-title-string
+			  ":"))
+     (gnc:html-markup-h2 (_ ""))
+     (gnc:html-markup-p
+      (_ "This report requires you to specify certain report options.")))
+    (if report-id
+	(gnc:html-text-append!
+	 p
+	 (gnc:html-markup-p
+	  (gnc:html-markup-anchor
+	   (gnc:html-build-url gnc:url-type-options
+			       (string-append "report-id="
+					      (sprintf #f "%a" report-id))
+			       #f)
+	   (_ "Edit report options")))))
+    p))
+
+
 (define (gnc:html-make-no-account-warning
 	 report-title-string report-id)
   (let ((p (gnc:make-html-text)))
Index: standard-reports.scm
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/standard-reports.scm,v
retrieving revision 1.14.4.3
retrieving revision 1.14.4.4
diff -Lsrc/report/standard-reports/standard-reports.scm -Lsrc/report/standard-reports/standard-reports.scm -u -r1.14.4.3 -r1.14.4.4
--- src/report/standard-reports/standard-reports.scm
+++ src/report/standard-reports/standard-reports.scm
@@ -75,6 +75,7 @@
 (use-modules (gnucash report general-journal))
 (use-modules (gnucash report general-ledger))
 (use-modules (gnucash report cash-flow))
+(use-modules (gnucash report budget))
 (use-modules (gnucash report category-barchart))
 (use-modules (gnucash report daily-reports))
 (use-modules (gnucash report net-barchart))
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/report/standard-reports/Makefile.am,v
retrieving revision 1.12.4.4
retrieving revision 1.12.4.5
diff -Lsrc/report/standard-reports/Makefile.am -Lsrc/report/standard-reports/Makefile.am -u -r1.12.4.4 -r1.12.4.5
--- src/report/standard-reports/Makefile.am
+++ src/report/standard-reports/Makefile.am
@@ -26,6 +26,7 @@
    average-balance.scm \
    balance-sheet.scm \
    cash-flow.scm \
+   budget.scm \
    category-barchart.scm \
    daily-reports.scm \
    equity-statement.scm \


More information about the gnucash-changes mailing list