GnuCash  4.901-15-g732a005710
gnc-optiondb.cpp
1 /********************************************************************\
2  * gnc-optiondb.cpp -- Collection of GncOption objects *
3  * Copyright (C) 2019 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 <functional>
25 #include <string>
26 #include <limits>
27 #include <sstream>
28 #include "kvp-value.hpp"
29 #include "qofbookslots.h"
30 #include "guid.hpp"
31 #include "gnc-optiondb.h"
32 #include "gnc-optiondb.hpp"
33 #include "gnc-optiondb-impl.hpp"
34 #include "gnc-option-ui.hpp"
35 
36 #include "gnc-session.h"
37 constexpr const char* log_module{G_LOG_DOMAIN};
38 
39 constexpr auto stream_max = std::numeric_limits<std::streamsize>::max();
40 using AliasedOption = std::pair<const char*, const char*>;
41 using OptionAlias = std::pair<const char*, AliasedOption>;
42 using OptionAliases = std::vector<OptionAlias>;
43 class Aliases
44 {
45  static const OptionAliases c_option_aliases;
46 public:
47  static const AliasedOption* find_alias (const char* old_name)
48  {
49  if (!old_name) return nullptr;
50  const auto alias =
51  std::find_if(c_option_aliases.begin(), c_option_aliases.end(),
52  [old_name](auto alias){
53  return std::strcmp(old_name, alias.first) == 0;
54  });
55  if (alias == c_option_aliases.end())
56  return nullptr;
57 
58  return &alias->second;
59  }
60 };
61 
62 const OptionAliases Aliases::c_option_aliases
63 {
64  {"Accounts to include", {nullptr, "Accounts"}},
65  {"Exclude transactions between selected accounts?",
66  {nullptr, "Exclude transactions between selected accounts"}},
67  {"Filter Accounts", {nullptr, "Filter By…"}},
68  {"Flatten list to depth limit?",
69  {nullptr, "Flatten list to depth limit"}},
70  {"From", {nullptr, "Start Date"}},
71  {"Report Accounts", {nullptr, "Accounts"}},
72  {"Report Currency", {nullptr, "Report's currency"}},
73  {"Show Account Code?", {nullptr, "Show Account Code"}},
74  {"Show Full Account Name?", {nullptr, "Show Full Account Name"}},
75  {"Show Multi-currency Totals?",
76  {nullptr, "Show Multi-currency Totals"}},
77  {"Show zero balance items?", {nullptr, "Show zero balance items"}},
78  {"Sign Reverses?", {nullptr, "Sign Reverses"}},
79  {"To", {nullptr, "End Date"}},
80  {"Charge Type", {nullptr, "Action"}}, // easy-invoice.scm, renamed June 2018
81  // the following 4 options in income-gst-statement.scm renamed Dec 2018
82  {"Individual income columns", {nullptr, "Individual sales columns"}},
83  {"Individual expense columns",
84  {nullptr, "Individual purchases columns"}},
85  {"Remittance amount", {nullptr, "Gross Balance"}},
86  {"Net Income", {nullptr, "Net Balance"}},
87  // transaction.scm:
88  {"Use Full Account Name?", {nullptr, "Use Full Account Name"}},
89  {"Use Full Other Account Name?",
90  {nullptr, "Use Full Other Account Name"}},
91  {"Void Transactions?", {"Filter", "Void Transactions"}},
92  {"Void Transactions", {"Filter", "Void Transactions"}},
93  {"Account Substring", {"Filter", "Account Name Filter"}},
94  {"Enable links", {nullptr, "Enable Links"}},
95  // trep-engine: moved currency options to own tab
96  {"Common Currency", {"Currency", "Common Currency"}},
97  {"Show original currency amount",
98  {"Currency", "Show original currency amount"}},
99  {"Report's currency", {"Currency", "Report's currency"}},
100  {"Reconcile Status", {nullptr, "Reconciled Status"}},
101  // new-owner-report.scm, renamed Oct 2020 to differentiate with
102  // Document Links:
103  {"Links", {nullptr, "Transaction Links"}},
104  // invoice.scm, renamed November 2018
105  {"Individual Taxes", {nullptr, "Use Detailed Tax Summary"}},
106  {"Show Accounts until level", {nullptr, "Levels of Subaccounts"}},
107  {"Invoice number", {nullptr, "Invoice Number"}},
108  {"Report title", {nullptr, "Report Title"}},
109  {"Extra notes", {nullptr, "Extra Notes"}},
110  // income-gst-statement.scm
111  {"default format", {nullptr, "Default Format"}},
112  {"Report format", {nullptr, "Report Format"}},
113  // ... replaced to …, Dec 2022
114  {"Filter By...", {nullptr, "Filter By…"}},
115  {"Specify date to filter by...", {nullptr, "Specify date to filter by…"}},
116 };
117 
118 static bool
119 operator==(const std::string& str, const char* cstr)
120 {
121  return strcmp(str.c_str(), cstr) == 0;
122 }
123 
124 void
125 GncOptionSection::foreach_option(std::function<void(GncOption&)> func)
126 {
127  std::for_each(m_options.begin(), m_options.end(), func);
128 }
129 
130 void
131 GncOptionSection::foreach_option(std::function<void(const GncOption&)> func) const
132 {
133  std::for_each(m_options.begin(), m_options.end(), func);
134 }
135 
136 void
137 GncOptionSection::add_option(GncOption&& option)
138 {
139  m_options.push_back(std::move(option));
140  if (!std::is_sorted(m_options.begin(), m_options.end()))
141  std::sort(m_options.begin(), m_options.end());
142 }
143 
144 void
145 GncOptionSection::remove_option(const char* name)
146 {
147  m_options.erase(std::remove_if(m_options.begin(), m_options.end(),
148  [name](const auto& option) -> bool
149  {
150  return option.get_name() == name;
151  }));
152 }
153 
154 const GncOption*
155 GncOptionSection::find_option(const char* name) const
156 {
157  auto option = std::find_if(m_options.begin(), m_options.end(),
158  [name](auto& option) -> bool {
159  return option.get_name() == name;
160  });
161  if (option != m_options.end())
162  return &*option;
163 
164  auto alias = Aliases::find_alias(name);
165  if (!alias || alias->first) // No alias or the alias
166  return nullptr; // is in a different section.
167  return find_option(alias->second);
168 }
169 
170 GncOptionDB::GncOptionDB() : m_default_section{} {}
171 
172 GncOptionDB::GncOptionDB(QofBook* book) : GncOptionDB() {}
173 
174 void
175 GncOptionDB::register_option(const char* sectname, GncOption&& option)
176 {
177  auto section = find_section(sectname);
178 
179  if (section)
180  {
181  section->add_option(std::move(option));
182  return;
183  }
184 
185  m_sections.push_back(std::make_shared<GncOptionSection>(sectname));
186  m_sections.back()->add_option(std::move(option));
187  if (!std::is_sorted(m_sections.begin(), m_sections.end()))
188  std::sort(m_sections.begin(), m_sections.end());
189 }
190 
191 void
192 GncOptionDB::register_option(const char* sectname, GncOption* option)
193 {
194  register_option(sectname, std::move(*option));
195  delete option;
196 }
197 
198 void
199 GncOptionDB::unregister_option(const char* sectname, const char* name)
200 {
201  auto section = find_section(sectname);
202  if (section)
203  section->remove_option(name);
204 }
205 
206 void
207 GncOptionDB::set_default_section(const char* sectname)
208 {
209  m_default_section = find_section(sectname);
210 }
211 
212 const GncOptionSection* const
213 GncOptionDB::get_default_section() const noexcept
214 {
215  return m_default_section;
216 }
217 
218 const GncOptionSection*
219 GncOptionDB::find_section(const std::string& section) const
220 {
221  auto db_section = std::find_if(m_sections.begin(), m_sections.end(),
222  [&section](auto& sect) -> bool
223  {
224  return section == sect->get_name();
225  });
226  return db_section == m_sections.end() ? nullptr : db_section->get();
227 }
228 
229 const GncOption*
230 GncOptionDB::find_option(const std::string& section, const char* name) const
231 {
232  auto db_section = const_cast<GncOptionDB*>(this)->find_section(section);
233  const GncOption* option = nullptr;
234  if (db_section)
235  option = db_section->find_option(name);
236  if (option)
237  return option;
238  auto alias = Aliases::find_alias(name);
239  /* Only try again if alias.first isn't
240  * nullptr. GncOptionSection::find_option already checked if the alias
241  * should have been in the same section.
242  */
243  if (alias && alias->first && section != alias->first)
244  return find_option(alias->first, alias->second);
245  return nullptr;
246 }
247 
248 std::string
249 GncOptionDB::lookup_string_option(const char* section, const char* name)
250 {
251  static const std::string empty_string{};
252 
253  auto db_opt = find_option(section, name);
254  if (!db_opt)
255  return empty_string;
256  return db_opt->get_value<std::string>();
257 }
258 
259 void
260 GncOptionDB::make_internal(const char* section, const char* name)
261 {
262 
263  auto db_opt = find_option(section, name);
264  if (db_opt)
265  db_opt->make_internal();
266 }
267 
268 static inline bool constexpr
269 is_eol(char c)
270 {
271  return c == '\n';
272 }
273 
274 static inline bool constexpr
275 is_whitespace(char c)
276 {
277  return c == ' ' || c == '\n' || c == '\t';
278 }
279 
280 static inline bool constexpr
281 is_begin_paren(char c)
282 {
283  return c == '(';
284 }
285 
286 static inline bool constexpr
287 is_end_paren(char c)
288 {
289  return c == ')';
290 }
291 
292 static inline bool constexpr
293 is_double_quote(char c)
294 {
295  return c == '"';
296 }
297 
298 static inline bool constexpr
299 is_single_quote(char c)
300 {
301  return c == '\'';
302 }
303 
304 static inline bool constexpr
305 is_semicolon(char c)
306 {
307  return c == ';';
308 }
309 
310 static inline bool constexpr
311 is_delim(char c)
312 {
313  return is_begin_paren(c) || is_end_paren(c) || is_whitespace(c) ||
314  is_single_quote(c) || is_double_quote(c) || is_semicolon(c);
315 }
316 
317 std::ostream&
318 GncOptionDB::save_option_key_value(std::ostream& oss,
319  const std::string& section,
320  const std::string& name) const noexcept
321 {
322 
323  auto db_opt = find_option(section, name.c_str());
324  if (!db_opt || !db_opt->is_changed())
325  return oss;
326  oss << section.substr(0, classifier_size_max) << ":" <<
327  name.substr(0, classifier_size_max) << "=" << *db_opt << ";";
328  return oss;
329 }
330 
331 std::istream&
332 GncOptionDB::load_option_key_value(std::istream& iss)
333 {
334 
335  char section[classifier_size_max], name[classifier_size_max];
336  iss.getline(section, classifier_size_max, ':');
337  iss.getline(name, classifier_size_max, '=');
338  if (!iss)
339  throw std::invalid_argument("Section or name delimiter not found or values too long");
340  auto option = find_option(section, name);
341  if (!option)
342  iss.ignore(stream_max, ';');
343  else
344  {
345  std::string value;
346  std::getline(iss, value, ';');
347  std::istringstream item_iss{value};
348  item_iss >> *option;
349  }
350  return iss;
351 }
352 
353 std::ostream&
354 GncOptionDB::save_to_key_value(std::ostream& oss) const noexcept
355 {
356 
357  foreach_section(
358  [&oss](const GncOptionSectionPtr& section)
359  {
360  oss << "[Options]\n";
361  section->foreach_option(
362  [&oss, &section](auto& option)
363  {
364  if (option.is_changed())
365  oss << section->get_name().substr(0, classifier_size_max) <<
366  ':' << option.get_name().substr(0, classifier_size_max) <<
367  '=' << option << '\n';
368  });
369  });
370  return oss;
371 }
372 
373 std::istream&
374 GncOptionDB::load_from_key_value(std::istream& iss)
375 {
376  if (iss.peek() == '[')
377  {
378  char buf[classifier_size_max];
379  iss.getline(buf, classifier_size_max);
380  if (strcmp(buf, "[Options]") != 0) // safe
381  throw std::runtime_error("Wrong secion header for options.");
382  }
383  // Otherwise assume we were sent here correctly:
384  while (iss.peek() != '[') //Indicates the start of the next file section
385  {
386  load_option_key_value(iss);
387  }
388  return iss;
389 }
390 
391 size_t
392 GncOptionDB::register_callback(GncOptionDBChangeCallback cb, void* data)
393 {
394  constexpr std::hash<GncOptionDBChangeCallback> cb_hash;
395  auto id{cb_hash(cb)};
396  if (std::find_if(m_callbacks.begin(), m_callbacks.end(),
397  [id](auto&cb)->bool{ return cb.m_id == id; }) == m_callbacks.end())
398  m_callbacks.emplace_back(id, cb, data);
399  return id;
400 }
401 
402 void
403 GncOptionDB::unregister_callback(size_t id)
404 {
405  std::remove_if(m_callbacks.begin(), m_callbacks.end(),
406  [id](auto& cb)->bool { return cb.m_id == id; });
407 }
408 
409 void
410 GncOptionDB::run_callbacks()
411 {
412  std::for_each(m_callbacks.begin(), m_callbacks.end(),
413  [](auto& cb)->void { cb.m_func(cb.m_data); });
414 }
415 
416 static inline void
417 counter_option_path(const GncOption& option, GSList* list, std::string& name)
418 {
419  constexpr const char* counters{"counters"};
420  constexpr const char* formats{"counter_formats"};
421  auto key = option.get_key();
422  name = key.substr(0, key.size() - 1);
423  list->next->data = (void*)name.c_str();
424  if (option.get_name().rfind("format")
425  != std::string::npos)
426  list->data = (void*)formats;
427  else
428  list->data = (void*)counters;
429 }
430 
431 static inline void
432 option_path(const GncOption& option, GSList* list)
433 {
434  list->next->data = (void*)option.get_name().c_str();
435  list->data = (void*)option.get_section().c_str();
436 }
437 
438 static inline KvpValue*
439 kvp_value_from_bool_option(const GncOption& option)
440 {
441  auto val{option.template get_value<bool>()};
442  // ~KvpValue will g_free the value.
443  return new KvpValue(val ? g_strdup("t") : g_strdup("f"));
444 }
445 
446 static bool
447 is_qofinstance_ui_type(GncOptionUIType type)
448 {
449  switch (type)
450  {
451  case GncOptionUIType::ACCOUNT_SEL:
452  case GncOptionUIType::BUDGET:
453  case GncOptionUIType::OWNER:
454  case GncOptionUIType::CUSTOMER:
455  case GncOptionUIType::VENDOR:
456  case GncOptionUIType::EMPLOYEE:
457  case GncOptionUIType::INVOICE:
458  case GncOptionUIType::TAX_TABLE:
459  case GncOptionUIType::QUERY:
460  return true;
461  default:
462  return false;
463  }
464 }
465 
466 static inline KvpValue*
467 kvp_value_from_qof_instance_option(const GncOption& option)
468 {
469  const QofInstance* inst{QOF_INSTANCE(option.template get_value<const QofInstance*>())};
470  auto guid = guid_copy(qof_instance_get_guid(inst));
471  return new KvpValue(guid);
472 }
473 
474 void
475 GncOptionDB::save_to_kvp(QofBook* book, bool clear_options) const noexcept
476 {
477  if (clear_options)
478  qof_book_options_delete(book, nullptr);
479  const_cast<GncOptionDB*>(this)->foreach_section(
480  [book](GncOptionSectionPtr& section)
481  {
482  section->foreach_option(
483  [book, &section](auto& option) {
484  if (option.is_changed())
485  {
486  /* We need the string name out here so that it stays in
487  * scope long enough to pass its c_str to
488  * gnc_book_set_option. */
489  std::string name;
490  /* qof_book_set_option wants a GSList path. Let's avoid
491  * allocating and make one here. */
492  GSList list_tail{}, list_head{nullptr, &list_tail};
493  if (strcmp(section->get_name().c_str(), "Counters") == 0)
494  counter_option_path(option, &list_head, name);
495  else
496  option_path(option, &list_head);
497  auto type{option.get_ui_type()};
498  KvpValue* kvp{};
499  if (type == GncOptionUIType::BOOLEAN)
500  kvp = kvp_value_from_bool_option(option);
501  else if (is_qofinstance_ui_type(type))
502  kvp = kvp_value_from_qof_instance_option(option);
503  else if (type == GncOptionUIType::NUMBER_RANGE)
504  /* The Gtk control uses a double so that's what we
505  * have to store. */
506  kvp = new KvpValue(option.template get_value<double>());
507  else
508  kvp = new KvpValue{g_strdup(option.template get_value<std::string>().c_str())};
509  qof_book_set_option(book, kvp, &list_head);
510  }
511  });
512  });
513 }
514 
515 static inline void
516 fill_option_from_string_kvp(GncOption& option, KvpValue* kvp)
517 {
518  auto str{kvp->get<const char*>()};
519  if (option.get_ui_type() == GncOptionUIType::BOOLEAN)
520  option.set_value(*str == 't' ? true : false);
521  else
522  option.set_value(std::string{str});
523 }
524 
525 static inline void
526 fill_option_from_guid_kvp(GncOption& option, KvpValue* kvp)
527 {
528  auto guid{kvp->get<GncGUID*>()};
529  option.set_value(
530  (const QofInstance*)qof_instance_from_guid(guid, option.get_ui_type()));
531 }
532 
533 void
534 GncOptionDB::load_from_kvp(QofBook* book) noexcept
535 {
536  foreach_section(
537  [book](GncOptionSectionPtr& section)
538  {
539  section->foreach_option(
540  [book, &section](GncOption& option)
541  {
542  // Make path list as above.
543  std::string name;
544  /* qof_book_set_option wants a GSList path. Let's avoid
545  * allocating and make one here. */
546  GSList list_tail{}, list_head{nullptr, &list_tail};
547  if (strcmp(section->get_name().c_str(), "Counters") == 0)
548  counter_option_path(option, &list_head, name);
549  else
550  option_path(option, &list_head);
551  auto kvp = qof_book_get_option(book, &list_head);
552  if (!kvp)
553  return;
554  switch (kvp->get_type())
555  {
556  case KvpValue::Type::DOUBLE:
557  option.set_value(kvp->get<double>());
558  break;
559  case KvpValue::Type::INT64:
560  option.set_value(kvp->get<int64_t>());
561  break;
562  case KvpValue::Type::STRING:
563  fill_option_from_string_kvp(option, kvp);
564  break;
565  case KvpValue::Type::GUID:
566  fill_option_from_guid_kvp(option, kvp);
567  break;
568  default:
569  return;
570  break;
571  }
572  });
573  });
574 }
575 
576 void
577 gnc_register_string_option(GncOptionDB* db, const char* section,
578  const char* name, const char* key,
579  const char* doc_string, std::string value)
580 {
581  GncOption option{section, name, key, doc_string, value,
582  GncOptionUIType::STRING};
583  db->register_option(section, std::move(option));
584 }
585 
586 void
587 gnc_register_text_option(GncOptionDB* db, const char* section, const char* name,
588  const char* key, const char* doc_string,
589  std::string value)
590 {
591  GncOption option{section, name, key, doc_string, value,
592  GncOptionUIType::TEXT};
593  db->register_option(section, std::move(option));
594 
595 }
596 
597 void
598 gnc_register_font_option(GncOptionDB* db, const char* section,
599  const char* name, const char* key,
600  const char* doc_string, std::string value)
601 {
602  GncOption option{section, name, key, doc_string, value,
603  GncOptionUIType::FONT};
604  db->register_option(section, std::move(option));
605 }
606 
607 void
608 gnc_register_budget_option(GncOptionDB* db, const char* section,
609  const char* name, const char* key,
610  const char* doc_string, GncBudget *value)
611 {
612  GncOption option{GncOptionQofInstanceValue{section, name, key, doc_string,
613  (const QofInstance*)value,
614  GncOptionUIType::BUDGET}};
615  db->register_option(section, std::move(option));
616 }
617 
618 void
619 gnc_register_color_option(GncOptionDB* db, const char* section,
620  const char* name, const char* key,
621  const char* doc_string, std::string value)
622 {
623  GncOption option{section, name, key, doc_string, value,
624  GncOptionUIType::COLOR};
625  db->register_option(section, std::move(option));
626 }
627 
628 void
630  const char* name, const char* key,
631  const char* doc_string, gnc_commodity *value)
632 {
633  GncOption option{GncOptionCommodityValue{section, name, key, doc_string,
634  value,
635  GncOptionUIType::COMMODITY}};
636  db->register_option(section, std::move(option));
637 }
638 
639 void
641  const char* name, const char* key,
642  const char* doc_string, const char* value)
643 {
644  gnc_commodity* commodity{};
645  const auto book{qof_session_get_book(gnc_get_current_session())};
646  const auto commodity_table{gnc_commodity_table_get_table(book)};
647  const auto namespaces{gnc_commodity_table_get_namespaces(commodity_table)};
648  for (auto node = namespaces; node && commodity == nullptr;
649  node = g_list_next(node))
650  {
651  commodity = gnc_commodity_table_lookup(commodity_table,
652  (const char*)(node->data),
653  value);
654  if (commodity)
655  break;
656  }
657  GncOption option{GncOptionCommodityValue{section, name, key, doc_string,
658  commodity,
659  GncOptionUIType::COMMODITY}};
660  db->register_option(section, std::move(option));
661 }
662 
663 void
665  const char* section, const char* name,
666  const char* key, const char* doc_string,
667  bool value)
668 {
669  GncOption option{section, name, key, doc_string, value,
670  GncOptionUIType::BOOLEAN};
671  db->register_option(section, std::move(option));
672 }
673 
674 void
675 gnc_register_pixmap_option(GncOptionDB* db, const char* section,
676  const char* name, const char* key,
677  const char* doc_string, std::string value)
678 {
679  GncOption option{section, name, key, doc_string, value,
680  GncOptionUIType::PIXMAP};
681  db->register_option(section, std::move(option));
682 }
683 
684 void
686  const char* name, const char* key,
687  const char* doc_string,
688  const GncOptionAccountList& value)
689 {
690  GncOption option{GncOptionAccountListValue{section, name, key, doc_string,
691  GncOptionUIType::ACCOUNT_LIST, value}};
692  db->register_option(section, std::move(option));
693 }
694 
695 void
697  const char* section, const char* name,
698  const char* key,
699  const char* doc_string,
700  const GncOptionAccountList& value,
701  GncOptionAccountTypeList&& allowed)
702 {
703  try
704  {
705  GncOption option{GncOptionAccountListValue{section, name, key, doc_string,
706  GncOptionUIType::ACCOUNT_LIST, value, std::move(allowed)}};
707  db->register_option(section, std::move(option));
708  }
709  catch (const std::invalid_argument& err)
710  {
711  PWARN("Account List Limited Option, value failed validation, option not registered.");
712  }
713 }
714 
715 using AccountPair = std::pair<GncOptionAccountList&,
716  const GncOptionAccountTypeList&>;
717 static void
718 find_children(Account* account, void* data)
719 {
720  auto datapair =
721  (AccountPair*)data;
722  GncOptionAccountList& list = datapair->first;
723  const GncOptionAccountTypeList& types = datapair->second;
724  if (std::find(types.begin(), types.end(),
725  xaccAccountGetType(account)) != types.end())
726  list.push_back(*qof_entity_get_guid(account));
727 }
728 
729 GncOptionAccountList
731  const GncOptionAccountTypeList& types)
732 {
733  GncOptionAccountList list;
734  AccountPair funcdata{list, types};
735  Account* base_acct = gnc_book_get_root_account(book);
736  gnc_account_foreach_descendant(base_acct, (AccountCb)find_children,
737  &funcdata);
738  return list;
739 }
740 
741 
742 void
744  const char* section, const char* name,
745  const char* key, const char* doc_string,
746  const Account* value,
747  GncOptionAccountTypeList&& allowed)
748 {
749  try
750  {
751  GncOption option{GncOptionAccountSelValue{section, name, key, doc_string,
752  GncOptionUIType::ACCOUNT_SEL, value, std::move(allowed)}};
753  db->register_option(section, std::move(option));
754  }
755  catch (const std::invalid_argument& err)
756  {
757  PWARN("Account Sel Limited Option, value failed validation, option not registerd.");
758  }
759 }
760 
761 void
763  const char* name, const char* key,
764  const char* doc_string, const char* default_val,
765  GncMultichoiceOptionChoices&& choices)
766 {
767  std::string defval{default_val};
768  auto found{std::find_if(choices.begin(), choices.end(),
769  [&defval](auto& choice)->bool {
770  return defval == std::get<0>(choice);
771  })};
772  if (found == choices.end())
773  defval = (choices.empty() ? std::string{"None"} :
774  std::get<0>(choices.at(0)));
775  GncOption option{GncOptionMultichoiceValue{section, name, key, doc_string,
776  defval.c_str(), std::move(choices)}};
777  db->register_option(section, std::move(option));
778 }
779 
780 void
781 gnc_register_list_option(GncOptionDB* db, const char* section,
782  const char* name, const char* key,
783  const char* doc_string, const char* value,
784  GncMultichoiceOptionChoices&& list)
785 {
786  GncOption option{GncOptionMultichoiceValue{section, name, key, doc_string,
787  value, std::move(list), GncOptionUIType::LIST}};
788  db->register_option(section, std::move(option));
789 }
790 
791 /* Only balance-forecast.scm, hello-world.scm, and net-charts.scm
792  * use decimals and fractional steps and they can be worked around.
793  */
794 template <typename ValueType> void
796  const char* name, const char* key,
797  const char* doc_string, ValueType value,
798  ValueType min, ValueType max, ValueType step)
799 {
800  try
801  {
802  GncOption option{GncOptionRangeValue<ValueType>{section, name, key,
803  doc_string, value, min,
804  max, step}};
805  db->register_option(section, std::move(option));
806  }
807  catch(const std::invalid_argument& err)
808  {
809  PWARN("Number Range Option %s, option not registerd.",
810  err.what());
811  }
812 }
813 
814 void
816  const char* section, const char* name,
817  const char* key, const char* doc_string,
818  int value)
819 {
820  // Pixel values don't make much sense so always use percent.
821  GncOption option{GncOptionRangeValue<int>{section, name, key, doc_string,
822  value, 10, 100, 1}};
823  db->register_option(section, std::move(option));
824 }
825 
826 void
827 gnc_register_query_option(GncOptionDB* db, const char* section,
828  const char* name, const QofQuery* value)
829 {
830  GncOption option{section, name, "", "", value,
831  GncOptionUIType::INTERNAL};
832  db->register_option(section, std::move(option));
833 }
834 
835 void
836 gnc_register_owner_option(GncOptionDB* db, const char* section,
837  const char* name, const char* key,
838  const char* doc_string, const GncOwner* value,
839  GncOwnerType type)
840 {
841  GncOptionUIType uitype;
842  switch (type)
843  {
844  case GNC_OWNER_CUSTOMER:
845  uitype = GncOptionUIType::CUSTOMER;
846  break;
847  case GNC_OWNER_EMPLOYEE:
848  uitype = GncOptionUIType::EMPLOYEE;
849  break;
850  case GNC_OWNER_JOB:
851  uitype = GncOptionUIType::JOB;
852  break;
853  case GNC_OWNER_VENDOR:
854  uitype = GncOptionUIType::VENDOR;
855  break;
856  default:
857  uitype = GncOptionUIType::INTERNAL;
858  };
859  GncOption option{section, name, key, doc_string, value,
860  uitype};
861  db->register_option(section, std::move(option));
862 }
863 
864 void
865 gnc_register_invoice_option(GncOptionDB* db, const char* section,
866  const char* name, const char* key,
867  const char* doc_string, GncInvoice* value)
868 {
869  GncOption option{GncOptionQofInstanceValue{section, name, key, doc_string,
870  (const QofInstance*)value,
871  GncOptionUIType::INVOICE}};
872  db->register_option(section, std::move(option));
873 }
874 
875 void
876 gnc_register_taxtable_option(GncOptionDB* db, const char* section,
877  const char* name, const char* key,
878  const char* doc_string, GncTaxTable* value)
879 {
880  GncOption option{GncOptionQofInstanceValue{section, name, key, doc_string,
881  (const QofInstance*)value,
882  GncOptionUIType::TAX_TABLE}};
883  db->register_option(section, std::move(option));
884 }
885 
886 void
888  const char* name, const char* key,
889  const char* doc_string, std::string value)
890 {
891  GncOption option{section, name, key, doc_string,
892  value, GncOptionUIType::INV_REPORT};
893  db->register_option(section, std::move(option));
894 }
895 
896 void
897 gnc_register_counter_option(GncOptionDB* db, const char* section,
898  const char* name, const char* key,
899  const char* doc_string, double value)
900 {
901  GncOption option{GncOptionRangeValue<double>{section, name, key, doc_string,
902  value, 0.0, 999999999.0, 1.0}};
903  db->register_option(section, std::move(option));
904 }
905 
906 void
908  const char* section, const char* name,
909  const char* key, const char* doc_string,
910  std::string value)
911 {
912  GncOption option{section, name, key, doc_string, value,
913  GncOptionUIType::STRING};
914  db->register_option(section, std::move(option));
915 }
916 
917 void
919  const char* name, const char* key,
920  const char* doc_string, std::string value)
921 {
922  GncOption option{section, name, key, doc_string, value,
923  GncOptionUIType::DATE_FORMAT};
924  db->register_option(section, std::move(option));
925 }
926 
927 void
928 gnc_register_currency_option(GncOptionDB* db, const char* section,
929  const char* name, const char* key,
930  const char* doc_string, gnc_commodity *value)
931 {
933  section, name, key, doc_string, value, GncOptionUIType::CURRENCY
934  }};
935  db->register_option(section, std::move(option));
936 }
937 
938 void
939 gnc_register_currency_option(GncOptionDB* db, const char* section,
940  const char* name, const char* key,
941  const char* doc_string, const char* value)
942 {
943  const auto book{qof_session_get_book(gnc_get_current_session())};
944  const auto commodity_table{gnc_commodity_table_get_table(book)};
945  const auto commodity = gnc_commodity_table_lookup(commodity_table,
946  "CURRENCY",
947  value);
949  section, name, key, doc_string, commodity, GncOptionUIType::CURRENCY
950  }};
951  db->register_option(section, std::move(option));
952 }
953 
954 void
955 gnc_register_date_option(GncOptionDB* db, const char* section,
956  const char* name, const char* key,
957  const char* doc_string, time64 time,
958  RelativeDateUI ui)
959 {
960  auto ui_type = ui == RelativeDateUI::BOTH ? GncOptionUIType::DATE_BOTH :
961  ui == RelativeDateUI::RELATIVE ? GncOptionUIType::DATE_RELATIVE :
962  GncOptionUIType::DATE_ABSOLUTE;
963  GncOption option{GncOptionDateValue(section, name, key, doc_string,
964  ui_type, time)};
965  db->register_option(section, std::move(option));
966 }
967 
968 void
969 gnc_register_date_option(GncOptionDB* db, const char* section,
970  const char* name, const char* key,
971  const char* doc_string, RelativeDatePeriod period,
972  RelativeDateUI ui)
973 {
974  auto ui_type = ui == RelativeDateUI::BOTH ? GncOptionUIType::DATE_BOTH :
975  ui == RelativeDateUI::RELATIVE ? GncOptionUIType::DATE_RELATIVE :
976  GncOptionUIType::DATE_ABSOLUTE;
977  GncOption option{GncOptionDateValue(section, name, key, doc_string,
978  ui_type, period)};
979  db->register_option(section, std::move(option));
980 }
981 
982 void
984  const char* section, const char* name,
985  const char* key, const char* doc_string,
986  RelativeDatePeriodVec& period_set,
987  bool both)
988 {
989  auto is_absolute = period_set.size() == 1 &&
990  period_set.front() == RelativeDatePeriod::ABSOLUTE;
991  auto ui_type = both ? GncOptionUIType::DATE_BOTH :
992  is_absolute ? GncOptionUIType::DATE_ABSOLUTE : GncOptionUIType::DATE_RELATIVE;
993  GncOption option{GncOptionDateValue(section, name, key, doc_string,
994  ui_type, period_set)};
995  if (is_absolute)
996  option.set_default_value(gnc_time(nullptr));
997  db->register_option(section, std::move(option));
998 }
999 
1000 
1001 static const RelativeDatePeriodVec begin_dates
1002 {
1003  RelativeDatePeriod::TODAY,
1004  RelativeDatePeriod::START_THIS_MONTH,
1005  RelativeDatePeriod::START_PREV_MONTH,
1006  RelativeDatePeriod::START_CURRENT_QUARTER,
1007  RelativeDatePeriod::START_PREV_QUARTER,
1008  RelativeDatePeriod::START_CAL_YEAR,
1009  RelativeDatePeriod::START_PREV_YEAR,
1010  RelativeDatePeriod::START_ACCOUNTING_PERIOD
1011 };
1012 
1013 void
1015  const char* name, const char* key,
1016  const char* doc_string, bool both)
1017 {
1018  auto ui_type = both ? GncOptionUIType::DATE_BOTH :
1019  GncOptionUIType::DATE_RELATIVE;
1020  GncOption option{GncOptionDateValue(section, name, key, doc_string,
1021  ui_type, begin_dates)};
1022  db->register_option(section, std::move(option));
1023 }
1024 
1025 static const RelativeDatePeriodVec end_dates
1026 {
1027  RelativeDatePeriod::TODAY,
1028  RelativeDatePeriod::END_THIS_MONTH,
1029  RelativeDatePeriod::END_PREV_MONTH,
1030  RelativeDatePeriod::END_CURRENT_QUARTER,
1031  RelativeDatePeriod::END_PREV_QUARTER,
1032  RelativeDatePeriod::END_CAL_YEAR,
1033  RelativeDatePeriod::END_PREV_YEAR,
1034  RelativeDatePeriod::END_ACCOUNTING_PERIOD
1035 };
1036 
1037 void
1039  const char* name, const char* key,
1040  const char* doc_string, bool both)
1041 {
1042  auto ui_type = both ? GncOptionUIType::DATE_BOTH :
1043  GncOptionUIType::DATE_RELATIVE;
1044  GncOption option{GncOptionDateValue(section, name, key, doc_string,
1045  ui_type, end_dates)};
1046  db->register_option(section, std::move(option));
1047 }
1048 
1049 void
1050 gnc_register_report_placement_option(GncOptionDBPtr& db,
1051  const char* section, const char* name)
1052 {
1053  /* This is a special option with it's own UI file so we have fake values to pass
1054  * to the template creation function.
1055  */
1056  GncOptionReportPlacementVec value;
1058  "no_key", "nodoc_string",
1059  value,GncOptionUIType::REPORT_PLACEMENT}};
1060  db->register_option(section, std::move(option));
1061 }
1062 
1063 void
1064 gnc_register_internal_option(GncOptionDBPtr& db,
1065  const char* section, const char* name,
1066  const std::string& value)
1067 {
1068  GncOption option{
1069  GncOptionValue<std::string>{section, name, "", "", value,
1070  GncOptionUIType::INTERNAL}};
1071  db->register_option(section, std::move(option));
1072 }
1073 
1074 void
1075 gnc_register_internal_option(GncOptionDBPtr& db,
1076  const char* section, const char* name,
1077  bool value)
1078 {
1079  GncOption option{
1080  GncOptionValue<bool>{section, name, "", "", value,
1081  GncOptionUIType::INTERNAL}};
1082  db->register_option(section, std::move(option));
1083 }
1084 
1085 GncOptionDB*
1087 {
1088  return new GncOptionDB;
1089 }
1090 
1091 void
1093 {
1094  PWARN("Direct Destroy called on GncOptionDB %" G_GUINT64_FORMAT, (uint64_t)odb);
1095 }
1096 
1097 GList*
1099 {
1100  GList* errors{};
1101  odb->foreach_section(
1102  [&errors](GncOptionSectionPtr& section){
1103  section->foreach_option(
1104  [&errors](GncOption& option) {
1105  try
1106  {
1107  option.set_option_from_ui_item();
1108  }
1109  catch (const std::invalid_argument& err)
1110  {
1111  PWARN("Option %s:%s failed to set its value %s",
1112  option.get_section().c_str(),
1113  option.get_name().c_str(), err.what());
1114  errors = g_list_prepend(errors,
1115  (void*)option.get_name().c_str());
1116  } });
1117  });
1118  if (!errors)
1119  odb->run_callbacks();
1120  return errors;
1121 }
1122 
1123 void
1125 {
1126  odb->foreach_section(
1127  [](GncOptionSectionPtr& section){
1128  section->foreach_option(
1129  [](GncOption& option) {
1130  option.set_ui_item_from_option();
1131  });
1132  });
1133 }
1134 
1135 void gnc_option_db_load(GncOptionDB* odb, QofBook* book)
1136 {
1137  odb->load_from_kvp(book);
1138 }
1139 
1140 void
1141 gnc_option_db_save(GncOptionDB* odb, QofBook* book,
1142  gboolean clear_options)
1143 {
1144  odb->save_to_kvp(book, static_cast<bool>(clear_options));
1145 }
1146 
1147 void
1149 {
1150  constexpr const char* business_section{N_("Business")};
1151  constexpr const char* counter_section{N_("Counters")};
1152  static const std::string empty_string{""};
1153 
1154 //Accounts Tab
1155 
1156  gnc_register_number_range_option<double>(odb, OPTION_SECTION_ACCOUNTS,
1157  OPTION_NAME_AUTO_READONLY_DAYS, "a",
1158  N_("Choose the number of days after which transactions will be read-only and cannot be edited anymore. This threshold is marked by a red line in the account register windows. If zero, all transactions can be edited and none are read-only."),
1159  0.0, 0.0, 3650.0, 1.0);
1160 
1161  gnc_register_simple_boolean_option(odb, OPTION_SECTION_ACCOUNTS,
1162  OPTION_NAME_NUM_FIELD_SOURCE, "b",
1163  N_("Check to have split action field used in registers for 'Num' field in place of transaction number; transaction number shown as 'T-Num' on second line of register. Has corresponding effect on business features, reporting and imports/exports."),
1164  false);
1165  gnc_register_simple_boolean_option(odb, OPTION_SECTION_ACCOUNTS,
1166  OPTION_NAME_TRADING_ACCOUNTS, "a",
1167  N_("Check to have trading accounts used for transactions involving more than one currency or commodity."),
1168  false);
1169 
1170 //Budgeting Tab
1171 
1172  gnc_register_budget_option(odb, OPTION_SECTION_BUDGETING,
1173  OPTION_NAME_DEFAULT_BUDGET, "a",
1174  N_("Budget to be used when none has been otherwise specified."),
1175  nullptr);
1176 
1177 //Counters Tab
1178 
1179  gnc_register_counter_option(odb, counter_section,
1180  N_("Customer number"), "gncCustomera",
1181  N_("The previous customer number generated. This number will be incremented to generate the next customer number."),
1182  0.0);
1183  gnc_register_counter_format_option(odb, counter_section,
1184  N_("Customer number format"),
1185  "gncCustomerb",
1186  N_("The format string to use for generating customer numbers. This is a printf-style format string."),
1187  empty_string);
1188  gnc_register_counter_option(odb, counter_section,
1189  N_("Employee number"), "gncEmployeea",
1190  N_("The previous employee number generated. This number will be incremented to generate the next employee number."),
1191  0.0);
1192  gnc_register_counter_format_option(odb, counter_section,
1193  N_("Employee number format"),
1194  "gncEmployeeb",
1195  N_("The format string to use for generating employee numbers. This is a printf-style format string."),
1196  empty_string);
1197  gnc_register_counter_option(odb, counter_section,
1198  N_("Invoice number"), "gncInvoicea",
1199  N_("The previous invoice number generated. This number will be incremented to generate the next invoice number."),
1200  0.0);
1201  gnc_register_counter_format_option(odb, counter_section,
1202  N_("Invoice number format"),
1203  "gncInvoiceb",
1204  N_("The format string to use for generating invoice numbers. This is a printf-style format string."),
1205  empty_string);
1206  gnc_register_counter_option(odb, counter_section,
1207  N_("Bill number"), "gncBilla",
1208  N_("The previous bill number generated. This number will be incremented to generate the next bill number."),
1209  0.0);
1210  gnc_register_counter_format_option(odb, counter_section,
1211  N_("Bill number format"), "gncBillb",
1212  N_("The format string to use for generating bill numbers. This is a printf-style format string."),
1213  empty_string);
1214  gnc_register_counter_option(odb, counter_section,
1215  N_("Expense voucher number"), "gncExpVouchera",
1216  N_("The previous expense voucher number generated. This number will be incremented to generate the next voucher number."),
1217  0.0);
1218  gnc_register_counter_format_option(odb, counter_section,
1219  N_("Expense voucher number format"),
1220  "gncExpVoucherb",
1221  N_("The format string to use for generating expense voucher numbers. This is a printf-style format string."),
1222  empty_string);
1223  gnc_register_counter_option(odb, counter_section,
1224  N_("Job number"), "gncJoba",
1225  N_("The previous job number generated. This number will be incremented to generate the next job number."),
1226  0.0);
1227  gnc_register_counter_format_option(odb, counter_section,
1228  N_("Job number format"), "gncJobb",
1229  N_("The format string to use for generating job numbers. This is a printf-style format string."),
1230  empty_string);
1231  gnc_register_counter_option(odb, counter_section,
1232  N_("Order number"), "gncOrdera",
1233  N_("The previous order number generated. This number will be incremented to generate the next order number."),
1234  0.0);
1235  gnc_register_counter_format_option(odb, counter_section,
1236  N_("Order number format"), "gncOrderb",
1237  N_("The format string to use for generating order numbers. This is a printf-style format string."),
1238  empty_string);
1239  gnc_register_counter_option(odb, counter_section,
1240  N_("Vendor number"), "gncVendora",
1241  N_("The previous vendor number generated. This number will be incremented to generate the next vendor number."),
1242  0.0);
1243  gnc_register_counter_format_option(odb, counter_section,
1244  N_("Vendor number format"), "gncVendorb",
1245  N_("The format string to use for generating vendor numbers. This is a printf-style format string."),
1246  empty_string);
1247 
1248 //Business Tab
1249 
1250  gnc_register_string_option(odb, business_section, N_("Company Name"), "a",
1251  N_("The name of your business."),
1252  empty_string);
1253  gnc_register_text_option(odb, business_section, N_("Company Address"), "b1",
1254  N_("The address of your business."),
1255  empty_string);
1256  gnc_register_string_option(odb, business_section,
1257  N_("Company Contact Person"), "b2",
1258  N_("The contact person to print on invoices."),
1259  empty_string);
1260  gnc_register_string_option(odb, business_section,
1261  N_("Company Phone Number"), "c1",
1262  N_("The contact person to print on invoices."),
1263  empty_string);
1264  gnc_register_string_option(odb, business_section,
1265  N_("Company Fax Number"), "c2",
1266  N_("The fax number of your business."),
1267  empty_string);
1268  gnc_register_string_option(odb, business_section,
1269  N_("Company Email Address"), "c3",
1270  N_ ("The email address of your business."),
1271  empty_string);
1272  gnc_register_string_option(odb, business_section,
1273  N_("Company Website URL"), "c4",
1274  N_("The URL address of your website."),
1275  empty_string);
1276  gnc_register_string_option(odb, business_section, N_("Company ID"), "c5",
1277  N_("The ID for your company (eg 'Tax-ID: 00-000000)."),
1278  empty_string);
1279  gnc_register_invoice_print_report_option(odb, business_section,
1280  OPTION_NAME_DEFAULT_INVOICE_REPORT, "e1",
1281  N_("The invoice report to be used for printing."),
1282  empty_string);
1283  gnc_register_number_range_option<double>(odb, business_section,
1284  OPTION_NAME_DEFAULT_INVOICE_REPORT_TIMEOUT, "e2",
1285  N_("Length of time to change the used invoice report. A value of 0 means disabled."),
1286  0.0, 0.0, 20.0, 1.0);
1287  gnc_register_taxtable_option(odb, business_section,
1288  N_("Default Customer TaxTable"), "f1",
1289  N_("The default tax table to apply to customers."),
1290  nullptr);
1291  gnc_register_taxtable_option(odb, business_section,
1292  N_("Default Vendor TaxTable"), "f2",
1293  N_("The default tax table to apply to vendors."),
1294  nullptr);
1295  gnc_register_dateformat_option(odb, business_section,
1296  N_("Fancy Date Format"), "g",
1297  N_("The default date format used for fancy printed dates."),
1298  empty_string);
1299 
1300 //Tax Tab
1301 
1302  gnc_register_string_option(odb, N_("Tax"), N_("Tax Number"), "a",
1303  N_("The electronic tax number of your business"),
1304  empty_string);
1305 }
1306 
1307 const char*
1308 gnc_option_db_lookup_string_value(GncOptionDB* odb, const char* section, const char* name)
1309 {
1310  auto value{odb->lookup_string_option(section, name)};
1311  if (value.empty())
1312  return nullptr;
1313  return strdup(value.c_str());
1314 }
1315 
1316 void
1318  const char* name, const char* value)
1319 {
1320  odb->set_option<std::string>(section, name, value);
1321 }
1322 
1323 const QofInstance*
1325  const char* name)
1326 {
1327  auto option{odb->find_option(section, name)};
1328  if (option)
1329  return option->get_value<const QofInstance*>();
1330  else
1331  return nullptr;
1332 }
1333 
1334 // Force creation of templates
1336  const char* section, const char* name,
1337  const char* key, const char* doc_string,
1338  int value, int min, int max, int step);
1340  const char* section, const char* name,
1341  const char* key, const char* doc_string,
1342  double value, double min,
1343  double max, double step);
Holds all of the options for a book, report, or stylesheet, organized by GncOptionSections.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
void gnc_option_db_clean(GncOptionDB *odb)
Reset all ui_items to the option value.
const QofInstance * gnc_option_db_lookup_qofinstance_value(GncOptionDB *odb, const char *section, const char *name)
Retrieve the string value of an option in the GncOptionDB.
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
void gnc_register_simple_boolean_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, bool value)
Create a new simple boolean option and register it in the options database.
KvpValue * qof_book_get_option(QofBook *book, GSList *path)
Read a single option value.
Definition: qofbook.cpp:1333
The generic option-value class.
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
This method will traverse all children of this accounts and their descendants, calling &#39;func&#39; on each...
Definition: Account.cpp:3251
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account&#39;s account type.
Definition: Account.cpp:3285
void gnc_register_invoice_print_report_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new print report option and register it in the options database.
GncGUID * guid_copy(const GncGUID *guid)
Returns a newly allocated GncGUID that matches the passed-in GUID.
Definition: guid.cpp:118
void gnc_register_number_range_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, ValueType value, ValueType min, ValueType max, ValueType step)
Create a new number range option and register it in the options database.
A legal date value is a pair of either a RelativeDatePeriod, the absolute flag and a time64...
C public interface for the Options Database.
void gnc_option_db_set_string_value(GncOptionDB *odb, const char *section, const char *name, const char *value)
Set the string value of an option in the GncOptionDB.
void gnc_option_db_save(GncOptionDB *odb, QofBook *book, gboolean clear_options)
Save the GncOptionDB contents into a book&#39;s options store.
void gnc_register_multichoice_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const char *default_val, GncMultichoiceOptionChoices &&choices)
Create a new multichoice option and register it in the options database.
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...
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void gnc_register_query_option(GncOptionDB *db, const char *section, const char *name, const QofQuery *value)
Create a new QofQuery option and register it in the options database.
void gnc_register_number_plot_size_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, int value)
Create a new plot-size option and register it in the options database.
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:574
void gnc_register_date_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, time64 time, RelativeDateUI ui)
Create a new date option and register it in the options database.
Multichoice options have a vector of valid options (GncMultichoiceOptionChoices) and validate the sel...
void gnc_register_counter_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, double value)
Create a new counter option and register it in the options database.
void gnc_register_account_sel_limited_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const Account *value, GncOptionAccountTypeList &&allowed)
Create a limited account selection option and register it in the options database.
GList * gnc_commodity_table_get_namespaces(const gnc_commodity_table *table)
Return a list of all namespaces in the commodity table.
void gnc_register_start_date_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, bool both)
Create a new start-date option and register it in the options database.
void gnc_option_db_load(GncOptionDB *odb, QofBook *book)
Load a book&#39;s options into the GncOptionDB.
void gnc_register_list_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const char *value, GncMultichoiceOptionChoices &&list)
Create a new list option and register it in the options database.
void gnc_option_db_destroy(GncOptionDB *odb)
Destruct and release a GncOptionDB.
RelativeDatePeriod
Reporting periods relative to the current date.
void gnc_register_dateformat_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new date format option and register it in the options database.
void gnc_register_color_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new color option and register it in the options database.
class GncOptionSection The upper-level classification implmentation.
void gnc_register_string_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new string option and register it in the options database.
void gnc_register_account_list_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const GncOptionAccountList &value)
Create a new account list option and register it in the options database.
void gnc_register_commodity_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, gnc_commodity *value)
Create a new commodity option and register it in the options database.
class GncOptionCommodityValue Commodities are stored with their namespace and mnemonic instead of the...
Used for numeric ranges and plot sizes.
const GncGUID * qof_entity_get_guid(gconstpointer ent)
void gnc_register_end_date_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, bool both)
Create a new end-date option and register it in the options database.
The primary C++ interface to options for books, reports, and stylesheets.
GList * gnc_option_db_commit(GncOptionDB *odb)
Write all changed ui_item values to their options.
const char * gnc_option_db_lookup_string_value(GncOptionDB *odb, const char *section, const char *name)
Retrieve the string value of an option in the GncOptionDB.
void gnc_register_taxtable_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, GncTaxTable *value)
Create a new taxtable option and register it in the options database.
void gnc_register_font_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new font option and register it in the options database.
time64 gnc_time(time64 *tbuf)
get the current local time
Definition: gnc-date.cpp:270
Implementation details for GncOptionDB.
void gnc_register_pixmap_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new pixmap option and register it in the options database.
gint64 time64
Many systems, including Microsoft Windows and BSD-derived Unixes like Darwin, are retaining the int-3...
Definition: gnc-date.h:87
void gnc_register_budget_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, GncBudget *value)
Create a new budget option and register it in the options database.
void gnc_register_currency_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, gnc_commodity *value)
Create a new currency option and register it in the options database.
void qof_book_set_option(QofBook *book, KvpValue *value, GSList *path)
Save a single option value.
Definition: qofbook.cpp:1320
void qof_book_options_delete(QofBook *book, GSList *path)
Delete the options.
Definition: qofbook.cpp:1340
void gnc_option_db_book_options(GncOptionDB *odb)
Register the standard option set for a QofBook.
The type used to store guids in C.
Definition: guid.h:75
A Query.
Definition: qofquery.cpp:74
void gnc_register_invoice_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, GncInvoice *value)
Create a new invoice option and register it in the options database.
GncOptionAccountList gnc_account_list_from_types(QofBook *book, const GncOptionAccountTypeList &types)
Extract a list of accounts in the book having one of the GNCAccountTypes in types.
void gnc_register_counter_format_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new counter format option and register it in the options database.
void gnc_register_text_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, std::string value)
Create a new text option and register it in the options database.
GncOptionUIType
Used by GncOptionClassifier to indicate to dialog-options what control should be displayed for the op...
modtime is the internal date of the last modtime See src/doc/business.txt for an explanation of the f...
void gnc_register_owner_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const GncOwner *value, GncOwnerType type)
Create a new GncOwner option and register it in the options database.
GncOptionDB * gnc_option_db_new(void)
Create an empty option database.
void gnc_register_account_list_limited_option(GncOptionDB *db, const char *section, const char *name, const char *key, const char *doc_string, const GncOptionAccountList &value, GncOptionAccountTypeList &&allowed)
Create a new limited account list option and register it in the options database. ...