gnucash master: Book-Currency Feature Step 3

J. Alex Aycinena alex.aycinena at code.gnucash.org
Sat Jun 27 19:07:57 EDT 2015


Updated	 via  https://github.com/Gnucash/gnucash/commit/5fdf14f8 (commit)
	from  https://github.com/Gnucash/gnucash/commit/06d5d0a2 (commit)



commit 5fdf14f8cbd024a4e7ff8f7800ffd5b44fb5449c
Author: Alex Aycinena <alex.aycinena at gmail.com>
Date:   Sat Jun 27 16:06:56 2015 -0700

    Book-Currency Feature Step 3
    
    Add an option to the File->Properties dialog to select a Currency Accounting Method, and to specify the book-currency and a default gains/loss policy if the 'book-currency' method is selected.
    Revert some changes made in prior commits. Other than storing and retrieving the
    book-currency and policy in book KVPs, the behavior of gnucash has not been
    affected by these changes. The changes made are:
    
         engine/policy.c & .h - define valid policies and their descriptions
             and hints; define functions gnc_get_valid_policy_list and
             gnc_valid_policy
         engine/engine.i - include policy.h; define 'CURRENCY-ACCOUNTING',
             'BOOK-CURRENCY', and 'DEFAULT-GAINS-POLICY' as option names
         engine/test/utest-Split.cpp - revert prior commit that modified test
             function for trading accounts
         engine/test/utest-Transaction.c - revert prior commit that modified test
             function for trading accounts
         libqof/qof/qofbookslots.h - revert prior commit that defined Currency
             Accounting Method; modify definitions of Currency Accounting and Book
             Currency; add definition of default gains policy; keep the previous
             Trading Accounts definition
         libqof/qof/qofbook.cpp & .h - reverted function to determine currency
             accounting method; add function to get book-currency, revert
             previously committed changes to function to determine if book uses
             trading accounts; add function to get gains policy; modify gobject
             properties accordingly
         libqof/qof/test/test-qofbook.c - revert prior modification to test
             function for trading accounts; define tests for book-currency and
             default gains policies
         app-utils/options.scm - define make-currency-accounting-option and
             required support functions
         app-utils/options-util.c & .h - make support functions of
             make-currency-accounting-option available in c code
         app-utils/test/test-options-util.c - include tests for using book-currency
         app-utils/gnc-ui-util.c & .h - define gnc_book_use_book_currency,
             gnc_book_get_book_currency and gnc_book_get_default_gains_policy
             functions
         app-utils/test/test-gnc-ui-util.c - set up tests for new gnc-ui-util
             functions
         app-utils/test/test-app-utils.c - include test-gnc-ui-util.c
         app-utils/test/Makefile.am - include test-gnc-ui-util.c
         app-utils/app-utils.scm - define and export book options for Currency
             Accounting, Book-Currency and Default Gains Policy; export required
             currency-accounting-option support functions
         app-utils/business-prefs.scm - replace the Trading Accounts boolean option
             with a currency-accounting-option and rearrange the order of the
             options
         gnome-utils/dialog-options.c - define functions for set-ui-widget,
             set-ui-value, and get-ui-value for 'currency-accounting' option and
             various other support functions

diff --git a/src/app-utils/app-utils.scm b/src/app-utils/app-utils.scm
index c62e93a..ccd78f9 100644
--- a/src/app-utils/app-utils.scm
+++ b/src/app-utils/app-utils.scm
@@ -114,6 +114,13 @@
 (export gnc:make-color-option)
 (export gnc:make-dateformat-option)
 (export gnc:dateformat-get-format)
+(export gnc:currency-accounting-option-get-curr-doc-string)
+(export gnc:currency-accounting-option-get-default-curr)
+(export gnc:currency-accounting-option-get-policy-doc-string)
+(export gnc:currency-accounting-option-get-default-policy)
+(export gnc:currency-accounting-option-selected-method)
+(export gnc:currency-accounting-option-selected-currency)
+(export gnc:currency-accounting-option-selected-policy)
 
 (export gnc:color->html)
 (export gnc:color-option->html)
@@ -322,10 +329,15 @@
 
 (define gnc:*option-section-accounts* OPTION-SECTION-ACCOUNTS)
 (define gnc:*option-name-trading-accounts* OPTION-NAME-TRADING-ACCOUNTS)
+(define gnc:*option-name-currency-accounting* OPTION-NAME-CURRENCY-ACCOUNTING)
+(define gnc:*option-name-book-currency* OPTION-NAME-BOOK-CURRENCY)
+(define gnc:*option-name-default-gains-policy* OPTION-NAME-DEFAULT-GAINS-POLICY)
 (define gnc:*option-name-auto-readonly-days* OPTION-NAME-AUTO-READONLY-DAYS)
 (define gnc:*option-name-num-field-source* OPTION-NAME-NUM-FIELD-SOURCE)
 
 (export gnc:*option-section-accounts* gnc:*option-name-trading-accounts*
+        gnc:*option-name-currency-accounting*
+        gnc:*option-name-book-currency* gnc:*option-name-default-gains-policy*
         gnc:*option-name-auto-readonly-days* gnc:*option-name-num-field-source*)
 
 (define gnc:*option-section-budgeting* OPTION-SECTION-BUDGETING)
diff --git a/src/app-utils/business-prefs.scm b/src/app-utils/business-prefs.scm
index a49ab43..d37b4dc 100644
--- a/src/app-utils/business-prefs.scm
+++ b/src/app-utils/business-prefs.scm
@@ -127,16 +127,10 @@
 
   ;; Accounts tab
 
