Add a multiselect boolean member to GncOptionAccountValue.

To support a variation available in dialog-options. Even though it's not
used in any GnuCash code nor documented anywhere it might be in some
custom reports.
This commit is contained in:
John Ralls 2020-03-10 14:48:06 -07:00
parent fce33799af
commit 3200bd4966
5 changed files with 50 additions and 25 deletions

View File

@ -37,7 +37,8 @@ GncOptionAccountValue::validate(const GncOptionAccountList& values) const
{ {
if (values.empty()) if (values.empty())
return false; return false;
if (get_ui_type() == GncOptionUIType::ACCOUNT_SEL && values.size() != 1) if ((get_ui_type() == GncOptionUIType::ACCOUNT_SEL || !m_multiselect) &&
values.size() != 1)
return false; return false;
if (m_allowed.empty()) if (m_allowed.empty())
return true; return true;

View File

@ -544,32 +544,32 @@ class GncOptionAccountValue : public OptionClassifier
public: public:
GncOptionAccountValue(const char* section, const char* name, GncOptionAccountValue(const char* section, const char* name,
const char* key, const char* doc_string, const char* key, const char* doc_string,
GncOptionUIType ui_type) : GncOptionUIType ui_type, bool multi=true) :
OptionClassifier{section, name, key, doc_string}, OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_ui_type{ui_type}, m_value{}, m_default_value{}, m_allowed{} {} m_value{}, m_default_value{}, m_allowed{}, m_multiselect{multi} {}
GncOptionAccountValue(const char* section, const char* name, GncOptionAccountValue(const char* section, const char* name,
const char* key, const char* doc_string, const char* key, const char* doc_string,
GncOptionUIType ui_type, GncOptionUIType ui_type,
const GncOptionAccountList& value) : const GncOptionAccountList& value, bool multi=true) :
OptionClassifier{section, name, key, doc_string}, OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_ui_type{ui_type}, m_value{value}, m_value{value}, m_default_value{std::move(value)}, m_allowed{},
m_default_value{std::move(value)}, m_allowed{} {} m_multiselect{multi} {}
GncOptionAccountValue(const char* section, const char* name, GncOptionAccountValue(const char* section, const char* name,
const char* key, const char* doc_string, const char* key, const char* doc_string,
GncOptionUIType ui_type, GncOptionUIType ui_type,
GncOptionAccountTypeList&& allowed) : GncOptionAccountTypeList&& allowed, bool multi=true) :
OptionClassifier{section, name, key, doc_string}, OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_ui_type{ui_type}, m_value{}, m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
m_default_value{}, m_allowed{std::move(allowed)} {} m_multiselect{multi} {}
GncOptionAccountValue(const char* section, const char* name, GncOptionAccountValue(const char* section, const char* name,
const char* key, const char* doc_string, const char* key, const char* doc_string,
GncOptionUIType ui_type, GncOptionUIType ui_type,
const GncOptionAccountList& value, const GncOptionAccountList& value,
GncOptionAccountTypeList&& allowed) : GncOptionAccountTypeList&& allowed, bool multi=true) :
OptionClassifier{section, name, key, doc_string}, OptionClassifier{section, name, key, doc_string}, m_ui_type{ui_type},
m_ui_type{ui_type}, m_value{}, m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
m_default_value{}, m_allowed{std::move(allowed)} { m_multiselect{multi} {
if (!validate(value)) if (!validate(value))
throw std::invalid_argument("Supplied Value not in allowed set."); throw std::invalid_argument("Supplied Value not in allowed set.");
m_value = value; m_value = value;
@ -588,11 +588,13 @@ public:
bool is_changed() const noexcept { return m_value != m_default_value; } bool is_changed() const noexcept { return m_value != m_default_value; }
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; } GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; } void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
bool is_multiselect() const noexcept { return m_multiselect; }
private: private:
GncOptionUIType m_ui_type; GncOptionUIType m_ui_type;
GncOptionAccountList m_value; GncOptionAccountList m_value;
GncOptionAccountList m_default_value; GncOptionAccountList m_default_value;
GncOptionAccountTypeList m_allowed; GncOptionAccountTypeList m_allowed;
bool m_multiselect;
}; };
template<> inline std::ostream& template<> inline std::ostream&

View File

