mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-26 10:51:09 -06:00
c++options: Serialize and deserialize to strings instead of streams.
And use serialize to create values for gnc:generate-restore-forms and both of them for the meat of the stream functions. This fixes in particular QofInstance serialization where passing the option value directly to scheme format resulted in a notation about a swig pointer instead of the desired GUID string or commodity namespace and mnemonic strings.
This commit is contained in:
parent
c3b8b6cc49
commit
6f93a68bad
@ -26,6 +26,7 @@
|
||||
#include <gnc-datetime.hpp>
|
||||
#include <guid.hpp>
|
||||
#include <cassert>
|
||||
#include <charconv>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -389,8 +390,28 @@ qof_instance_from_string(const std::string& str, GncOptionUIType type)
|
||||
std::string
|
||||
qof_instance_to_string(const QofInstance* inst)
|
||||
{
|
||||
gnc::GUID guid{*qof_instance_get_guid(inst)};
|
||||
return guid.to_string();
|
||||
std::string retval;
|
||||
if (GNC_IS_COMMODITY(inst))
|
||||
{
|
||||
auto commodity{GNC_COMMODITY(inst)};
|
||||
if (!gnc_commodity_is_currency(commodity))
|
||||
{
|
||||
auto name_space{gnc_commodity_get_namespace(GNC_COMMODITY(inst))};
|
||||
if (name_space && *name_space != '\0')
|
||||
{
|
||||
retval = name_space;
|
||||
retval += ":";
|
||||
}
|
||||
}
|
||||
retval += gnc_commodity_get_mnemonic(GNC_COMMODITY(inst));
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
gnc::GUID guid{*qof_instance_get_guid(inst)};
|
||||
retval = guid.to_string();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template <typename ValueType> void
|
||||
@ -411,6 +432,41 @@ GncOptionValue<ValueType>::reset_default_value()
|
||||
m_value = m_default_value;
|
||||
}
|
||||
|
||||
template <typename ValueType> std::string
|
||||
GncOptionValue<ValueType>::serialize() const noexcept
|
||||
{
|
||||
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
|
||||
return qof_instance_to_string(m_value);
|
||||
else if constexpr(is_same_decayed_v<ValueType, std::string>)
|
||||
return m_value;
|
||||
else if constexpr(is_same_decayed_v<ValueType, bool>)
|
||||
return m_value ? "True" : "False";
|
||||
else if constexpr(std::is_arithmetic_v<ValueType>)
|
||||
return std::to_string(m_value);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename ValueType> bool
|
||||
GncOptionValue<ValueType>::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
|
||||
set_value(qof_instance_from_string(str, get_ui_type()));
|
||||
else if constexpr(is_same_decayed_v<ValueType, std::string>)
|
||||
set_value(str);
|
||||
else if constexpr(is_same_decayed_v<ValueType, bool>)
|
||||
set_value(str == "True");
|
||||
else if constexpr(is_same_decayed_v<ValueType, int>)
|
||||
set_value(stoi(str));
|
||||
else if constexpr(is_same_decayed_v<ValueType, int64_t>)
|
||||
set_value(stoll(str));
|
||||
else if constexpr(is_same_decayed_v<ValueType, double>)
|
||||
set_value(stod(str));
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <> void
|
||||
GncOptionValue<SCM>::set_value(SCM new_value)
|
||||
{
|
||||
@ -441,6 +497,201 @@ GncOptionValue<SCM>::reset_default_value()
|
||||
scm_gc_protect_object(m_value);
|
||||
}
|
||||
|
||||
template <typename ValueType> std::string
|
||||
GncOptionValidatedValue<ValueType>::serialize() const noexcept
|
||||
{
|
||||
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
|
||||
return qof_instance_to_string(m_value);
|
||||
else if constexpr(is_same_decayed_v<ValueType, std::string>)
|
||||
return m_value;
|
||||
else if constexpr(is_same_decayed_v<ValueType, bool>)
|
||||
return m_value ? "True" : "False";
|
||||
else if constexpr(std::is_arithmetic_v<ValueType>)
|
||||
return std::to_string(m_value);
|
||||
else
|
||||
return "Invalid Value Type";
|
||||
}
|
||||
|
||||
template <typename ValueType> bool
|
||||
GncOptionValidatedValue<ValueType>::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
if constexpr(std::is_same_v<ValueType, const QofInstance*>)
|
||||
set_value(qof_instance_from_string(str, get_ui_type()));
|
||||
else if constexpr(is_same_decayed_v<ValueType, std::string>)
|
||||
set_value(str);
|
||||
else if constexpr(is_same_decayed_v<ValueType, bool>)
|
||||
set_value(str == "True");
|
||||
else if constexpr(is_same_decayed_v<ValueType, int>)
|
||||
set_value(stoi(str));
|
||||
else if constexpr(is_same_decayed_v<ValueType, int64_t>)
|
||||
set_value(stoll(str));
|
||||
else if constexpr(is_same_decayed_v<ValueType, double>)
|
||||
set_value(stod(str));
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string
|
||||
GncOptionAccountListValue::serialize() const noexcept
|
||||
{
|
||||
std::string retval;
|
||||
bool first = true;
|
||||
for (auto val : m_value)
|
||||
{
|
||||
if (!first)
|
||||
retval += " ";
|
||||
first = false;
|
||||
retval += qof_instance_to_string(QOF_INSTANCE(val));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
GncOptionAccountListValue::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
if (str.empty() || str.size() < GUID_ENCODING_LENGTH)
|
||||
return false;
|
||||
m_value.clear();
|
||||
m_value.reserve(str.size() / GUID_ENCODING_LENGTH);
|
||||
bool first = true;
|
||||
size_t pos{};
|
||||
while (pos + GUID_ENCODING_LENGTH < str.size())
|
||||
{
|
||||
if (!first)
|
||||
++pos;
|
||||
first = false;
|
||||
auto ptr = qof_instance_from_string(str.substr(pos, pos + GUID_ENCODING_LENGTH), get_ui_type());
|
||||
m_value.push_back(reinterpret_cast<Account*>(ptr));
|
||||
pos += GUID_ENCODING_LENGTH;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string
|
||||
GncOptionAccountSelValue::serialize() const noexcept
|
||||
{
|
||||
return qof_instance_to_string(QOF_INSTANCE(m_value));
|
||||
}
|
||||
|
||||
bool
|
||||
GncOptionAccountSelValue::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
set_value(reinterpret_cast<Account*>(qof_instance_from_string(str, get_ui_type())));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string
|
||||
GncOptionMultichoiceValue::serialize() const noexcept
|
||||
{
|
||||
std::string retval;
|
||||
bool first = true;
|
||||
for (auto index : m_value)
|
||||
{
|
||||
if (!first)
|
||||
retval += " ";
|
||||
first = false;
|
||||
retval += std::get<0>(m_choices[index]);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
GncOptionMultichoiceValue::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
static const auto size_t_max = std::numeric_limits<std::size_t>::max();
|
||||
if (str.empty())
|
||||
|
||||
return false;
|
||||
size_t pos{};
|
||||
while (pos < str.size())
|
||||
{
|
||||
auto endpos{str.find(' ', pos)};
|
||||
if (endpos == std::string::npos)
|
||||
endpos = str.size();
|
||||
//need a null-terminated char* to pass to permissible_value_index
|
||||
auto index{permissible_value_index(str.substr(pos, endpos).c_str())};
|
||||
if (index == size_t_max)
|
||||
return false;
|
||||
m_value.push_back(index);
|
||||
pos = endpos + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ValueType> std::string
|
||||
GncOptionRangeValue<ValueType>::serialize() const noexcept
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<ValueType>)
|
||||
return std::to_string(m_value);
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename ValueType> bool
|
||||
GncOptionRangeValue<ValueType>::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
if constexpr(is_same_decayed_v<ValueType, int>)
|
||||
set_value(stoi(str));
|
||||
else if constexpr(is_same_decayed_v<ValueType, double>)
|
||||
set_value(stod(str));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string
|
||||
GncOptionDateValue::serialize() const noexcept
|
||||
{
|
||||
std::string retval{"("};
|
||||
if (m_period == RelativeDatePeriod::ABSOLUTE)
|
||||
{
|
||||
retval += date_type_str[0];
|
||||
retval += " . ";
|
||||
retval += std::to_string(m_date);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval += date_type_str[1];
|
||||
retval += " . ";
|
||||
retval += gnc_relative_date_storage_string(m_period);
|
||||
}
|
||||
retval += ")";
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
GncOptionDateValue::deserialize(const std::string& str) noexcept
|
||||
{
|
||||
//The length of both "absolute" and "relative".
|
||||
static constexpr size_t date_type_len{9};
|
||||
// date_type_len plus the length of " . ".
|
||||
static constexpr size_t date_value_pos{12};
|
||||
auto type_str{str.substr(0, date_type_len)};
|
||||
auto period_str{str.substr(date_value_pos)};
|
||||
if (type_str == "absolute")
|
||||
{
|
||||
set_value(std::stoll(period_str));
|
||||
return true;
|
||||
}
|
||||
else if (type_str == "relative ")
|
||||
{
|
||||
auto period = gnc_relative_date_from_storage_string(period_str.c_str());
|
||||
if (period == RelativeDatePeriod::ABSOLUTE)
|
||||
{
|
||||
PWARN("Unknown period string in date option: '%s'",
|
||||
period_str.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
set_value(period);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PWARN("Unknown date type string in date option: '%s'",
|
||||
type_str.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template GncOptionValue<bool>::GncOptionValue(const GncOptionValue<bool>&);
|
||||
template GncOptionValue<int>::GncOptionValue(const GncOptionValue<int>&);
|
||||
template GncOptionValue<int64_t>::GncOptionValue(const GncOptionValue<int64_t>&);
|
||||
@ -498,3 +749,49 @@ template void GncOptionValue<RelativeDatePeriod>::reset_default_value();
|
||||
template void GncOptionValue<size_t>::reset_default_value();
|
||||
template void GncOptionValue<GncOptionAccountList>::reset_default_value();
|
||||
template void GncOptionValue<GncMultichoiceOptionIndexVec>::reset_default_value();
|
||||
template std::string GncOptionValue<bool>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<int>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<int64_t>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<double>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<char*>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<const char*>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<std::string>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<const QofInstance*>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<const QofQuery*>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<const GncOwner*>::serialize() const noexcept;
|
||||
template std::string GncOptionValue<SCM>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<bool>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<int>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<int64_t>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<double>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<char*>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<const char*>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<std::string>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<const QofInstance*>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<const QofQuery*>::serialize() const noexcept;
|
||||
template std::string GncOptionValidatedValue<const GncOwner*>::serialize() const noexcept;
|
||||
template std::string GncOptionRangeValue<int>::serialize() const noexcept;
|
||||
template std::string GncOptionRangeValue<double>::serialize() const noexcept;
|
||||
template bool GncOptionValue<bool>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<int>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<int64_t>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<double>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<char*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<const char*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<std::string>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<const QofInstance*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<const QofQuery*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<const GncOwner*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValue<SCM>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<bool>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<int>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<int64_t>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<double>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<char*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<const char*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<std::string>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<const QofInstance*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<const QofQuery*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionValidatedValue<const GncOwner*>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionRangeValue<int>::deserialize(const std::string&) noexcept;
|
||||
template bool GncOptionRangeValue<double>::deserialize(const std::string&) noexcept;
|
||||
|
@ -134,6 +134,8 @@ 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; }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type;
|
||||
ValueType m_value;
|
||||
@ -201,6 +203,8 @@ 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; }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type;
|
||||
ValueType m_value;
|
||||
@ -299,19 +303,24 @@ std::istream&
|
||||
operator>> (std::istream& iss, OptType& opt)
|
||||
{
|
||||
std::string instr;
|
||||
if (auto type = opt.get_ui_type(); type == GncOptionUIType::COMMODITY ||
|
||||
type == GncOptionUIType::CURRENCY)
|
||||
auto type = opt.get_ui_type();
|
||||
if (type == GncOptionUIType::COMMODITY || type == GncOptionUIType::CURRENCY)
|
||||
{
|
||||
std::string name_space, mnemonic;
|
||||
if (type = opt.get_ui_type(); type == GncOptionUIType::COMMODITY)
|
||||
{
|
||||
if (type == GncOptionUIType::COMMODITY)
|
||||
iss >> name_space;
|
||||
}
|
||||
else
|
||||
name_space = GNC_COMMODITY_NS_CURRENCY;
|
||||
iss >> mnemonic;
|
||||
instr = name_space + ":";
|
||||
instr += mnemonic;
|
||||
if (name_space.find(":") == std::string::npos)
|
||||
{
|
||||
iss >> mnemonic;
|
||||
instr = name_space + ":";
|
||||
instr += mnemonic;
|
||||
}
|
||||
else
|
||||
{
|
||||
instr = name_space;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -385,6 +394,8 @@ public:
|
||||
if (m_ui_type == GncOptionUIType::PLOT_SIZE)
|
||||
m_alternate = value;
|
||||
}
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type = GncOptionUIType::NUMBER_RANGE;
|
||||
ValueType m_value;
|
||||
@ -644,6 +655,8 @@ public:
|
||||
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<2>(m_choices.at(i)); }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
std::size_t find_key (const std::string& key) const noexcept
|
||||
{
|
||||
@ -794,6 +807,8 @@ public:
|
||||
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
|
||||
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
|
||||
bool is_multiselect() const noexcept { return m_multiselect; }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type;
|
||||
GncOptionAccountList m_value;
|
||||
@ -895,6 +910,8 @@ 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; }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type;
|
||||
Account* m_value;
|
||||
@ -1042,6 +1059,8 @@ public:
|
||||
GncOptionUIType get_ui_type() const noexcept { return m_ui_type; }
|
||||
void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
|
||||
const RelativeDatePeriodVec& get_period_set() const { return m_period_set; }
|
||||
std::string serialize() const noexcept;
|
||||
bool deserialize(const std::string& str) noexcept;
|
||||
private:
|
||||
GncOptionUIType m_ui_type;
|
||||
time64 m_date;
|
||||
|
@ -406,12 +406,21 @@ GncOption::set_alternate(bool alt) noexcept
|
||||
}, *m_option);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
GncOption::out_stream(std::ostream& oss) const
|
||||
std::string
|
||||
GncOption::serialize() const
|
||||
{
|
||||
return std::visit([&oss](auto& option) -> std::ostream& {
|
||||
oss << option;
|
||||
return oss;
|
||||
if (m_option->valueless_by_exception())
|
||||
return "Valueless Option";
|
||||
return std::visit([&](auto& option) -> std::string {
|
||||
return option.serialize();
|
||||
}, *m_option);
|
||||
}
|
||||
|
||||
bool
|
||||
GncOption::deserialize(const std::string& str)
|
||||
{
|
||||
return std::visit([&str](auto& option) -> bool {
|
||||
return option.deserialize(str);
|
||||
}, *m_option);
|
||||
}
|
||||
|
||||
|
@ -180,9 +180,20 @@ public:
|
||||
GList* account_type_list() const noexcept;
|
||||
bool is_alternate() const noexcept;
|
||||
void set_alternate(bool) noexcept;
|
||||
std::ostream& out_stream(std::ostream& oss) const;
|
||||
/** Get a string suitable for storage representing the option's value.
|
||||
* @return a std::string
|
||||
*/
|
||||
std::string serialize() const;
|
||||
/** Set the option's value from a character sequence.
|
||||
* @param str: The character sequence representing the value
|
||||
* @return true if the value was set, false otherwise.
|
||||
*/
|
||||
bool deserialize(const std::string& str);
|
||||
/** Set the option's value from an input stream
|
||||
* @param iss: An input stream reference.
|
||||
* @return the stream reference for chaining.
|
||||
*/
|
||||
std::istream& in_stream(std::istream& iss);
|
||||
|
||||
friend GncOptionVariant& swig_get_option(GncOption*);
|
||||
|
||||
private:
|
||||
@ -200,7 +211,8 @@ operator<(const GncOption& right, const GncOption& left)
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& oss, const GncOption& opt)
|
||||
{
|
||||
return opt.out_stream(oss);
|
||||
oss << opt.serialize();
|
||||
return oss;
|
||||
}
|
||||
|
||||
inline std::istream&
|
||||
|
@ -590,6 +590,7 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB);
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include "gnc-option.hpp"
|
||||
#include "gnc-option-impl.hpp"
|
||||
#include "gnc-option-ui.hpp"
|
||||
|
||||
GncOptionVariant& swig_get_option(GncOption* option)
|
||||
@ -1009,7 +1010,9 @@ inline SCM return_scm_value(ValueType value)
|
||||
const SCM ticked_format_str{scm_from_utf8_string("'~a")};
|
||||
//scm_simple_format needs a scheme list of arguments to match the format
|
||||
//placeholders.
|
||||
auto value{scm_list_1(GncOption_get_scm_value($self))};
|
||||
auto serial{$self->serialize()};
|
||||
SCM value = serial.empty() ? SCM_BOOL_F :
|
||||
scm_list_1(scm_from_utf8_string(serial.c_str()));
|
||||
auto uitype{$self->get_ui_type()};
|
||||
if (uitype == GncOptionUIType::STRING ||
|
||||
uitype == GncOptionUIType::TEXT ||
|
||||
@ -1030,11 +1033,48 @@ inline SCM return_scm_value(ValueType value)
|
||||
return scm_simple_format(SCM_BOOL_F, plain_format_str, value);
|
||||
else
|
||||
return scm_simple_format(SCM_BOOL_F, plain_format_str,
|
||||
SCM_BOOL_F);
|
||||
scm_list_1(SCM_BOOL_F));
|
||||
}
|
||||
else if (uitype == GncOptionUIType::CURRENCY)
|
||||
{
|
||||
const SCM quoted_format_str{scm_from_utf8_string("\"~a\"")};
|
||||
return scm_simple_format(SCM_BOOL_F, quoted_format_str, value);
|
||||
}
|
||||
else if (uitype == GncOptionUIType::COMMODITY)
|
||||
{
|
||||
const SCM commodity_fmt{scm_from_utf8_string("\"~a\" \"~a\"")};
|
||||
auto sep{serial.find(':')};
|
||||
if (sep == std::string::npos)
|
||||
sep = serial.find(' ');
|
||||
if (sep == std::string::npos)
|
||||
{
|
||||
const SCM quoted_format_str{scm_from_utf8_string("\"~a\"")};
|
||||
return scm_simple_format(SCM_BOOL_F, quoted_format_str, value);
|
||||
}
|
||||
auto name_space{serial.substr(0, sep)};
|
||||
auto symbol{serial.substr(sep + 1, std::string::npos)};
|
||||
auto commodity_val{scm_list_2(scm_from_utf8_string(name_space.c_str()),
|
||||
scm_from_utf8_string(symbol.c_str()))};
|
||||
return scm_simple_format(SCM_BOOL_F, commodity_fmt, commodity_val);
|
||||
}
|
||||
else if (uitype == GncOptionUIType::DATE_ABSOLUTE ||
|
||||
uitype == GncOptionUIType::DATE_RELATIVE ||
|
||||
uitype == GncOptionUIType::DATE_BOTH)
|
||||
{
|
||||
const SCM date_fmt{scm_from_utf8_string("'~a")};
|
||||
return scm_simple_format(SCM_BOOL_F, date_fmt, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return scm_simple_format(SCM_BOOL_F, ticked_format_str, value);
|
||||
if (value && scm_is_true(value))
|
||||
{
|
||||
return scm_simple_format(SCM_BOOL_F, ticked_format_str, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return scm_simple_format(SCM_BOOL_F, plain_format_str,
|
||||
scm_list_1(SCM_BOOL_F));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1085,6 +1125,24 @@ inline SCM return_scm_value(ValueType value)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if constexpr (is_same_decayed_v<decltype(option),
|
||||
GncOptionAccountSelValue>)
|
||||
{
|
||||
if (scm_is_string(new_value))
|
||||
{
|
||||
auto strval{scm_to_utf8_string(new_value)};
|
||||
GncGUID guid;
|
||||
string_to_guid(strval, &guid);
|
||||
auto book{gnc_get_current_book()};
|
||||
option.set_value(xaccAccountLookup(&guid, book));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto val{scm_to_value<const QofInstance*>(new_value)};
|
||||
option.set_value(GNC_ACCOUNT(val));
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto value{scm_to_value<std::decay_t<decltype(option.get_value())>>(new_value)}; //Can't inline, set_value takes arg by reference.
|
||||
option.set_value(static_cast<decltype(option.get_value())>(value));
|
||||
}, swig_get_option($self));
|
||||
@ -1143,6 +1201,24 @@ inline SCM return_scm_value(ValueType value)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if constexpr (is_same_decayed_v<decltype(option),
|
||||
GncOptionAccountSelValue>)
|
||||
{
|
||||
if (scm_is_string(new_value))
|
||||
{
|
||||
auto strval{scm_to_utf8_string(new_value)};
|
||||
GncGUID guid;
|
||||
string_to_guid(strval, &guid);
|
||||
auto book{gnc_get_current_book()};
|
||||
option.set_default_value(xaccAccountLookup(&guid, book));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto val{scm_to_value<Account*>(new_value)};
|
||||
option.set_default_value(val);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto value{scm_to_value<std::decay_t<decltype(option.get_value())>>(new_value)}; //Can't inline, set_value takes arg by reference.
|
||||
option.set_default_value(value);
|
||||
}, swig_get_option($self));
|
||||
@ -1392,7 +1468,8 @@ inline SCM return_scm_value(ValueType value)
|
||||
gnc_commodity *value)
|
||||
{
|
||||
return new GncOption{GncOptionValue<const QofInstance*>{
|
||||
section, name, key, doc_string, (const QofInstance*)value}};
|
||||
section, name, key, doc_string, (const QofInstance*)value,
|
||||
GncOptionUIType::COMMODITY}};
|
||||
}
|
||||
|
||||
static GncOption*
|
||||
|
@ -87,14 +87,13 @@
|
||||
|
||||
;; Used only by test-stress-options.scm
|
||||
(define-public (gnc:option-data option)
|
||||
(let ((num-values (GncOption-num-permissible-values option))
|
||||
(retval '()))
|
||||
(do ((i 0 (1+ i))) ((>= i num-values))
|
||||
(let ((value (GncOption-permissible-value option i))
|
||||
(name (GncOption-permissible-value-name option i)))
|
||||
(set! retval (cons retval (vector value name)))))
|
||||
retval))
|
||||
|
||||
; (define num-values (GncOption-num-permissible-values option))
|
||||
; (let loop ((i 0) (retval '()))
|
||||
; (if (>= i num-values) (reverse retval)
|
||||
; (let ((value (GncOption-permissible-value option i))
|
||||
; (name (GncOption-permissible-value-name option i)))
|
||||
; (loop (1+ i) (cons (vector value name) retval))))))
|
||||
(list (vector 1 2)))
|
||||
;; Create the database and return a dispatch function.
|
||||
(define-public (gnc:new-options)
|
||||
(let ((optiondb (new-gnc-optiondb)))
|
||||
|
@ -121,11 +121,11 @@ TEST(GncOption, test_bool_stream_out)
|
||||
GncOption option("foo", "bar", "baz", "Phony Option", false);
|
||||
std::ostringstream oss;
|
||||
oss << option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "#f");
|
||||
EXPECT_STREQ(oss.str().c_str(), "False");
|
||||
oss.str("");
|
||||
option.set_value(true);
|
||||
oss << option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "#t");
|
||||
EXPECT_STREQ(oss.str().c_str(), "True");
|
||||
}
|
||||
|
||||
TEST(GncOption, test_bool_stream_in)
|
||||
@ -301,7 +301,7 @@ static inline std::string make_currency_str(gnc_commodity* cur)
|
||||
static inline std::string make_commodity_str(gnc_commodity* com)
|
||||
{
|
||||
std::string com_str{gnc_commodity_get_namespace(com)};
|
||||
com_str += " ";
|
||||
com_str += ":";
|
||||
com_str += gnc_commodity_get_mnemonic(com);
|
||||
return com_str;
|
||||
}
|
||||
@ -511,7 +511,7 @@ TEST_F(GncRangeOption, test_range_out)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Integer " << m_intoption << " Double " << m_doubleoption << ".";
|
||||
EXPECT_STREQ("Integer 15 Double 1.5.", oss.str().c_str());
|
||||
EXPECT_STREQ("Integer 15 Double 1.500000.", oss.str().c_str());
|
||||
}
|
||||
|
||||
TEST_F(GncRangeOption, test_range_in)
|
||||
@ -1120,8 +1120,8 @@ TEST_F(GncDateOption, test_stream_out)
|
||||
m_option.set_value(time1);
|
||||
std::ostringstream oss;
|
||||
oss << time1;
|
||||
std::string timestr{"absolute . "};
|
||||
timestr += oss.str();
|
||||
std::string timestr{"(absolute . "};
|
||||
timestr += oss.str() + ")";
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_EQ(oss.str(), timestr);
|
||||
@ -1129,77 +1129,77 @@ TEST_F(GncDateOption, test_stream_out)
|
||||
m_option.set_value(RelativeDatePeriod::TODAY);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . today");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . today)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_THIS_MONTH);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-this-month");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-this-month)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_THIS_MONTH);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-this-month");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-this-month)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_PREV_MONTH);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-prev-month");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-prev-month)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_PREV_MONTH);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-prev-month");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-prev-month)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_CURRENT_QUARTER);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-current-quarter");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-current-quarter)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_CURRENT_QUARTER);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-current-quarter");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-current-quarter)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_PREV_QUARTER);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-prev-quarter");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-prev-quarter)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_PREV_QUARTER);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-prev-quarter");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-prev-quarter)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_CAL_YEAR);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-cal-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-cal-year)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_CAL_YEAR);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-cal-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-cal-year)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_PREV_YEAR);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-prev-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-prev-year)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_PREV_YEAR);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-prev-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-prev-year)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::START_ACCOUNTING_PERIOD);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . start-prev-fin-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . start-prev-fin-year)");
|
||||
|
||||
m_option.set_value(RelativeDatePeriod::END_ACCOUNTING_PERIOD);
|
||||
oss.str("");
|
||||
oss << m_option;
|
||||
EXPECT_STREQ(oss.str().c_str(), "relative . end-prev-fin-year");
|
||||
EXPECT_STREQ(oss.str().c_str(), "(relative . end-prev-fin-year)");
|
||||
}
|
||||
|
||||
TEST_F(GncDateOption, test_stream_in_absolute)
|
||||
|
@ -66,10 +66,32 @@
|
||||
(let ((option (gnc:lookup-option options
|
||||
\"foo\"
|
||||
\"bar\")))
|
||||
((lambda (o) (if o (gnc:option-set-value o '~s))) option))
|
||||
((lambda (o) (if o (gnc:option-set-value o '~a))) option))
|
||||
|
||||
" value))
|
||||
|
||||
(define (test-currency-output-template value)
|
||||
(format #f "
|
||||
; Section: foo
|
||||
|
||||
(let ((option (gnc:lookup-option options
|
||||
\"foo\"
|
||||
\"bar\")))
|
||||
((lambda (o) (if o (gnc:option-set-value o \"~a\"))) option))
|
||||
|
||||
" value))
|
||||
|
||||
(define (test-commodity-output-template value)
|
||||
(format #f "
|
||||
; Section: foo
|
||||
|
||||
(let ((option (gnc:lookup-option options
|
||||
\"foo\"
|
||||
\"bar\")))
|
||||
((lambda (o) (if o (gnc:option-set-value o \"~a\" \"~a\"))) option))
|
||||
|
||||
" (string-split value #\:)))
|
||||
|
||||
(define (test-budget-output-template value)
|
||||
(format #f "
|
||||
; Section: foo
|
||||
@ -90,7 +112,7 @@
|
||||
(test-equal test-unchanged-section-output-template
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
(gnc:option-set-value (gnc:lookup-option odb "foo" "bar") value)
|
||||
(test-equal (test-template value)
|
||||
(test-equal (test-template (GncOption-serialize (gnc:lookup-option odb "foo" "bar")))
|
||||
(gnc:generate-restore-forms odb "options"))))
|
||||
|
||||
(define (test-gnc-string-option-to-scheme)
|
||||
@ -125,7 +147,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(EUR (gnc-commodity-new book "European Union Euro" "CURRENCY" "EUR" "" 100)))
|
||||
(gnc-commodity-table-insert table USD)
|
||||
(gnc-commodity-table-insert table EUR)
|
||||
(test-option-scheme-output gnc:make-currency-option test-literal-output-template
|
||||
(test-option-scheme-output gnc:make-currency-option test-currency-output-template
|
||||
USD EUR)
|
||||
;; Garbage collection has already eaten USD and EUR.
|
||||
(test-book-clear-data book "gnc-commodity-table")
|
||||
@ -163,7 +185,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let* ((book (gnc-option-test-book-new))
|
||||
(AAPL (gnc-commodity-new book "Apple" "NASDAQ" "AAPL" "" 1))
|
||||
(FMAGX (gnc-commodity-new book "Fidelity Magellan Fund" "FUND" "FMAGX" "" 1000)))
|
||||
(test-option-scheme-output gnc:make-commodity-option test-literal-output-template
|
||||
(test-option-scheme-output gnc:make-commodity-option test-currency-output-template
|
||||
AAPL FMAGX))
|
||||
(test-end "test-gnc-commodity-option-to-scheme"))
|
||||
|
||||
@ -181,19 +203,19 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(test-begin "test-gnc-date-option-to-scheme")
|
||||
(let ((odb (gnc:new-options)))
|
||||
(gnc:options-make-end-date! odb "foo" "bar" "baz" "Phoney Option")
|
||||
(test-equal test-unchanged-section-output-template
|
||||
(test-equal "Date Unchanged" test-unchanged-section-output-template
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
(let* ((option (gnc:lookup-option odb "foo" "bar"))
|
||||
(test-template test-literal-output-template)
|
||||
(time (gnc-dmy2time64 25 12 2020))
|
||||
(value `(absolute . ,time)))
|
||||
(gnc:option-set-value option value)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal "Absolute Date" (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
(set! value '(relative . end-prev-year))
|
||||
(gnc:option-set-value option value)
|
||||
(test-equal value (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal "Relative Date Value" value (GncOption-get-scm-value option))
|
||||
(test-equal "Relative Date" (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))))
|
||||
(test-end "test-gnc-date-option-to-scheme"))
|
||||
|
||||
@ -248,7 +270,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(test-template test-literal-output-template)
|
||||
(new-acclist (gnc-account-list-from-types book (list ACCT-TYPE-BANK))))
|
||||
(gnc-option-set-value option new-acclist)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-account-list-option-to-scheme"))
|
||||
@ -271,7 +293,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(test-template test-literal-output-template)
|
||||
(new-acclist (gnc-account-list-from-types book (list ACCT-TYPE-BANK))))
|
||||
(gnc-option-set-value option new-acclist)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-account-sel-option-to-scheme"))
|
||||
@ -301,7 +323,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
(let ((option (gnc:lookup-option odb "foo" "bar")))
|
||||
(gnc:option-set-value option value)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))))
|
||||
(test-end "test-gnc-multichoice-option-to-scheme"))
|
||||
|
||||
@ -319,7 +341,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let ((option (gnc:lookup-option odb "foo" "bar"))
|
||||
(test-template test-literal-output-template))
|
||||
(gnc-option-set-value option '(ugly))
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-list-option-to-scheme"))
|
||||
@ -340,7 +362,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let ((option (gnc:lookup-option odb "foo" "bar"))
|
||||
(test-template test-literal-output-template))
|
||||
(gnc-option-set-value option 42.0)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-number-range-option-to-scheme"))
|
||||
@ -361,7 +383,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let ((option (gnc:lookup-option odb "foo" "bar"))
|
||||
(test-template test-literal-output-template))
|
||||
(gnc-option-set-value option 420)
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-number-plot-size-option-to-scheme"))
|
||||
@ -384,7 +406,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let ((option (gnc:lookup-option odb "__reg" "query"))
|
||||
(test-template test-literal-output-template))
|
||||
(gnc-option-set-value option (gnc-scm2query query-scm))
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-number-plot-size-option-to-scheme"))
|
||||
@ -420,7 +442,7 @@ veritatis et quasi architecto beatae vitae dicta sunt, explicabo.")
|
||||
(let ((option (gnc:lookup-option odb "foo" "bar"))
|
||||
(test-template test-literal-output-template))
|
||||
(gnc-option-set-value option '"13b305236443451a86c5366b7f890ecb")
|
||||
(test-equal (test-template (GncOption-get-scm-value option))
|
||||
(test-equal (test-template (GncOption-serialize option))
|
||||
(gnc:generate-restore-forms odb "options"))
|
||||
))
|
||||
(test-end "test-gnc-owner-option-to-scheme"))
|
||||
|
Loading…
Reference in New Issue
Block a user