mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-01 13:09:41 -06:00
Support different GncOptionMultichoiceValue key types.
Scheme can use strings, symbols, or ints as keys in multichoice options, but C++ can handle only strings. Add conversion and tracking so that the right key type gets sent back to Scheme.
This commit is contained in:
parent
55a2ed1df8
commit
fba0248548
@ -500,7 +500,8 @@ operator>> (std::istream& iss, OptType& opt)
|
||||
|
||||
using GncMultichoiceOptionEntry = std::tuple<const std::string,
|
||||
const std::string,
|
||||
const std::string>;
|
||||
const std::string,
|
||||
GncOptionMultichoiceKeyType>;
|
||||
using GncMultichoiceOptionIndexVec = std::vector<std::size_t>;
|
||||
using GncMultichoiceOptionChoices = std::vector<GncMultichoiceOptionEntry>;
|
||||
|
||||
@ -575,7 +576,8 @@ public:
|
||||
if (vec.size() == 1)
|
||||
return std::get<0>(m_choices.at(vec[0]));
|
||||
else
|
||||
return c_list_string;
|
||||
throw std::length_error("Retrieving multiple values from a multichoice isn't implemented.");
|
||||
|
||||
}
|
||||
const std::string& get_default_value() const
|
||||
{
|
||||
@ -671,6 +673,7 @@ public:
|
||||
bool is_changed() const noexcept { return m_value != m_default_value; }
|
||||
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
|
||||
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
|
||||
GncOptionMultichoiceKeyType get_keytype(unsigned i) const { return std::get<3>(m_choices.at(i)); }
|
||||
private:
|
||||
std::size_t find_key (const std::string& key) const noexcept
|
||||
{
|
||||
|
@ -63,6 +63,13 @@ using GncOptionVariant = std::variant<GncOptionValue<std::string>,
|
||||
|
||||
using GncOptionVariantPtr = std::unique_ptr<GncOptionVariant>;
|
||||
|
||||
enum class GncOptionMultichoiceKeyType
|
||||
{
|
||||
SYMBOL,
|
||||
STRING,
|
||||
NUMBER,
|
||||
};
|
||||
|
||||
class GncOption
|
||||
{
|
||||
public:
|
||||
|
@ -51,7 +51,8 @@ using GncOptionAccountList = std::vector<const Account*>;
|
||||
using GncOptionAccountTypeList = std::vector<GNCAccountType>;
|
||||
using GncMultichoiceOptionEntry = std::tuple<const std::string,
|
||||
const std::string,
|
||||
const std::string>;
|
||||
const std::string,
|
||||
GncOptionMultichoiceKeyType>;
|
||||
using GncMultichoiceOptionChoices = std::vector<GncMultichoiceOptionEntry>;
|
||||
|
||||
/**
|
||||
|
@ -256,14 +256,34 @@ gnc_option_test_book_destroy(QofBook* book)
|
||||
|
||||
%typemap(in) GncMultichoiceOptionChoices&& (GncMultichoiceOptionChoices choices)
|
||||
{
|
||||
using KeyType = GncOptionMultichoiceKeyType;
|
||||
auto len = scm_to_size_t(scm_length($input));
|
||||
for (std::size_t i = 0; i < len; ++i)
|
||||
{
|
||||
SCM vec = scm_list_ref($input, scm_from_size_t(i));
|
||||
std::string key{scm_to_utf8_string(SCM_SIMPLE_VECTOR_REF(vec, 0))};
|
||||
SCM keyval, v_ref_0 = SCM_SIMPLE_VECTOR_REF(vec, 0);
|
||||
GncOptionMultichoiceKeyType keytype;
|
||||
if (scm_is_symbol(v_ref_0))
|
||||
{
|
||||
keyval = scm_symbol_to_string(SCM_SIMPLE_VECTOR_REF(vec, 0));
|
||||
keytype = KeyType::SYMBOL;
|
||||
}
|
||||
else if (scm_is_string(v_ref_0))
|
||||
{
|
||||
keyval = SCM_SIMPLE_VECTOR_REF(vec, 0);
|
||||
keytype = KeyType::STRING;
|
||||
}
|
||||
else if (scm_is_integer(v_ref_0))
|
||||
{
|
||||
keyval = scm_number_to_string(v_ref_0, scm_from_uint(10u));
|
||||
keytype = KeyType::NUMBER;
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("Unsupported key type in multichoice option.");
|
||||
std::string key{scm_to_utf8_string(keyval)};
|
||||
std::string name{scm_to_utf8_string(SCM_SIMPLE_VECTOR_REF(vec, 1))};
|
||||
std::string desc{scm_to_utf8_string(SCM_SIMPLE_VECTOR_REF(vec, 2))};
|
||||
choices.push_back({std::move(key), std::move(name), std::move(desc)});
|
||||
choices.push_back({std::move(key), std::move(name), std::move(desc), keytype});
|
||||
}
|
||||
$1 = &choices;
|
||||
}
|
||||
@ -404,6 +424,45 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
%ignore gnc_register_start_date_option(GncOptionDB*, const char*, const char*, const char*, const char*, bool);
|
||||
%ignore gnc_register_end_date_option(GncOptionDB*, const char*, const char*, const char*, const char*, bool);
|
||||
|
||||
|
||||
%ignore GncOptionMultichoiceKeyType;
|
||||
/* Replace GncOptionMultichoiceValue::get_value with one that restores the keytype that Scheme sent it. */
|
||||
%inline %{
|
||||
SCM get_scm_value(const GncOptionMultichoiceValue& option)
|
||||
{
|
||||
using KeyType = GncOptionMultichoiceKeyType;
|
||||
auto scm_value = [](const char* value, KeyType keytype) -> SCM {
|
||||
auto scm_str{scm_from_utf8_string(value)};
|
||||
switch (keytype)
|
||||
{
|
||||
case KeyType::SYMBOL:
|
||||
return scm_string_to_symbol(scm_str);
|
||||
case KeyType::STRING:
|
||||
return scm_str;
|
||||
case KeyType::NUMBER:
|
||||
return scm_string_to_number(scm_str, scm_from_int(10));
|
||||
};
|
||||
};
|
||||
|
||||
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]));
|
||||
auto values{scm_list_1(SCM_UNDEFINED)};
|
||||
for(auto index : indexes)
|
||||
{
|
||||
auto val{scm_list_1(scm_value(option.permissible_value(index),
|
||||
option.get_keytype(index)))};
|
||||
values = scm_append(scm_list_2(val, values));
|
||||
}
|
||||
return scm_reverse(values);
|
||||
}
|
||||
%}
|
||||
|
||||
%include "gnc-option-date.hpp"
|
||||
%include "gnc-option.hpp"
|
||||
%include "gnc-option-impl.hpp"
|
||||
@ -421,6 +480,9 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
SCM get_scm_value()
|
||||
{
|
||||
return std::visit([](const auto& option)->SCM {
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
|
||||
GncOptionMultichoiceValue>)
|
||||
return get_scm_value(option);
|
||||
auto value{option.get_value()};
|
||||
if constexpr (std::is_same_v<std::decay_t<decltype(value)>,
|
||||
SCM>)
|
||||
|
Loading…
Reference in New Issue
Block a user