33 #ifndef GNC_OPTION_IMPL_HPP_ 34 #define GNC_OPTION_IMPL_HPP_ 43 #include "gnc-datetime.hpp" 58 size_t constexpr classifier_size_max{50};
59 size_t constexpr sort_tag_size_max{10};
70 std::string m_section;
72 std::string m_sort_tag;
74 std::string m_doc_string;
79 auto constexpr uint16_t_max = std::numeric_limits<uint16_t>::max();
85 template <
typename ValueType>
90 const char* key,
const char* doc_string,
94 m_ui_type(ui_type), m_value{value}, m_default_value{value} { }
100 ValueType get_value()
const {
return m_value; }
101 ValueType get_default_value()
const {
return m_default_value; }
102 void set_value(ValueType new_value);
103 void set_default_value(ValueType new_value);
104 void reset_default_value();
105 void mark_saved() noexcept { m_dirty =
false; }
106 bool is_dirty()
const noexcept {
return m_dirty; }
107 bool is_changed()
const noexcept {
return m_value != m_default_value; }
109 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
110 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
111 std::string serialize()
const noexcept;
112 bool deserialize(
const std::string& str) noexcept;
116 ValueType m_default_value;
134 using GncOwnerPtr = std::unique_ptr<GncOwner, GncOwnerDeleter>;
139 const char* section,
const char* name,
140 const char* key,
const char* doc_string,
147 const GncOwner* get_default_value()
const;
148 void set_value(
const GncOwner* new_value);
149 void set_default_value(
const GncOwner* new_value);
150 void reset_default_value();
151 void mark_saved() noexcept { m_dirty =
false; }
152 bool is_dirty()
const noexcept {
return m_dirty; }
153 bool is_changed()
const noexcept;
155 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
156 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
157 std::string serialize()
const noexcept;
158 bool deserialize(
const std::string& str) noexcept;
162 GncOwnerPtr m_default_value;
171 using GncItem = std::pair<QofIdTypeConst, GncGUID>;
176 const char* section,
const char* name,
177 const char* key,
const char* doc_string,
186 GncItem get_item()
const {
return m_value; }
187 GncItem get_default_item()
const {
return m_default_value; }
189 void set_default_value(
const QofInstance* new_value);
190 void reset_default_value();
191 void mark_saved() noexcept { m_dirty =
false; }
192 bool is_dirty()
const noexcept {
return m_dirty; }
193 bool is_changed()
const noexcept;
195 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
196 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
197 std::string serialize()
const noexcept;
198 bool deserialize(
const std::string& str) noexcept;
219 const char* key,
const char* doc_string,
220 gnc_commodity* value,
223 m_ui_type{ui_type}, m_is_currency{ui_type == GncOptionUIType::CURRENCY},
229 if (!validate(value))
230 throw std::invalid_argument(
"Attempt to create GncOptionCommodityValue with currency UIType and non-currency value.");
236 gnc_commodity* get_value()
const;
237 gnc_commodity* get_default_value()
const;
238 bool validate(gnc_commodity*)
const noexcept;
239 void set_value(gnc_commodity* value);
240 void set_default_value(gnc_commodity* value);
241 void reset_default_value();
242 void mark_saved() noexcept { m_dirty =
false; }
243 bool is_dirty()
const noexcept {
return m_dirty; }
244 bool is_changed()
const noexcept;
246 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
247 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
248 std::string serialize()
const noexcept;
249 bool deserialize(
const std::string& str) noexcept;
253 std::string m_namespace;
254 std::string m_mnemonic;
255 std::string m_default_namespace;
256 std::string m_default_mnemonic;
260 QofInstance* qof_instance_from_string(
const std::string& str,
263 std::string qof_instance_to_string(
const QofInstance* inst);
265 template <
typename T>
268 static constexpr
bool value =
272 template <
typename T>
inline constexpr
bool 275 template <
typename T>
278 static constexpr
bool value =
282 template <
typename T>
inline constexpr
bool 285 template <
typename T>
288 static constexpr
bool value =
292 template <
typename T>
inline constexpr
bool 303 template<
class OptType,
304 typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
305 ! (is_QofInstanceValue_v<OptType> ||
306 is_RangeValue_v<OptType>),
int> = 0>
307 std::ostream&
operator<<(std::ostream& oss,
const OptType& opt)
309 oss << opt.get_value();
313 template<>
inline std::ostream&
314 operator<< <GncOptionValue<bool>>(std::ostream& oss,
317 oss << (opt.get_value() ?
"#t" :
"#f");
324 oss << opt.serialize();
328 template<
class OptType,
329 typename std::enable_if_t<is_QofInstanceValue_v<OptType>,
int> = 0>
331 operator<< (std::ostream& oss,
const OptType& opt)
333 auto value = opt.get_value();
334 oss << qof_instance_to_string(value);
338 template<
class OptType,
339 typename std::enable_if_t<is_OptionClassifier_v<OptType> &&
340 !(is_QofInstanceValue_v<OptType> ||
341 is_RangeValue_v<OptType>),
int> = 0>
342 std::istream&
operator>>(std::istream& iss, OptType& opt)
344 if constexpr (std::is_same_v<std::decay_t<decltype(opt.get_value())>,
const _gncOwner*> ||
345 std::is_same_v<std::decay_t<decltype(opt.get_value())>,
const _QofQuery*> ||
346 std::is_same_v<std::decay_t<decltype(opt.get_value())>, GncOptionDateFormat>)
350 std::decay_t<decltype(opt.get_value())> value;
352 opt.set_value(value);
359 template<
class OptType,
360 typename std::enable_if_t<is_QofInstanceValue_v<OptType>,
int> = 0>
362 operator>> (std::istream& iss, OptType& opt)
366 opt.set_value(qof_instance_from_string(instr, opt.get_ui_type()));
370 template<>
inline std::istream&
376 opt.set_value(instr ==
"#t" ?
true :
false);
380 template<>
inline std::istream&
384 uint32_t id, wide, high;
385 iss >>
id >> wide >> high;
386 opt.set_value(GncOptionReportPlacementVec{{id, wide, high}});
395 template <
typename ValueType>
400 const char* key,
const char* doc_string,
401 ValueType value, ValueType min,
402 ValueType max, ValueType step) :
404 max, step, GncOptionUIType::NUMBER_RANGE} {}
406 const char* key,
const char* doc_string,
407 ValueType value, ValueType min,
410 m_value{value >= min && value <= max ? value : min},
411 m_default_value{value >= min && value <= max ? value : min},
412 m_min{min}, m_max{max}, m_step{step} {
413 if constexpr(is_same_decayed_v<ValueType, int>)
414 set_alternate(
true);}
419 ValueType get_value()
const {
return m_value; }
420 ValueType get_default_value()
const {
return m_default_value; }
421 bool validate(ValueType value) {
return value >= m_min && value <= m_max; }
422 void set_value(ValueType value)
424 if (this->validate(value))
430 throw std::invalid_argument(
"Validation failed, value not set.");
432 void set_default_value(ValueType value)
434 if (this->validate(value))
435 m_value = m_default_value = value;
437 throw std::invalid_argument(
"Validation failed, value not set.");
439 void get_limits(ValueType& upper, ValueType& lower, ValueType& step)
const noexcept
445 void reset_default_value() { m_value = m_default_value; }
446 void mark_saved() noexcept { m_dirty =
false; }
447 bool is_dirty()
const noexcept {
return m_dirty; }
448 bool is_changed()
const noexcept {
return m_value != m_default_value; }
450 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
451 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
452 bool is_alternate()
const noexcept {
return m_alternate; }
453 void set_alternate(
bool value) noexcept { m_alternate = value; }
454 std::string serialize()
const noexcept;
455 bool deserialize(
const std::string& str) noexcept;
459 ValueType m_default_value;
463 bool m_alternate{
false};
467 template<
class OptType,
468 typename std::enable_if_t<is_RangeValue_v<OptType>,
int> = 0>
470 operator<< (std::ostream& oss,
const OptType& opt)
472 if (opt.get_ui_type() == GncOptionUIType::PLOT_SIZE)
473 oss << (opt.is_alternate() ?
"pixels" :
"percent") <<
" ";
474 oss << opt.get_value();
478 template<
class OptType,
479 typename std::enable_if_t<is_RangeValue_v<OptType>,
int> = 0>
481 operator>> (std::istream& iss, OptType& opt)
483 if (opt.get_ui_type() == GncOptionUIType::PLOT_SIZE)
487 opt.set_alternate(strncmp(alt.c_str(),
"percent",
488 strlen(
"percent")) == 0);
490 if constexpr (std::is_same_v<std::decay_t<OptType>,
506 using GncMultichoiceOptionEntry = std::tuple<
const std::string,
508 GncOptionMultichoiceKeyType>;
509 using GncMultichoiceOptionIndexVec = std::vector<uint16_t>;
510 using GncMultichoiceOptionChoices = std::vector<GncMultichoiceOptionEntry>;
531 const char* key,
const char* doc_string,
533 GncMultichoiceOptionChoices&& choices,
537 m_value{}, m_default_value{}, m_choices{std::move(choices)}
541 if (
auto index = find_key(value);
542 index != uint16_t_max)
544 m_value.push_back(index);
545 m_default_value.push_back(index);
551 const char* key,
const char* doc_string,
553 GncMultichoiceOptionChoices&& choices,
557 m_value{}, m_default_value{}, m_choices{std::move(choices)}
559 if (index < m_choices.size())
561 m_value.push_back(index);
562 m_default_value.push_back(index);
567 const char* key,
const char* doc_string,
568 GncMultichoiceOptionIndexVec&& indices,
569 GncMultichoiceOptionChoices&& choices,
573 m_value{indices}, m_default_value{std::move(indices)},
574 m_choices{std::move(choices)} {}
580 const std::string& get_value()
const 582 auto vec{m_value.size() > 0 ? m_value : m_default_value};
584 return c_empty_string;
586 return std::get<0>(m_choices.at(vec[0]));
588 return c_list_string;
591 const std::string& get_default_value()
const 593 if (m_default_value.size() == 1)
594 return std::get<0>(m_choices.at(m_default_value[0]));
595 else if (m_default_value.size() == 0)
596 return c_empty_string;
598 return c_list_string;
601 uint16_t get_index()
const 603 if (m_value.size() > 0)
605 if (m_default_value.size() > 0)
606 return m_default_value[0];
609 const GncMultichoiceOptionIndexVec& get_multiple()
const noexcept
613 const GncMultichoiceOptionIndexVec& get_default_multiple()
const noexcept
615 return m_default_value;
617 bool validate(
const std::string& value)
const noexcept
619 auto index = find_key(value);
620 return index != uint16_t_max;
623 bool validate(
const GncMultichoiceOptionIndexVec& indexes)
const noexcept
625 for (
auto index : indexes)
626 if (index >= m_choices.size())
631 void set_value(
const std::string& value)
633 auto index = find_key(value);
634 if (index != uint16_t_max)
637 m_value.push_back(index);
641 throw std::invalid_argument(
"Value not a valid choice.");
644 void set_value(uint16_t index)
646 if (index < m_choices.size())
649 m_value.push_back(index);
653 throw std::invalid_argument(
"Value not a valid choice.");
656 void set_default_value(
const std::string& value)
658 auto index = find_key(value);
659 if (index != uint16_t_max)
662 m_value.push_back(index);
663 m_default_value.clear();
664 m_default_value.push_back(index);
667 throw std::invalid_argument(
"Value not a valid choice.");
670 void set_default_value(uint16_t index)
672 if (index < m_choices.size())
675 m_value.push_back(index);
676 m_default_value.clear();
677 m_default_value.push_back(index);
680 throw std::invalid_argument(
"Value not a valid choice.");
683 void set_multiple(
const GncMultichoiceOptionIndexVec& indexes)
685 if (validate(indexes))
688 throw std::invalid_argument(
"One of the supplied indexes was out of range.");
690 void set_default_multiple(
const GncMultichoiceOptionIndexVec& indexes)
692 if (validate(indexes))
693 m_value = m_default_value = indexes;
695 throw std::invalid_argument(
"One of the supplied indexes was out of range.");
697 uint16_t num_permissible_values()
const noexcept
699 return m_choices.size();
701 uint16_t permissible_value_index(
const char* key)
const noexcept
703 return find_key(key);
705 const char* permissible_value(uint16_t index)
const 707 return std::get<0>(m_choices.at(index)).c_str();
709 const char* permissible_value_name(uint16_t index)
const 711 return std::get<1>(m_choices.at(index)).c_str();
713 void reset_default_value() { m_value = m_default_value; }
714 void mark_saved() noexcept { m_dirty =
false; }
715 bool is_dirty()
const noexcept {
return m_dirty; }
716 bool is_changed()
const noexcept {
return m_value != m_default_value; }
718 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
719 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
720 GncOptionMultichoiceKeyType get_keytype(
unsigned i)
const {
return std::get<2>(m_choices.at(i)); }
721 std::string serialize()
const noexcept;
722 bool deserialize(
const std::string& str) noexcept;
724 uint16_t find_key (
const std::string& key)
const noexcept
726 auto iter = std::find_if(m_choices.begin(), m_choices.end(),
728 return std::get<0>(choice) == key; });
729 if (iter != m_choices.end())
730 return iter - m_choices.begin();
736 GncMultichoiceOptionIndexVec m_value;
737 GncMultichoiceOptionIndexVec m_default_value;
738 GncMultichoiceOptionChoices m_choices;
740 static const std::string c_empty_string;
741 static const std::string c_list_string;
744 template<>
inline std::ostream&
745 operator<< <GncOptionMultichoiceValue>(std::ostream& oss,
748 auto vec{opt.get_multiple()};
750 for (
auto index : vec)
756 oss << opt.permissible_value(index);
761 template<>
inline std::istream&
765 GncMultichoiceOptionIndexVec values;
769 std::getline(iss, str,
' ');
772 auto index = opt.permissible_value_index(str.c_str());
773 if (index != uint16_t_max)
774 values.push_back(index);
777 std::string err = str +
" is not one of ";
779 err +=
"'s permissible values.";
780 throw std::invalid_argument(err);
786 opt.set_multiple(values);
792 using GncOptionAccountList = std::vector<GncGUID>;
794 using GncOptionAccountTypeList = std::vector<GNCAccountType>;
817 const char* key,
const char* doc_string,
820 m_value{}, m_default_value{}, m_allowed{}, m_multiselect{multi} {}
823 const char* key,
const char* doc_string,
825 const GncOptionAccountList& value,
bool multi=
true) :
827 m_value{value}, m_default_value{std::move(value)}, m_allowed{},
828 m_multiselect{multi} {}
830 const char* key,
const char* doc_string,
832 GncOptionAccountTypeList&& allowed,
bool multi=
true) :
834 m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
835 m_multiselect{multi} {}
837 const char* key,
const char* doc_string,
839 const GncOptionAccountList& value,
840 GncOptionAccountTypeList&& allowed,
bool multi=
true) :
842 m_value{}, m_default_value{}, m_allowed{std::move(allowed)},
843 m_multiselect{multi} {
844 if (!validate(value))
845 throw std::invalid_argument(
"Supplied Value not in allowed set.");
847 m_default_value = std::move(value);
855 GncOptionAccountList get_value()
const;
856 GncOptionAccountList get_default_value()
const;
857 bool validate (
const GncOptionAccountList& values)
const;
858 void set_value (GncOptionAccountList values) {
859 if (validate(values))
866 void set_default_value (GncOptionAccountList values) {
867 if (validate(values))
869 m_value = m_default_value = values;
872 void reset_default_value() { m_value = m_default_value; }
873 void mark_saved() noexcept { m_dirty =
false; }
874 bool is_dirty()
const noexcept {
return m_dirty; }
875 bool is_changed()
const noexcept;
877 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
878 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
879 bool is_multiselect()
const noexcept {
return m_multiselect; }
880 std::string serialize()
const noexcept;
881 bool deserialize(
const std::string& str) noexcept;
884 GncOptionAccountList m_value;
885 GncOptionAccountList m_default_value;
886 GncOptionAccountTypeList m_allowed;
891 template<>
inline std::ostream&
892 operator<< <GncOptionAccountListValue>(std::ostream& oss,
895 auto values{opt.get_value()};
897 for (
auto value : values)
910 template<>
inline std::istream&
914 GncOptionAccountList values;
918 std::getline(iss, str,
' ');
922 values.push_back(*guid);
927 opt.set_value(values);
940 const char* key,
const char* doc_string,
946 const char* key,
const char* doc_string,
953 const char* key,
const char* doc_string,
955 GncOptionAccountTypeList&& allowed) :
958 m_allowed{std::move(allowed)} {}
960 const char* key,
const char* doc_string,
963 GncOptionAccountTypeList&& allowed) :
966 if (!validate(value))
967 throw std::invalid_argument(
"Supplied Value not in allowed set.");
971 const Account* get_value()
const;
972 const Account* get_default_value()
const;
973 bool validate (
const Account* value)
const;
974 void set_value (
const Account* value) {
983 void set_default_value (
const Account* value) {
987 m_value = m_default_value = *guid;
992 void reset_default_value() { m_value = m_default_value; }
993 void mark_saved() noexcept { m_dirty =
false; }
994 bool is_dirty()
const noexcept {
return m_dirty; }
995 bool is_changed()
const noexcept {
return !
guid_equal(&m_value, &m_default_value); }
997 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
998 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
999 std::string serialize()
const noexcept;
1000 bool deserialize(
const std::string& str) noexcept;
1005 GncOptionAccountTypeList m_allowed;
1006 bool m_dirty{
false};
1009 template<>
inline std::ostream&
1010 operator<< <GncOptionAccountSelValue>(std::ostream& oss,
1013 auto value{opt.get_value()};
1014 oss << qof_instance_to_string(QOF_INSTANCE(value));
1018 template<>
inline std::istream&
1024 std::getline(iss, str,
' ');
1026 value = (
Account*)qof_instance_from_string(str, opt.get_ui_type());
1027 opt.set_value(value);
1048 const char* key,
const char* doc_string,
1051 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1052 m_period{RelativeDatePeriod::TODAY},
1053 m_default_period{RelativeDatePeriod::TODAY},
1056 const char* key,
const char* doc_string,
1059 m_ui_type{ui_type}, m_date{time}, m_default_date{time},
1060 m_period{RelativeDatePeriod::ABSOLUTE},
1061 m_default_period{RelativeDatePeriod::ABSOLUTE},
1064 const char* key,
const char* doc_string,
1068 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1069 m_period{period}, m_default_period{period},
1072 const char* key,
const char* doc_string,
1074 const RelativeDatePeriodVec& period_set) :
1076 m_ui_type{ui_type}, m_date{INT64_MAX}, m_default_date{INT64_MAX},
1077 m_period{period_set.back()},
1078 m_default_period{period_set.back()},
1079 m_period_set{period_set} {}
1084 time64 get_value()
const noexcept;
1085 time64 get_default_value()
const noexcept;
1088 uint16_t get_period_index()
const noexcept;
1089 uint16_t get_default_period_index()
const noexcept;
1090 std::ostream& out_stream(std::ostream& oss)
const noexcept;
1091 std::istream& in_stream(std::istream& iss);
1093 bool validate(
time64 time) {
1094 if (time > MINTIME && time < MAXTIME)
1099 if (validate(value))
1106 void set_value(
time64 time) {
1109 m_period = RelativeDatePeriod::ABSOLUTE;
1114 void set_value(uint16_t index) noexcept;
1116 if (validate(value))
1118 m_period = m_default_period = value;
1119 m_date = m_default_date = INT64_MAX;
1122 void set_default_value(
time64 time) {
1125 m_period = m_default_period = RelativeDatePeriod::ABSOLUTE;
1126 m_date = m_default_date = time;
1129 uint16_t num_permissible_values()
const noexcept
1131 return m_period_set.size();
1133 uint16_t permissible_value_index(
const char* key)
const noexcept;
1134 const char* permissible_value(uint16_t index)
const 1138 const char* permissible_value_name(uint16_t index)
const 1142 void reset_default_value() {
1143 m_period = m_default_period;
1144 m_date = m_default_date;
1146 void mark_saved() noexcept { m_dirty =
false; }
1147 bool is_dirty()
const noexcept {
return m_dirty; }
1148 bool is_changed()
const noexcept {
return m_period != m_default_period &&
1149 m_date != m_default_date; }
1151 void make_internal() { m_ui_type = GncOptionUIType::INTERNAL; }
1152 bool is_internal() {
return m_ui_type == GncOptionUIType::INTERNAL; }
1153 const RelativeDatePeriodVec& get_period_set()
const {
return m_period_set; }
1154 std::string serialize()
const noexcept;
1155 bool deserialize(
const std::string& str) noexcept;
1162 RelativeDatePeriodVec m_period_set;
1163 bool m_dirty{
false};
1166 template<>
inline std::ostream&
1167 operator<< <GncOptionDateValue>(std::ostream& oss,
1170 return opt.out_stream(oss);
1173 template<>
inline std::istream&
1177 return opt.in_stream(iss);
1181 #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.