33 #ifndef GNC_OPTION_IMPL_HPP_ 34 #define GNC_OPTION_IMPL_HPP_ 43 #include "gnc-datetime.hpp" 59 size_t constexpr classifier_size_max{50};
60 size_t constexpr sort_tag_size_max{10};
71 std::string m_section;
73 std::string m_sort_tag;
75 std::string m_doc_string;
80 auto constexpr uint16_t_max = std::numeric_limits<uint16_t>::max();
86 template <
typename ValueType>
91 const char* key,
const char* doc_string,
95 m_ui_type(ui_type), m_value{value}, m_default_value{value} { }
101 ValueType get_value()
const {
return m_value; }
102 ValueType get_default_value()
const {
return m_default_value; }
103 void set_value(ValueType new_value);
104 void set_default_value(ValueType new_value);
105 void reset_default_value();
106 void mark_saved() noexcept { m_dirty =
false; }
107 bool is_dirty()
const noexcept {
return m_dirty; }
108 bool is_changed()
const noexcept {
return m_value != m_default_value; }
110 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
111 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
112 std::string serialize()
const noexcept;
113 bool deserialize(
const std::string& str) noexcept;
117 ValueType m_default_value;
135 using GncOwnerPtr = std::unique_ptr<GncOwner, GncOwnerDeleter>;
140 const char* section,
const char* name,
141 const char* key,
const char* doc_string,
148 const GncOwner* get_default_value()
const;
149 void set_value(
const GncOwner* new_value);
150 void set_default_value(
const GncOwner* new_value);
151 void reset_default_value();
152 void mark_saved() noexcept { m_dirty =
false; }
153 bool is_dirty()
const noexcept {
return m_dirty; }
154 bool is_changed()
const noexcept;
156 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
157 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
158 std::string serialize()
const noexcept;
159 bool deserialize(
const std::string& str) noexcept;
163 GncOwnerPtr m_default_value;
172 using GncItem = std::pair<QofIdTypeConst, GncGUID>;
177 const char* section,
const char* name,
178 const char* key,
const char* doc_string,
187 GncItem get_item()
const {
return m_value; }
188 GncItem get_default_item()
const {
return m_default_value; }
190 void set_default_value(
const QofInstance* new_value);
191 void reset_default_value();
192 void mark_saved() noexcept { m_dirty =
false; }
193 bool is_dirty()
const noexcept {
return m_dirty; }
194 bool is_changed()
const noexcept;
196 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
197 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
198 std::string serialize()
const noexcept;
199 bool deserialize(
const std::string& str) noexcept;
220 const char* key,
const char* doc_string,
221 gnc_commodity* value,
224 m_ui_type{ui_type}, m_is_currency{ui_type == GncOptionUIType::CURRENCY},
230 if (!validate(value))
231 throw std::invalid_argument(
"Attempt to create GncOptionCommodityValue with currency UIType and non-currency value.");
237 gnc_commodity* get_value()
const;
238 gnc_commodity* get_default_value()
const;
239 bool validate(gnc_commodity*)
const noexcept;
240 void set_value(gnc_commodity* value);
241 void set_default_value(gnc_commodity* value);
242 void reset_default_value();
243 void mark_saved() noexcept { m_dirty =
false; }
244 bool is_dirty()
const noexcept {
return m_dirty; }
245 bool is_changed()
const noexcept;
247 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
248 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
249 std::string serialize()
const noexcept;
250 bool deserialize(
const std::string& str) noexcept;
254 std::string m_namespace;
255 std::string m_mnemonic;
256 std::string m_default_namespace;
257 std::string m_default_mnemonic;
261 QofInstance* qof_instance_from_string(
const std::string& str,
264 std::string qof_instance_to_string(
const QofInstance* inst);
266 template <
typename T>
269 static constexpr
bool value =
273 template <
typename T>
inline constexpr
bool 276 template <
typename T>
279 static constexpr
bool value =
283 template <
typename T>
inline constexpr
bool 286 template <
typename T>
289 static constexpr
bool value =
293 template <
typename T>
inline constexpr
bool 304 template<
class OptType,
305 typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
306 ! (is_QofInstanceValue_v<OptType> ||
307 is_RangeValue_v<OptType>),
int> = 0>
308 std::ostream&
operator<<(std::ostream& oss,
const OptType& opt)
310 oss << opt.get_value();
314 template<>
inline std::ostream&
315 operator<< <GncOptionValue<bool>>(std::ostream& oss,
318 oss << (opt.get_value() ?
"#t" :
"#f");
325 oss << opt.serialize();
329 template<
class OptType,
330 typename std::enable_if_t<is_QofInstanceValue_v<OptType>,
int> = 0>
332 operator<< (std::ostream& oss,
const OptType& opt)
334 auto value = opt.get_value();
335 oss << qof_instance_to_string(value);
339 template<
class OptType,
340 typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
341 !(is_QofInstanceValue_v<OptType> ||
342 is_RangeValue_v<OptType>),
int> = 0>
343 std::istream&
operator>>(std::istream& iss, OptType& opt)
345 if constexpr (std::is_same_v<std::decay_t<decltype(opt.get_value())>,
const _gncOwner*> ||
346 std::is_same_v<std::decay_t<decltype(opt.get_value())>,
const _QofQuery*> ||
347 std::is_same_v<std::decay_t<decltype(opt.get_value())>, GncOptionDateFormat>)
351 std::decay_t<decltype(opt.get_value())> value;
353 opt.set_value(value);
360 template<
class OptType,
361 typename std::enable_if_t<is_QofInstanceValue_v<OptType>,
int> = 0>
363 operator>> (std::istream& iss, OptType& opt)
367 opt.set_value(qof_instance_from_string(instr, opt.get_ui_type()));
371 template<>
inline std::istream&
377 opt.set_value(instr ==
"#t" ?
true :
false);
381 template<>
inline std::istream&
385 uint32_t id, wide, high;
386 iss >>
id >> wide >> high;
387 opt.set_value(GncOptionReportPlacementVec{{id, wide, high}});
396 template <
typename ValueType>
401 const char* key,
const char* doc_string,
402 ValueType value, ValueType min,
403 ValueType max, ValueType step) :
405 max, step, GncOptionUIType::NUMBER_RANGE} {}
407 const char* key,
const char* doc_string,
408 ValueType value, ValueType min,
411 m_value{value >= min && value <= max ? value : min},
412 m_default_value{value >= min && value <= max ? value : min},
413 m_min{min}, m_max{max}, m_step{step} {
414 if constexpr(is_same_decayed_v<ValueType, int>)
415 set_alternate(
true);}
420 ValueType get_value()
const {
return m_value; }
421 ValueType get_default_value()
const {
return m_default_value; }
422 bool validate(ValueType value) {
return value >= m_min && value <= m_max; }
423 void set_value(ValueType value)
425 if (this->validate(value))
431 throw std::invalid_argument(
"Validation failed, value not set.");
433 void set_default_value(ValueType value)
435 if (this->validate(value))
436 m_value = m_default_value = value;
438 throw std::invalid_argument(
"Validation failed, value not set.");
440 void get_limits(ValueType& upper, ValueType& lower, ValueType& step)
const noexcept
446 void reset_default_value() { m_value = m_default_value; }
447 void mark_saved() noexcept { m_dirty =
false; }
448 bool is_dirty()
const noexcept {
return m_dirty; }
449 bool is_changed()
const noexcept {
return m_value != m_default_value; }
451 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
452 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
453 bool is_alternate()
const noexcept {
return m_alternate; }
454 void set_alternate(
bool value) noexcept { m_alternate = value; }
455 std::string serialize()
const noexcept;
456 bool deserialize(
const std::string& str) noexcept;
460 ValueType m_default_value;
464 bool m_alternate{
false};
468 template<
class OptType,
469 typename std::enable_if_t<is_RangeValue_v<OptType>,
int> = 0>
471 operator<< (std::ostream& oss,
const OptType& opt)
473 if (opt.get_ui_type() == GncOptionUIType::PLOT_SIZE)
474 oss << (opt.is_alternate() ?
"pixels" :
"percent") <<
" ";
475 oss << opt.get_value();
479 template<
class OptType,
480 typename std::enable_if_t<is_RangeValue_v<OptType>,
int> = 0>
482 operator>> (std::istream& iss, OptType& opt)
484 if (opt.get_ui_type() == GncOptionUIType::PLOT_SIZE)
488 opt.set_alternate(strncmp(alt.c_str(),
"percent",
489 strlen(
"percent")) == 0);
491 if constexpr (std::is_same_v<std::decay_t<OptType>,
507 using GncMultichoiceOptionEntry = std::tuple<
const std::string,
509 GncOptionMultichoiceKeyType>;
510 using GncMultichoiceOptionIndexVec = std::vector<uint16_t>;
511 using GncMultichoiceOptionChoices = std::vector<GncMultichoiceOptionEntry>;
532 const char* key,
const char* doc_string,
534 GncMultichoiceOptionChoices&& choices,
538 m_value{}, m_default_value{}, m_choices{std::move(choices)}
542 if (
auto index = find_key(value);
543 index != uint16_t_max)
545 m_value.push_back(index);
546 m_default_value.push_back(index);
552 const char* key,
const char* doc_string,
554 GncMultichoiceOptionChoices&& choices,
558 m_value{}, m_default_value{}, m_choices{std::move(choices)}
560 if (index < m_choices.size())
562 m_value.push_back(index);
563 m_default_value.push_back(index);
568 const char* key,
const char* doc_string,
569 GncMultichoiceOptionIndexVec&& indices,
570 GncMultichoiceOptionChoices&& choices,
574 m_value{indices}, m_default_value{std::move(indices)},
575 m_choices{std::move(choices)} {}
581 const std::string& get_value()
const 583 auto vec{m_value.size() > 0 ? m_value : m_default_value};
585 return c_empty_string;
587 return std::get<0>(m_choices.at(vec[0]));
589 return c_list_string;
592 const std::string& get_default_value()
const 594 if (m_default_value.size() == 1)
595 return std::get<0>(m_choices.at(m_default_value[0]));
596 else if (m_default_value.size() == 0)
597 return c_empty_string;
599 return c_list_string;
602 uint16_t get_index()
const 604 if (m_value.size() > 0)
606 if (m_default_value.size() > 0)
607 return m_default_value[0];
610 const GncMultichoiceOptionIndexVec& get_multiple()
const noexcept
614 const GncMultichoiceOptionIndexVec& get_default_multiple()
const noexcept
616 return m_default_value;
618 bool validate(
const std::string& value)
const noexcept
620 auto index = find_key(value);
621 return index != uint16_t_max;
624 bool validate(
const GncMultichoiceOptionIndexVec& indexes)
const noexcept
626 for (
auto index : indexes)
627 if (index >= m_choices.size())
632 void set_value(
const std::string& value)
634 auto index = find_key(value);
635 if (index != uint16_t_max)
638 m_value.push_back(index);
642 throw std::invalid_argument(
"Value not a valid choice.");
645 void set_value(uint16_t index)
647 if (index < m_choices.size())
650 m_value.push_back(index);
654 throw std::invalid_argument(
"Value not a valid choice.");
657 void set_default_value(
const std::string& value)
659 auto index = find_key(value);
660 if (index != uint16_t_max)
663 m_value.push_back(index);
664 m_default_value.clear();
665 m_default_value.push_back(index);
668 throw std::invalid_argument(
"Value not a valid choice.");
671 void set_default_value(uint16_t index)
673 if (index < m_choices.size())
676 m_value.push_back(index);
677 m_default_value.clear();
678 m_default_value.push_back(index);
681 throw std::invalid_argument(
"Value not a valid choice.");
684 void set_multiple(
const GncMultichoiceOptionIndexVec& indexes)
686 if (validate(indexes))
689 throw std::invalid_argument(
"One of the supplied indexes was out of range.");
691 void set_default_multiple(
const GncMultichoiceOptionIndexVec& indexes)
693 if (validate(indexes))
694 m_value = m_default_value = indexes;
696 throw std::invalid_argument(
"One of the supplied indexes was out of range.");
698 uint16_t num_permissible_values()
const noexcept
700 return m_choices.size();
702 uint16_t permissible_value_index(
const char* key)
const noexcept
704 return find_key(key);
706 const char* permissible_value(uint16_t index)
const 708 return std::get<0>(m_choices.at(index)).c_str();
710 const char* permissible_value_name(uint16_t index)
const 712 return std::get<1>(m_choices.at(index)).c_str();
714 void reset_default_value() { m_value = m_default_value; }
715 void mark_saved() noexcept { m_dirty =
false; }
716 bool is_dirty()
const noexcept {
return m_dirty; }
717 bool is_changed()
const noexcept {
return m_value != m_default_value; }
719 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
720 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
721 GncOptionMultichoiceKeyType get_keytype(
unsigned i)
const {
return std::get<2>(m_choices.at(i)); }
722 std::string serialize()
const noexcept;
723 bool deserialize(
const std::string& str) noexcept;
725 uint16_t find_key (
const std::string& key)
const noexcept
727 auto iter = std::find_if(m_choices.begin(), m_choices.end(),
729 return std::get<0>(choice) == key; });
730 if (iter != m_choices.end())
731 return iter - m_choices.begin();
737 GncMultichoiceOptionIndexVec m_value;
738 GncMultichoiceOptionIndexVec m_default_value;
739 GncMultichoiceOptionChoices m_choices;
741 static const std::string c_empty_string;
742 static const std::string c_list_string;
745 template<>
inline std::ostream&
746 operator<< <GncOptionMultichoiceValue>(std::ostream& oss,
749 auto vec{opt.get_multiple()};
751 for (
auto index : vec)
757 oss << opt.permissible_value(index);
762 template<>
inline std::istream&
766 GncMultichoiceOptionIndexVec values;
770 std::getline(iss, str,
' ');
773 auto index = opt.permissible_value_index(str.c_str());
774 if (index != uint16_t_max)
775 values.push_back(index);
778 std::string err = str +
" is not one of ";
780 err +=
"'s permissible values.";
781 throw std::invalid_argument(err);
787 opt.set_multiple(values);
793 using GncOptionAccountList = std::vector<GncGUID>;
795 using GncOptionAccountTypeList = std::vector<GNCAccountType>;
818 const char* key,
const char* doc_string,
821 m_value{}, m_default_value{}, m_allowed{}, m_multiselect{multi} {}
824 const char* key,
const char* doc_string,
826 const GncOptionAccountList& value,
bool multi=
true) :
828 m_value{value}, m_default_value{std::move(value)}, m_allowed{},
829 m_multiselect{multi} {}
831 const char* key,
const char* doc_string,
833 GncOptionAccountTypeList&& allowed,
bool multi=
true) :
835 m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
836 m_multiselect{multi} {}
838 const char* key,
const char* doc_string,
840 const GncOptionAccountList& value,
841 GncOptionAccountTypeList&& allowed,
bool multi=
true) :
843 m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
844 m_multiselect{multi} {
845 if (!validate(value))
846 throw std::invalid_argument(
"Supplied Value not in allowed set.");
848 m_default_value = std::move(value);
856 GncOptionAccountList get_value()
const;
857 GncOptionAccountList get_default_value()
const;
858 bool validate (
const GncOptionAccountList& values)
const;
859 void set_value (GncOptionAccountList values) {
860 if (validate(values))
867 void set_default_value (GncOptionAccountList values) {
868 if (validate(values))
870 m_value = m_default_value = values;
873 void reset_default_value() { m_value = m_default_value; }
874 void mark_saved() noexcept { m_dirty =
false; }
875 bool is_dirty()
const noexcept {
return m_dirty; }
876 bool is_changed()
const noexcept;
878 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
879 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
880 bool is_multiselect()
const noexcept {
return m_multiselect; }
881 std::string serialize()
const noexcept;
882 bool deserialize(
const std::string& str) noexcept;
885 GncOptionAccountList m_value;
886 GncOptionAccountList m_default_value;
887 GncOptionAccountTypeList m_allowed;
892 template<>
inline std::ostream&
893 operator<< <GncOptionAccountListValue>(std::ostream& oss,
896 auto values{opt.get_value()};
898 for (
auto value : values)
911 template<>
inline std::istream&
915 GncOptionAccountList values;
919 std::getline(iss, str,
' ');
923 values.push_back(*guid);
928 opt.set_value(values);
941 const char* key,
const char* doc_string,
947 const char* key,
const char* doc_string,
954 const char* key,
const char* doc_string,
956 GncOptionAccountTypeList&& allowed) :
959 m_allowed{std::move(allowed)} {}
961 const char* key,
const char* doc_string,
964 GncOptionAccountTypeList&& allowed) :
967 if (!validate(value))
968 throw std::invalid_argument(
"Supplied Value not in allowed set.");
972 const Account* get_value()
const;
973 const Account* get_default_value()
const;
974 bool validate (
const Account* value)
const;
975 void set_value (
const Account* value) {
984 void set_default_value (
const Account* value) {
988 m_value = m_default_value = *guid;
993 void reset_default_value() { m_value = m_default_value; }
994 void mark_saved() noexcept { m_dirty =
false; }
995 bool is_dirty()
const noexcept {
return m_dirty; }
996 bool is_changed()
const noexcept {
return !
guid_equal(&m_value, &m_default_value); }
998 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
999 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
1000 std::string serialize()
const noexcept;
1001 bool deserialize(
const std::string& str) noexcept;
1006 GncOptionAccountTypeList m_allowed;
1007 bool m_dirty{
false};
1010 template<>
inline std::ostream&
1011 operator<< <GncOptionAccountSelValue>(std::ostream& oss,
1014 auto value{opt.get_value()};
1015 oss << qof_instance_to_string(QOF_INSTANCE(value));
1019 template<>
inline std::istream&
1025 std::getline(iss, str,
' ');
1027 value = (
Account*)qof_instance_from_string(str, opt.get_ui_type());
1028 opt.set_value(value);
1049 const char* key,
const char* doc_string,
1052 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1053 m_period{RelativeDatePeriod::TODAY},
1054 m_default_period{RelativeDatePeriod::TODAY},
1057 const char* key,
const char* doc_string,
1060 m_ui_type{ui_type}, m_date{time}, m_default_date{time},
1061 m_period{RelativeDatePeriod::ABSOLUTE},
1062 m_default_period{RelativeDatePeriod::ABSOLUTE},
1065 const char* key,
const char* doc_string,
1069 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1070 m_period{period}, m_default_period{period},
1073 const char* key,
const char* doc_string,
1075 const RelativeDatePeriodVec& period_set) :
1077 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1078 m_period{period_set.back()},
1079 m_default_period{period_set.back()},
1080 m_period_set{period_set} {}
1085 time64 get_value()
const noexcept;
1086 time64 get_default_value()
const noexcept;
1089 uint16_t get_period_index()
const noexcept;
1090 uint16_t get_default_period_index()
const noexcept;
1091 std::ostream& out_stream(std::ostream& oss)
const noexcept;
1092 std::istream& in_stream(std::istream& iss);
1094 bool validate(
time64 time) {
1095 if (time > MINTIME && time < MAXTIME)
1100 if (validate(value))
1107 void set_value(
time64 time) {
1110 m_period = RelativeDatePeriod::ABSOLUTE;
1115 void set_value(uint16_t index) noexcept;
1117 if (validate(value))
1119 m_period = m_default_period = value;
1120 m_date = m_default_date = INT64_MAX;
1123 void set_default_value(
time64 time) {
1126 m_period = m_default_period = RelativeDatePeriod::ABSOLUTE;
1127 m_date = m_default_date = time;
1130 uint16_t num_permissible_values()
const noexcept
1132 return m_period_set.size();
1134 uint16_t permissible_value_index(
const char* key)
const noexcept;
1135 const char* permissible_value(uint16_t index)
const 1139 const char* permissible_value_name(uint16_t index)
const 1143 void reset_default_value() {
1144 m_period = m_default_period;
1145 m_date = m_default_date;
1147 void mark_saved() noexcept { m_dirty =
false; }
1148 bool is_dirty()
const noexcept {
return m_dirty; }
1149 bool is_changed()
const noexcept {
return m_period != m_default_period &&
1150 m_date != m_default_date; }
1152 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
1153 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
1154 const RelativeDatePeriodVec& get_period_set()
const {
return m_period_set; }
1155 std::string serialize()
const noexcept;
1156 bool deserialize(
const std::string& str) noexcept;
1163 RelativeDatePeriodVec m_period_set;
1164 bool m_dirty{
false};
1167 template<>
inline std::ostream&
1168 operator<< <GncOptionDateValue>(std::ostream& oss,
1171 return opt.out_stream(oss);
1174 template<>
inline std::istream&
1178 return opt.in_stream(iss);
1182 #endif //GNC_OPTION_IMPL_HPP_
std::pair< QofIdTypeConst, GncGUID > GncItem
class GncOptionQofinstanceValue
const char * gnc_relative_date_display_string(RelativeDatePeriod per)
Provide the string representation of a relative date for displaying value to a user.
The generic option-value class.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
GList * account_type_list() const noexcept
Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
A legal date value is a pair of either a RelativeDatePeriod, the absolute flag and a time64...
GList * account_type_list() const noexcept
Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
gchar * guid_to_string_buff(const GncGUID *guid, gchar *str)
The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory po...
Set one or more accounts on which to report, optionally restricted to certain account types...
This class is the parent of all option implementations.
C++ Public interface for individual options.
Account handling public routines.
Multichoice options have a vector of valid options (GncMultichoiceOptionChoices) and validate the sel...
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
#define GUID_ENCODING_LENGTH
Number of characters needed to encode a guid as a string not including the null terminator.
RelativeDatePeriod
Reporting periods relative to the current date.
class GncOptionCommodityValue Commodities are stored with their namespace and mnemonic instead of the...
Used for numeric ranges and plot sizes.
class GncOptionGncOwnerValue
const GncGUID * qof_entity_get_guid(gconstpointer ent)
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
const char * gnc_relative_date_storage_string(RelativeDatePeriod per)
Provide the string representation of a relative date for persisting the value.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
The type used to store guids in C.
GncOptionUIType
Used by GncOptionClassifier to indicate to dialog-options what control should be displayed for the op...
Commodity handling public routines.