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