-  (reg-option 
-   (gnc:make-simple-boolean-option
-    gnc:*option-section-accounts* gnc:*option-name-trading-accounts*
-    "a" (N_ "Check to have trading accounts used for transactions involving more than one currency or commodity.")
-    #f))
-
   (reg-option
    (gnc:make-number-range-option
 	gnc:*option-section-accounts* gnc:*option-name-auto-readonly-days*
-	"b" (N_ "Choose the number of days after which transactions will be read-only and cannot be edited anymore. This threshold is marked by a red line in the account register windows. If zero, all transactions can be edited and none are read-only.")
+	"a" (N_ "Choose the number of days after which transactions will be read-only and cannot be edited anymore. This threshold is marked by a red line in the account register windows. If zero, all transactions can be edited and none are read-only.")
 	0 ;; default
 	0 ;; lower bound
 	3650 ;; upper bound
@@ -147,9 +141,30 @@
   (reg-option 
    (gnc:make-simple-boolean-option
     gnc:*option-section-accounts* gnc:*option-name-num-field-source*
-    "c" (N_ "Check to have split action field used in registers for 'Num' field in place of transaction number; transaction number shown as 'T-Num' on second line of register. Has corresponding effect on business features, reporting and imports/exports.")
+    "b" (N_ "Check to have split action field used in registers for 'Num' field in place of transaction number; transaction number shown as 'T-Num' on second line of register. Has corresponding effect on business features, reporting and imports/exports.")
     #f))
 
+ (reg-option
+   (gnc:make-currency-accounting-option
+    gnc:*option-section-accounts* gnc:*option-name-currency-accounting*
+    "c"
+    (N_ "Select the currency accounting method to use for transactions involving more than one currency or commodity.")
+    'neither
+    (list
+      (vector 'trading
+              (N_ "Use Trading Accounts")
+              (N_ "Check to have trading accounts used for transactions involving more than one currency or commodity."))
+      (vector 'book-currency
+              (N_ "Use a Book-Currency")
+              (N_ "Check to use a book-currency for transactions involving more than one currency or commodity."))
+      (vector 'neither
+              (N_ "Use neither Trading Accounts nor a Book-Currency")
+              (N_ "Check to use neither trading accounts nor a book-currency for transactions involving more than one currency or commodity.")))
+    (N_ "Select the book-currency which is to be used to track costs of transactions involving currencies or commodities other than the book-currency.")
+    (gnc-default-currency)
+    (N_ "Select the default gains policy; this policy will be used unless over-ridden at the account level.")
+    'fifo))
+
   ;; Budgeting Tab
 
   (reg-option
diff --git a/src/app-utils/gnc-ui-util.c b/src/app-utils/gnc-ui-util.c
index 73f3bd8..72d8c51 100644
--- a/src/app-utils/gnc-ui-util.c
+++ b/src/app-utils/gnc-ui-util.c
@@ -266,6 +266,69 @@ gnc_book_option_num_field_source_change_cb (gboolean num_action)
     gnc_gui_refresh_all ();
 }
 
+/** Returns TRUE if both book-currency and default gain/loss policy KVPs exist
+  * and are valid and trading accounts are not used. */
+gboolean
+gnc_book_use_book_currency (QofBook *book)
+{
+    const gchar *policy;
+    const gchar *currency;
+
+    if (!book) return FALSE;
+
+    policy = qof_book_get_default_gains_policy (book);
+    currency = qof_book_get_book_currency (book);
+
+    /* If either a default gain/loss policy or a book-currency does not exist,
+       book-currency accounting method not valid */
+    if (!policy || !currency)
+       return FALSE;
+
+    /* If both exist, both must be valid */
+    if (!gnc_valid_policy (policy) || !gnc_commodity_table_lookup
+                                        (gnc_commodity_table_get_table
+                                          (gnc_get_current_book()),
+                                            GNC_COMMODITY_NS_CURRENCY,
+                                             currency))
+       return FALSE;
+
+    /* If both exist and are valid, there must be no trading accounts flag */
+    if (qof_book_use_trading_accounts (book))
+       return FALSE;
+
+    return TRUE;
+}
+
+/** Returns pointer to Book Currency name for book or NULL; determines
+  * that both book-currency and default gain/loss policy KVPs exist and that
+  * both are valid, a requirement for the 'book-currency' currency accounting
+  * method to apply. */
+const gchar *
+gnc_book_get_book_currency (QofBook *book)
+{
+    if (!book) return NULL;
+
+    if (gnc_book_use_book_currency (book))
+        return qof_book_get_book_currency (book);
+
+    return NULL;
+}
+
+/** Returns pointer to default gain/loss policy for book or NULL; determines
+  * that both book-currency and default gain/loss policy KVPs exist and that
+  * both are valid, a requirement for the 'book-currency' currency accounting
+  * method to apply. */
+const gchar *
+gnc_book_get_default_gains_policy (QofBook *book)
+{
+    if (!book) return NULL;
+
+    if (gnc_book_use_book_currency (book))
+        return qof_book_get_default_gains_policy (book);
+
+    return NULL;
+}
+
 Account *
 gnc_get_current_root_account (void)
 {
diff --git a/src/app-utils/gnc-ui-util.h b/src/app-utils/gnc-ui-util.h
index 281ffc6..13701ae 100644
--- a/src/app-utils/gnc-ui-util.h
+++ b/src/app-utils/gnc-ui-util.h
@@ -80,6 +80,23 @@ const gchar * gnc_get_current_book_tax_type (void);
   * callbacks when num_field_source book option changes so that
   * registers/reports can update themselves; sets feature flag */
 void gnc_book_option_num_field_source_change_cb (gboolean num_action);
+
+/** Returns TRUE if both book-currency and default gain/loss policy KVPs exist
+  * and are valid and trading accounts are not used */
+gboolean gnc_book_use_book_currency (QofBook *book);
+
+/** Returns pointer to Book Currency name for book or NULL; determines
+  * that both book-currency and default gain/loss policy KVPs exist and that
+  * both are valid, a requirement for the 'book-currency' currency accounting
+  * method to apply. */
+const gchar * gnc_book_get_book_currency (QofBook *book);
+
+/** Returns pointer to default gain/loss policy for book or NULL; determines
+  * that both book-currency and default gain/loss policy KVPs exist and that
+  * both are valid, a requirement for the 'book-currency' currency accounting
+  * method to apply. */
+const gchar * gnc_book_get_default_gains_policy (QofBook *book);
+
 Account * gnc_get_current_root_account (void);
 gnc_commodity_table * gnc_get_current_commodities (void);
 
diff --git a/src/app-utils/option-util.c b/src/app-utils/option-util.c
index a1f03d6..829749e 100644
--- a/src/app-utils/option-util.c
+++ b/src/app-utils/option-util.c
@@ -31,7 +31,6 @@
 
 #include "Account.h"
 #include "option-util.h"
-#include "engine-helpers-guile.h"
 #include "glib-helpers.h"
 #include "gnc-guile-utils.h"
 #include "qof.h"
@@ -109,6 +108,13 @@ struct _Getters
     SCM date_option_value_type;
     SCM date_option_value_absolute;
     SCM date_option_value_relative;
+    SCM currency_accounting_option_currency_doc_string;
+    SCM currency_accounting_option_default_currency;
+    SCM currency_accounting_option_policy_doc_string;
+    SCM currency_accounting_option_default_policy;
+    SCM currency_accounting_option_method;
+    SCM currency_accounting_option_book_currency;
+    SCM currency_accounting_option_selected_default_policy;
 };
 
 
@@ -577,6 +583,20 @@ initialize_getters(void)
         scm_c_eval_string("gnc:date-option-absolute-time");
     getters.date_option_value_relative =
         scm_c_eval_string("gnc:date-option-relative-time");
+    getters.currency_accounting_option_currency_doc_string =
+        scm_c_eval_string("gnc:currency-accounting-option-get-curr-doc-string");
+    getters.currency_accounting_option_default_currency =
+        scm_c_eval_string("gnc:currency-accounting-option-get-default-curr");
+    getters.currency_accounting_option_policy_doc_string =
+        scm_c_eval_string("gnc:currency-accounting-option-get-policy-doc-string");
+    getters.currency_accounting_option_default_policy =
+        scm_c_eval_string("gnc:currency-accounting-option-get-default-policy");
+    getters.currency_accounting_option_method =
+        scm_c_eval_string("gnc:currency-accounting-option-selected-method");
+    getters.currency_accounting_option_book_currency =
+        scm_c_eval_string("gnc:currency-accounting-option-selected-currency");
+    getters.currency_accounting_option_selected_default_policy =
+        scm_c_eval_string("gnc:currency-accounting-option-selected-policy");
 
     getters_initialized = TRUE;
 }
@@ -653,8 +673,8 @@ gnc_option_sort_tag(GNCOption *option)
 
 /********************************************************************\
  * gnc_option_documentation                                         *
- *   returns the malloc'ed sort tag of the option, or NULL          *
- *   if it can't be retrieved.                                      *
+ *   returns the malloc'ed documentation string of the option, or   *
+ *   NULL if it can't be retrieved.                                 *
  *                                                                  *
  * Args: option - the GNCOption                                     *
  * Returns: malloc'ed char * or NULL                                *
@@ -2634,6 +2654,133 @@ gnc_date_option_value_get_relative (SCM option_value)
     return scm_call_1 (getters.date_option_value_relative, option_value);
 }
 
+/********************************************************************\
+ * gnc_currency_accounting_option_currency_documentation            *
+ *   returns the malloc'ed documentation string for currency        *
+ *   selector of the currency-accounting option, or NULL if it      *
+ *   can't be retrieved.                                            *
+ *                                                                  *
+ * Args: option - the GNCOption                                     *
+ * Returns: malloc'ed char * or NULL                                *
+\********************************************************************/
+char *
+gnc_currency_accounting_option_currency_documentation(GNCOption *option)
+{
+    initialize_getters();
+
+    return gnc_scm_call_1_to_string
+              (getters.currency_accounting_option_currency_doc_string,
+                                     option->guile_option);
+}
+
+
+/********************************************************************\
+ * gnc_currency_accounting_option_get_default_currency              *
+ *   returns the SCM value for the currency-accounting option       *
+ *   default currency.                                              *
+ *                                                                  *
+ * Args: option - the GNCOption                                     *
+ * Returns: SCM value                                               *
+\********************************************************************/
+SCM
+gnc_currency_accounting_option_get_default_currency(GNCOption *option)
+{
+    initialize_getters();
+
+    return scm_call_1
+              (getters.currency_accounting_option_default_currency,
+                                        option->guile_option);
+}
+
+
+/********************************************************************\
+ * gnc_currency_accounting_option_policy_documentation              *
+ *   returns the malloc'ed documentation string for policy          *
+ *   selector of the currency-accounting option, or NULL if it      *
+ *   can't be retrieved.                                            *
+ *                                                                  *
+ * Args: option - the GNCOption                                     *
+ * Returns: malloc'ed char * or NULL                                *
+\********************************************************************/
+char *
+gnc_currency_accounting_option_policy_documentation(GNCOption *option)
+{
+    initialize_getters();
+
+    return gnc_scm_call_1_to_string
+              (getters.currency_accounting_option_policy_doc_string,
+                                     option->guile_option);
+}
+
+
+/********************************************************************\
+ * gnc_currency_accounting_option_get_default_policy                *
+ *   returns the SCM value for the currency-accounting option       *
+ *   default policy.                                                *
+ *                                                                  *
+ * Args: option - the GNCOption                                     *
+ * Returns: SCM value                                               *
+\********************************************************************/
+SCM
+gnc_currency_accounting_option_get_default_policy(GNCOption *option)
+{
+    initialize_getters();
+
+    return scm_call_1
+              (getters.currency_accounting_option_default_policy,
+                                        option->guile_option);
+}
+
+
+/*******************************************************************\
+ * gnc_currency_accounting_option_value_get_method                 *
+ *   get the currency accounting method of the option as a symbol  *
+ *                                                                 *
+ * Args: option_value - option value to get method of              *
+ * Return: SCM value                                               *
+\*******************************************************************/
+SCM
+gnc_currency_accounting_option_value_get_method (SCM option_value)
+{
+    initialize_getters();
+
+    return scm_call_1 (getters.currency_accounting_option_method, option_value);
+}
+
+/*******************************************************************\
+ * gnc_currency_accounting_option_value_get_book_currency          *
+ *   get the book-currency if that is the currency accounting      *
+ *   method of the option as a symbol                              *
+ *                                                                 *
+ * Args: option_value - option value to get method of              *
+ * Return: SCM value                                               *
+\*******************************************************************/
+SCM
+gnc_currency_accounting_option_value_get_book_currency (SCM option_value)
+{
+    initialize_getters();
+
+    return scm_call_1 (getters.currency_accounting_option_book_currency, option_value);
+}
+
+/*******************************************************************\
+ * gnc_currency_accounting_option_value_get_default_policy         *
+ *   get the default policy if book-currency is the currency       *
+ *   accounting  method of the option as a symbol                  *
+ *                                                                 *
+ * Args: option_value - option value to get method of              *
+ * Return: SCM value                                               *
+\*******************************************************************/
+SCM
+gnc_currency_accounting_option_value_get_default_policy (SCM option_value)
+{
+    initialize_getters();
+
+    return scm_call_1
+        (getters.currency_accounting_option_selected_default_policy,
+          option_value);
+}
+
 /*******************************************************************\
  * gnc_option_db_set_option_selectable_by_name                     *
  *   set the sensitivity of the option widget                      *
diff --git a/src/app-utils/option-util.h b/src/app-utils/option-util.h
index b3b29b9..5b16c7d 100644
--- a/src/app-utils/option-util.h
+++ b/src/app-utils/option-util.h
@@ -29,6 +29,7 @@
 #include "guile-mappings.h"
 
 #include "gnc-commodity.h"
+#include "engine-helpers-guile.h"
 #include "qof.h"
 
 typedef struct gnc_option GNCOption;
@@ -251,6 +252,14 @@ char * gnc_date_option_value_get_type (SCM option_value);
 Timespec gnc_date_option_value_get_absolute (SCM option_value);
 SCM gnc_date_option_value_get_relative (SCM option_value);
 
+char * gnc_currency_accounting_option_currency_documentation(GNCOption *option);
+SCM gnc_currency_accounting_option_get_default_currency(GNCOption *option);
+char * gnc_currency_accounting_option_policy_documentation(GNCOption *option);
+SCM gnc_currency_accounting_option_get_default_policy(GNCOption *option);
+SCM gnc_currency_accounting_option_value_get_method (SCM option_value);
+SCM gnc_currency_accounting_option_value_get_book_currency (SCM option_value);
+SCM gnc_currency_accounting_option_value_get_default_policy (SCM option_value);
+
 void gnc_option_db_set_option_selectable_by_name(SCM guile_options,
         const char *section,
         const char *name,
diff --git a/src/app-utils/options.scm b/src/app-utils/options.scm
index 1019dfd..1ed4dda 100644
--- a/src/app-utils/options.scm
+++ b/src/app-utils/options.scm
@@ -1313,6 +1313,217 @@
 (define (gnc:dateformat-get-format v)
   (cadddr v))
 
+(define (gnc:make-currency-accounting-option
+         section
+         name
+         sort-tag
+         radiobutton-documentation-string
+         default-radiobutton-value
+         ok-radiobutton-values
+         book-currency-documentation-string
+         default-book-currency-value
+         default-cap-gains-policy-documentation-string
+         default-cap-gains-policy-value
+        )
+  (define (legal-val val p-vals)
+    (cond ((null? p-vals) #f)
+          ((not (symbol? val)) #f)
+          ((eq? val (vector-ref (car p-vals) 0)) #t)
+          (else (legal-val val (cdr p-vals)))))
+
+  (define (currency-lookup currency-string)
+    (if (string? currency-string)
+        (gnc-commodity-table-lookup
+         (gnc-commodity-table-get-table (gnc-get-current-book))
+         GNC_COMMODITY_NS_CURRENCY currency-string)
+        #f))
+
+  (define (currency? val)
+    (gnc-commodity-is-currency (currency-lookup val)))
+
+  (define (vector-strings p-vals)
+    (if (null? p-vals)
+        '()
+        (cons (vector-ref (car p-vals) 1)
+              (cons (vector-ref (car p-vals) 2)
+                    (vector-strings (cdr p-vals))))))
+
+  (define (currency->scm currency)
+    (if (string? currency)
+        currency
+        (gnc-commodity-get-mnemonic currency)))
+
+  (define (scm->currency currency)
+    (currency-lookup currency))
+
+  (let* ((value (if (eq? 'book-currency default-radiobutton-value)
+                    (cons default-radiobutton-value
+                          (cons default-book-currency-value
+                                (cons default-cap-gains-policy-value '())))
+                    (cons default-radiobutton-value '())))
+         (value->string (lambda ()
+                          (string-append "'" (gnc:value->string
+                                               (car value)))))
+         (trading-accounts-path (list (car gnc:*kvp-option-path*)
+                                      gnc:*option-section-accounts*
+                                      gnc:*option-name-trading-accounts*))
+         (book-currency-path (list (car gnc:*kvp-option-path*)
+                                   gnc:*option-section-accounts*
+                                   gnc:*option-name-book-currency*))
+         (gains-policy-path (list (car gnc:*kvp-option-path*)
+                                  gnc:*option-section-accounts*
+                                  gnc:*option-name-default-gains-policy*)))
+    (gnc:make-option
+     section name sort-tag 'currency-accounting
+     radiobutton-documentation-string
+     (lambda () value)
+     (lambda (x)
+       (if (legal-val (car x) ok-radiobutton-values)
+           (set! value x)
+           (gnc:error "Illegal Radiobutton option set")))
+     (lambda () (if (eq? 'book-currency default-radiobutton-value)
+                    (cons default-radiobutton-value
+                          (cons default-book-currency-value
+                                (cons default-cap-gains-policy-value '())))
+                    (cons default-radiobutton-value '())))
+     (gnc:restore-form-generator value->string)
+     (lambda (f p)
+       (if (eq? 'book-currency (car value))
+           (begin
+             ;; Currency = selected currency
+             (kvp-frame-set-slot-path-gslist
+                f
+                (currency->scm (cadr value))
+                book-currency-path)
+             ;; Default Gains Policy = selected policy
+             (kvp-frame-set-slot-path-gslist
+                f
+                (symbol->string (caddr value))
+                gains-policy-path))
+           (if (eq? 'trading (car value))
+               ;; Use Trading Accounts = "t"
+               (kvp-frame-set-slot-path-gslist f "t" trading-accounts-path))))
+     (lambda (f p)
+       (let* ((trading-option-path-kvp?
+                       (kvp-frame-get-slot-path-gslist
+                        f trading-accounts-path))
+              (trading? (if (and trading-option-path-kvp?
+                                 (string=? "t" trading-option-path-kvp?))
+                            #t
+                            #f))
+              (book-currency #f)
+              (cap-gains-policy #f)
+              (v (if trading?
+                     'trading
+                     (let* ((book-currency-option-path-kvp?
+                                 (kvp-frame-get-slot-path-gslist
+                                     f book-currency-path))
+                            (gains-policy-option-path-kvp?
+                                 (kvp-frame-get-slot-path-gslist
+                                     f gains-policy-path))
+                            (book-currency?
+                               (if (and book-currency-option-path-kvp?
+                                        gains-policy-option-path-kvp?
+                                        (string?
+                                           book-currency-option-path-kvp?)
+                                        (string?
+                                           gains-policy-option-path-kvp?)
+                                        (if book-currency-option-path-kvp?
+                                            (currency?
+                                              book-currency-option-path-kvp?))
+                                        (if gains-policy-option-path-kvp?
+                                            (gnc-valid-policy
+                                              gains-policy-option-path-kvp?)))
+                                   (begin
+                                     (set! book-currency
+                                               book-currency-option-path-kvp?)
+                                     (set! cap-gains-policy
+                                               gains-policy-option-path-kvp?)
+                                     #t)
+                                   #f)))
+                           (if book-currency?
+                               'book-currency
+                               'neither)))))
+         (if (and v (symbol? v) (legal-val v ok-radiobutton-values))
+             (set! value (cons v (if (eq? 'book-currency v)
+                                     (list (scm->currency book-currency)
+                                           (string->symbol cap-gains-policy))
+                                     '())))
+             (set! value (cons 'neither '())))))
+     (lambda (x)
+       (if (list? x)
+           (if (legal-val (car x) ok-radiobutton-values)
+               (if (eq? 'book-currency (car x))
+                   (if (currency? (currency->scm (cadr x)))
+                       (if (gnc-valid-policy (symbol->string (caddr x)))
+                           (list #t x)
+                           (list #f "cap-gains-policy-option: illegal value"))
+                       (list #f "currency-option: illegal value"))
+                   (list #t x))
+               (list #f "radiobutton-option: illegal choice"))
+           (list #f "value not a list")))
+     (vector book-currency-documentation-string
+             default-book-currency-value
+             default-cap-gains-policy-documentation-string
+             default-cap-gains-policy-value)
+     (vector (lambda () (length ok-radiobutton-values))
+             (lambda (x) (vector-ref (list-ref ok-radiobutton-values x) 0))
+             (lambda (x) (vector-ref (list-ref ok-radiobutton-values x) 1))
+             (lambda (x) (vector-ref (list-ref ok-radiobutton-values x) 2))
+             (lambda (x)
+               (gnc:multichoice-list-lookup ok-radiobutton-values x)))
+     (lambda () (vector-strings ok-radiobutton-values))
+     #f)))
+
+(define (gnc:get-currency-accounting-option-data-curr-doc-string option-data)
+  (vector-ref option-data 0))
+
+(define (gnc:get-currency-accounting-option-data-default-curr option-data)
+  (vector-ref option-data 1))
+
+(define (gnc:get-currency-accounting-option-data-policy-doc-string option-data)
+  (vector-ref option-data 2))
+
+(define (gnc:get-currency-accounting-option-data-policy-default option-data)
+  (vector-ref option-data 3))
+
+(define (gnc:currency-accounting-option-get-curr-doc-string option)
+  (if (eq? (gnc:option-type option) 'currency-accounting)
+      (gnc:get-currency-accounting-option-data-curr-doc-string
+        (gnc:option-data option))
+      (gnc:error "Not a currency accounting option")))
+
+(define (gnc:currency-accounting-option-get-default-curr option)
+  (if (eq? (gnc:option-type option) 'currency-accounting)
+      (gnc:get-currency-accounting-option-data-default-curr
+        (gnc:option-data option))
+      (gnc:error "Not a currency accounting option")))
+
+(define (gnc:currency-accounting-option-get-policy-doc-string option)
+  (if (eq? (gnc:option-type option) 'currency-accounting)
+      (gnc:get-currency-accounting-option-data-policy-doc-string
+        (gnc:option-data option))
+      (gnc:error "Not a currency accounting option")))
+
+(define (gnc:currency-accounting-option-get-default-policy option)
+  (if (eq? (gnc:option-type option) 'currency-accounting)
+      (gnc:get-currency-accounting-option-data-policy-default
+        (gnc:option-data option))
+      (gnc:error "Not a currency accounting option")))
+
+(define (gnc:currency-accounting-option-selected-method option-value)
+  (car option-value))
+
+(define (gnc:currency-accounting-option-selected-currency option-value)
+  (if (eq? (car option-value) 'book-currency)
+      (cadr option-value)
+      #f))
+
+(define (gnc:currency-accounting-option-selected-policy option-value)
+  (if (eq? (car option-value) 'book-currency)
+      (caddr option-value)
+      #f))
+
 ;; Create a new options database
 (define (gnc:new-options)
   (define option-hash (make-hash-table 23))
diff --git a/src/app-utils/test/Makefile.am b/src/app-utils/test/Makefile.am
index ab7822b..4000490 100644
--- a/src/app-utils/test/Makefile.am
+++ b/src/app-utils/test/Makefile.am
@@ -67,7 +67,9 @@ AM_CPPFLAGS = \
 
 test_app_utils_SOURCES = \
 	test-app-utils.c \
-	test-option-util.c
+	test-option-util.c \
+	test-gnc-ui-util.c
+
 
 test_app_utils_CFLAGS = \
 	${DEFAULT_INCLUDES} \
diff --git a/src/app-utils/test/test-app-utils.c b/src/app-utils/test/test-app-utils.c
index 123494e..03ea193 100644
--- a/src/app-utils/test/test-app-utils.c
+++ b/src/app-utils/test/test-app-utils.c
@@ -27,6 +27,7 @@
 #include <gnc-module.h>
 
 extern void test_suite_option_util (void);
+extern void test_suite_gnc_ui_util (void);
 
 static void
 guile_main (void *closure, int argc, char **argv)
@@ -37,6 +38,7 @@ guile_main (void *closure, int argc, char **argv)
     mod = gnc_module_load ("gnucash/app-utils", 0);
 
     test_suite_option_util ();
+    test_suite_gnc_ui_util ();
     retval = g_test_run ();
 
     exit (retval);
diff --git a/src/app-utils/test/test-gnc-ui-util.c b/src/app-utils/test/test-gnc-ui-util.c
new file mode 100644
index 0000000..a6a84cb
--- /dev/null
+++ b/src/app-utils/test/test-gnc-ui-util.c
@@ -0,0 +1,216 @@
+/********************************************************************
+ * test-gnc-ui-util.c: GLib g_test test suite for gnc-ui-util.c.	    *
+ * Copyright 2015 Alex Aycinena <alex.aycinena at gmail.com>		    *
+ *                                                                  *
+ * This program is free software; you can redistribute it and/or    *
+ * modify it under the terms of the GNU General Public License as   *
+ * published by the Free Software Foundation; either version 2 of   *
+ * the License, or (at your option) any later version.              *
+ *                                                                  *
+ * This program is distributed in the hope that it will be useful,  *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
+ * GNU General Public License for more details.                     *
+ *                                                                  *
+ * You should have received a copy of the GNU General Public License*
+ * along with this program; if not, you can retrieve it from        *
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html            *
+ * or contact:                                                      *
+ *                                                                  *
+ * Free Software Foundation           Voice:  +1-617-542-5942       *
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org                   *
+ ********************************************************************/
+
+#include <config.h>
+#include <glib.h>
+#include <unittest-support.h>
+#include <qof.h>
+/*#include <qofbookslots.h> */
+
+#include "../gnc-ui-util.h"
+
+static const gchar *suitename = "/app-utils/gnc-ui-util";
+void test_suite_gnc_ui_util (void);
+
+typedef struct
+{
+    QofBook *book;
+    GSList *hdlrs;
+} Fixture;
+
+/* Expose a mostly-private QofInstance function to load options into
+ * the Book.
+ */
+/*extern KvpFrame *qof_instance_get_slots (const QofInstance*); */
+
+static void
+setup (Fixture *fixture, gconstpointer pData)
+{
+    fixture->book = qof_book_new ();
+    fixture->hdlrs = NULL;
+}
+
+static void
+teardown (Fixture *fixture, gconstpointer pData)
+{
+    qof_book_destroy (fixture->book);
+    g_slist_free_full (fixture->hdlrs, test_free_log_handler);
+    test_clear_error_list();
+}
+
+static void
+test_book_use_book_currency( Fixture *fixture, gconstpointer pData )
+{
+    const gchar *cur;
+    const gchar *pol;
+
+    g_test_message( "Testing with no currency accounting method selected" );
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+
+    g_test_message( "Testing with trading accounts set to true - t" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "trading-accts", "t",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with valid book-currency but default-gains-policy set to nonsense" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "USD",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "random",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with valid default-gains-policy but book-currency set to nonsense" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "myMoney",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "fifo",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with book-currency and default-gains-policy set to nonsense" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "myMoney",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "random",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with book-currency set and no default-gains-policy" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "USD",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with default-gains-policy set and no book-currency" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "fifo",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with book-currency and default-gains-policy set to valid values and with trading accounts set to true - t" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "trading-accts", "t",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "USD",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "fifo",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    g_assert( !gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
+
+    g_test_message( "Testing with book-currency and default-gains-policy set to valid values and no trading accounts flag" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "book-currency", "USD",
+		      NULL);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "fifo",
+		      NULL);
+    cur = gnc_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , "USD" );
+    pol = gnc_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , "fifo" );
+    g_assert( gnc_book_use_book_currency ( fixture-> book ));
+    qof_book_commit_edit (fixture->book);
+}
+
+void
+test_suite_gnc_ui_util (void)
+{
+    GNC_TEST_ADD( suitename, "use book-currency", Fixture, NULL, setup, test_book_use_book_currency, teardown );
+
+}
diff --git a/src/app-utils/test/test-option-util.c b/src/app-utils/test/test-option-util.c
index 8fef4c0..9a0a188 100644
--- a/src/app-utils/test/test-option-util.c
+++ b/src/app-utils/test/test-option-util.c
@@ -60,10 +60,10 @@ setup_kvp (Fixture *fixture, gconstpointer pData)
     slots = qof_instance_get_slots (QOF_INSTANCE (book));
     qof_begin_edit (QOF_INSTANCE (book));
     qof_instance_set (QOF_INSTANCE (book),
-		      "trading-accts", "t",
-		      "split-action-num-field", "t",
-		      "autoreadonly-days", (double)21,
-		      NULL);
+                     "trading-accts", "t",
+                     "split-action-num-field", "t",
+                     "autoreadonly-days", (double)21,
+                     NULL);
 
     kvp_frame_set_string (slots, "options/Business/Company Name",
 			  "Bogus Company");
@@ -71,6 +71,20 @@ setup_kvp (Fixture *fixture, gconstpointer pData)
 }
 
 static void
+setup_kvp_book_currency (Fixture *fixture, gconstpointer pData)
+{
+    QofBook *book;
+    setup (fixture, pData);
+    book = fixture->book;
+    qof_begin_edit (QOF_INSTANCE (book));
+    qof_instance_set (QOF_INSTANCE (book),
+                     "book-currency", "GTQ",
+                     "default-gains-policy", "fifo",
+                     NULL);
+    qof_commit_edit (QOF_INSTANCE (book));
+}
+
+static void
 teardown (Fixture *fixture, gconstpointer pData)
 {
     qof_book_destroy (fixture->book);
@@ -81,12 +95,31 @@ teardown (Fixture *fixture, gconstpointer pData)
 static void
 test_option_load_from_kvp (Fixture *fixture, gconstpointer pData)
 {
+    gchar *str = NULL;
+    SCM symbol_value;
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
 
     qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
-    g_assert (gnc_option_db_lookup_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
- OPTION_NAME_TRADING_ACCOUNTS, FALSE));
+    symbol_value = gnc_currency_accounting_option_value_get_method (
+                        gnc_option_db_lookup_option (odb,
+                            OPTION_SECTION_ACCOUNTS,
+                            OPTION_NAME_CURRENCY_ACCOUNTING,
+                            SCM_BOOL_F));
+    if (scm_is_symbol(symbol_value))
+    {
+        SCM string_value = scm_symbol_to_string (symbol_value);
+        if (scm_is_string (string_value))
+        {
+            str = scm_to_utf8_string (string_value);
+        }
+    }
+    g_assert_cmpstr (str, ==, "trading");
+    if (str)
+        g_free (str);
+    g_assert (gnc_option_db_lookup_boolean_option (odb,
+                        OPTION_SECTION_ACCOUNTS,
+                        OPTION_NAME_NUM_FIELD_SOURCE, FALSE));
     g_assert_cmpstr (gnc_option_db_lookup_string_option (odb, "Business", "Company Name", FALSE), ==, "Bogus Company");
     g_assert_cmpfloat (gnc_option_db_lookup_number_option (odb, OPTION_SECTION_ACCOUNTS, OPTION_NAME_AUTO_READONLY_DAYS, FALSE), ==, 21);
 
@@ -94,15 +127,77 @@ test_option_load_from_kvp (Fixture *fixture, gconstpointer pData)
 }
 
 static void
+test_option_load_from_kvp_book_currency (Fixture *fixture, gconstpointer pData)
+{
+    gchar *str = NULL;
+    SCM symbol_value;
+    const gchar *curr = NULL;
+    SCM curr_scm;
+    gnc_commodity *commodity;
+    QofBook *book = fixture->book;
+    GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
+
+    qof_book_load_options (book, gnc_option_db_load_from_kvp, odb);
+    symbol_value = gnc_currency_accounting_option_value_get_method (
+                        gnc_option_db_lookup_option (odb,
+                            OPTION_SECTION_ACCOUNTS,
+                            OPTION_NAME_CURRENCY_ACCOUNTING,
+                            SCM_BOOL_F));
+    if (scm_is_symbol(symbol_value))
+    {
+        SCM string_value = scm_symbol_to_string (symbol_value);
+        if (scm_is_string (string_value))
+        {
+            str = scm_to_utf8_string (string_value);
+        }
+    }
+    g_assert_cmpstr (str, ==, "book-currency");
+    if (str)
+        g_free (str);
+    symbol_value = gnc_currency_accounting_option_value_get_default_policy (
+                        gnc_option_db_lookup_option (odb,
+                            OPTION_SECTION_ACCOUNTS,
+                            OPTION_NAME_CURRENCY_ACCOUNTING,
+                            SCM_BOOL_F));
+    if (scm_is_symbol(symbol_value))
+    {
+        SCM string_value = scm_symbol_to_string (symbol_value);
+        if (scm_is_string (string_value))
+        {
+            str = scm_to_utf8_string (string_value);
+        }
+    }
+    g_assert_cmpstr (str, ==, "fifo");
+    if (str)
+        g_free (str);
+    curr_scm = gnc_currency_accounting_option_value_get_book_currency(
+                        gnc_option_db_lookup_option(odb,
+                            OPTION_SECTION_ACCOUNTS,
+                            OPTION_NAME_CURRENCY_ACCOUNTING,
+                            SCM_BOOL_F));
+    commodity = gnc_scm_to_commodity (curr_scm);
+    if (commodity)
+    {
+        curr = gnc_commodity_get_mnemonic (commodity);
+    }
+    g_assert_cmpstr (curr, ==, "GTQ");
+
+    gnc_option_db_destroy (odb);
+}
+
+static void
 test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
 {
     QofBook *book = fixture->book;
     GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
     KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
 
+    g_assert (gnc_option_db_set_option (odb, OPTION_SECTION_ACCOUNTS,
+						OPTION_NAME_CURRENCY_ACCOUNTING,
+						scm_cons (scm_from_locale_symbol("trading"), SCM_EOL)));
     g_assert (gnc_option_db_set_boolean_option (odb, OPTION_SECTION_ACCOUNTS,
-						OPTION_NAME_TRADING_ACCOUNTS,
-						TRUE));
+                                               OPTION_NAME_NUM_FIELD_SOURCE,
+                                               TRUE));
     g_assert (gnc_option_db_set_string_option (odb, "Business", "Company Name",
 					       "Bogus Company"));
     g_assert (gnc_option_db_set_number_option (odb, OPTION_SECTION_ACCOUNTS,
@@ -110,17 +205,38 @@ test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
 					       17));
     qof_book_save_options (book, gnc_option_db_save_to_kvp, odb, TRUE);
     g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Trading Accounts"), == , "t");
+    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Use Split Action Field for Number"), == , "t");
     g_assert_cmpstr (kvp_frame_get_string (slots, "options/Business/Company Name"), ==, "Bogus Company");
     g_assert_cmpfloat (kvp_frame_get_double (slots, "options/Accounts/Day Threshold for Read-Only Transactions (red line)"), ==, 17);
 
     gnc_option_db_destroy (odb);
 }
 
+static void
+test_option_save_to_kvp_book_currency (Fixture *fixture, gconstpointer pData)
+{
+    QofBook *book = fixture->book;
+    GNCOptionDB *odb = gnc_option_db_new_for_type (QOF_ID_BOOK);
+    KvpFrame *slots = qof_instance_get_slots (QOF_INSTANCE (book));
+
+    g_assert (gnc_option_db_set_option (odb, OPTION_SECTION_ACCOUNTS,
+						OPTION_NAME_CURRENCY_ACCOUNTING,
+						scm_cons (scm_from_locale_symbol("book-currency"),
+                        scm_cons (scm_from_utf8_string("GTQ"),
+                        scm_cons (scm_from_locale_symbol("fifo"), SCM_EOL)))));
+    qof_book_save_options (book, gnc_option_db_save_to_kvp, odb, TRUE);
+    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Book Currency"), == , "GTQ");
+    g_assert_cmpstr (kvp_frame_get_string (slots,  "options/Accounts/Default Gains Policy"), == , "fifo");
+
+    gnc_option_db_destroy (odb);
+}
 
 void
 test_suite_option_util (void)
 {
     GNC_TEST_ADD (suitename, "Option DB Load from KVP", Fixture, NULL, setup_kvp, test_option_load_from_kvp, teardown);
+    GNC_TEST_ADD (suitename, "Option DB Load from KVP - Book Currency", Fixture, NULL, setup_kvp_book_currency, test_option_load_from_kvp_book_currency, teardown);
     GNC_TEST_ADD (suitename, "Option DB Save to KVP", Fixture, NULL, setup, test_option_save_to_kvp, teardown);
+    GNC_TEST_ADD (suitename, "Option DB Save to KVP - Book Currency", Fixture, NULL, setup, test_option_save_to_kvp_book_currency, teardown);
 
 }
diff --git a/src/engine/engine.i b/src/engine/engine.i
index 41ce57c..99d1c5a 100644
--- a/src/engine/engine.i
+++ b/src/engine/engine.i
@@ -14,6 +14,7 @@
 #include "gnc-hooks-scm.h"
 #include "engine-helpers.h"
 #include "engine-helpers-guile.h"
+#include "policy.h"
 #include "SX-book.h"
 #include "kvp-scm.h"
 #include "glib-helpers.h"
@@ -136,6 +137,7 @@ functions. */
 %typemap(in) char * num;
 %typemap(in) char * action;
 
+%include <policy.h>
 %include <gnc-pricedb.h>
 
 QofSession * qof_session_new (void);
@@ -348,6 +350,9 @@ KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, GSList *key_path);
 
     SET_ENUM("OPTION-SECTION-ACCOUNTS");
     SET_ENUM("OPTION-NAME-TRADING-ACCOUNTS");
+    SET_ENUM("OPTION-NAME-CURRENCY-ACCOUNTING");
+    SET_ENUM("OPTION-NAME-BOOK-CURRENCY");
+    SET_ENUM("OPTION-NAME-DEFAULT-GAINS-POLICY");
     SET_ENUM("OPTION-NAME-AUTO-READONLY-DAYS");
     SET_ENUM("OPTION-NAME-NUM-FIELD-SOURCE");
 
diff --git a/src/engine/policy.c b/src/engine/policy.c
index fbb382c..38da205 100644
--- a/src/engine/policy.c
+++ b/src/engine/policy.c
@@ -42,8 +42,85 @@
 #include "policy.h"
 #include "policy-p.h"
 
+#ifndef SWIG             /* swig doesn't see N_() as a string constant */
+#include <glib/gi18n.h>
+#else
+#define N_(string) string
+#endif
+
+#define FIFO_POLICY            "fifo"
+#define FIFO_POLICY_DESC    N_("First In, First Out")
+#define FIFO_POLICY_HINT    N_("Use oldest lots first.")
+#define LIFO_POLICY            "lifo"
+#define LIFO_POLICY_DESC    N_("Last In, First Out")
+#define LIFO_POLICY_HINT    N_("Use newest lots first.")
+#define AVERAGE_POLICY         "average"
+#define AVERAGE_POLICY_DESC N_("Average")
+#define AVERAGE_POLICY_HINT N_("Average cost of open lots.")
+#define MANUAL_POLICY          "manual"
+#define MANUAL_POLICY_DESC  N_("Manual")
+#define MANUAL_POLICY_HINT  N_("Manually select lots.")
+
 //static QofLogModule log_module = GNC_MOD_LOT;
 
+GList *
+gnc_get_valid_policy_list (void)
+{
+    GList *return_list = NULL;
+    GList *policy_list1 = NULL;
+    GList *policy_list2 = NULL;
+    GList *policy_list3 = NULL;
+    GList *policy_list4 = NULL;
+
+    policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY_HINT);
+    policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY_DESC);
+    policy_list1 = g_list_prepend (policy_list1, MANUAL_POLICY);
+    return_list = g_list_prepend (return_list, policy_list1);
+    policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY_HINT);
+    policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY_DESC);
+    policy_list2 = g_list_prepend (policy_list2, AVERAGE_POLICY);
+    return_list = g_list_prepend (return_list, policy_list2);
+    policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY_HINT);
+    policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY_DESC);
+    policy_list3 = g_list_prepend (policy_list3, LIFO_POLICY);
+    return_list = g_list_prepend (return_list, policy_list3);
+    policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY_HINT);
+    policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY_DESC);
+    policy_list4 = g_list_prepend (policy_list4, FIFO_POLICY);
+    return_list = g_list_prepend (return_list, policy_list4);
+
+    return return_list;
+}
+
+gboolean
+gnc_valid_policy (const gchar *name)
+{
+    GList *list_of_policies = NULL;
+    gboolean ret_val = FALSE;
+
+    if (!name)
+        return ret_val;
+
+    list_of_policies = gnc_get_valid_policy_list();
+    if (!list_of_policies)
+    {
+        return ret_val;
+    }
+    else
+    {
+        GList *l = NULL;
+        for (l = list_of_policies; l != NULL; l = l->next)
+        {
+            GList *policy_list = l->data;
+            if (g_strcmp0(policy_list->data, name) == 0)
+                ret_val = TRUE;
+            g_list_free(policy_list);
+        }
+        g_list_free(list_of_policies);
+    return ret_val;
+    }
+}
+
 static Split *
 DirectionPolicyGetSplit (GNCPolicy *pcy, GNCLot *lot, short reverse)
 {
diff --git a/src/engine/policy.h b/src/engine/policy.h
index f59acac..5c4ad8c 100644
--- a/src/engine/policy.h
+++ b/src/engine/policy.h
@@ -39,6 +39,23 @@
 
 typedef struct gncpolicy_s GNCPolicy;
 
+/** Valid Policy List
+ *  Provides a glist of glists for implemented policies. For each implemented
+ *  policy, this glist contains: name, description, hint, as follows:
+ *    glist(
+ *       glist("fifo", "First In First Out", "Use oldest lots first.")
+ *       glist("lifo", "Last In First Out", "Use newest lots first.")
+ *       etc.
+ *         )
+ *  Both levels of lists must be freed with g_list_free().
+ */
+GList * gnc_get_valid_policy_list (void);
+
+/** Valid Policy
+ *  Uses the Valid Policy List to determine if a policy name is valid.
+ */
+gboolean gnc_valid_policy (const gchar *name);
+
 /** First-in, First-out Policy
  *  This policy will create FIFO Lots.  FIFO Lots have the following
  *  properties:
diff --git a/src/engine/test/utest-Split.cpp b/src/engine/test/utest-Split.cpp
index 733e5fb..4e3425d 100644
--- a/src/engine/test/utest-Split.cpp
+++ b/src/engine/test/utest-Split.cpp
@@ -1808,7 +1808,7 @@ test_xaccSplitGetOtherSplit (Fixture *fixture, gconstpointer pData)
     g_assert (kvp_frame_get_slot (split1->inst.kvp_data, "lot-split") == NULL);
     qof_book_begin_edit (book);
     qof_instance_set (QOF_INSTANCE (book),
-		      "currency-accounting", "trading",
+		      "trading-accts", "t",
 		      NULL);
     qof_book_commit_edit (book);
     g_assert (xaccTransUseTradingAccounts (txn));
diff --git a/src/engine/test/utest-Transaction.c b/src/engine/test/utest-Transaction.c
index 8c3ee23..7611c2c 100644
--- a/src/engine/test/utest-Transaction.c
+++ b/src/engine/test/utest-Transaction.c
@@ -1053,7 +1053,7 @@ test_xaccTransGetImbalance_trading (Fixture *fixture,
     MonetaryList *mlist;
     qof_book_begin_edit (book);
     qof_instance_set (QOF_INSTANCE (book),
-		      "currency-accounting", "trading",
+		      "trading-accts", "t",
 		      NULL);
     qof_book_commit_edit (book);
 
@@ -1140,7 +1140,7 @@ test_xaccTransIsBalanced_trading (Fixture *fixture, gconstpointer pData)
 
     qof_book_begin_edit (book);
     qof_instance_set (QOF_INSTANCE (book),
-		      "currency-accounting", "trading",
+		      "trading-accts", "t",
 		      NULL);
     qof_book_commit_edit (book);
 
diff --git a/src/gnome-utils/dialog-options.c b/src/gnome-utils/dialog-options.c
index 64aba22..e590b90 100644
--- a/src/gnome-utils/dialog-options.c
+++ b/src/gnome-utils/dialog-options.c
@@ -125,6 +125,7 @@ void gnc_options_dialog_response_cb(GtkDialog *dialog, gint response,
 static void gnc_options_dialog_reset_cb(GtkWidget * w, gpointer data);
 void gnc_options_dialog_list_select_cb (GtkTreeSelection *selection,
                                         gpointer data);
+GList * gnc_option_get_ui_widgets_currency_accounting(GtkWidget *widget);
 
 GtkWidget *
 gnc_option_get_gtk_widget (GNCOption *option)
@@ -397,6 +398,69 @@ gnc_option_set_selectable_internal (GNCOption *option, gboolean selectable)
     gtk_widget_set_sensitive (widget, selectable);
 }
 
+GList *
+gnc_option_get_ui_widgets_currency_accounting (GtkWidget *widget)
+{
+    GList *list1, *list2, *list3;
+    GList *list = NULL;
+    GList *return_list = NULL;
+    GtkWidget *book_currency_widget= NULL;
+    GtkWidget *default_cost_policy_widget= NULL;
+    GtkWidget *book_currency_vbox_widget= NULL;
+    GtkWidget *default_cost_policy_vbox_widget= NULL;
+
+    /* children of the frame, the 1st of which is 1 vbox1 */
+    list1 = gtk_container_get_children (GTK_CONTAINER (widget));
+    /* children of vbox1 which are 3 hbox's */
+    list2 = gtk_container_get_children (GTK_CONTAINER (list1->data));
+    g_list_free(list1);
+    /* create list of button widgets */
+    for (list3 = list2; list3; list3 = list3->next)
+    {
+        GList *vbox2list = NULL;
+        /* children of each hbox, the 1st of which is a vbox2 */
+        vbox2list = gtk_container_get_children
+                                   (GTK_CONTAINER (list3->data));
+        /* children of 1st vbox2, the 1st of which is a button */
+        list1 = gtk_container_get_children
+                               (GTK_CONTAINER (vbox2list->data));
+        list = g_list_append (list, list1->data);
+        g_list_free(vbox2list);
+        g_list_free(list1);
+    }
+    return_list = g_list_append (return_list, list);
+    /* point list2 to 2nd hbox, which is for book-currency */
+    list2 = list2->next;
+    /* children of book-currency hbox which is 3 vbox2's */
+    list1 = gtk_container_get_children (GTK_CONTAINER (list2->data));
+    g_list_free(list2);
+    /* point list1 to 2nd vbox2, which is for book-currency widget*/
+    list1 = list1->next;
+    book_currency_vbox_widget = list1->data;
+    /* children of book-currency vbox2 which is a label and the
+       book-currency widget */
+    list2 = gtk_container_get_children (GTK_CONTAINER (list1->data));
+    list2 = list2->next;
+    book_currency_widget = list2->data;
+    return_list = g_list_append (return_list, book_currency_widget);
+    g_list_free(list2);
+    /* point list1 to 3rd vbox2, which is for policy widget*/
+    list1 = list1->next;
+    default_cost_policy_vbox_widget = list1->data;
+    /* children of policy vbox2 which is a label and the
+       policy multichoice widget */
+    list2 = gtk_container_get_children (GTK_CONTAINER (list1->data));
+    list2 = list2->next;
+    default_cost_policy_widget = list2->data;
+    return_list = g_list_append (return_list, default_cost_policy_widget);
+    return_list = g_list_append (return_list, book_currency_vbox_widget);
+    return_list = g_list_append (return_list, default_cost_policy_vbox_widget);
+    g_list_free(list2);
+    g_list_free(list1);
+
+    return return_list;
+}
+
 static void
 gnc_option_default_cb(GtkWidget *widget, GNCOption *option)
 {
@@ -450,6 +514,127 @@ gnc_option_radiobutton_cb(GtkWidget *w, gpointer data)
     gnc_option_changed_widget_cb(widget, option);
 }
 
