GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-option.cpp
1/********************************************************************\
2 * gnc-option.cpp -- Application options system *
3 * Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
4 * *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation; either version 2 of *
8 * the License, or (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License*
16 * along with this program; if not, contact: *
17 * *
18 * Free Software Foundation Voice: +1-617-542-5942 *
19 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 * Boston, MA 02110-1301, USA gnu@gnu.org *
21 * *
22\********************************************************************/
23
24#include "gnc-option.hpp"
25#include "gnc-option-impl.hpp"
26#include "gnc-option-uitype.hpp"
27#include "gnc-option-ui.hpp"
28#include "gncOwner.h"
29#include "kvp-value.hpp"
30
31static const char* log_module{"gnc.engine.gnc-option"};
32
33#include "qoflog.h"
34
35template <typename ValueType,
36 typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
37 int>>
38GncOption::GncOption(const char* section, const char* name,
39 const char* key, const char* doc_string,
40 ValueType value, GncOptionUIType ui_type) :
41 m_option{std::make_unique<GncOptionVariant>(
42 std::in_place_type<GncOptionValue<ValueType>>,
43 section, name, key, doc_string, value, ui_type)}
44{
45}
46
47template <typename ValueType> ValueType
48GncOption::get_value() const
49{
50 return std::visit(
51 [](const auto& option)->ValueType {
52 if constexpr (is_same_decayed_v<decltype(option.get_value()),
53 ValueType>)
54 return option.get_value();
55 if constexpr (is_same_decayed_v<decltype(option),
57 {
58 if constexpr (is_same_decayed_v<ValueType,
60 return option.get_period();
61 if constexpr (std::is_same_v<ValueType, time64>)
62 return option.get_value();
63 if constexpr (std::is_same_v<ValueType, uint16_t>)
64 return option.get_period_index();
65 return ValueType{};
66 }
67 if constexpr (is_same_decayed_v<decltype(option),
69 {
70 if constexpr (std::is_same_v<ValueType, uint16_t>)
71 return option.get_index();
72 if constexpr (is_same_decayed_v<ValueType,
73 GncMultichoiceOptionIndexVec>)
74 return option.get_multiple();
75 }
76 return ValueType {};
77 }, *m_option);
78}
79
80template <typename ValueType> ValueType
81GncOption::get_default_value() const
82{
83 return std::visit(
84 [](const auto& option)->ValueType {
85 if constexpr (is_same_decayed_v<decltype(option.get_value()),
86 ValueType>)
87 return option.get_default_value();
88 if constexpr (is_same_decayed_v<decltype(option),
90 {
91 if constexpr (is_same_decayed_v<ValueType,
93 return option.get_default_period();
94 if constexpr (std::is_same_v<ValueType, time64>)
95 return option.get_value();
96 if constexpr (std::is_same_v<ValueType, uint16_t>)
97 return option.get_default_period_index();
98 return ValueType{};
99 }
100 if constexpr
101 (is_same_decayed_v<decltype(option),
103 is_same_decayed_v<ValueType,
104 GncMultichoiceOptionIndexVec>)
105 return option.get_default_multiple();
106 return ValueType {};
107 }, *m_option);
108
109}
110
111template <typename ValueType> void
112GncOption::set_value(ValueType value)
113{
114 std::visit(
115 [value](auto& option) {
116 if constexpr
117 (is_same_decayed_v<decltype(option.get_value()), ValueType> ||
118 is_same_decayed_v<decltype(option), GncOptionDateFormat> ||
119 (is_same_decayed_v<decltype(option),
121 (is_same_decayed_v<ValueType, RelativeDatePeriod> ||
122 std::is_same_v<ValueType, time64> ||
123 std::is_same_v<ValueType, uint16_t>)))
124 option.set_value(value);
125 else if constexpr (is_same_decayed_v<decltype(option),
127 {
128 if constexpr (is_same_decayed_v<ValueType,
129 GncMultichoiceOptionIndexVec>)
130 option.set_multiple(value);
131 else if constexpr
132 (std::is_same_v<ValueType, uint16_t> ||
133 is_same_decayed_v<ValueType, std::string> ||
134 std::is_same_v<std::remove_cv<ValueType>, char*>)
135 option.set_value(value);
136 }
137 else
138 PWARN("No set_value handler: get_value returns %s, value_type is %s",
139 typeid(option.get_value()).name(), typeid(value).name());
140 }, *m_option);
141}
142
143template <typename ValueType> void
144GncOption::set_default_value(ValueType value)
145{
146 std::visit(
147 [value](auto& option) {
148 if constexpr
149 (is_same_decayed_v<decltype(option.get_value()), ValueType>||
150 is_same_decayed_v<decltype(option), GncOptionDateFormat> ||
151 (is_same_decayed_v<decltype(option), GncOptionDateValue> &&
152 (is_same_decayed_v<ValueType, RelativeDatePeriod> ||
153 std::is_same_v<ValueType, time64> ||
154 std::is_same_v<ValueType, uint16_t>)))
155 option.set_default_value(value);
156 if constexpr (is_same_decayed_v<decltype(option),
158 {
159 if constexpr (is_same_decayed_v<ValueType,
160 GncMultichoiceOptionIndexVec>)
161 option.set_default_multiple(value);
162 else if constexpr
163 (std::is_same_v<ValueType, uint16_t> ||
164 is_same_decayed_v<ValueType, std::string> ||
165 std::is_same_v<std::remove_cv<ValueType>, char*>)
166 option.set_default_value(value);
167 }
168 }, *m_option);
169}
170void
171GncOption::reset_default_value()
172{
173 std::visit([](auto& option) { option.reset_default_value(); }, *m_option);
174}
175
176template <typename ValueType> void
177GncOption::get_limits(ValueType& max, ValueType& min, ValueType& step) const noexcept
178{
179 std::visit([&max, &min, &step](const auto& option) {
180 if constexpr
181 (is_same_decayed_v<decltype(option),
183 option.get_limits(max, min, step);
184 }, *m_option);
185}
186
187const std::string&
188GncOption::get_section() const
189{
190 return std::visit([](const auto& option)->const std::string& {
191 return option.m_section;
192 }, *m_option);
193}
194
195const std::string&
196GncOption::get_name() const
197{
198 return std::visit([](const auto& option)->const std::string& {
199 return option.m_name;
200 }, *m_option);
201}
202
203const std::string&
204GncOption::get_key() const
205{
206 return std::visit([](const auto& option)->const std::string& {
207 return option.m_sort_tag;
208 }, *m_option);
209}
210
211const std::string&
212GncOption::get_docstring() const
213{
214 return std::visit([](const auto& option)->const std::string& {
215 return option.m_doc_string;
216 }, *m_option);
217}
218
219void
220GncOption::set_ui_item(GncOptionUIItemPtr&& ui_item)
221{
222
223 auto opt_ui_type = std::visit([](const auto& option)->GncOptionUIType {
224 return option.get_ui_type();
225 }, *m_option);
226
227 //ui_item may be nullptr to free the old m_ui_item.
228 if (ui_item && ui_item->get_ui_type() != opt_ui_type)
229 {
230 PERR("Setting option %s:%s UI element failed, mismatched UI types.",
231 get_section().c_str(), get_name().c_str());
232 return;
233 }
234
235 m_ui_item = std::move(ui_item);
236}
237
238void
239GncOption::set_ui_item_selectable(bool selectable) const noexcept
240{
241 if (m_ui_item)
242 m_ui_item->set_selectable(selectable);
243}
244
245const GncOptionUIType
246GncOption::get_ui_type() const
247{
248 return std::visit([](const auto& option)->GncOptionUIType {
249 return option.get_ui_type();
250 }, *m_option);
251}
252
253GncOptionUIItem* const
254GncOption::get_ui_item() const
255{
256 return m_ui_item.get();
257}
258
259void
260GncOption::set_ui_item_from_option()
261{
262 if (!m_ui_item)
263 return;
264 m_ui_item->set_ui_item_from_option(*this);
265}
266
267void
268GncOption::set_option_from_ui_item()
269{
270 if (!m_ui_item)
271 return;
272 m_ui_item->set_option_from_ui_item(*this);
273}
274
275void
276GncOption::make_internal()
277{
278 if (m_ui_item)
279 {
280 PERR("Option %s:%s has a UI Element, can't be INTERNAL.",
281 get_section().c_str(), get_name().c_str());
282 return;
283 }
284 std::visit([](auto& option) {
285 option.make_internal();
286 }, *m_option);
287}
288
289bool
290GncOption::is_internal()
291{
292 return std::visit([](auto& option)->bool {
293 return option.is_internal();
294 }, *m_option);
295}
296
297void
299{
300 std::visit([](auto& option)->void {
301 option.mark_saved();
302 }, *m_option);
303}
304
305bool
306GncOption::is_dirty() const noexcept
307{
308 return std::visit([](const auto& option)->bool {
309 return option.is_dirty();
310 }, *m_option);
311}
312
313bool
314GncOption::is_changed() const noexcept
315{
316 return std::visit([](const auto& option)->bool {
317 return option.is_changed();
318 }, *m_option);
319}
320
321bool
323{
324 return std::visit(
325 [](const auto& option)->bool {
326 if constexpr (is_same_decayed_v<decltype(option),
328 return option.is_multiselect();
329 else
330 return false;
331 }, *m_option);
332}
333
334template<typename ValueType> bool
335GncOption::validate(ValueType value) const
336{
337 return std::visit(
338 [value] (const auto& option) -> bool {
339 if constexpr ((is_same_decayed_v<decltype(option),
341 is_same_decayed_v<ValueType, std::string>) ||
342 (is_same_decayed_v<decltype(option),
344 is_same_decayed_v<ValueType,
345 GncMultichoiceOptionIndexVec>) ||
346 (is_same_decayed_v<decltype(option),
348 is_same_decayed_v<ValueType, gnc_commodity*>))
349 return option.validate(value);
350 else
351 return false;
352 }, *m_option);
353}
354
355std::uint16_t
357{
358 return std::visit(
359 [] (const auto& option) -> uint16_t {
360 if constexpr (is_same_decayed_v<decltype(option),
362 is_same_decayed_v<decltype(option),
364 return option.num_permissible_values();
365 else
366 return uint16_t_max;
367 }, *m_option);
368}
369
370std::uint16_t
372{
373 return std::visit(
374 [&value] (const auto& option) -> uint16_t {
375 if constexpr (is_same_decayed_v<decltype(option),
377 is_same_decayed_v<decltype(option),
379 return option.permissible_value_index(value);
380 else
381 return uint16_t_max;
382 }, *m_option);
383}
384
385const char*
386GncOption::permissible_value(std::uint16_t index) const
387{
388 return std::visit([index] (const auto& option) -> const char* {
389 if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
391 std::is_same_v<std::decay_t<decltype(option)>,
393 return option.permissible_value(index);
394 else
395 return "";
396 }, *m_option);
397}
398
399const char*
400GncOption::permissible_value_name(std::uint16_t index) const
401{
402 return std::visit([index] (const auto& option) -> const char* {
403 if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
405 std::is_same_v<std::decay_t<decltype(option)>,
407 return option.permissible_value_name(index);
408 else
409 return "";
410 }, *m_option);
411}
412
413GList*
415{
416 return std::visit([] (const auto& option) -> GList* {
417 if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
419 return option.account_type_list();
420 else
421 return nullptr;
422 }, *m_option);
423}
424
425bool
426GncOption::is_alternate() const noexcept
427{
428 return std::visit([](auto& option) -> bool {
429 if constexpr(is_RangeValue_v<decltype(option)>)
430 return option.is_alternate();
431 return false;
432 }, *m_option);
433}
434
435void
436GncOption::set_alternate(bool alt) noexcept
437{
438 std::visit([alt](auto& option) {
439 if constexpr(is_RangeValue_v<decltype(option)>)
440 option.set_alternate(alt);
441 }, *m_option);
442}
443
444std::string
446{
447 if (m_option->valueless_by_exception())
448 return "Valueless Option";
449 return std::visit([&](auto& option) -> std::string {
450 return option.serialize();
451 }, *m_option);
452}
453
454bool
455GncOption::deserialize(const std::string& str)
456{
457 return std::visit([&str](auto& option) -> bool {
458 return option.deserialize(str);
459 }, *m_option);
460}
461
462std::istream&
463GncOption::in_stream(std::istream& iss)
464{
465 return std::visit([&iss](auto& option) -> std::istream& {
466 iss >> option;
467 return iss;
468 }, *m_option);
469}
470
471/* We must instantiate all of the templates we need here because we don't expose
472 * the template implementation in the public header.
473 */
474
475
476template GncOption::GncOption(const char*, const char*, const char*,
477 const char*, bool, GncOptionUIType);
478//template GncOption::GncOption(const char*, const char*, const char*,
479// const char*, int, GncOptionUIType);
480template GncOption::GncOption(const char*, const char*, const char*,
481 const char*, int64_t, GncOptionUIType);
482//template GncOption::GncOption(const char*, const char*, const char*,
483// const char*, const char*, GncOptionUIType);
484//template GncOption::GncOption(const char*, const char*, const char*,
485// const char*, double, GncOptionUIType);
486template GncOption::GncOption(const char*, const char*, const char*,
487 const char*, std::string, GncOptionUIType);
488template GncOption::GncOption(const char*, const char*, const char*,
489 const char*, const QofQuery*, GncOptionUIType);
490
491template GncOption::GncOption(const char *, const char*, const char*,
492 const char *, GncOptionDateFormat,
494
495template bool GncOption::get_value<bool>() const;
496template int GncOption::get_value<int>() const;
497template int64_t GncOption::get_value<int64_t>() const;
498template double GncOption::get_value<double>() const;
499template uint16_t GncOption::get_value<uint16_t>() const;
500template const char* GncOption::get_value<const char*>() const;
501template std::string GncOption::get_value<std::string>() const;
502template const QofInstance* GncOption::get_value<const QofInstance*>() const;
503template const GncOwner* GncOption::get_value<const GncOwner*>() const;
504template gnc_commodity* GncOption::get_value<gnc_commodity*>() const;
505template const Account* GncOption::get_value<const Account*>() const;
506template RelativeDatePeriod GncOption::get_value<RelativeDatePeriod>() const;
507template GncOptionAccountList GncOption::get_value<GncOptionAccountList>() const;
508template GncMultichoiceOptionIndexVec GncOption::get_value<GncMultichoiceOptionIndexVec>() const;
509template GncOptionReportPlacementVec GncOption::get_value<GncOptionReportPlacementVec>() const;
510template GncOptionDateFormat GncOption::get_value<GncOptionDateFormat>() const;
511
512template bool GncOption::get_default_value<bool>() const;
513template int GncOption::get_default_value<int>() const;
514template int64_t GncOption::get_default_value<int64_t>() const;
515template double GncOption::get_default_value<double>() const;
516template const char* GncOption::get_default_value<const char*>() const;
517template std::string GncOption::get_default_value<std::string>() const;
518template const QofInstance* GncOption::get_default_value<const QofInstance*>() const;
519template gnc_commodity* GncOption::get_default_value<gnc_commodity*>() const;
520template const Account* GncOption::get_default_value<const Account*>() const;
521template RelativeDatePeriod GncOption::get_default_value<RelativeDatePeriod>() const;
522template GncOptionAccountList GncOption::get_default_value<GncOptionAccountList>() const;
523template GncMultichoiceOptionIndexVec GncOption::get_default_value<GncMultichoiceOptionIndexVec>() const;
524template GncOptionReportPlacementVec GncOption::get_default_value<GncOptionReportPlacementVec>() const;
525template GncOptionDateFormat GncOption::get_default_value<GncOptionDateFormat>() const;
526
527template void GncOption::set_value(bool);
528template void GncOption::set_value(int);
529template void GncOption::set_value(int64_t);
530template void GncOption::set_value(double);
531template void GncOption::set_value(char*);
532template void GncOption::set_value(const char*);
533template void GncOption::set_value(std::string);
534template void GncOption::set_value(const QofInstance*);
535template void GncOption::set_value(const GncOwner*);
536template void GncOption::set_value(gnc_commodity*);
537template void GncOption::set_value(const Account*);
538template void GncOption::set_value(RelativeDatePeriod);
539template void GncOption::set_value(uint16_t);
540template void GncOption::set_value(GncOptionAccountList);
541template void GncOption::set_value(GncMultichoiceOptionIndexVec);
542template void GncOption::set_value(GncOptionReportPlacementVec);
543template void GncOption::set_value(GncOptionDateFormat);
544
545template void GncOption::set_default_value(bool);
546template void GncOption::set_default_value(int);
547template void GncOption::set_default_value(int64_t);
548template void GncOption::set_default_value(double);
549template void GncOption::set_default_value(char*);
550template void GncOption::set_default_value(const char*);
551template void GncOption::set_default_value(std::string);
552template void GncOption::set_default_value(const QofInstance*);
553template void GncOption::set_default_value(const Account*);
554template void GncOption::set_default_value(RelativeDatePeriod);
555template void GncOption::set_default_value(uint16_t);
556template void GncOption::set_default_value(GncOptionAccountList);
557template void GncOption::set_default_value(GncMultichoiceOptionIndexVec);
558template void GncOption::set_default_value(GncOptionReportPlacementVec);
559template void GncOption::set_default_value(GncOptionDateFormat);
560
561template void GncOption::get_limits(double&, double&, double&) const noexcept;
562template void GncOption::get_limits(int&, int&, int&) const noexcept;
563template bool GncOption::validate(bool) const;
564template bool GncOption::validate(int) const;
565template bool GncOption::validate(int64_t) const;
566template bool GncOption::validate(double) const;
567template bool GncOption::validate(const char*) const;
568template bool GncOption::validate(std::string) const;
569template bool GncOption::validate(const QofInstance*) const;
570template bool GncOption::validate(gnc_commodity*) const;
571template bool GncOption::validate(const Account*) const;
572template bool GncOption::validate(const QofQuery*) const;
573template bool GncOption::validate(RelativeDatePeriod) const;
574template bool GncOption::validate(GncMultichoiceOptionIndexVec) const;
575template bool GncOption::validate(GncOptionReportPlacementVec) const;
576template bool GncOption::validate(GncOptionDateFormat) const;
577
578template GncOption* gnc_make_option<const std::string&>(const char*,
579 const char*,
580 const char*,
581 const char*,
582 const std::string&,
584template GncOption* gnc_make_option<bool>(const char*, const char*, const char*,
585 const char*, bool, GncOptionUIType);
586template GncOption* gnc_make_option<int64_t>(const char*, const char*,
587 const char*, const char*, int64_t,
Set one or more accounts on which to report, optionally restricted to certain account types.
class GncOptionCommodityValue Commodities are stored with their namespace and mnemonic instead of the...
A legal date value is a pair of either a RelativeDatePeriod, the absolute flag and a time64,...
Multichoice options have a vector of valid options (GncMultichoiceOptionChoices) and validate the sel...
Used for numeric ranges and plot sizes.
Holds a pointer to the UI item which will control the option and an enum representing the type of the...
The generic option-value class.
Represents the public interface for an option.
Implementation templates and specializtions for GncOption values.
OptionUITypes.
C++ Public interface for individual options.
Business Interface: Object OWNERs.
bool validate(ValueType value) const
Not implemented for GncOptionValue.
void get_limits(ValueType &, ValueType &, ValueType &) const noexcept
Implemented only for GncOptionNumericRange.
GList * account_type_list() const noexcept
Implemented only for GncOptionAccountListValue.
void mark_saved() noexcept
Mark the option as needing to be saved.
bool is_dirty() const noexcept
const char * permissible_value(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
const char * permissible_value_name(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
std::istream & in_stream(std::istream &iss)
Set the option's value from an input stream.
bool deserialize(const std::string &str)
Set the option's value from a character sequence.
bool is_multiselect() const noexcept
uint16_t permissible_value_index(const char *value) const
Implemented only for GncOptionMultiselectValue.
bool is_changed() const noexcept
uint16_t num_permissible_values() const
Implemented only for GncOptionMultiselectValue.
std::string serialize() const
Get a string suitable for storage representing the option's value.
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
RelativeDatePeriod
Reporting periods relative to the current date.
GncOptionUIType
Used by GncOptionClassifier to indicate to dialog-options what control should be displayed for the op...
STRUCTS.
A Query.
Definition qofquery.cpp:75