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
This commit is contained in:
Alex Aycinena
2015-06-27 16:06:56 -07:00
parent 06d5d0a20a
commit 5fdf14f8cb
21 changed files with 1671 additions and 218 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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 *

View File

@@ -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,

View File

@@ -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))

View File

@@ -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} \

View File

@@ -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);

View File

@@ -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@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@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 );
}

View File

@@ -60,16 +60,30 @@ 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");
qof_commit_edit (QOF_INSTANCE (book));
}
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)
{
@@ -81,18 +95,96 @@ 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);
gnc_option_db_destroy (odb);
}
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)
{
@@ -100,9 +192,12 @@ test_option_save_to_kvp (Fixture *fixture, gconstpointer pData)
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);
}

View File

@@ -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");

View File

@@ -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)
{

View File

@@ -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:

View File

@@ -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));

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,13 +141,6 @@ qof_book_get_property (GObject* object,
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_CURRENCY_ACCOUNTING:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_CURRENCY_ACCOUNTING);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_BOOK_CURRENCY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
@@ -159,6 +148,13 @@ qof_book_get_property (GObject* object,
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_DEFAULT_GAINS_POLICY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_POLICY);
qof_instance_get_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_AUTO_READONLY_DAYS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
@@ -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,13 +212,6 @@ qof_book_set_property (GObject *object,
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_CURRENCY_ACCOUNTING:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_CURRENCY_ACCOUNTING);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_BOOK_CURRENCY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
@@ -229,6 +219,13 @@ qof_book_set_property (GObject *object,
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_DEFAULT_GAINS_POLICY:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_POLICY);
qof_instance_set_kvp (QOF_INSTANCE (book), key, value);
g_free (key);
break;
case PROP_OPT_AUTO_READONLY_DAYS:
key = g_strdup_printf ("%s/%s/%s", KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
@@ -284,22 +281,6 @@ qof_book_class_init (QofBookClass *klass)
NULL,
G_PARAM_READWRITE));
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,
@@ -307,7 +288,19 @@ qof_book_class_init (QofBookClass *klass)
"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,63 +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)
{
KvpFrame *kvp;
KvpValue *value;
if (!book)
{
PWARN ("No book!!!");
return CURRENCY_ACCOUNTING_NEITHER;
}
/* Get the KVP from the current book */
kvp = qof_instance_get_slots (QOF_INSTANCE (book));
if (!kvp)
{
PWARN ("Book has no KVP_Frame");
return CURRENCY_ACCOUNTING_NEITHER;
}
/* Get the Currency Accounting Method */
value = kvp_frame_get_slot_path (kvp,
KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_CURRENCY_ACCOUNTING,
NULL);
if (value)
{
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 CURRENCY_ACCOUNTING_NEITHER;
}
/* Returns pointer to Book Currency unique_name for book or NULL */
/** 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_unique_name (QofBook *book)
qof_book_get_book_currency (QofBook *book)
{
KvpFrame *kvp;
KvpValue *value;
@@ -971,30 +914,14 @@ qof_book_get_book_currency_unique_name (QofBook *book)
return NULL;
}
/* Get the Currency Accounting Method */
value = kvp_frame_get_slot_path (kvp,
KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_CURRENCY_ACCOUNTING,
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 */
/* See if there is a 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 book-currency */
{
return NULL;
}
@@ -1002,32 +929,59 @@ qof_book_get_book_currency_unique_name (QofBook *book)
return kvp_value_get_string (value);
}
/** 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)
{
KvpFrame *kvp;
KvpValue *value;
if (!book)
{
PWARN ("No book!!!");
return NULL;
}
/* Get the KVP from the current book */
kvp = qof_instance_get_slots (QOF_INSTANCE (book));
if (!kvp)
{
PWARN ("Book has no KVP_Frame");
return NULL;
}
/* See if there is a default gain/loss policy */
value = kvp_frame_get_slot_path (kvp,
KVP_OPTION_PATH,
OPTION_SECTION_ACCOUNTS,
OPTION_NAME_DEFAULT_GAINS_POLICY,
NULL);
if (!value)
/* No default gain/loss policy, therefore not valid book-currency
accounting method */
{
return NULL;
}
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;
}

View File

@@ -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 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 Book Currency unique_name for book or NULL */
const gchar * qof_book_get_book_currency_unique_name (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. */

View File

@@ -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

View File

@@ -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 )
{
@@ -388,66 +385,89 @@ test_book_use_trading_accounts( Fixture *fixture, gconstpointer pData )
}
static void
test_book_use_trading_accounts_currency_accounting( Fixture *fixture, gconstpointer pData )
{
g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
g_test_message( "Testing with existing currency-accounting set to 'trading'" );
qof_book_begin_edit (fixture->book);
qof_instance_set (QOF_INSTANCE (fixture->book),
"currency-accounting", "trading",
NULL);
g_assert( qof_book_use_trading_accounts( fixture-> book ) == TRUE );
g_test_message( "Testing with existing currency-accounting set to 'book-currency'" );
qof_instance_set (QOF_INSTANCE (fixture->book),
"currency-accounting", "book-currency",
NULL);
g_assert( qof_book_use_trading_accounts( fixture-> book ) == FALSE );
qof_book_commit_edit (fixture->book);
}
static void
test_book_use_book_currency( Fixture *fixture, gconstpointer pData )
{
const char *cur;
const gchar *cur;
const gchar *pol;
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, == , 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);
g_test_message( "Testing with currency-accounting set to 'trading' and no book-currency" );
qof_instance_set (QOF_INSTANCE (fixture->book),
"currency-accounting", "trading",
"trading-accts", "t",
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",
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 book-currency set" );
qof_instance_set (QOF_INSTANCE (fixture->book),
"book-currency", "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",
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, == , 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 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 = 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();
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);
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 = 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 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", "USD",
NULL);
qof_instance_set (QOF_INSTANCE (fixture->book),
"default-gains-policy", "fifo",
NULL);
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 );