+static void
+gnc_option_currency_accounting_set_sensitivity(GNCOption *option,
+                                               gboolean set_sensitivity)
+{
+    GtkWidget *option_widget;
+    GtkWidget *book_currency_widget;
+    GtkWidget *default_cost_policy_widget;
+    GtkWidget *book_currency_vbox_widget;
+    GtkWidget *default_cost_policy_vbox_widget;
+    GList *list = NULL;
+    GList *sub_widgets = NULL;
+
+    option_widget = gnc_option_get_gtk_widget (option);
+    sub_widgets = gnc_option_get_ui_widgets_currency_accounting (option_widget);
+    list = sub_widgets->data; /* save this to be able to free it */
+    sub_widgets = sub_widgets->next;
+    book_currency_widget = sub_widgets->data;
+    sub_widgets = sub_widgets->next;
+    default_cost_policy_widget = sub_widgets->data;
+    sub_widgets = sub_widgets->next;
+    book_currency_vbox_widget = sub_widgets->data;
+    sub_widgets = sub_widgets->next;
+    default_cost_policy_vbox_widget = sub_widgets->data;
+    g_list_free(sub_widgets);
+    g_list_free(list);
+    if (set_sensitivity)
+    {
+        SCM curr_scm;
+        SCM list_symbol;
+        gnc_commodity *commodity;
+        int index;
+        GList *list_of_policies = NULL;
+
+        curr_scm = gnc_currency_accounting_option_get_default_currency(option);
+        commodity = gnc_scm_to_commodity (curr_scm);
+        if (commodity)
+        {
+            gnc_currency_edit_set_currency
+                (GNC_CURRENCY_EDIT(book_currency_widget), commodity);
+        }
+        else
+        {
+            gnc_currency_edit_set_currency
+                (GNC_CURRENCY_EDIT(book_currency_widget), gnc_default_currency());
+        }
+        gtk_widget_set_sensitive(book_currency_vbox_widget, TRUE);
+
+        list_of_policies = gnc_get_valid_policy_list();
+        if (list_of_policies)
+        {
+            GList *l = NULL;
+            gint i = 0;
+            list_symbol =
+                gnc_currency_accounting_option_get_default_policy(option);
+            for (l = list_of_policies; l != NULL; l = l->next)
+            {
+                /* First item in policy_list is internal name of policy */
+                GList *policy_list = l->data;
+                if (g_strcmp0(policy_list->data,
+                               gnc_scm_symbol_to_locale_string(list_symbol))
+                               == 0)
+                {
+                    /* GtkComboBox per-item tooltip changes needed below */
+                    gnc_combott_set_active(
+                                    GNC_COMBOTT(default_cost_policy_widget), i);
+                }
+                i++;
+                g_list_free(policy_list);
+            }
+            g_list_free(list_of_policies);
+        }
+        else
+        {
+           gnc_combott_set_active
+                    (GNC_COMBOTT(default_cost_policy_widget), -1);
+        }
+        gtk_widget_set_sensitive(default_cost_policy_vbox_widget, TRUE);
+    }
+    else
+    {
+        GtkWidget *new_book_currency_widget = NULL;
+
+        /* since there is no 'gnc_currency_edit_set_currency(widget, -1)' like
+           there is for 'gnc_combott_set_active', do this as a work around so
+           the dialog is cleared of currency when switched out of 'book-
+           currency' choice */
+        gtk_widget_destroy (book_currency_widget);
+        new_book_currency_widget = gnc_currency_edit_new();
+        g_signal_connect(G_OBJECT(new_book_currency_widget),
+                         "changed",
+                         G_CALLBACK(gnc_option_changed_widget_cb),
+                         option);
+        gtk_box_pack_start (GTK_BOX (book_currency_vbox_widget),
+                            new_book_currency_widget, FALSE, FALSE, 0);
+        gtk_widget_show_all(book_currency_vbox_widget);
+        gtk_widget_set_sensitive(book_currency_vbox_widget, FALSE);
+        gnc_combott_set_active(GNC_COMBOTT(default_cost_policy_widget), -1);
+        gtk_widget_set_sensitive(default_cost_policy_vbox_widget, FALSE);
+    }
+}
+
+static void
+gnc_option_currency_accounting_non_book_cb(GtkWidget *widget, gpointer data)
+{
+    /* widget is the radiobutton */
+    GNCOption *option = data;
+
+    gnc_option_currency_accounting_set_sensitivity (option, FALSE);
+    gnc_option_radiobutton_cb(widget, data);
+}
+
+static void
+gnc_option_currency_accounting_book_cb(GtkWidget *widget, gpointer data)
+{
+    /* widget is the radiobutton */
+    GNCOption *option = data;
+
+    gnc_option_currency_accounting_set_sensitivity (option, TRUE);
+    gnc_option_radiobutton_cb(widget, data);
+}
+
 static GtkWidget *
 gnc_option_create_date_widget (GNCOption *option)
 {
@@ -678,6 +863,146 @@ gnc_option_create_radiobutton_widget(char *name, GNCOption *option)
     return frame;
 }
 
