GnuCash  4.11-354-g0815ab64c1
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, size_t>)
63  return option.get_period_index();
64  return ValueType{};
65  }
66  if constexpr (is_same_decayed_v<decltype(option),
68  {
69  if constexpr (std::is_same_v<ValueType, size_t>)
70  return option.get_index();
71  if constexpr (is_same_decayed_v<ValueType,
72  GncMultichoiceOptionIndexVec>)
73  return option.get_multiple();
74  }
75  return ValueType {};
76  }, *m_option);
77 }
78 
79 template <typename ValueType> ValueType
80 GncOption::get_default_value() const
81 {
82  return std::visit(
83  [](const auto option)->ValueType {
84  if constexpr (is_same_decayed_v<decltype(option.get_value()),
85  ValueType>)
86  return option.get_default_value();
87  if constexpr (is_same_decayed_v<decltype(option),
89  {
90  if constexpr (is_same_decayed_v<ValueType,
92  return option.get_default_period();
93  if constexpr (std::is_same_v<ValueType, size_t>)
94  return option.get_default_period_index();
95  return ValueType{};
96  }
97  if constexpr
98  (is_same_decayed_v<decltype(option),
100  is_same_decayed_v<ValueType,
101  GncMultichoiceOptionIndexVec>)
102  return option.get_default_multiple();
103  return ValueType {};
104  }, *m_option);
105 
106 }
107 
108 template <typename ValueType> void
109 GncOption::set_value(ValueType value)
110 {
111  std::visit(
112  [value](auto& option) {
113  if constexpr
114  (is_same_decayed_v<decltype(option.get_value()), ValueType> ||
115  (is_same_decayed_v<decltype(option),
117  (is_same_decayed_v<ValueType, RelativeDatePeriod> ||
118  std::is_same_v<ValueType, size_t>)))
119  option.set_value(value);
120  if constexpr (is_same_decayed_v<decltype(option),
122  {
123  if constexpr (is_same_decayed_v<ValueType,
124  GncMultichoiceOptionIndexVec>)
125  option.set_multiple(value);
126  else if constexpr
127  (std::is_same_v<ValueType, size_t> ||
128  is_same_decayed_v<ValueType, std::string> ||
129  std::is_same_v<std::remove_cv<ValueType>, char*>)
130  option.set_value(value);
131  }
132  }, *m_option);
133 }
134 
135 template <typename ValueType> void
136 GncOption::set_default_value(ValueType value)
137 {
138  std::visit(
139  [value](auto& option) {
140  if constexpr
141  (is_same_decayed_v<decltype(option.get_value()), ValueType>||
142  (is_same_decayed_v<decltype(option), GncOptionDateValue> &&
143  (is_same_decayed_v<ValueType, RelativeDatePeriod> ||
144  std::is_same_v<ValueType, size_t>)))
145  option.set_default_value(value);
146  if constexpr (is_same_decayed_v<decltype(option),
148  {
149  if constexpr (is_same_decayed_v<ValueType,
150  GncMultichoiceOptionIndexVec>)
151  option.set_default_multiple(value);
152  else if constexpr
153  (std::is_same_v<ValueType, size_t> ||
154  is_same_decayed_v<ValueType, std::string> ||
155  std::is_same_v<std::remove_cv<ValueType>, char*>)
156  option.set_default_value(value);
157  }
158  }, *m_option);
159 }
160 void
161 GncOption::reset_default_value()
162 {
163  std::visit([](auto& option) { option.reset_default_value(); }, *m_option);
164 }
165 
166 template <typename ValueType> void
167 GncOption::get_limits(ValueType& max, ValueType& min, ValueType& step) const noexcept
168 {
169  std::visit([&max, &min, &step](const auto& option) {
170  if constexpr
171  (is_same_decayed_v<decltype(option),
173  option.get_limits(max, min, step);
174  }, *m_option);
175 }
176 
177 const std::string&
178 GncOption::get_section() const
179 {
180  return std::visit([](const auto& option)->const std::string& {
181  return option.m_section;
182  }, *m_option);
183 }
184 
185 const std::string&
186 GncOption::get_name() const
187 {
188  return std::visit([](const auto& option)->const std::string& {
189  return option.m_name;
190  }, *m_option);
191 }
192 
193 const std::string&
194 GncOption::get_key() const
195 {
196  return std::visit([](const auto& option)->const std::string& {
197  return option.m_sort_tag;
198  }, *m_option);
199 }
200 
201 const std::string&
202 GncOption::get_docstring() const
203 {
204  return std::visit([](const auto& option)->const std::string& {
205  return option.m_doc_string;
206  }, *m_option);
207 }
208 
209 void
210 GncOption::set_ui_item(GncOptionUIItemPtr&& ui_item)
211 {
212 
213  auto opt_ui_type = std::visit([](const auto& option)->GncOptionUIType {
214  return option.get_ui_type();
215  }, *m_option);
216 
217  if (ui_item->get_ui_type() != opt_ui_type)
218  {
219  PERR("Setting option %s:%s UI element failed, mismatched UI types.",
220  get_section().c_str(), get_name().c_str());
221  return;
222  }
223 
224  m_ui_item = std::move(ui_item);
225 }
226 
227 void
228 GncOption::set_ui_item_selectable(bool selectable) const noexcept
229 {
230  if (m_ui_item)
231  m_ui_item->set_selectable(selectable);
232 }
233 
234 const GncOptionUIType
235 GncOption::get_ui_type() const
236 {
237  return std::visit([](const auto& option)->GncOptionUIType {
238  return option.get_ui_type();
239  }, *m_option);
240 }
241 
242 GncOptionUIItem* const
243 GncOption::get_ui_item() const
244 {
245  return m_ui_item.get();
246 }
247 
248 void
249 GncOption::set_ui_item_from_option()
250 {
251  if (!m_ui_item)
252  return;
253  m_ui_item->set_ui_item_from_option(*this);
254 }
255 
256 void
257 GncOption::set_option_from_ui_item()
258 {
259  if (!m_ui_item)
260  return;
261  m_ui_item->set_option_from_ui_item(*this);
262 }
263 
264 void
265 GncOption::make_internal()
266 {
267  if (m_ui_item)
268  {
269  PERR("Option %s:%s has a UI Element, can't be INTERNAL.",
270  get_section().c_str(), get_name().c_str());
271  return;
272  }
273  std::visit([](auto& option) {
274  option.make_internal();
275  }, *m_option);
276 }
277 
278 bool
279 GncOption::is_changed() const noexcept
280 {
281  return std::visit([](const auto& option)->bool {
282  return option.is_changed();
283  }, *m_option);
284 }
285 
286 bool
288 {
289  return std::visit(
290  [](const auto& option)->bool {
291  if constexpr (is_same_decayed_v<decltype(option),
293  return option.is_multiselect();
294  else
295  return false;
296  }, *m_option);
297 }
298 
299 template<typename ValueType> bool
300 GncOption::validate(ValueType value) const
301 {
302  return std::visit(
303  [value] (const auto& option) -> bool {
304  if constexpr ((is_same_decayed_v<decltype(option),
306  is_same_decayed_v<ValueType, std::string>) ||
307  (is_same_decayed_v<decltype(option),
309  is_same_decayed_v<ValueType,
310  GncMultichoiceOptionIndexVec>) ||
311  (is_same_decayed_v<decltype(option),
313  is_same_decayed_v<ValueType, gnc_commodity*>))
314  return option.validate(value);
315  else
316  return false;
317  }, *m_option);
318 }
319 
320 std::size_t
322 {
323  return std::visit(
324  [] (const auto& option) -> size_t {
325  if constexpr (is_same_decayed_v<decltype(option),
327  is_same_decayed_v<decltype(option),
329  return option.num_permissible_values();
330  else
331  return size_t_max;
332  }, *m_option);
333 }
334 
335 std::size_t
336 GncOption::permissible_value_index(const char* value) const
337 {
338  return std::visit(
339  [&value] (const auto& option) -> size_t {
340  if constexpr (is_same_decayed_v<decltype(option),
342  is_same_decayed_v<decltype(option),
344  return option.permissible_value_index(value);
345  else
346  return size_t_max;
347  }, *m_option);
348 }
349 
350 const char*
351 GncOption::permissible_value(std::size_t index) const
352 {
353  return std::visit([index] (const auto& option) -> const char* {
354  if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
356  std::is_same_v<std::decay_t<decltype(option)>,
358  return option.permissible_value(index);
359  else
360  return "";
361  }, *m_option);
362 }
363 
364 const char*
365 GncOption::permissible_value_name(std::size_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_name(index);
373  else
374  return "";
375  }, *m_option);
376 }
377 
378 GList*
380 {
381  return std::visit([] (const auto& option) -> GList* {
382  if constexpr (std::is_same_v<std::decay_t<decltype(option)>,
384  return option.account_type_list();
385  else
386  return nullptr;
387  }, *m_option);
388 }
389 
390 bool
391 GncOption::is_alternate() const noexcept
392 {
393  return std::visit([](auto& option) -> bool {
394  if constexpr(is_RangeValue_v<decltype(option)>)
395  return option.is_alternate();
396  return false;
397  }, *m_option);
398 }
399 
400 void
401 GncOption::set_alternate(bool alt) noexcept
402 {
403  std::visit([alt](auto& option) {
404  if constexpr(is_RangeValue_v<decltype(option)>)
405  option.set_alternate(alt);
406  }, *m_option);
407 }
408 
409 std::string
411 {
412  if (m_option->valueless_by_exception())
413  return "Valueless Option";
414  return std::visit([&](auto& option) -> std::string {
415  return option.serialize();
416  }, *m_option);
417 }
418 
419 bool
420 GncOption::deserialize(const std::string& str)
421 {
422  return std::visit([&str](auto& option) -> bool {
423  return option.deserialize(str);
424  }, *m_option);
425 }
426 
427 std::istream&
428 GncOption::in_stream(std::istream& iss)
429 {
430  return std::visit([&iss](auto& option) -> std::istream& {
431  iss >> option;
432  return iss;
433  }, *m_option);
434 }
435 
436 /* We must instantiate all of the templates we need here because we don't expose
437  * the template implementation in the public header.
438  */
439 
440 
441 template GncOption::GncOption(const char*, const char*, const char*,
442  const char*, bool, GncOptionUIType);
443 //template GncOption::GncOption(const char*, const char*, const char*,
444 // const char*, int, GncOptionUIType);
445 template GncOption::GncOption(const char*, const char*, const char*,
446  const char*, int64_t, GncOptionUIType);
447 //template GncOption::GncOption(const char*, const char*, const char*,
448 // const char*, const char*, GncOptionUIType);
449 //template GncOption::GncOption(const char*, const char*, const char*,
450 // const char*, double, GncOptionUIType);
451 template GncOption::GncOption(const char*, const char*, const char*,
452  const char*, std::string, GncOptionUIType);
453 template GncOption::GncOption(const char*, const char*, const char*,
454  const char*, const QofQuery*, GncOptionUIType);
455 template GncOption::GncOption(const char*, const char*, const char*,
456  const char*, const GncOwner*, GncOptionUIType);
457 
458 template bool GncOption::get_value<bool>() const;
459 template int GncOption::get_value<int>() const;
460 template int64_t GncOption::get_value<int64_t>() const;
461 template double GncOption::get_value<double>() const;
462 template size_t GncOption::get_value<size_t>() const;
463 template const char* GncOption::get_value<const char*>() const;
464 template std::string GncOption::get_value<std::string>() const;
465 template const QofInstance* GncOption::get_value<const QofInstance*>() const;
466 template gnc_commodity* GncOption::get_value<gnc_commodity*>() const;
467 template const Account* GncOption::get_value<const Account*>() const;
468 template RelativeDatePeriod GncOption::get_value<RelativeDatePeriod>() const;
469 template GncOptionAccountList GncOption::get_value<GncOptionAccountList>() const;
470 template GncMultichoiceOptionIndexVec GncOption::get_value<GncMultichoiceOptionIndexVec>() const;
471 template GncOptionReportPlacementVec GncOption::get_value<GncOptionReportPlacementVec>() const;
472 
473 template bool GncOption::get_default_value<bool>() const;
474 template int GncOption::get_default_value<int>() const;
475 template int64_t GncOption::get_default_value<int64_t>() const;
476 template double GncOption::get_default_value<double>() const;
477 template const char* GncOption::get_default_value<const char*>() const;
478 template std::string GncOption::get_default_value<std::string>() const;
479 template const QofInstance* GncOption::get_default_value<const QofInstance*>() const;
480 template gnc_commodity* GncOption::get_default_value<gnc_commodity*>() const;
481 template const Account* GncOption::get_default_value<const Account*>() const;
482 template RelativeDatePeriod GncOption::get_default_value<RelativeDatePeriod>() const;
483 template GncOptionAccountList GncOption::get_default_value<GncOptionAccountList>() const;
484 template GncMultichoiceOptionIndexVec GncOption::get_default_value<GncMultichoiceOptionIndexVec>() const;
485 template GncOptionReportPlacementVec GncOption::get_default_value<GncOptionReportPlacementVec>() const;
486 
487 template void GncOption::set_value(bool);
488 template void GncOption::set_value(int);
489 template void GncOption::set_value(int64_t);
490 template void GncOption::set_value(double);
491 template void GncOption::set_value(char*);
492 template void GncOption::set_value(const char*);
493 template void GncOption::set_value(std::string);
494 template void GncOption::set_value(const QofInstance*);
495 template void GncOption::set_value(gnc_commodity*);
496 template void GncOption::set_value(const Account*);
497 template void GncOption::set_value(RelativeDatePeriod);
498 template void GncOption::set_value(size_t);
499 template void GncOption::set_value(GncOptionAccountList);
500 template void GncOption::set_value(GncMultichoiceOptionIndexVec);
501 template void GncOption::set_value(GncOptionReportPlacementVec);
502 
503 template void GncOption::set_default_value(bool);
504 template void GncOption::set_default_value(int);
505 template void GncOption::set_default_value(int64_t);
506 template void GncOption::set_default_value(double);
507 template void GncOption::set_default_value(char*);
508 template void GncOption::set_default_value(const char*);
509 template void GncOption::set_default_value(std::string);
510 template void GncOption::set_default_value(const QofInstance*);
511 template void GncOption::set_default_value(const Account*);
512 template void GncOption::set_default_value(RelativeDatePeriod);
513 template void GncOption::set_default_value(size_t);
514 template void GncOption::set_default_value(GncOptionAccountList);
515 template void GncOption::set_default_value(GncMultichoiceOptionIndexVec);
516 template void GncOption::set_default_value(GncOptionReportPlacementVec);
517 
518 template void GncOption::get_limits(double&, double&, double&) const noexcept;
519 template void GncOption::get_limits(int&, int&, int&) const noexcept;
520 template bool GncOption::validate(bool) const;
521 template bool GncOption::validate(int) const;
522 template bool GncOption::validate(int64_t) const;
523 template bool GncOption::validate(double) const;
524 template bool GncOption::validate(const char*) const;
525 template bool GncOption::validate(std::string) const;
526 template bool GncOption::validate(const QofInstance*) const;
527 template bool GncOption::validate(gnc_commodity*) const;
528 template bool GncOption::validate(const Account*) const;
529 template bool GncOption::validate(const QofQuery*) const;
530 template bool GncOption::validate(RelativeDatePeriod) const;
531 template bool GncOption::validate(GncMultichoiceOptionIndexVec) const;
532 template bool GncOption::validate(GncOptionReportPlacementVec) const;
533 
534 template GncOption* gnc_make_option<const std::string&>(const char*,
535  const char*,
536  const char*,
537  const char*,
538  const std::string&,
540 template GncOption* gnc_make_option<bool>(const char*, const char*, const char*,
541  const char*, bool, GncOptionUIType);
542 template GncOption* gnc_make_option<int64_t>(const char*, const char*,
543  const char*, const char*, int64_t,
545 
546 
bool is_multiselect() const noexcept
Definition: gnc-option.cpp:287
std::size_t num_permissible_values() const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:321
bool deserialize(const std::string &str)
Set the option&#39;s value from a character sequence.
Definition: gnc-option.cpp:420
OptionUITypes.
A legal date value is a pair of either a RelativeDatePeriod, the absolute flag and a time64...
STL namespace.
const char * permissible_value(std::size_t index) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:351
std::size_t permissible_value_index(const char *value) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:336
const char * permissible_value_name(std::size_t index) const
Implemented only for GncOptionMultiselectValue.
Definition: gnc-option.cpp:365
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
Represents the public interface for an option.
Definition: gnc-option.hpp:131
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:300
Multichoice options have a vector of valid options (GncMultichoiceOptionChoices) and validate the sel...
std::string serialize() const
Get a string suitable for storage representing the option&#39;s value.
Definition: gnc-option.cpp:410
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...
void get_limits(ValueType &, ValueType &, ValueType &) const noexcept
Implemented only for GncOptionNumericRange.
Definition: gnc-option.cpp:167
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:428
GList * account_type_list() const noexcept
Implemented only for GncOptionAccountListValue.
Definition: gnc-option.cpp:379