GnuCash  4.12-527-g05ffd3d4eb
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 
29 static const char* log_module{"gnc.app-utils.gnc-option"};
30 
31 extern "C"
32 {
33 #include "qoflog.h"
34 }
35 
36 template <typename ValueType,
37  typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
38  int>>
39 GncOption::GncOption(const char* section, const char* name,
40  const char* key, const char* doc_string,
41  ValueType value, GncOptionUIType ui_type) :
42  m_option{std::make_unique<GncOptionVariant>(
43  std::in_place_type<GncOptionValue<ValueType>>,
44  section, name, key, doc_string, value, ui_type)}
45 {
46 }
47 
48 template <typename ValueType> ValueType
49 GncOption::get_value() const
50 {
51  return std::visit(
52  [](const auto option)->ValueType {
53  if constexpr (is_same_decayed_v<decltype(option.get_value()),
54  ValueType>)
55  return option.get_value();
56  if constexpr (is_same_decayed_v<decltype(option),
58  {
59  if constexpr (is_same_decayed_v<ValueType,
61  return option.get_period();
62  if constexpr (std::is_same_v<ValueType, time64>)
63  return option.get_value();
64  if constexpr (std::is_same_v<ValueType, uint16_t>)
65  return option.get_period_index();
66  return ValueType{};
67  }
68  if constexpr (is_same_decayed_v<decltype(option),
70  {
71  if constexpr (std::is_same_v<ValueType, uint16_t>)
72  return option.get_index();
73  if constexpr (is_same_decayed_v<ValueType,
74  GncMultichoiceOptionIndexVec>)
75  return option.get_multiple();
76  }
77  return ValueType {};
78  }, *m_option);
79 }
80 
81 template <typename ValueType> ValueType
82 GncOption::get_default_value() const
83 {
84  return std::visit(
85  [](const auto option)->ValueType {
86  if constexpr (is_same_decayed_v<decltype(option.get_value()),
87  ValueType>)
88  return option.get_default_value();
89  if constexpr (is_same_decayed_v<decltype(option),
91  {
92  if constexpr (is_same_decayed_v<ValueType,
94  return option.get_default_period();
95  if constexpr (std::is_same_v<ValueType, time64>)
96  return option.get_value();
97  if constexpr (std::is_same_v<ValueType, uint16_t>)
98  return option.get_default_period_index();
99  return ValueType{};
100  }
101  if constexpr
102  (is_same_decayed_v<decltype(option),
104  is_same_decayed_v<ValueType,
105  GncMultichoiceOptionIndexVec>)
106  return option.get_default_multiple();
107  return ValueType {};
108  }, *m_option);
109 
110 }
111 
112 template <typename ValueType> void
113 GncOption::set_value(ValueType value)
114 {
115  std::visit(
116  [value](auto& option) {
117  if constexpr
118  (is_same_decayed_v<decltype(option.get_value()), ValueType> ||
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  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  }, *m_option);
138 }
139 
140 template <typename ValueType> void
141 GncOption::set_default_value(ValueType value)
142 {
143  std::visit(
144  [value](auto& option) {
145  if constexpr
146  (is_same_decayed_v<decltype(option.get_value()), ValueType>||
147  (is_same_decayed_v<decltype(option), GncOptionDateValue> &&
148  (is_same_decayed_v<ValueType, RelativeDatePeriod> ||
149  std::is_same_v<ValueType, time64> ||
150  std::is_same_v<ValueType, uint16_t>)))
151  option.set_default_value(value);
152  if constexpr (is_same_decayed_v<decltype(option),
154  {
155  if constexpr (is_same_decayed_v<ValueType,
156  GncMultichoiceOptionIndexVec>)
157  option.set_default_multiple(value);
158  else if constexpr
159  (std::is_same_v<ValueType, uint16_t> ||
160  is_same_decayed_v<ValueType, std::string> ||
161  std::is_same_v<std::remove_cv<ValueType>, char*>)
162  option.set_default_value(value);
163  }
164  }, *m_option);
165 }
166 void
167 GncOption::reset_default_value()
168 {
169  std::visit([](auto& option) { option.reset_default_value(); }, *m_option);
170 }
171 
172 template <typename ValueType> void
173 GncOption::get_limits(ValueType& max, ValueType& min, ValueType& step) const noexcept
174 {
175  std::visit([&max, &min, &step](const auto& option) {
176  if constexpr
177  (is_same_decayed_v<decltype(option),
179  option.get_limits(max, min, step);
180  }, *m_option);
181 }
182 
183 const std::string&
184 GncOption::get_section() const
185 {
186  return std::visit([](const auto& option)->const std::string& {
187  return option.m_section;
188  }, *m_option);
189 }
190 
191 const std::string&
192 GncOption::get_name() const
193 {
194  return std::visit([](const auto& option)->const std::string& {
195  return option.m_name;
196  }, *m_option);
197 }
198 
199 const std::string&
200 GncOption::get_key() const
201 {
202  return std::visit([](const auto& option)->const std::string& {
203  return option.m_sort_tag;
204  }, *m_option);
205 }
206 
207 const std::string&
208 GncOption::get_docstring() const
209 {
210  return std::visit([](const auto& option)->const std::string& {
211  return option.m_doc_string;
212  }, *m_option);
213 }
214 
215 void
216 GncOption::set_ui_item(GncOptionUIItemPtr&& ui_item)
217 {
218 
219  auto opt_ui_type = std::visit([](const auto& option)->GncOptionUIType {
220  return option.get_ui_type();
221  }, *m_option);
222 
223  if (ui_item->get_ui_type() != opt_ui_type)
224  {
225  PERR("Setting option %s:%s UI element failed, mismatched UI types.",
226  get_section().c_str(), get_name().c_str());
227  return;
228  }
229 
230  m_ui_item = std::move(ui_item);
231 }
232 
233 void
234 GncOption::set_ui_item_selectable(bool selectable) const noexcept
235 {
236  if (m_ui_item)
237  m_ui_item->set_selectable(selectable);
238 }
239 
240 const GncOptionUIType
241 GncOption::get_ui_type() const
242 {
243  return std::visit([](const auto& option)->GncOptionUIType {
244  return option.get_ui_type();
245  }, *m_option);
246 }
247 
248 GncOptionUIItem* const
249 GncOption::get_ui_item() const
250 {
251  return m_ui_item.get();
252 }
253 
254 void
255 GncOption::set_ui_item_from_option()
256 {
257  if (!m_ui_item)
258  return;
259  m_ui_item->set_ui_item_from_option(*this);
260 }
261 
262 void
263 GncOption::set_option_from_ui_item()
264 {
265  if (!m_ui_item)
266  return;
267  m_ui_item->set_option_from_ui_item(*this);
268 }
269 
270 void
271 GncOption::make_internal()
272 {
273  if (m_ui_item)
274  {
275  PERR("Option %s:%s has a UI Element, can't be INTERNAL.",
276  get_section().c_str(), get_name().c_str());
277  return;
278  }
279  std::visit([](auto& option) {
280  option.make_internal();
281  }, *m_option);
282 }
283 
284 bool
285 GncOption::is_internal()
286 {
287  return std::visit([](auto& option)->bool {
288  return option.is_internal();
289  }, *m_option);
290 }
291 
292 bool
293 GncOption::is_changed() const noexcept
294 {
295  return std::visit([](const auto& option)->bool {
296  return option.is_changed();
297  }, *m_option);
298 }
299 
300 bool
302 {
303  return std::visit(
304  [](const auto& option)->bool {
305  if constexpr (is_same_decayed_v<decltype(option),
307  return option.is_multiselect();
308  else
309  return false;
310  }, *m_option);
311 }
312 
313 template<typename ValueType> bool
314 GncOption::validate(ValueType value) const
315 {
316  return std::visit(
317  [value] (const auto& option) -> bool {
318  if constexpr ((is_same_decayed_v<decltype(option),
320  is_same_decayed_v<ValueType, std::string>) ||
321  (is_same_decayed_v<decltype(option),
323  is_same_decayed_v<ValueType,
324  GncMultichoiceOptionIndexVec>) ||
325  (is_same_decayed_v<decltype(option),
327  is_same_decayed_v<ValueType, gnc_commodity*>))
328  return option.validate(value);
329  else
330  return false;
331  }, *m_option);
332 }
333 
334 std::uint16_t
336 {
337  return std::visit(
338  [] (const auto& option) -> uint16_t {
339  if constexpr (is_same_decayed_v<decltype(option),
341  is_same_decayed_v<decltype(option),
343  return option.num_permissible_values();
344  else
345  return uint16_t_max;
346  }, *m_option);
347 }
348 
349 std::uint16_t
350 GncOption::permissible_value_index(const char* value) const
351 {
352  return std::visit(
353  [&value] (const auto& option) -> uint16_t {
354  if constexpr (is_same_decayed_v<decltype(option),
356  is_same_decayed_v<decltype(option),
358  return option.permissible_value_index(value);
359  else
360  return uint16_t_max;
361  }, *m_option);
362 }
363 
364 const char*
365 GncOption::permissible_value(std::uint16_t index) const
366 {
367  return std::visit([index] (const auto& option) -> const char* {
368  if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
370  std::is_same_v<std::decay_t<decltype(option)>,
372  return option.permissible_value(index);
373  else
374  return "";
375  }, *m_option);
376 }
377 
378 const char*
379 GncOption::permissible_value_name(std::uint16_t index) const
380 {
381  return std::visit([index] (const auto& option) -> const char* {
382  if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
384  std::is_same_v<std::decay_t<decltype(option)>,
386  return option.permissible_value_name(index);
387  else
388  return "";
389  }, *m_option);
390 }
391 
392 GList*
394 {
395  return std::visit([] (const auto& option) -> GList* {
396  if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
398  return option.account_type_list();
399  else
400  return nullptr;
401  }, *m_option);
402 }
403 
404 bool
405 GncOption::is_alternate() const noexcept
406 {
407  return std::visit([](auto& option) -> bool {
408  if constexpr(is_RangeValue_v<decltype(option)>)
409  return option.is_alternate();
410  return false;
411  }, *m_option);
412 }
413 
414 void
415 GncOption::set_alternate(bool alt) noexcept
416 {
417  std::visit([alt](auto& option) {
418  if constexpr(is_RangeValue_v<decltype(option)>)
419  option.set_alternate(alt);
420  }, *m_option);
421 }
422 
423 std::string
425 {
426  if (m_option->valueless_by_exception())
427  return "Valueless Option";
428  return std::visit([&](auto& option) -> std::string {
429  return option.serialize();
430  }, *m_option);
431 }
432 
433 bool
434 GncOption::deserialize(const std::string& str)
435 {
436  return std::visit([&str](auto& option) -> bool {
437  return option.deserialize(str);
438  }, *m_option);
439 }
440 
441 std::istream&
442 GncOption::in_stream(std::istream& iss)
443 {
444  return std::visit([&iss](auto& option) -> std::istream& {
445  iss >> option;
446  return iss;
447  }, *m_option);
448 }
449 
450 /* We must instantiate all of the templates we need here because we don't expose
451  * the template implementation in the public header.
452  */
453 
454 
455 template GncOption::GncOption(const char*, const char*, const char*,
456  const char*, bool, GncOptionUIType);
457 //template GncOption::GncOption(const char*, const char*, const char*,
458 // const char*, int, GncOptionUIType);
459 template GncOption::GncOption(const char*, const char*, const char*,
460  const char*, int64_t, GncOptionUIType);
461 //template GncOption::GncOption(const char*, const char*, const char*,
462 // const char*, const char*, GncOptionUIType);
463 //template GncOption::GncOption(const char*, const char*, const char*,
464 // const char*, double, GncOptionUIType);
465 template GncOption::GncOption(const char*, const char*, const char*,
466  const char*, std::string, GncOptionUIType);
467 template GncOption::GncOption(const char*, const char*, const char*,
468  const char*, const QofQuery*, GncOptionUIType);
469 template GncOption::GncOption(const char*, const char*, const char*,
470  const char*, const GncOwner*, GncOptionUIType);
471 
472 template bool GncOption::get_value<bool>() const;
473 template int GncOption::get_value<int>() const;
474 template int64_t GncOption::get_value<int64_t>() const;
475 template double GncOption::get_value<double>() const;
476 template uint16_t GncOption::get_value<uint16_t>() const;
477 template const char* GncOption::get_value<const char*>() const;
478 template std::string GncOption::get_value<std::string>() const;
479 template const QofInstance* GncOption::get_value<const QofInstance*>() const;
480 template gnc_commodity* GncOption::get_value<gnc_commodity*>() const;
481 template const Account* GncOption::get_value<const Account*>() const;
482 template RelativeDatePeriod GncOption::get_value<RelativeDatePeriod>() const;
483 template GncOptionAccountList GncOption::get_value<GncOptionAccountList>() const;
484 template GncMultichoiceOptionIndexVec GncOption::get_value<GncMultichoiceOptionIndexVec>() const;
485 template GncOptionReportPlacementVec GncOption::get_value<GncOptionReportPlacementVec>() const;
486 
487 template bool GncOption::get_default_value<bool>() const;
488 template int GncOption::get_default_value<int>() const;
489 template int64_t GncOption::get_default_value<int64_t>() const;
490 template double GncOption::get_default_value<double>() const;
491 template const char* GncOption::get_default_value<const char*>() const;
492 template std::string GncOption::get_default_value<std::string>() const;
493 template const QofInstance* GncOption::get_default_value<const QofInstance*>() const;
494 template gnc_commodity* GncOption::get_default_value<gnc_commodity*>() const;
495 template const Account* GncOption::get_default_value<const Account*>() const;
496 template RelativeDatePeriod GncOption::get_default_value<RelativeDatePeriod>() const;
497 template GncOptionAccountList GncOption::get_default_value<GncOptionAccountList>() const;
498 template GncMultichoiceOptionIndexVec GncOption::get_default_value<GncMultichoiceOptionIndexVec>() const;
499 template GncOptionReportPlacementVec GncOption::get_default_value<GncOptionReportPlacementVec>() const;
500 
501 template void GncOption::set_value(bool);
502 template void GncOption::set_value(int);
503 template void GncOption::set_value(int64_t);
504 template void GncOption::set_value(double);
505 template void GncOption::set_value(char*);
506 template void GncOption::set_value(const char*);
507 template void GncOption::set_value(std::string);
508 template void GncOption::set_value(const QofInstance*);
509 template void GncOption::set_value(gnc_commodity*);
510 template void GncOption::set_value(const Account*);
511 template void GncOption::set_value(RelativeDatePeriod);
512 template void GncOption::set_value(uint16_t);
513 template void GncOption::set_value(GncOptionAccountList);
514 template void GncOption::set_value(GncMultichoiceOptionIndexVec);
515 template void GncOption::set_value(GncOptionReportPlacementVec);
516 
517 template void GncOption::set_default_value(bool);
518 template void GncOption::set_default_value(int);
519 template void GncOption::set_default_value(int64_t);
520 template void GncOption::set_default_value(double);
521 template void GncOption::set_default_value(char*);
522 template void GncOption::set_default_value(const char*);
523 template void GncOption::set_default_value(std::string);
524 template void GncOption::set_default_value(const QofInstance*);
525 template void GncOption::set_default_value(const Account*);
526 template void GncOption::set_default_value(RelativeDatePeriod);
527 template void GncOption::set_default_value(uint16_t);
528 template void GncOption::set_default_value(GncOptionAccountList);
529 template void GncOption::set_default_value(GncMultichoiceOptionIndexVec);
530 template void GncOption::set_default_value(GncOptionReportPlacementVec);
531 
532 template void GncOption::get_limits(double&, double&, double&) const noexcept;
533 template void GncOption::get_limits(int&, int&, int&) const noexcept;
534 template bool GncOption::validate(bool) const;
535 template bool GncOption::validate(int) const;
536 template bool GncOption::validate(int64_t) const;
537 template bool GncOption::validate(double) const;
538 template bool GncOption::validate(const char*) const;
539 template bool GncOption::validate(std::string) const;
540 template bool GncOption::validate(const QofInstance*) const;
541 template bool GncOption::validate(gnc_commodity*) const;
542 template bool GncOption::validate(const Account*) const;
543 template bool GncOption::validate(const QofQuery*) const;
544 template bool GncOption::validate(RelativeDatePeriod) const;
545 template bool GncOption::validate(GncMultichoiceOptionIndexVec) const;
546 template bool GncOption::validate(GncOptionReportPlacementVec) const;
547 
548 template GncOption* gnc_make_option<const std::string&>(const char*,
549  const char*,
550  const char*,
551  const char*,
552  const std::string&,
554 template GncOption* gnc_make_option<bool>(const char*, const char*, const char*,
555  const char*, bool, GncOptionUIType);
556 template GncOption* gnc_make_option<int64_t>(const char*, const char*,
557  const char*, const char*, int64_t,
559 
560 
bool is_multiselect() const noexcept
Definition: gnc-option.cpp:301
bool deserialize(const std::string &str)
Set the option&#39;s value from a character sequence.
Definition: gnc-option.cpp:434
uint16_t permissible_value_index(const char *value) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:350
OptionUITypes.
A legal date value is a pair of either a RelativeDatePeriod, the absolute flag and a time64...
STL namespace.
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
Represents the public interface for an option.
Definition: gnc-option.hpp:130
Set one or more accounts on which to report, optionally restricted to certain account types...
C++ Public interface for individual options.
bool validate(ValueType value) const
Not implemented for GncOptionValue.
Definition: gnc-option.cpp:314
Multichoice options have a vector of valid options (GncMultichoiceOptionChoices) and validate the sel...
uint16_t num_permissible_values() const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:335
std::string serialize() const
Get a string suitable for storage representing the option&#39;s value.
Definition: gnc-option.cpp:424
RelativeDatePeriod
Reporting periods relative to the current date.
Implementation templates and specializtions for GncOption values.
class GncOptionCommodityValue Commodities are stored with their namespace and mnemonic instead of the...
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...
const char * permissible_value(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:365
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:93
void get_limits(ValueType &, ValueType &, ValueType &) const noexcept
Implemented only for GncOptionNumericRange.
Definition: gnc-option.cpp:173
const char * permissible_value_name(uint16_t index) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:379
A Query.
Definition: qofquery.cpp:77
GncOptionUIType
Used by GncOptionClassifier to indicate to dialog-options what control should be displayed for the op...
std::istream & in_stream(std::istream &iss)
Set the option&#39;s value from an input stream.
Definition: gnc-option.cpp:442
GList * account_type_list() const noexcept
Implemented only for GncOptionAccountListValue.
Definition: gnc-option.cpp:393