+static GtkWidget *
+gnc_option_create_currency_accounting_widget (char *name, GNCOption *option)
+{
+    GtkWidget *frame = NULL, *vbox1 = NULL;
+    GtkWidget *widget = NULL;
+    int num_values;
+    GList *list_of_policies = NULL;
+    int i;
+
+    num_values = gnc_option_num_permissible_values(option);
+
+    g_return_val_if_fail(num_values == 3, NULL);
+
+    list_of_policies = gnc_get_valid_policy_list();
+
+    g_return_val_if_fail(g_list_length (list_of_policies) >= 0, NULL);
+
+    /* Create our button frame */
+    frame = gtk_frame_new (name);
+
+    /* Create the verticle button box */
+    vbox1 = gtk_vbox_new (FALSE, 5);
+    gtk_container_add (GTK_CONTAINER (frame), vbox1);
+
+    /* Iterate over the three options and create a radio button for each one */
+    for (i = 0; i < num_values; i++)
+    {
+        char *label;
+        char *tip;
+        GtkWidget *vbox2 = NULL, *hbox = NULL;
+
+        label = gnc_option_permissible_value_name(option, i);
+        tip = gnc_option_permissible_value_description(option, i);
+
+        widget =
+            gtk_radio_button_new_with_label_from_widget (widget ?
+                    GTK_RADIO_BUTTON (widget) :
+                    NULL,
+                    label && *label ? _(label) : "");
+        g_object_set_data (G_OBJECT (widget), "gnc_radiobutton_index",
+                           GINT_TO_POINTER (i));
+        gtk_widget_set_tooltip_text(widget, tip && *tip ? _(tip) : "");
+        /* Use hbox & vbox2 for all buttons so they are all at the same level;
+           easier to get in set/get ui functions */
+        hbox = gtk_hbox_new(FALSE, 5);
+        vbox2 = gtk_vbox_new(FALSE, 5);
+        gtk_box_pack_start (GTK_BOX (vbox2), widget, FALSE, FALSE, 0);
+        gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
+        if (i == 1) /* book-currency */
+        {
+            GtkWidget *widget_label;
+            GtkWidget *book_currency_widget = NULL,
+                      *default_cost_policy_widget = NULL;
+
+            g_signal_connect(G_OBJECT(widget),
+                         "toggled",
+                         G_CALLBACK(gnc_option_currency_accounting_book_cb),
+                         option);
+            tip = gnc_currency_accounting_option_currency_documentation(option);
+            widget_label = gtk_label_new( _("Book Currency") );
+            book_currency_widget = gnc_currency_edit_new();
+            g_signal_connect(G_OBJECT(book_currency_widget),
+                         "changed",
+                         G_CALLBACK(gnc_option_changed_widget_cb),
+                         option);
+            vbox2 = gtk_vbox_new(FALSE, 5);
+            gtk_widget_set_tooltip_text(vbox2, tip && *tip ? _(tip) : "");
+            gtk_box_pack_start (GTK_BOX (vbox2), widget_label, FALSE, FALSE, 0);
+            gtk_box_pack_start (GTK_BOX (vbox2),
+                                book_currency_widget, FALSE, FALSE, 0);
+            gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
+            if (list_of_policies)
+            {
+                GtkListStore *store;
+                GtkTreeIter  iter;
+                char *itemstring;
+                char *description;
+                GList *l = NULL;
+
+                store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+                /* Add values to the list store, entry and tooltip */
+                for (l = list_of_policies; l != NULL; l = l->next)
+                {
+                    GList *policy_list = l->data;
+                    /* First item in policy_list is internal name of policy */
+                    policy_list = policy_list->next;
+                    /* Second item in policy_list is policy description */
+                    itemstring = policy_list->data;
+                    policy_list = policy_list->next;
+                    /* Third item in policy_list is policy hint */
+                    description = policy_list->data;
+                    gtk_list_store_append (store, &iter);
+                    gtk_list_store_set
+                           (store,
+                            &iter,
+                            0,
+                            (itemstring && *itemstring) ? _(itemstring) : "",
+                            1,
+                            (description && *description) ? _(description) : "",
+                            -1);
+                    g_list_free(policy_list);
+                }
+                g_list_free(list_of_policies);
+                /* Create the new Combo with tooltip and add the store */
+                default_cost_policy_widget = GTK_WIDGET(gnc_combott_new());
+                g_object_set( G_OBJECT( default_cost_policy_widget ),
+                              "model",
+                              GTK_TREE_MODEL(store),
+                              NULL );
+                g_object_unref(store);
+
+                g_signal_connect(G_OBJECT(default_cost_policy_widget), "changed",
+                                 G_CALLBACK(gnc_option_multichoice_cb), option);
+            }
+            tip = gnc_currency_accounting_option_policy_documentation(option);
+            widget_label = gtk_label_new( _("Default Gains Policy") );
+            vbox2 = gtk_vbox_new(FALSE, 5);
+            gtk_widget_set_tooltip_text(vbox2, tip && *tip ? _(tip) : "");
+            gtk_box_pack_start (GTK_BOX (vbox2), widget_label, FALSE, FALSE, 0);
+            gtk_box_pack_start (GTK_BOX (vbox2),
+                                 default_cost_policy_widget, FALSE, FALSE, 0);
+            gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
+        }
+        else /* trading or neither */
+        {
+            g_signal_connect(G_OBJECT(widget),
+                         "toggled",
+                         G_CALLBACK(gnc_option_currency_accounting_non_book_cb),
+                         option);
+        }
+        gtk_box_pack_start (GTK_BOX (vbox1), hbox, FALSE, FALSE, 0);
+
+        if (label)
+            free (label);
+        if (tip)
+            free (tip);
+    }
+    return frame;
+}
+
 static void
 gnc_option_account_cb(GtkTreeSelection *selection, gpointer data)
 {
@@ -2167,6 +2492,27 @@ gnc_option_set_ui_widget_budget (GNCOption *option, GtkBox *page_box,
     return value;
 }
 
+static GtkWidget *
+gnc_option_set_ui_widget_currency_accounting (GNCOption *option,
+                                              GtkBox *page_box,
+                                              char *name, char *documentation,
+                                              /* Return values */
+                                              GtkWidget **enclosing,
+                                              gboolean *packed)
+{
+    GtkWidget *value;
+
+    *enclosing = gtk_hbox_new(FALSE, 5);
+
+    value = gnc_option_create_currency_accounting_widget(name, option);
+    gnc_option_set_widget (option, value);
+
+    gnc_option_set_ui_value(option, FALSE);
+    gtk_box_pack_start(GTK_BOX(*enclosing), value, FALSE, FALSE, 0);
+    gtk_widget_show_all(*enclosing);
+    return value;
+}
+
 /*************************
  *       SET VALUE       *
  *************************
@@ -2632,6 +2978,144 @@ gnc_option_set_ui_value_dateformat (GNCOption *option, gboolean use_default,
     return FALSE;
 }
 
+static gboolean
+gnc_option_set_ui_value_currency_accounting (GNCOption *option,
+                                             gboolean use_default,
+                                             GtkWidget *widget, SCM value)
+{
+    if (scm_is_pair(value))
+    {
+        SCM rb_symbol;
+
+        rb_symbol = gnc_currency_accounting_option_value_get_method (value);
+
+        if (rb_symbol)
+        {
+            int index;
+
+            index = gnc_option_permissible_value_index(option, rb_symbol);
+            if (index < 0)
+                return TRUE;
+            else
+            {
+                GtkWidget *button;
+                int i;
+                gpointer val;
+                GList *list = NULL;
+                GList *sub_widgets = NULL;
+
+                sub_widgets =
+                    gnc_option_get_ui_widgets_currency_accounting (widget);
+                list = sub_widgets->data;
+                g_list_free(sub_widgets);
+
+                /* stop when list of buttons is pointing at index */
+                for (i = 0; i < index && list; i++)
+                    list = list->next;
+                g_return_val_if_fail (list, TRUE);
+
+                button = list->data; /* this is selected button */
+                g_list_free(list);
+                val = g_object_get_data (G_OBJECT (button),
+                                            "gnc_radiobutton_index");
+                g_return_val_if_fail (GPOINTER_TO_INT (val) == index, TRUE);
+
+                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+                /* when an unselected button in a group is clicked the clicked
+                   button receives the “toggled” signal, as does the
+                   previously selected button; however, if the first button
+                   is active when the currency-accounting dialog is created,
+                   that is, it's read from the option, the "toggled" handler
+                   is not called while it is if any other button is active.
+                   To get desired result, that is, to set sensitivity to
+                   FALSE, explicitly call the handler here if first button */
+                if (index == 0)
+                    gnc_option_currency_accounting_non_book_cb(button,
+                        (gpointer) option);
+                if (g_strcmp0(gnc_option_permissible_value_name(option,
+                                                                 index),
+                                "Use a Book-Currency") == 0)
+                {
+                    GtkWidget *book_currency_widget;
+                    GtkWidget *default_cost_policy_widget;
+                    SCM curr_scm;
+                    SCM list_symbol;
+                    gnc_commodity *commodity;
+                    GList *list_of_policies = NULL;
+
+                    /* note that we have to call this function again here
+                       because the callback routines called above, or
+                       initiated by GTK, change the widget pointers, so we
+                       can't keep and use those called above */
+                    sub_widgets =
+                        gnc_option_get_ui_widgets_currency_accounting
+                                                                   (widget);
+                    list = sub_widgets->data; // needed just to free button list
+                    sub_widgets = sub_widgets->next;
+                    book_currency_widget = sub_widgets->data;
+                    sub_widgets = sub_widgets->next;
+                    default_cost_policy_widget = sub_widgets->data;
+                    g_list_free(sub_widgets);
+                    g_list_free(list);
+                    curr_scm =
+                        gnc_currency_accounting_option_value_get_book_currency
+                        (value);
+                    commodity = gnc_scm_to_commodity (curr_scm);
+                    if (commodity)
+                    {
+                        gnc_currency_edit_set_currency
+                            (GNC_CURRENCY_EDIT(book_currency_widget),
+                             commodity);
+                    }
+                    else
+                    {
+                        gnc_currency_edit_set_currency
+                            (GNC_CURRENCY_EDIT(book_currency_widget),
+                             gnc_default_currency());
+                    }
+                    list_of_policies = gnc_get_valid_policy_list();
+                    if (list_of_policies)
+                    {
+                        GList *l = NULL;
+                        gint i = 0;
+                        list_symbol =
+                       gnc_currency_accounting_option_value_get_default_policy
+                            (value);
+                        for (l = list_of_policies; l != NULL; l = l->next)
+                        {
+                            /* First item in policy_list is internal name of
+                               policy */
+                            GList *policy_list = l->data;
+                            if (g_strcmp0(policy_list->data,
+                                   gnc_scm_symbol_to_locale_string(list_symbol))
+                                   == 0)
+                            {
+                                /* GtkComboBox per-item tooltip changes needed
+                                   below */
+                                gnc_combott_set_active(
+                                    GNC_COMBOTT(default_cost_policy_widget),
+                                    i);
+                            }
+                            i++;
+                            g_list_free(policy_list);
+                        }
+                        g_list_free(list_of_policies);
+                    }
+                    else
+                    {
+                        gnc_combott_set_active
+                            (GNC_COMBOTT(default_cost_policy_widget), -1);
+                    }
+                }
+                return FALSE;
+            }
+        }
+        return TRUE;
+    }
+    return TRUE;
+}
+
+
 /*************************
  *       GET VALUE       *
  *************************
@@ -2939,6 +3423,77 @@ gnc_option_get_ui_value_dateformat (GNCOption *option, GtkWidget *widget)
     return (gnc_dateformat_option_set_value(format, months, years, custom));
 }
 
+static SCM
+gnc_option_get_ui_value_currency_accounting (GNCOption *option, GtkWidget *widget)
+{
+    gpointer _index;
+    int index;
+    SCM value = SCM_EOL;
+
+    _index = g_object_get_data(G_OBJECT(widget), "gnc_radiobutton_index");
+    index = GPOINTER_TO_INT(_index);
+
+    /* build the return list in reverse order */
+    if (g_strcmp0(gnc_option_permissible_value_name(option, index),
+                  "Use a Book-Currency") == 0)
+    {
+        GtkWidget *book_currency_widget;
+        GtkWidget *default_cost_policy_widget;
+        GList *list = NULL; /* needed just to free the button list */
+        GList *sub_widgets = NULL;
+        gnc_commodity *commodity;
+        int policy_index;
+        SCM val;
+        GList *list_of_policies = NULL;
+        const char *str = NULL;
+
+        sub_widgets = gnc_option_get_ui_widgets_currency_accounting (widget);
+        list = sub_widgets->data;
+        sub_widgets = sub_widgets->next;
+        book_currency_widget = sub_widgets->data;
+        sub_widgets = sub_widgets->next;
+        default_cost_policy_widget = sub_widgets->data;
+        g_list_free(sub_widgets);
+        g_list_free(list);
+
+        /* GtkComboBox per-item tooltip changes needed below */
+        policy_index =
+            gnc_combott_get_active(GNC_COMBOTT(default_cost_policy_widget));
+        list_of_policies = gnc_get_valid_policy_list();
+        if (list_of_policies)
+        {
+            GList *l = NULL;
+            gint i = 0;
+            for (l = list_of_policies; l != NULL; l = l->next)
+            {
+                GList *policy_list = l->data;
+                if(i == policy_index)
+                    str = policy_list->data;
+                i++;
+                g_list_free(policy_list);
+            }
+            g_list_free(list_of_policies);
+        }
+        if (str)
+        {
+            val = scm_from_locale_symbol(str);
+        }
+        else
+        {
+            val = SCM_EOL;
+        }
+        value = scm_cons(val, value);
+
+        commodity =
+            gnc_currency_edit_get_currency(
+                GNC_CURRENCY_EDIT(book_currency_widget));
+        val = gnc_commodity_to_scm(commodity);
+        value = scm_cons(val, value);
+    }
+
+    return (scm_cons (gnc_option_permissible_value(option, index), value));
+}
+
 /************************************/
 /*          INITIALIZATION          */
 /************************************/
