diff --git a/bindings/guile/gnc-optiondb.i b/bindings/guile/gnc-optiondb.i index 4e3874bc51..e8a559fd3a 100644 --- a/bindings/guile/gnc-optiondb.i +++ b/bindings/guile/gnc-optiondb.i @@ -319,6 +319,12 @@ scm_from_value(GncOptionReportPlacementVec value) return scm_reverse(s_list); } +template <> inline SCM +scm_from_value(GncOptionDateFormat value) +{ + return SCM_BOOL_F; +} + static std::string scm_color_list_to_string(SCM list) { @@ -564,7 +570,6 @@ gnc_option_test_book_destroy(QofBook* book) %ignore operator>>(std::istream&, GncOption&); %ignore GncOption::_get_option(); - %rename(gnc_register_date_option_set) gnc_register_date_option(GncOptionDBPtr&, const char*, const char*, const char*, const char*, RelativeDatePeriodVec&, @@ -804,7 +809,8 @@ wrap_unique_ptr(GncOptionDBPtr, GncOptionDB); %ignore gnc_register_taxtable_option(GncOptionDB*, const char*, const char*, const char*, const char*, GncTaxTable*); %ignore gnc_register_counter_option(GncOptionDB*, const char*, const char*, const char*, const char*, double); %ignore gnc_register_counter_format_option(GncOptionDB*, const char*, const char*, const char*, const char*, std::string); -%ignore gnc_register_dateformat_option(GncOptionDB*, const char*, const char*, const char*, const char*, std::string); +%ignore gnc_register_dateformat_option(GncOptionDB*, const char*, const char*, const char*, const char*, GncOptionDateFormat&&); +%ignore gnc_register_dateformat_option(GncOptionDBPtr&, const char*, const char*, const char*, const char*, GncOptionDateFormat&&); %ignore gnc_register_date_option(GncOptionDB*, const char*, const char*, const char*, const char*, RelativeDatePeriod, RelativeDateUI); %ignore gnc_register_date_option(GncOptionDB*, const char*, const char*, const char*, const char*, time64, RelativeDateUI); %ignore gnc_register_date_option(GncOptionDB*, const char*, const char*, const char*, const char*, RelativeDatePeriodVec, bool); diff --git a/gnucash/gnome-utils/gnc-option-gtk-ui.cpp b/gnucash/gnome-utils/gnc-option-gtk-ui.cpp index e9f96f99c2..8babd0ce13 100644 --- a/gnucash/gnome-utils/gnc-option-gtk-ui.cpp +++ b/gnucash/gnome-utils/gnc-option-gtk-ui.cpp @@ -1682,13 +1682,21 @@ public: void set_ui_item_from_option(GncOption& option) noexcept override { auto widget{GNC_DATE_FORMAT(get_widget())}; - gnc_date_format_set_custom(widget, - option.get_value().c_str()); + auto [format, months, years, custom] = option.get_value(); + gnc_date_format_set_format(widget, format); + gnc_date_format_set_months(widget, months); + gnc_date_format_set_years(widget, years); + gnc_date_format_set_custom(widget, custom.c_str()); } void set_option_from_ui_item(GncOption& option) noexcept override { auto widget{GNC_DATE_FORMAT(get_widget())}; - option.set_value(std::string{gnc_date_format_get_custom(widget)}); + GncOptionDateFormat format{ + gnc_date_format_get_format(widget), + gnc_date_format_get_months(widget), + gnc_date_format_get_years(widget), + gnc_date_format_get_custom(widget)}; + option.set_value(format); } }; diff --git a/libgnucash/engine/gnc-option-impl.cpp b/libgnucash/engine/gnc-option-impl.cpp index b60b18a2ae..df6a57e462 100644 --- a/libgnucash/engine/gnc-option-impl.cpp +++ b/libgnucash/engine/gnc-option-impl.cpp @@ -1038,6 +1038,7 @@ template void GncOptionValue::set_value(uint16_t); template void GncOptionValue::set_value(GncOptionAccountList); template void GncOptionValue::set_value(GncMultichoiceOptionIndexVec); template void GncOptionValue::set_value(GncOptionReportPlacementVec); +template void GncOptionValue::set_value(GncOptionDateFormat); template void GncOptionValue::set_default_value(bool); template void GncOptionValue::set_default_value(int); template void GncOptionValue::set_default_value(int64_t); @@ -1052,6 +1053,7 @@ template void GncOptionValue::set_default_value(uint16_t); template void GncOptionValue::set_default_value(GncOptionAccountList); template void GncOptionValue::set_default_value(GncMultichoiceOptionIndexVec); template void GncOptionValue::set_default_value(GncOptionReportPlacementVec); +template void GncOptionValue::set_default_value(GncOptionDateFormat); template void GncOptionValue::reset_default_value(); template void GncOptionValue::reset_default_value(); template void GncOptionValue::reset_default_value(); @@ -1066,6 +1068,7 @@ template void GncOptionValue::reset_default_value(); template void GncOptionValue::reset_default_value(); template void GncOptionValue::reset_default_value(); template void GncOptionValue::reset_default_value(); +template void GncOptionValue::reset_default_value(); template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionValue::serialize() const noexcept; @@ -1076,6 +1079,7 @@ template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionValue::serialize() const noexcept; +template std::string GncOptionValue::serialize() const noexcept; template std::string GncOptionRangeValue::serialize() const noexcept; template std::string GncOptionRangeValue::serialize() const noexcept; template bool GncOptionValue::deserialize(const std::string&) noexcept; @@ -1088,5 +1092,6 @@ template bool GncOptionValue::deserialize(const std::string&) noexc template bool GncOptionValue::deserialize(const std::string&) noexcept; template bool GncOptionValue::deserialize(const std::string&) noexcept; template bool GncOptionValue::deserialize(const std::string&) noexcept; +template bool GncOptionValue::deserialize(const std::string&) noexcept; template bool GncOptionRangeValue::deserialize(const std::string&) noexcept; template bool GncOptionRangeValue::deserialize(const std::string&) noexcept; diff --git a/libgnucash/engine/gnc-option-impl.hpp b/libgnucash/engine/gnc-option-impl.hpp index 4ebaa36708..0a279f5bdb 100644 --- a/libgnucash/engine/gnc-option-impl.hpp +++ b/libgnucash/engine/gnc-option-impl.hpp @@ -341,7 +341,8 @@ template>(std::istream& iss, OptType& opt) { if constexpr (std::is_same_v, const _gncOwner*> || - std::is_same_v, const _QofQuery*>) + std::is_same_v, const _QofQuery*> || + std::is_same_v, GncOptionDateFormat>) return iss; else { diff --git a/libgnucash/engine/gnc-option.cpp b/libgnucash/engine/gnc-option.cpp index 8b1005230a..0078e69238 100644 --- a/libgnucash/engine/gnc-option.cpp +++ b/libgnucash/engine/gnc-option.cpp @@ -115,6 +115,7 @@ GncOption::set_value(ValueType value) [value](auto& option) { if constexpr (is_same_decayed_v || + is_same_decayed_v || (is_same_decayed_v && (is_same_decayed_v || @@ -146,6 +147,7 @@ GncOption::set_default_value(ValueType value) [value](auto& option) { if constexpr (is_same_decayed_v|| + is_same_decayed_v || (is_same_decayed_v && (is_same_decayed_v || std::is_same_v || @@ -486,6 +488,10 @@ template GncOption::GncOption(const char*, const char*, const char*, template GncOption::GncOption(const char*, const char*, const char*, const char*, const QofQuery*, GncOptionUIType); +template GncOption::GncOption(const char *, const char*, const char*, + const char *, GncOptionDateFormat, + GncOptionUIType); + template bool GncOption::get_value() const; template int GncOption::get_value() const; template int64_t GncOption::get_value() const; @@ -501,6 +507,7 @@ template RelativeDatePeriod GncOption::get_value() const; template GncOptionAccountList GncOption::get_value() const; template GncMultichoiceOptionIndexVec GncOption::get_value() const; template GncOptionReportPlacementVec GncOption::get_value() const; +template GncOptionDateFormat GncOption::get_value() const; template bool GncOption::get_default_value() const; template int GncOption::get_default_value() const; @@ -515,6 +522,7 @@ template RelativeDatePeriod GncOption::get_default_value() c template GncOptionAccountList GncOption::get_default_value() const; template GncMultichoiceOptionIndexVec GncOption::get_default_value() const; template GncOptionReportPlacementVec GncOption::get_default_value() const; +template GncOptionDateFormat GncOption::get_default_value() const; template void GncOption::set_value(bool); template void GncOption::set_value(int); @@ -532,6 +540,7 @@ template void GncOption::set_value(uint16_t); template void GncOption::set_value(GncOptionAccountList); template void GncOption::set_value(GncMultichoiceOptionIndexVec); template void GncOption::set_value(GncOptionReportPlacementVec); +template void GncOption::set_value(GncOptionDateFormat); template void GncOption::set_default_value(bool); template void GncOption::set_default_value(int); @@ -547,6 +556,7 @@ template void GncOption::set_default_value(uint16_t); template void GncOption::set_default_value(GncOptionAccountList); template void GncOption::set_default_value(GncMultichoiceOptionIndexVec); template void GncOption::set_default_value(GncOptionReportPlacementVec); +template void GncOption::set_default_value(GncOptionDateFormat); template void GncOption::get_limits(double&, double&, double&) const noexcept; template void GncOption::get_limits(int&, int&, int&) const noexcept; @@ -563,6 +573,7 @@ template bool GncOption::validate(const QofQuery*) const; template bool GncOption::validate(RelativeDatePeriod) const; template bool GncOption::validate(GncMultichoiceOptionIndexVec) const; template bool GncOption::validate(GncOptionReportPlacementVec) const; +template bool GncOption::validate(GncOptionDateFormat) const; template GncOption* gnc_make_option(const char*, const char*, diff --git a/libgnucash/engine/gnc-option.hpp b/libgnucash/engine/gnc-option.hpp index 267c0aaee5..a15641a458 100644 --- a/libgnucash/engine/gnc-option.hpp +++ b/libgnucash/engine/gnc-option.hpp @@ -66,6 +66,7 @@ class GncOptionMultichoiceValue; template class GncOptionRangeValue; class GncOptionCommodityValue; class GncOptionDateValue; +using GncOptionDateFormat = std::tuple; using GncOptionReportPlacement = std::tuple; using GncOptionReportPlacementVec = std::vector; template @@ -113,7 +114,8 @@ using GncOptionVariant = std::variant, GncOptionRangeValue, GncOptionRangeValue, GncOptionCommodityValue, - GncOptionDateValue>; + GncOptionDateValue, + GncOptionValue>; using GncOptionVariantPtr = std::unique_ptr; diff --git a/libgnucash/engine/gnc-optiondb.cpp b/libgnucash/engine/gnc-optiondb.cpp index e30199b210..f423164db7 100644 --- a/libgnucash/engine/gnc-optiondb.cpp +++ b/libgnucash/engine/gnc-optiondb.cpp @@ -28,6 +28,7 @@ #include #include "gnc-option-uitype.hpp" #include "kvp-value.hpp" +#include "kvp-frame.hpp" #include "qofbookslots.h" #include "guid.hpp" #include "gnc-optiondb.h" @@ -436,6 +437,30 @@ kvp_value_from_qof_instance_option(const GncOption& option) return new KvpValue(guid); } +/* GncOptionDateFormat Constants and support functions. These are frozen for backwards compatibility. */ + +static const char* date_format_frame_key = "Fancy Date Format"; +static const char* date_format_custom_key ="custom"; +static const char* date_format_months_key = "month"; +static const char* date_format_years_key = "years"; +static const char *date_format_format_key = "fmt"; + +static inline KvpValue * +kvp_frame_from_date_format_option(const GncOption& option) +{ + auto [format, months, years, custom] = option.get_value(); + + if (format == QOF_DATE_FORMAT_UNSET) + return nullptr; + + auto frame{new KvpFrame}; + frame->set({date_format_format_key}, new KvpValue(g_strdup(gnc_date_dateformat_to_string(format)))); + frame->set({date_format_months_key}, new KvpValue(g_strdup(gnc_date_monthformat_to_string(months)))); + frame->set({date_format_years_key}, new KvpValue(static_cast(years))); + frame->set({date_format_custom_key}, new KvpValue(g_strdup(custom.c_str()))); + return new KvpValue(frame); +}; + void GncOptionDB::save_to_kvp(QofBook* book, bool clear_options) const noexcept { @@ -476,6 +501,8 @@ GncOptionDB::save_to_kvp(QofBook* book, bool clear_options) const noexcept kvp = new KvpValue(option.template get_value()); } } + else if (type == GncOptionUIType::DATE_FORMAT) + kvp = kvp_frame_from_date_format_option(option); else { auto str{option.template get_value()}; @@ -506,6 +533,33 @@ fill_option_from_guid_kvp(GncOption& option, KvpValue* kvp) (const QofInstance*)qof_instance_from_guid(guid, option.get_ui_type())); } +static inline void +fill_option_from_date_format_kvp(GncOption& option, KvpValue* kvp) +{ + GncOptionDateFormat default_fmt{QOF_DATE_FORMAT_UNSET, GNCDATE_MONTH_NUMBER, true, ""}; + auto frame{kvp->get()}; + if (!frame) + { + option.set_value(default_fmt); + return; + } + auto format_str{frame->get_slot({date_format_format_key})->get()}; + QofDateFormat format; + if (!format_str || gnc_date_string_to_dateformat(format_str, &format)) + { + option.set_value(default_fmt); + return; + } + GNCDateMonthFormat months = GNCDATE_MONTH_NUMBER; + auto months_str{frame->get_slot({date_format_months_key})->get()}; + if (months_str) + gnc_date_string_to_monthformat(months_str, &months); + auto years_num{frame->get_slot({date_format_years_key})->get()}; + bool years = static_cast(years_num); + auto custom_str{frame->get_slot({date_format_custom_key})->get()}; + option.set_value({format, months, years, custom_str ? custom_str : ""}); +} + void GncOptionDB::load_from_kvp(QofBook* book) noexcept { @@ -556,6 +610,10 @@ GncOptionDB::load_from_kvp(QofBook* book) noexcept case KvpValue::Type::GUID: fill_option_from_guid_kvp(option, kvp); break; + case KvpValue::Type::FRAME: + if (g_strcmp0(option.get_name().c_str(), date_format_frame_key) == 0) + fill_option_from_date_format_kvp(option, kvp); + break; default: return; break; @@ -909,9 +967,9 @@ gnc_register_counter_format_option(GncOptionDB* db, void gnc_register_dateformat_option(GncOptionDB* db, const char* section, const char* name, const char* key, - const char* doc_string, std::string value) + const char* doc_string, GncOptionDateFormat&& value) { - GncOption option{section, name, key, doc_string, value, + GncOption option{section, name, key, doc_string, std::move(value), GncOptionUIType::DATE_FORMAT}; db->register_option(section, std::move(option)); } @@ -1284,10 +1342,11 @@ gnc_option_db_book_options(GncOptionDB* odb) N_("Default Vendor TaxTable"), "f2", N_("The default tax table to apply to vendors."), nullptr); + gnc_register_dateformat_option(odb, business_section, N_("Fancy Date Format"), "g", N_("The default date format used for fancy printed dates."), - empty_string); + {QOF_DATE_FORMAT_UNSET, GNCDATE_MONTH_NUMBER, true, ""}); //Tax Tab diff --git a/libgnucash/engine/gnc-optiondb.hpp b/libgnucash/engine/gnc-optiondb.hpp index 7a9cd8ca61..9bdefed313 100644 --- a/libgnucash/engine/gnc-optiondb.hpp +++ b/libgnucash/engine/gnc-optiondb.hpp @@ -806,7 +806,7 @@ inline void gnc_register_counter_format_option(GncOptionDBPtr& db, void gnc_register_dateformat_option(GncOptionDB* db, const char* section, const char* name, const char* key, const char* doc_string, - std::string value); + GncOptionDateFormat&& value); /** * As above but takes a const GncOptionDBPtr& (const std::unique_ptr&) for calling from C++. @@ -815,10 +815,10 @@ inline void gnc_register_dateformat_option(GncOptionDBPtr& db, const char* section, const char* name, const char* key, const char* doc_string, - std::string value) + GncOptionDateFormat&& value) { gnc_register_dateformat_option(db.get(), section, name, key, - doc_string, value); + doc_string, std::move(value)); } enum RelativeDateUI : uint8_t