mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
GncOptionMultichoiceValue allow setting a default selection.
Instead of arbitrarily using the first allowed value. Also update tests for the Scheme type addition to GncMultichoiceOptionChoices, intercept more cases where the value needs to be transformed, and go back to emitting a string instead of throwing in GncOptionMultichoiceValue::get_value when m_values has more than one value.
This commit is contained in:
parent
c62b526ba0
commit
534a7c2893
@ -576,7 +576,7 @@ public:
|
||||
if (vec.size() == 1)
|
||||
return std::get<0>(m_choices.at(vec[0]));
|
||||
else
|
||||
throw std::length_error("Retrieving multiple values from a multichoice isn't implemented.");
|
||||
return c_list_string;
|
||||
|
||||
}
|
||||
const std::string& get_default_value() const
|
||||
|
@ -990,11 +990,19 @@ gnc_register_account_sel_limited_option(GncOptionDB* db,
|
||||
void
|
||||
gnc_register_multichoice_option(GncOptionDB* db, const char* section,
|
||||
const char* name, const char* key,
|
||||
const char* doc_string,
|
||||
const char* doc_string, const char* default_val,
|
||||
GncMultichoiceOptionChoices&& choices)
|
||||
{
|
||||
std::string defval{default_val};
|
||||
auto found{std::find_if(choices.begin(), choices.end(),
|
||||
[&defval](auto& choice)->bool {
|
||||
return defval == std::get<0>(choice);
|
||||
})};
|
||||
if (found == choices.end())
|
||||
defval = (choices.empty() ? std::string{"None"} :
|
||||
std::get<0>(choices.at(0)));
|
||||
GncOption option{GncOptionMultichoiceValue{section, name, key, doc_string,
|
||||
std::get<0>(choices.at(0)).c_str(), std::move(choices)}};
|
||||
defval.c_str(), std::move(choices)}};
|
||||
db->register_option(section, std::move(option));
|
||||
}
|
||||
|
||||
@ -1471,7 +1479,7 @@ gnc_option_db_lookup_string_value(GncOptionDB* odb, const char* section, const c
|
||||
{
|
||||
auto value{odb->lookup_string_option(section, name)};
|
||||
if (value.empty())
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
return strdup(value.c_str());
|
||||
}
|
||||
|
||||
|
@ -383,6 +383,7 @@ inline void gnc_register_account_sel_limited_option(GncOptionDBPtr& db,
|
||||
void gnc_register_multichoice_option(GncOptionDB* db,
|
||||
const char* section, const char* name,
|
||||
const char* key, const char* doc_string,
|
||||
const char* default_val,
|
||||
GncMultichoiceOptionChoices&& value);
|
||||
|
||||
/**
|
||||
@ -391,10 +392,12 @@ void gnc_register_multichoice_option(GncOptionDB* db,
|
||||
inline void gnc_register_multichoice_option(GncOptionDBPtr& db,
|
||||
const char* section, const char* name,
|
||||
const char* key, const char* doc_string,
|
||||
const char* default_val,
|
||||
GncMultichoiceOptionChoices&& value)
|
||||
{
|
||||
gnc_register_multichoice_option(db.get(), section, name,
|
||||
key, doc_string, std::move(value));
|
||||
key, doc_string, default_val,
|
||||
std::move(value));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -441,7 +441,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
%ignore gnc_register_account_list_limited_option(GncOptionDB*, const char*, const char*, const char*, const char*, const GncOptionAccountList&, GncOptionAccountTypeList&&);
|
||||
%ignore gnc_register_account_list_option(GncOptionDB*, const char*, const char*, const char*, const char*, const GncOptionAccountList&);
|
||||
%ignore gnc_register_account_sel_limited_option(GncOptionDB*, const char*, const char*, const char*, const char*, const GncOptionAccountList&, GncOptionAccountTypeList&&);
|
||||
%ignore gnc_register_multichoice_option(GncOptionDB*, const char*, const char*, const char*, const char*, GncMultichoiceOptionChoices&&);
|
||||
%ignore gnc_register_multichoice_option(GncOptionDB*, const char*, const char*, const char*, const char*, const char*, GncMultichoiceOptionChoices&&);
|
||||
%ignore gnc_register_list_option(GncOptionDB*, const char*, const char*, const char*, const char*, const char*, GncMultichoiceOptionChoices&&);
|
||||
%ignore gnc_register_number_Plot_size_option(GncOptionDB*, const char*, const char*, const char*, const char*, int);
|
||||
%ignore gnc_register_query_option(GncOptionDB*, const char*, const char*, const char*, const char*, QofQuery*);
|
||||
@ -497,12 +497,16 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
"(end-next-year RelativeDatePeriod-END-NEXT-YEAR)"
|
||||
"(start-accounting-period RelativeDatePeriod-START-ACCOUNTING-PERIOD)"
|
||||
"(end-accounting-period RelativeDatePeriod-END-ACCOUNTING-PERIOD))");
|
||||
|
||||
return reldate_values;
|
||||
}
|
||||
%}
|
||||
|
||||
%ignore GncOptionMultichoiceKeyType;
|
||||
|
||||
%inline %{
|
||||
SCM get_scm_value(const GncOptionMultichoiceValue& option)
|
||||
inline SCM scm_from_multichoices (const GncMultichoiceOptionIndexVec& indexes,
|
||||
const GncOptionMultichoiceValue& option)
|
||||
{
|
||||
using KeyType = GncOptionMultichoiceKeyType;
|
||||
auto scm_value = [](const char* value, KeyType keytype) -> SCM {
|
||||
@ -514,15 +518,12 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
case KeyType::STRING:
|
||||
return scm_str;
|
||||
case KeyType::NUMBER:
|
||||
return scm_string_to_number(scm_str, scm_from_int(10));
|
||||
return scm_string_to_number(scm_str,
|
||||
scm_from_int(10));
|
||||
};
|
||||
return SCM_BOOL_F;
|
||||
};
|
||||
|
||||
auto indexes = option.get_multiple();
|
||||
if (indexes.empty())
|
||||
indexes = option.get_default_multiple();
|
||||
if (indexes.empty())
|
||||
return SCM_BOOL_F;
|
||||
if (indexes.size() == 1) // FIXME: Should use bool member to decide
|
||||
return scm_value(option.permissible_value(indexes[0]),
|
||||
option.get_keytype(indexes[0]));
|
||||
@ -536,6 +537,27 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
return scm_reverse(values);
|
||||
}
|
||||
|
||||
|
||||
SCM get_scm_value(const GncOptionMultichoiceValue& option)
|
||||
{
|
||||
|
||||
auto indexes = option.get_multiple();
|
||||
if (indexes.empty())
|
||||
indexes = option.get_default_multiple();
|
||||
if (indexes.empty())
|
||||
return SCM_BOOL_F;
|
||||
return scm_from_multichoices(indexes, option);
|
||||
}
|
||||
|
||||
SCM get_scm_default_value(const GncOptionMultichoiceValue& option)
|
||||
{
|
||||
|
||||
auto indexes = option.get_default_multiple();
|
||||
if (indexes.empty())
|
||||
return SCM_BOOL_F;
|
||||
return scm_from_multichoices(indexes, option);
|
||||
}
|
||||
|
||||
SCM get_scm_value(const GncOptionRangeValue<int>& option)
|
||||
{
|
||||
auto val{option.get_value()};
|
||||
@ -543,6 +565,13 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
return scm_cons(desig, scm_from_int(val));
|
||||
}
|
||||
|
||||
SCM get_scm_default_value(const GncOptionRangeValue<int>& option)
|
||||
{
|
||||
auto val{option.get_default_value()};
|
||||
auto desig{scm_c_eval_string(val > 100 ? "'pixels" : "'percent")};
|
||||
return scm_cons(desig, scm_from_int(val));
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%include "gnc-option-date.hpp"
|
||||
@ -581,6 +610,11 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
if (!$self)
|
||||
return SCM_BOOL_F;
|
||||
return std::visit([](const auto& option)->SCM {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
|
||||
GncOptionMultichoiceValue> ||
|
||||
std::is_same_v<std::decay_t<decltype(option)>,
|
||||
GncOptionRangeValue<int>>)
|
||||
return get_scm_default_value(option);
|
||||
auto value{option.get_default_value()};
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(value)>,
|
||||
SCM>)
|
||||
@ -705,14 +739,20 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
GncOption* gnc_make_multichoice_option(const char* section,
|
||||
const char* name, const char* key,
|
||||
const char* doc_string,
|
||||
const char* default_val,
|
||||
GncMultichoiceOptionChoices&& choices)
|
||||
{
|
||||
try {
|
||||
std::string defval{default_val};
|
||||
auto found{std::find_if(choices.begin(), choices.end(),
|
||||
[&defval](auto& choice)->bool {
|
||||
return defval == std::get<0>(choice);
|
||||
})};
|
||||
if (found == choices.end())
|
||||
defval = (choices.empty() ? std::string{"None"} :
|
||||
std::get<0>(choices.at(0)));
|
||||
return new GncOption{GncOptionMultichoiceValue{section, name, key,
|
||||
doc_string,
|
||||
choices.empty() ? "None" :
|
||||
std::get<0>(choices.at(0)).c_str(),
|
||||
std::move(choices)}};
|
||||
doc_string, defval.c_str(), std::move(choices)}};
|
||||
}
|
||||
catch (const std::exception& err)
|
||||
{
|
||||
|
@ -949,18 +949,20 @@ TEST_F(GncOptionAccountTest, test_account_list_from_scheme)
|
||||
EXPECT_EQ(acclist[1], sel_option.get_value<GncOptionAccountList>()[0]);
|
||||
}
|
||||
|
||||
using KT = GncOptionMultichoiceKeyType;
|
||||
class GncOptionMultichoiceTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
GncOptionMultichoiceTest() :
|
||||
m_option{GncOptionMultichoiceValue{"foo", "bar", "baz",
|
||||
"Phony Option", "plugh",
|
||||
{
|
||||
{"plugh", "xyzzy", "thud"},
|
||||
{"waldo", "pepper", "salt"},
|
||||
{"pork", "sausage", "links"},
|
||||
{"corge", "grault", "garply"}
|
||||
}}} {}
|
||||
m_option{GncOptionMultichoiceValue
|
||||
{"foo", "bar", "baz",
|
||||
"Phony Option", "plugh",
|
||||
{
|
||||
{"plugh", "xyzzy", "thud", KT::STRING},
|
||||
{"waldo", "pepper", "salt", KT::STRING},
|
||||
{"pork", "sausage", "links", KT::STRING},
|
||||
{"corge", "grault", "garply", KT::STRING}
|
||||
}}} {}
|
||||
GncOption m_option;
|
||||
};
|
||||
|
||||
@ -1052,15 +1054,15 @@ class GncOptionListTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
GncOptionListTest() :
|
||||
m_option{GncOptionMultichoiceValue{"foo", "bar", "baz",
|
||||
"Phony Option",
|
||||
GncMultichoiceOptionIndexVec{0, 2},
|
||||
{
|
||||
{"plugh", "xyzzy", "thud"},
|
||||
{"waldo", "pepper", "salt"},
|
||||
{"pork", "sausage", "links"},
|
||||
{"corge", "grault", "garply"}
|
||||
}}} {}
|
||||
m_option{GncOptionMultichoiceValue{
|
||||
"foo", "bar", "baz", "Phony Option",
|
||||
GncMultichoiceOptionIndexVec{0, 2},
|
||||
{
|
||||
{"plugh", "xyzzy", "thud", KT::STRING},
|
||||
{"waldo", "pepper", "salt", KT::STRING},
|
||||
{"pork", "sausage", "links", KT::STRING},
|
||||
{"corge", "grault", "garply", KT::STRING}
|
||||
}}} {}
|
||||
GncOption m_option;
|
||||
};
|
||||
|
||||
|
@ -174,15 +174,18 @@ TEST_F(GncOptionDBTest, test_register_account_sel_limited_option_fail_construct)
|
||||
EXPECT_FALSE(m_db->find_option("foo", "bar"));
|
||||
}
|
||||
|
||||
using KT = GncOptionMultichoiceKeyType;
|
||||
TEST_F(GncOptionDBTest, test_register_multichoice_option)
|
||||
{
|
||||
GncMultichoiceOptionChoices choices{
|
||||
{ "plugh", "xyzzy", "thud"},
|
||||
{ "waldo", "pepper", "salt"},
|
||||
{ "pork", "sausage", "links"},
|
||||
{ "corge", "grault", "garply"}};
|
||||
{ "plugh", "xyzzy", "thud", KT::STRING},
|
||||
{ "waldo", "pepper", "salt", KT::STRING},
|
||||
{ "pork", "sausage", "links", KT::STRING},
|
||||
{ "corge", "grault", "garply", KT::STRING}};
|
||||
gnc_register_multichoice_option(m_db, "foo", "bar", "baz",
|
||||
"Phony Option", std::move(choices));
|
||||
"Phony Option", "waldo",
|
||||
std::move(choices));
|
||||
EXPECT_STREQ("waldo", m_db->lookup_string_option("foo", "bar").c_str());
|
||||
ASSERT_TRUE(m_db->set_option("foo", "bar", std::string{"corge"}));
|
||||
EXPECT_STREQ("corge", m_db->lookup_string_option("foo", "bar").c_str());
|
||||
}
|
||||
|
@ -23,6 +23,19 @@
|
||||
|
||||
(use-modules (srfi srfi-64))
|
||||
(use-modules (tests srfi64-extras))
|
||||
|
||||
;; This is a special case where we can't use the exported registration function
|
||||
;; because we need to transform the default argument first depending on its
|
||||
;; Scheme type.
|
||||
(define (gnc:register-multichoice-option options section name key docstring default multichoice)
|
||||
(issue-deprecation-warning "gnc:make-multichoice-option is deprecated. Make and register the option in one command with gnc-register-multichoice-option.")
|
||||
(let ((defval (cond ((symbol? default)
|
||||
(symbol->string default))
|
||||
((number? default)
|
||||
(number->string default))
|
||||
(else default))))
|
||||
(gnc-register-multichoice-option options section name key docstring defval multichoice)))
|
||||
|
||||
;; Load the C++ option implementation, avoiding the options.scm ones.
|
||||
(eval-when
|
||||
(compile load eval expand)
|
||||
@ -154,17 +167,17 @@
|
||||
(let* ((option-db (new-gnc-optiondb))
|
||||
(multilist (list
|
||||
(list "plugh" (cons 'text "xyzzy") (cons 'tip "thud"))
|
||||
(list "waldo" (cons 'text "pepper") (cons 'tip "salt"))
|
||||
(list 'waldo (cons 'text "pepper") (cons 'tip "salt"))
|
||||
(list "pork" (cons 'text "sausage") (cons 'tip "links"))
|
||||
(list "corge" (cons 'text "grault") (cons 'tip "garply"))))
|
||||
(multichoice (keylist->vectorlist multilist))
|
||||
(multi-opt (gnc-register-multichoice-option option-db "foo" "bar" "baz"
|
||||
"Phony Option" multichoice)))
|
||||
(multi-opt (gnc:register-multichoice-option option-db "foo" "bar" "baz"
|
||||
"Phony Option" 'waldo multichoice)))
|
||||
|
||||
(test-equal "plugh" (gnc-option-value option-db "foo" "bar"))
|
||||
(test-equal 'waldo (gnc-option-value option-db "foo" "bar"))
|
||||
(gnc-set-option option-db "foo" "bar" "corge")
|
||||
(test-equal "corge" (gnc-option-value option-db "foo" "bar"))
|
||||
(test-equal "plugh" (gnc-option-default-value option-db "foo" "bar")))
|
||||
(test-equal 'waldo (gnc-option-default-value option-db "foo" "bar")))
|
||||
(test-end "test-gnc-test-multichoice-option"))
|
||||
|
||||
(define (test-gnc-make-list-option)
|
||||
|
Loading…
Reference in New Issue
Block a user