@@ -3015,6 +3570,12 @@ static void gnc_options_initialize_options (void)
             "budget", gnc_option_set_ui_widget_budget,
             gnc_option_set_ui_value_budget, gnc_option_get_ui_value_budget
         },
+        {
+            "currency-accounting",
+            gnc_option_set_ui_widget_currency_accounting,
+            gnc_option_set_ui_value_currency_accounting,
+            gnc_option_get_ui_value_currency_accounting
+        },
         { NULL, NULL, NULL, NULL }
     };
     int i;
diff --git a/src/libqof/qof/qofbook.cpp b/src/libqof/qof/qofbook.cpp
index 3ff9ba6..8d7f7db 100644
--- a/src/libqof/qof/qofbook.cpp
+++ b/src/libqof/qof/qofbook.cpp
@@ -21,7 +21,7 @@
 
 /*
  * FILE:
- * qofbook.c
+ * qofbook.cpp
  *
  * FUNCTION:
  * Encapsulate all the information about a QOF dataset.
@@ -66,14 +66,17 @@ enum
     PROP_0,
 //  PROP_ROOT_ACCOUNT,		/* Table */
 //  PROP_ROOT_TEMPLATE,		/* Table */
-/*   keep trading accounts property, while adding currency accounting
-     preperty, so that files prior to 2.7 can be read/processed; GUI changed
-     to use currency accounting property as of 2.7 */
+/*   keep trading accounts property, while adding book-currency and default
+     gains properties, so that files prior to 2.7 can be read/processed; GUI
+     changed to use all three properties as of 2.7. Trading accounts, on the
+     one hand, and book-currency plus default-gains-policy, on the other,
+     are mutually exclusive */
     PROP_OPT_TRADING_ACCOUNTS,	/* KVP */
