/********************************************************************\ * gnc-option.hpp -- Application options system * * Copyright (C) 2020 John Ralls * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License* * along with this program; if not, contact: * * * * Free Software Foundation Voice: +1-617-542-5942 * * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * * Boston, MA 02110-1301, USA gnu@gnu.org * * * \********************************************************************/ /** @addtogroup Engine @{ */ /** @addtogroup Options @{ */ /** @file gnc-option.hpp @brief C++ Public interface for individual options. @author Copyright 2020-2021 John Ralls */ #ifndef GNC_OPTION_HPP_ #define GNC_OPTION_HPP_ #include #include #include #include #include #include #include #include #include #include "gnc-option-ui.hpp" #include "gnc-option-date.hpp" #include "guid.hpp" struct OptionClassifier; class GncOptionUIItem; using GncOptionUIItemPtr = std::unique_ptr; #ifndef SWIG //SWIG pulls in GncOwner from swig-engine. struct _gncOwner; using GncOwner = _gncOwner; struct _QofQuery; using QofQuery = _QofQuery; #endif struct QofInstance_s; using QofInstance = QofInstance_s; template class GncOptionValue; class GncOptionGncOwnerValue; class GncOptionQofInstanceValue; class GncOptionAccountListValue; class GncOptionAccountSelValue; class GncOptionMultichoiceValue; template class GncOptionRangeValue; class GncOptionCommodityValue; class GncOptionDateValue; using GncOptionDateFormat = std::tuple; using GncOptionReportPlacement = std::tuple; using GncOptionReportPlacementVec = std::vector; template struct is_OptionClassifier { static constexpr bool value = std::is_base_of_v>; }; template inline constexpr bool is_OptionClassifier_v = is_OptionClassifier::value; template struct is_same_decayed { static constexpr bool value = std::is_same_v, std::decay_t>; }; template inline constexpr bool is_same_decayed_v = is_same_decayed::value; template struct is_RangeValue { static constexpr bool value = (is_same_decayed_v> || is_same_decayed_v>); }; template inline constexpr bool is_RangeValue_v = is_RangeValue::value; using GncOptionVariant = std::variant, GncOptionValue, GncOptionValue, GncOptionQofInstanceValue, GncOptionGncOwnerValue, GncOptionValue, GncOptionValue, GncOptionAccountListValue, GncOptionAccountSelValue, GncOptionMultichoiceValue, GncOptionRangeValue, GncOptionRangeValue, GncOptionCommodityValue, GncOptionDateValue, GncOptionValue>; using GncOptionVariantPtr = std::unique_ptr; enum class GncOptionMultichoiceKeyType { SYMBOL, STRING, NUMBER, }; /** @class GncOption * @brief Represents the public interface for an option. * Polymorphism is provided by a std::variant member containing GncOptionValue * types. */ class GncOption { public: template , int> = 0> GncOption(OptionType option) : m_option{std::make_unique(option)} {} template , int> = 0> GncOption(const char* section, const char* name, const char* key, const char* doc_string, ValueType value, GncOptionUIType ui_type = GncOptionUIType::INTERNAL); template void set_value(ValueType value); template void set_default_value(ValueType value); template ValueType get_default_value() const; template ValueType get_value() const; void reset_default_value(); const std::string& get_section() const; const std::string& get_name() const; const std::string& get_key() const; const std::string& get_docstring() const; void set_ui_item(GncOptionUIItemPtr&& ui_elem); const GncOptionUIType get_ui_type() const; void set_ui_item_selectable(bool) const noexcept; GncOptionUIItem* const get_ui_item() const; void set_ui_item_from_option(); void set_option_from_ui_item(); void make_internal(); bool is_internal(); /** Mark the option as needing to be saved. */ void mark_saved() noexcept; /** @returns true if the option has been marked as needing to be saved. */ bool is_dirty() const noexcept; /** @returns true if the option value differs from its default value. */ bool is_changed() const noexcept; /** @returns false unless m_option contains a GncOptionMultiselectValue or * GncOptionAccountListValue for which multiple selections have been enabled. */ bool is_multiselect() const noexcept; /** Implemented only for GncOptionNumericRange */ template void get_limits(ValueType&, ValueType&, ValueType&) const noexcept; /** Not implemented for GncOptionValue. */ template bool validate(ValueType value) const; /** Implemented only for GncOptionMultiselectValue. */ uint16_t num_permissible_values() const; /** Implemented only for GncOptionMultiselectValue. */ uint16_t permissible_value_index(const char* value) const; /** Implemented only for GncOptionMultiselectValue. */ const char* permissible_value(uint16_t index) const; /** Implemented only for GncOptionMultiselectValue. */ const char* permissible_value_name(uint16_t index) const; /** Implemented only for GncOptionAccountListValue. */ GList* account_type_list() const noexcept; bool is_alternate() const noexcept; void set_alternate(bool) noexcept; /** Get a string suitable for storage representing the option's value. * @return a std::string */ std::string serialize() const; /** Set the option's value from a character sequence. * @param str: The character sequence representing the value * @return true if the value was set, false otherwise. */ bool deserialize(const std::string& str); /** Set the option's value from an input stream * @param iss: An input stream reference. * @return the stream reference for chaining. */ std::istream& in_stream(std::istream& iss); friend GncOptionVariant& swig_get_option(GncOption*); void set_widget_changed (std::any cb) { m_widget_changed = cb; } std::any& get_widget_changed () { return m_widget_changed; } private: inline static const std::string c_empty_string{""}; GncOptionVariantPtr m_option; GncOptionUIItemPtr m_ui_item{nullptr}; std::any m_widget_changed{}; }; inline bool operator<(const GncOption& right, const GncOption& left) { return right.get_key() < left.get_key(); } inline std::ostream& operator<<(std::ostream& oss, const GncOption& opt) { oss << opt.serialize(); return oss; } inline std::istream& operator>>(std::istream& iss, GncOption& opt) { return opt.in_stream(iss); } inline std::ostream& output_color_value(std::ostream& oss, const std::string& value) { oss << "'("; oss << std::fixed << std::showpoint << std::setprecision(1); auto len{value.length() > 8 ? 8 : value.length()}; for (size_t i{}; i < len; i += 2) { oss << static_cast(stoi(value.substr(i, 2), nullptr, 16)); if (i < 6) oss << " "; } if (len < 8) oss << 256.0; oss << ")"; return oss; } /** * Free function wrapping GncOption's constructor. The type of GncOptionValue to * create is determined from the UI type. Some GncOptionValue types require more * parameters for their constructors and can't be created with this function. */ template GncOption* gnc_make_option(const char* section, const char* name, const char* key, const char* doc_string, ValueType value, GncOptionUIType ui_type) { return new GncOption(section, name, key, doc_string, value, ui_type); } #endif //GNC_OPTION_HPP_ /** @} @} */