@ -201,6 +201,18 @@ GncOption::is_changed() const noexcept
}, *m_option); }, *m_option);
} }
bool
GncOption::is_multiselect() const noexcept
{
return std::visit([](const auto& option)->bool {
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
GncOptionAccountValue>)
return option.is_multiselect();
else
return false;
}, *m_option);
}
template<typename ValueType> bool template<typename ValueType> bool
GncOption::validate(ValueType value) const GncOption::validate(ValueType value) const
{ {

View File

@ -86,6 +86,7 @@ public:
void set_option_from_ui_item(); void set_option_from_ui_item();
void make_internal(); void make_internal();
bool is_changed() const noexcept; bool is_changed() const noexcept;
bool is_multiselect() const noexcept;
template <typename ValueType> bool validate(ValueType value) const; template <typename ValueType> bool validate(ValueType value) const;
std::size_t num_permissible_values() const; std::size_t num_permissible_values() const;
std::size_t permissible_value_index(const char* value) const; std::size_t permissible_value_index(const char* value) const;

View File

@ -757,29 +757,34 @@ TEST_F(GncOptionAccountTest, test_option_value_limited_constructor)
EXPECT_THROW({ EXPECT_THROW({
GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option", GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
acclistbad, {ACCT_TYPE_BANK}); acclistbad,
GncOptionAccountTypeList{ACCT_TYPE_BANK});
}, std::invalid_argument); }, std::invalid_argument);
EXPECT_THROW({ EXPECT_THROW({
GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option", GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_SEL, GncOptionUIType::ACCOUNT_SEL,
acclistgood, {ACCT_TYPE_BANK}); acclistgood,
GncOptionAccountTypeList{ACCT_TYPE_BANK});
}, std::invalid_argument); }, std::invalid_argument);
EXPECT_NO_THROW({ EXPECT_NO_THROW({
GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option", GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
acclistgood, {ACCT_TYPE_BANK}); acclistgood,
GncOptionAccountTypeList{ACCT_TYPE_BANK});
}); });
EXPECT_NO_THROW({ EXPECT_NO_THROW({
GncOptionAccountList accsel{acclistgood[0]}; GncOptionAccountList accsel{acclistgood[0]};
GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option", GncOptionAccountValue option("foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
accsel, {ACCT_TYPE_BANK}); accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK});
}); });
GncOptionAccountValue option {"foo", "bar", "baz", "Bogus Option", GncOptionAccountValue option {"foo", "bar", "baz", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, acclistgood, {ACCT_TYPE_BANK}}; GncOptionUIType::ACCOUNT_LIST, acclistgood,
GncOptionAccountTypeList{ACCT_TYPE_BANK}};
EXPECT_FALSE(option.get_value().empty()); EXPECT_FALSE(option.get_value().empty());
EXPECT_FALSE(option.get_default_value().empty()); EXPECT_FALSE(option.get_default_value().empty());
EXPECT_EQ(true, option.validate(acclistgood)); EXPECT_EQ(true, option.validate(acclistgood));
@ -804,7 +809,8 @@ TEST_F(GncOptionAccountTest, test_account_list_out)
GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz", GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz",
"Bogus Option", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
accsel, {ACCT_TYPE_BANK}}}; accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
acc_guids = gnc::GUID{*qof_instance_get_guid(accsel[0])}.to_string(); acc_guids = gnc::GUID{*qof_instance_get_guid(accsel[0])}.to_string();
oss.str(""); oss.str("");
@ -830,7 +836,8 @@ TEST_F(GncOptionAccountTest, test_account_list_in)
GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz", GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz",
"Bogus Option", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
accsel, {ACCT_TYPE_BANK}}}; accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
GncOptionAccountList acclistbad{list_of_types({ACCT_TYPE_STOCK})}; GncOptionAccountList acclistbad{list_of_types({ACCT_TYPE_STOCK})};
acc_guids = gnc::GUID{*qof_instance_get_guid(acclistbad[1])}.to_string(); acc_guids = gnc::GUID{*qof_instance_get_guid(acclistbad[1])}.to_string();
acc_guids += " "; acc_guids += " ";
@ -885,7 +892,8 @@ TEST_F(GncOptionAccountTest, test_account_list_to_scheme)
GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz", GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz",
"Bogus Option", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
accsel, {ACCT_TYPE_BANK}}}; accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
acc_guids = make_account_list_SCM_str(accsel); acc_guids = make_account_list_SCM_str(accsel);
oss.str(""); oss.str("");
@ -909,7 +917,8 @@ TEST_F(GncOptionAccountTest, test_account_list_from_scheme)
GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz", GncOption sel_option{GncOptionAccountValue{"foo", "bar", "baz",
"Bogus Option", "Bogus Option",
GncOptionUIType::ACCOUNT_LIST, GncOptionUIType::ACCOUNT_LIST,
accsel, {ACCT_TYPE_BANK}}}; accsel,
GncOptionAccountTypeList{ACCT_TYPE_BANK}}};
GncOptionAccountList acclistbad{list_of_types({ACCT_TYPE_STOCK})}; GncOptionAccountList acclistbad{list_of_types({ACCT_TYPE_STOCK})};
acc_guids = make_account_list_SCM_str(acclistbad); acc_guids = make_account_list_SCM_str(acclistbad);
iss.str(acc_guids); iss.str(acc_guids);