-    PROP_OPT_CURRENCY_ACCOUNTING,	/* KVP */
-/*   Book currency property only applies if currency accounting method is
-     set to 'book-currency' */
+/*   Book currency and default gains properties only apply if currency
+     accounting method selected in GUI is 'book-currency'; both required and
+     both are exclusive with trading accounts */
     PROP_OPT_BOOK_CURRENCY, 	/* KVP */
+    PROP_OPT_DEFAULT_GAINS_POLICY, 	/* KVP */
     PROP_OPT_AUTO_READONLY_DAYS,/* KVP */
     PROP_OPT_NUM_FIELD_SOURCE,	/* KVP */
     PROP_OPT_DEFAULT_BUDGET,	/* KVP */
@@ -82,13 +85,6 @@ enum
     N_PROPERTIES		/* Just a counter */
 };
 
-enum
-{
-    CURRENCY_ACCOUNTING_TRADING,
-    CURRENCY_ACCOUNTING_BOOK_CURRENCY,
-    CURRENCY_ACCOUNTING_NEITHER,
-};
-
 QOF_GOBJECT_GET_TYPE(QofBook, qof_book, QOF_TYPE_INSTANCE, {});
 QOF_GOBJECT_DISPOSE(qof_book);
 QOF_GOBJECT_FINALIZE(qof_book);
@@ -145,17 +141,17 @@ qof_book_get_property (GObject* object,
 	qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
-    case PROP_OPT_CURRENCY_ACCOUNTING:
+    case PROP_OPT_BOOK_CURRENCY:
 	key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
 			       OPTION_SECTION_ACCOUNTS,
-			       OPTION_NAME_CURRENCY_ACCOUNTING);
+                   OPTION_NAME_BOOK_CURRENCY);
 	qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
-    case PROP_OPT_BOOK_CURRENCY:
+    case PROP_OPT_DEFAULT_GAINS_POLICY:
 	key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
 			       OPTION_SECTION_ACCOUNTS,
-                   OPTION_NAME_BOOK_CURRENCY);
+                   OPTION_NAME_DEFAULT_GAINS_POLICY);
 	qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
@@ -179,6 +175,7 @@ qof_book_get_property (GObject* object,
 			       OPTION_NAME_DEFAULT_BUDGET);
 	qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
+	break;
     case PROP_OPT_FY_END:
 	key = const_cast<char*>("fy_end");
 	qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
@@ -215,17 +212,17 @@ qof_book_set_property (GObject      *object,
 	qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
-    case PROP_OPT_CURRENCY_ACCOUNTING:
+    case PROP_OPT_BOOK_CURRENCY:
 	key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
 			       OPTION_SECTION_ACCOUNTS,
-			       OPTION_NAME_CURRENCY_ACCOUNTING);
+                   OPTION_NAME_BOOK_CURRENCY);
 	qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
-    case PROP_OPT_BOOK_CURRENCY:
+    case PROP_OPT_DEFAULT_GAINS_POLICY:
 	key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
 			       OPTION_SECTION_ACCOUNTS,
-                   OPTION_NAME_BOOK_CURRENCY);
+                   OPTION_NAME_DEFAULT_GAINS_POLICY);
 	qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
 	g_free (key);
 	break;
@@ -286,28 +283,24 @@ qof_book_class_init (QofBookClass *klass)
 
     g_object_class_install_property
     (gobject_class,
-     PROP_OPT_CURRENCY_ACCOUNTING,
-     g_param_spec_string("currency-accounting",
-                         "Select Currency Accounting Method",
-			 "Scheme 'trading', 'book-currency', or 'neither' (or NULL). "
-			 "If 'trading', then the book uses trading accounts for "
-			 "managing multiple-currency transactions.  If 'book-currency', "
-			 "then the book uses the 'book-currency' as a reference currency "
-             "for managing multiple-currency transactions. If 'neither', or "
-             "if the property is not set or NULL, then the book handles "
-             "multiple-currency transactions in the traditional way gnucash "
-             "has in the past.",
-                         NULL,
-                         G_PARAM_READWRITE));
-
-    g_object_class_install_property
-    (gobject_class,
      PROP_OPT_BOOK_CURRENCY,
      g_param_spec_string("book-currency",
                          "Select Book Currency",
 			 "The reference currency used to manage multiple-currency "
              "transactions when 'book-currency' currency accounting method "
-             "selected.",
+             "selected; requires valid default gains/loss policy.",
+                         NULL,
+                         G_PARAM_READWRITE));
+
+    g_object_class_install_property
+    (gobject_class,
+     PROP_OPT_DEFAULT_GAINS_POLICY,
+     g_param_spec_string("default-gains-policy",
+                         "Select Default Gains Policy",
+			 "The default policy to be used to calculate gains/losses on "
+             "dispositions of currencies/commodities other than "
+             "'book-currency' when 'book-currency' currency accounting "
+             "method selected; requires valid book-currency.",
                          NULL,
                          G_PARAM_READWRITE));
 
@@ -895,9 +888,13 @@ qof_book_validate_counter_format_internal(const gchar *p,
     return NULL;
 }
 
-/* Returns Currency Accounting Method for book */
-gint
-qof_book_currency_accounting_method (const QofBook *book)
+/** Returns pointer to book-currency name for book, if one exists in the
+  * KVP, or NULL; does not validate contents nor determine if there is a valid
+  * default gain/loss policy, both of which are required, for the
+  * 'book-currency' currency accounting method to apply. Use instead
+  * 'gnc_book_get_book_currency' which does these validations. */
+const gchar *
+qof_book_get_book_currency (QofBook *book)
 {
     KvpFrame *kvp;
     KvpValue *value;
@@ -905,7 +902,7 @@ qof_book_currency_accounting_method (const QofBook *book)
     if (!book)
     {
         PWARN ("No book!!!");
-        return CURRENCY_ACCOUNTING_NEITHER;
+        return NULL;
     }
 
     /* Get the KVP from the current book */
@@ -914,44 +911,31 @@ qof_book_currency_accounting_method (const QofBook *book)
     if (!kvp)
     {
         PWARN ("Book has no KVP_Frame");
-        return CURRENCY_ACCOUNTING_NEITHER;
+        return NULL;
     }
 
-    /* Get the Currency Accounting Method */
+    /* See if there is a book currency */
     value = kvp_frame_get_slot_path (kvp,
                                      KVP_OPTION_PATH,
                                      OPTION_SECTION_ACCOUNTS,
-                                     OPTION_NAME_CURRENCY_ACCOUNTING,
+                                     OPTION_NAME_BOOK_CURRENCY,
                                      NULL);
-    if (value)
+    if (!value)
+    /* No book-currency */
     {
-        if (strcmp (kvp_value_get_string (value), "trading") == 0)
-           return CURRENCY_ACCOUNTING_TRADING;
-        if (strcmp (kvp_value_get_string (value), "book-currency") == 0)
-        /* Must have a specified book-currency for 'book-currency' Currency
-           Accounting Method to be valid */
-        {
-            value = kvp_frame_get_slot_path (kvp,
-                                             KVP_OPTION_PATH,
-                                             OPTION_SECTION_ACCOUNTS,
-                                             OPTION_NAME_BOOK_CURRENCY,
-                                             NULL);
-            if (!value)
-            /* Book-currency currency accounting method selected but no
-               book-currency specified - something is wrong */
-            {
-                return CURRENCY_ACCOUNTING_NEITHER;
-            }
-            /* Something is stored there - presumably a valid currency */
-            return CURRENCY_ACCOUNTING_BOOK_CURRENCY;
-        }
+        return NULL;
     }
-    return CURRENCY_ACCOUNTING_NEITHER;
+
+    return kvp_value_get_string (value);
 }
 
-/* Returns pointer to Book Currency unique_name for book or NULL */
+/** Returns pointer to default gain/loss policy for book, if one exists in the
+  * KVP, or NULL; does not validate contents nor determine if there is a valid
+  * book-currency, both of which are required, for the 'book-currency'
+  * currency accounting method to apply. Use instead
+  * 'gnc_book_get_default_gains_policy' which does these validations. */
 const gchar *
-qof_book_get_book_currency_unique_name (QofBook *book)
+qof_book_get_default_gains_policy (QofBook *book)
 {
     KvpFrame *kvp;
     KvpValue *value;
@@ -971,30 +955,15 @@ qof_book_get_book_currency_unique_name (QofBook *book)
         return NULL;
     }
 
-    /* Get the Currency Accounting Method */
+    /* See if there is a default gain/loss policy */
     value = kvp_frame_get_slot_path (kvp,
                                      KVP_OPTION_PATH,
                                      OPTION_SECTION_ACCOUNTS,
-                                     OPTION_NAME_CURRENCY_ACCOUNTING,
+                                     OPTION_NAME_DEFAULT_GAINS_POLICY,
                                      NULL);
     if (!value)
-       /* No currency accounting method selected; therefore no book-currency */
-       return NULL;
-
-    if (!(strcmp (kvp_value_get_string (value), "book-currency") == 0))
-       /* Not book-currency currency accounting method; therefore no
-           book-currency */
-       return NULL;
-
-    /* Book-currency is the currency accounting method; get the book currency */
-    value = kvp_frame_get_slot_path (kvp,
-                                     KVP_OPTION_PATH,
-                                     OPTION_SECTION_ACCOUNTS,
-                                     OPTION_NAME_BOOK_CURRENCY,
-                                     NULL);
-    if (!value)
-    /* Book-currency currency accounting method selected but no book-currency
-       specified - something is wrong */
+    /* No default gain/loss policy, therefore not valid book-currency
+       accounting method */
     {
         return NULL;
     }
@@ -1002,32 +971,17 @@ qof_book_get_book_currency_unique_name (QofBook *book)
     return kvp_value_get_string (value);
 }
 
+
 /* Determine whether this book uses trading accounts */
 gboolean
 qof_book_use_trading_accounts (const QofBook *book)
 {
-    /* Prior to version 2.7, Gnucash had a boolean flag for trading accounts;
-       need to accommodate files from version 2.6 and earlier */
     const char *opt = NULL;
     qof_instance_get (QOF_INSTANCE (book),
 		      "trading-accts", &opt,
 		      NULL);
     if (opt && opt[0] == 't' && opt[1] == 0)
         return TRUE;
-
-    /* Else, get the Currency Accounting Method */
-    if (qof_book_currency_accounting_method (book) == CURRENCY_ACCOUNTING_TRADING)
-        return TRUE;
-    return FALSE;
-}
-
-/* Returns TRUE if this book uses a book-currency */
-gboolean
-qof_book_use_book_currency (const QofBook *book)
-{
-    /* Get the Currency Accounting Method */
-    if (qof_book_currency_accounting_method (book) == CURRENCY_ACCOUNTING_BOOK_CURRENCY)
-        return TRUE;
     return FALSE;
 }
 
diff --git a/src/libqof/qof/qofbook.h b/src/libqof/qof/qofbook.h
index e3f27fa..776a441 100644
--- a/src/libqof/qof/qofbook.h
+++ b/src/libqof/qof/qofbook.h
@@ -245,11 +245,19 @@ void qof_book_mark_readonly(QofBook *book);
 /** Returns flag indicating whether this book uses trading accounts */
 gboolean qof_book_use_trading_accounts (const QofBook *book);
 
-/** Returns TRUE if this book uses a book-currency */
-gboolean qof_book_use_book_currency (const QofBook *book);
-
-/** Returns pointer to Book Currency unique_name for book or NULL */
-const gchar * qof_book_get_book_currency_unique_name (QofBook *book);
+/** Returns pointer to book-currency name for book, if one exists in the
+  * KVP, or NULL; does not validate contents nor determine if there is a valid
+  * default gain/loss policy, both of which are required, for the
+  * 'book-currency' currency accounting method to apply. Use instead
+  * 'gnc_book_get_book_currency' which does these validations. */
+const gchar * qof_book_get_book_currency (QofBook *book);
+
+/** Returns pointer to default gain/loss policy for book, if one exists in the
+  * KVP, or NULL; does not validate contents nor determine if there is a valid
+  * book-currency, both of which are required, for the 'book-currency'
+  * currency accounting method to apply. Use instead
+  * 'gnc_book_get_default_gains_policy' which does these validations. */
+const gchar * qof_book_get_default_gains_policy (QofBook *book);
 
 /** Returns TRUE if the auto-read-only feature should be used, otherwise
  * FALSE. This is just a wrapper on qof_book_get_num_days_autoreadonly() == 0. */
diff --git a/src/libqof/qof/qofbookslots.h b/src/libqof/qof/qofbookslots.h
index 8259462..f820fd3 100644
--- a/src/libqof/qof/qofbookslots.h
+++ b/src/libqof/qof/qofbookslots.h
@@ -64,8 +64,9 @@
 
 #define OPTION_SECTION_ACCOUNTS        N_("Accounts")
 #define OPTION_NAME_TRADING_ACCOUNTS   N_("Use Trading Accounts")
-#define OPTION_NAME_CURRENCY_ACCOUNTING   N_("Select Currency Accounting Method")
-#define OPTION_NAME_BOOK_CURRENCY      N_("Select Book Currency")
+#define OPTION_NAME_CURRENCY_ACCOUNTING   N_("Currency Accounting")
+#define OPTION_NAME_BOOK_CURRENCY      N_("Book Currency")
+#define OPTION_NAME_DEFAULT_GAINS_POLICY      N_("Default Gains Policy")
 #define OPTION_NAME_AUTO_READONLY_DAYS N_("Day Threshold for Read-Only Transactions (red line)")
 #define OPTION_NAME_NUM_FIELD_SOURCE   N_("Use Split Action Field for Number")
 
@@ -80,6 +81,7 @@
  * OPTION-NAME-TRADING-ACCOUNTS
  * OPTION-NAME-CURRENCY-ACCOUNTING
  * OPTION-NAME-BOOK-CURRENCY
+ * OPTION_NAME_DEFAULT_GAINS_POLICY
  * OPTION-NAME-AUTO-READONLY-DAYS
  * OPTION-NAME_NUM-FIELD-SOURCE
  * OPTION-SECTION-BUDGETING
diff --git a/src/libqof/qof/test/test-qofbook.c b/src/libqof/qof/test/test-qofbook.c
index eb1aa2e..b6ad804 100644
--- a/src/libqof/qof/test/test-qofbook.c
+++ b/src/libqof/qof/test/test-qofbook.c
@@ -364,9 +364,6 @@ test_book_increment_and_format_counter ( Fixture *fixture, gconstpointer pData )
     g_free( r );
 }
 
-/* keep this testing of trading accounts, while adding testing of currency-
-   accounting-based trading accounts, so that files prior to version 2.7
-   can be read/processed */
 static void
 test_book_use_trading_accounts( Fixture *fixture, gconstpointer pData )
 {
@@ -389,65 +386,88 @@ test_book_use_trading_accounts( Fixture *fixture, gconstpointer pData )
 }
 
 static void
-test_book_use_trading_accounts_currency_accounting( Fixture *fixture, gconstpointer pData )
+test_book_use_book_currency( Fixture *fixture, gconstpointer pData )
 {
-    g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
+    const gchar *cur;
+    const gchar *pol;
 
-    g_test_message( "Testing with existing currency-accounting set to 'trading'" );
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+
+    g_test_message( "Testing with existing trading accounts set to true - t" );
     qof_book_begin_edit (fixture->book);
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "currency-accounting", "trading",
+		      "trading-accts", "t",
 		      NULL);
-    g_assert( qof_book_use_trading_accounts( fixture-> book ) == TRUE );
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
 
-    g_test_message( "Testing with existing currency-accounting set to 'book-currency'" );
+    g_test_message( "Testing with book-currency set and no default-gains-policy" );
+    qof_book_begin_edit (fixture->book);
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "currency-accounting", "book-currency",
+		      "book-currency", "USD",
 		      NULL);
-    g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , "USD" );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , NULL );
     qof_book_commit_edit (fixture->book);
 
-}
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
 
-static void
-test_book_use_book_currency( Fixture *fixture, gconstpointer pData )
-{
-    const char *cur;
+    g_test_message( "Testing with default-gains-policy set and no book-currency" );
+    qof_book_begin_edit (fixture->book);
+    qof_instance_set (QOF_INSTANCE (fixture->book),
+		      "default-gains-policy", "fifo",
+		      NULL);
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , NULL );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , "fifo" );
+    qof_book_commit_edit (fixture->book);
 
-    g_assert( qof_book_use_book_currency( fixture-> book ) == FALSE );
-    g_assert( qof_book_get_book_currency_unique_name( fixture-> book ) == FALSE );
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
 
+    g_test_message( "Testing with book-currency and default-gains-policy set to nonsense" );
     qof_book_begin_edit (fixture->book);
-    g_test_message( "Testing with currency-accounting set to 'trading' and no book-currency" );
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "currency-accounting", "trading",
+		      "book-currency", "myMoney",
 		      NULL);
-    g_assert( qof_book_use_book_currency( fixture-> book ) == FALSE );
-    g_assert( qof_book_get_book_currency_unique_name( fixture-> book ) == FALSE );
-
-    g_test_message( "Testing with currency-accounting set to 'book-currency' and no book-currency set" );
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "currency-accounting", "book-currency",
+		      "default-gains-policy", "random",
 		      NULL);
-    g_assert( qof_book_use_book_currency( fixture-> book ) == FALSE );
-    g_assert( qof_book_get_book_currency_unique_name( fixture-> book ) == FALSE );
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , "myMoney" );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , "random" );
+    qof_book_commit_edit (fixture->book);
+
+    qof_book_destroy( fixture->book );
+    fixture->book = qof_book_new();
 
-    g_test_message( "Testing with currency-accounting set to 'book-currency' and  book-currency set" );
+    g_test_message( "Testing with book-currency and default-gains-policy set to valid values" );
+    qof_book_begin_edit (fixture->book);
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "book-currency", "CURRENCY::USD",
+		      "book-currency", "USD",
 		      NULL);
-    g_assert( qof_book_use_book_currency( fixture-> book ) == TRUE );
-    cur = qof_book_get_book_currency_unique_name( fixture->book );
-    g_assert_cmpstr( cur, == , "CURRENCY::USD");
-
-    g_test_message( "Testing with currency-accounting set to 'trading' and book-currency still set" );
     qof_instance_set (QOF_INSTANCE (fixture->book),
-		      "currency-accounting", "trading",
+		      "default-gains-policy", "fifo",
 		      NULL);
-    g_assert( qof_book_use_book_currency( fixture-> book ) == FALSE );
-    g_assert( qof_book_get_book_currency_unique_name( fixture-> book ) == FALSE );
+    cur = qof_book_get_book_currency( fixture-> book );
+    g_assert_cmpstr( cur, == , "USD" );
+    pol = qof_book_get_default_gains_policy( fixture-> book );
+    g_assert_cmpstr( pol, == , "fifo" );
     qof_book_commit_edit (fixture->book);
-
 }
 
 static void
@@ -822,7 +842,6 @@ test_suite_qofbook ( void )
     GNC_TEST_ADD( suitename, "get counter format", Fixture, NULL, setup, test_book_get_counter_format, teardown );
     GNC_TEST_ADD( suitename, "increment and format counter", Fixture, NULL, setup, test_book_increment_and_format_counter, teardown );
     GNC_TEST_ADD( suitename, "use trading accounts", Fixture, NULL, setup, test_book_use_trading_accounts, teardown );
-    GNC_TEST_ADD( suitename, "use trading accounts - currency accounting", Fixture, NULL, setup, test_book_use_trading_accounts_currency_accounting, teardown );
     GNC_TEST_ADD( suitename, "use book-currency", Fixture, NULL, setup, test_book_use_book_currency, teardown );
     GNC_TEST_ADD( suitename, "get autofreeze days", Fixture, NULL, setup, test_book_get_num_days_autofreeze, teardown );
     GNC_TEST_ADD( suitename, "use split action for num field", Fixture, NULL, setup, test_book_use_split_action_for_num_field, teardown );



Summary of changes:
 src/app-utils/app-utils.scm           |  12 +
 src/app-utils/business-prefs.scm      |  31 +-
 src/app-utils/gnc-ui-util.c           |  63 ++++
 src/app-utils/gnc-ui-util.h           |  17 ++
 src/app-utils/option-util.c           | 153 +++++++++-
 src/app-utils/option-util.h           |   9 +
 src/app-utils/options.scm             | 211 +++++++++++++
 src/app-utils/test/Makefile.am        |   4 +-
 src/app-utils/test/test-app-utils.c   |   2 +
 src/app-utils/test/test-gnc-ui-util.c | 216 +++++++++++++
 src/app-utils/test/test-option-util.c | 132 +++++++-
 src/engine/engine.i                   |   5 +
 src/engine/policy.c                   |  77 +++++
 src/engine/policy.h                   |  17 ++
 src/engine/test/utest-Split.cpp       |   2 +-
 src/engine/test/utest-Transaction.c   |   4 +-
 src/gnome-utils/dialog-options.c      | 561 ++++++++++++++++++++++++++++++++++
 src/libqof/qof/qofbook.cpp            | 164 ++++------
 src/libqof/qof/qofbook.h              |  18 +-
 src/libqof/qof/qofbookslots.h         |   6 +-
 src/libqof/qof/test/test-qofbook.c    |  97 +++---
 21 files changed, 1627 insertions(+), 174 deletions(-)
 create mode 100644 src/app-utils/test/test-gnc-ui-util.c



More information about the gnucash-changes mailing list