Branch data Line data Source code
1 : : /********************************************************************\
2 : : * gnc-option.hpp -- Application options system *
3 : : * Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
4 : : * *
5 : : * This program is free software; you can redistribute it and/or *
6 : : * modify it under the terms of the GNU General Public License as *
7 : : * published by the Free Software Foundation; either version 2 of *
8 : : * the License, or (at your option) any later version. *
9 : : * *
10 : : * This program is distributed in the hope that it will be useful, *
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 : : * GNU General Public License for more details. *
14 : : * *
15 : : * You should have received a copy of the GNU General Public License*
16 : : * along with this program; if not, contact: *
17 : : * *
18 : : * Free Software Foundation Voice: +1-617-542-5942 *
19 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
21 : : * *
22 : : \********************************************************************/
23 : : /** @addtogroup Engine
24 : : @{ */
25 : : /** @addtogroup Options
26 : : @{ */
27 : :
28 : : /** @file gnc-option.hpp
29 : : @brief C++ Public interface for individual options.
30 : : @author Copyright 2020-2021 John Ralls <jralls@ceridwen.us>
31 : : */
32 : :
33 : : #ifndef GNC_OPTION_HPP_
34 : : #define GNC_OPTION_HPP_
35 : :
36 : : #include <glib.h>
37 : : #include <any>
38 : : #include <string>
39 : : #include <iostream>
40 : : #include <iomanip>
41 : : #include <type_traits>
42 : : #include <variant>
43 : : #include <memory>
44 : : #include <tuple>
45 : : #include <cstdint>
46 : : #include "gnc-option-ui.hpp"
47 : : #include "gnc-option-date.hpp"
48 : : #include "guid.hpp"
49 : :
50 : : struct OptionClassifier;
51 : : class GncOptionUIItem;
52 : : using GncOptionUIItemPtr = std::unique_ptr<GncOptionUIItem>;
53 : : #ifndef SWIG //SWIG pulls in GncOwner from swig-engine.
54 : : struct _gncOwner;
55 : : using GncOwner = _gncOwner;
56 : : struct _QofQuery;
57 : : using QofQuery = _QofQuery;
58 : : #endif
59 : : struct QofInstance_s;
60 : : using QofInstance = QofInstance_s;
61 : : template <typename ValueType> class GncOptionValue;
62 : : class GncOptionGncOwnerValue;
63 : : class GncOptionQofInstanceValue;
64 : : class GncOptionAccountListValue;
65 : : class GncOptionAccountSelValue;
66 : : class GncOptionMultichoiceValue;
67 : : template <typename ValueType> class GncOptionRangeValue;
68 : : class GncOptionCommodityValue;
69 : : class GncOptionDateValue;
70 : : using GncOptionDateFormat = std::tuple<QofDateFormat, GNCDateMonthFormat, bool, std::string>;
71 : : using GncOptionReportPlacement = std::tuple<uint32_t, uint32_t, uint32_t>;
72 : : using GncOptionReportPlacementVec = std::vector<GncOptionReportPlacement>;
73 : : template <typename T>
74 : : struct is_OptionClassifier
75 : : {
76 : : static constexpr bool value =
77 : : std::is_base_of_v<OptionClassifier, std::decay_t<T>>;
78 : : };
79 : :
80 : : template <typename T> inline constexpr bool
81 : : is_OptionClassifier_v = is_OptionClassifier<T>::value;
82 : :
83 : : template <typename T, typename U>
84 : : struct is_same_decayed
85 : : {
86 : : static constexpr bool value = std::is_same_v<std::decay_t<T>,
87 : : std::decay_t<U>>;
88 : : };
89 : :
90 : : template <typename T, typename U> inline constexpr bool
91 : : is_same_decayed_v = is_same_decayed<T, U>::value;
92 : :
93 : : template <typename T>
94 : : struct is_RangeValue
95 : : {
96 : : static constexpr bool value =
97 : : (is_same_decayed_v<T, GncOptionRangeValue<int>> ||
98 : : is_same_decayed_v<T, GncOptionRangeValue<double>>);
99 : : };
100 : :
101 : : template <typename T> inline constexpr bool
102 : : is_RangeValue_v = is_RangeValue<T>::value;
103 : :
104 : :
105 : : using GncOptionVariant = std::variant<GncOptionValue<std::string>,
106 : : GncOptionValue<bool>,
107 : : GncOptionValue<int64_t>,
108 : : GncOptionQofInstanceValue,
109 : : GncOptionGncOwnerValue,
110 : : GncOptionValue<const QofQuery*>,
111 : : GncOptionValue<GncOptionReportPlacementVec>,
112 : : GncOptionAccountListValue,
113 : : GncOptionAccountSelValue,
114 : : GncOptionMultichoiceValue,
115 : : GncOptionRangeValue<int>,
116 : : GncOptionRangeValue<double>,
117 : : GncOptionCommodityValue,
118 : : GncOptionDateValue,
119 : : GncOptionValue<GncOptionDateFormat>>;
120 : :
121 : : using GncOptionVariantPtr = std::unique_ptr<GncOptionVariant>;
122 : :
123 : : enum class GncOptionMultichoiceKeyType
124 : : {
125 : : SYMBOL,
126 : : STRING,
127 : : NUMBER,
128 : : };
129 : :
130 : : /** @class GncOption
131 : : * @brief Represents the public interface for an option.
132 : : * Polymorphism is provided by a std::variant member containing GncOptionValue
133 : : * types.
134 : : */
135 : :
136 : : class GncOption
137 : : {
138 : : public:
139 : : template <typename OptionType,
140 : : typename std::enable_if_t<is_OptionClassifier_v<OptionType>,
141 : : int> = 0>
142 : :
143 : 34946 : GncOption(OptionType option) :
144 : 34946 : m_option{std::make_unique<GncOptionVariant>(option)} {}
145 : : template <typename ValueType,
146 : : typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
147 : : int> = 0>
148 : : GncOption(const char* section, const char* name,
149 : : const char* key, const char* doc_string,
150 : : ValueType value,
151 : : GncOptionUIType ui_type = GncOptionUIType::INTERNAL);
152 : : template <typename ValueType> void set_value(ValueType value);
153 : : template <typename ValueType> void set_default_value(ValueType value);
154 : : template <typename ValueType> ValueType get_default_value() const;
155 : : template <typename ValueType> ValueType get_value() const;
156 : : void reset_default_value();
157 : :
158 : : const std::string& get_section() const;
159 : : const std::string& get_name() const;
160 : : const std::string& get_key() const;
161 : : const std::string& get_docstring() const;
162 : : void set_ui_item(GncOptionUIItemPtr&& ui_elem);
163 : : const GncOptionUIType get_ui_type() const;
164 : : void set_ui_item_selectable(bool) const noexcept;
165 : : GncOptionUIItem* const get_ui_item() const;
166 : : void set_ui_item_from_option();
167 : : void set_option_from_ui_item();
168 : : void make_internal();
169 : : bool is_internal();
170 : : /** Mark the option as needing to be saved. */
171 : : void mark_saved() noexcept;
172 : : /** @returns true if the option has been marked as needing to be saved. */
173 : : bool is_dirty() const noexcept;
174 : : /** @returns true if the option value differs from its default value. */
175 : : bool is_changed() const noexcept;
176 : : /** @returns false unless m_option contains a GncOptionMultiselectValue or
177 : : * GncOptionAccountListValue for which multiple selections have been enabled.
178 : : */
179 : : bool is_multiselect() const noexcept;
180 : : /** Implemented only for GncOptionNumericRange */
181 : : template <typename ValueType> void get_limits(ValueType&, ValueType&,
182 : : ValueType&) const noexcept;
183 : : /** Not implemented for GncOptionValue. */
184 : : template <typename ValueType> bool validate(ValueType value) const;
185 : : /** Implemented only for GncOptionMultiselectValue. */
186 : : uint16_t num_permissible_values() const;
187 : : /** Implemented only for GncOptionMultiselectValue. */
188 : : uint16_t permissible_value_index(const char* value) const;
189 : : /** Implemented only for GncOptionMultiselectValue. */
190 : : const char* permissible_value(uint16_t index) const;
191 : : /** Implemented only for GncOptionMultiselectValue. */
192 : : const char* permissible_value_name(uint16_t index) const;
193 : : /** Implemented only for GncOptionAccountListValue. */
194 : : GList* account_type_list() const noexcept;
195 : : bool is_alternate() const noexcept;
196 : : void set_alternate(bool) noexcept;
197 : : /** Get a string suitable for storage representing the option's value.
198 : : * @return a std::string
199 : : */
200 : : std::string serialize() const;
201 : : /** Set the option's value from a character sequence.
202 : : * @param str: The character sequence representing the value
203 : : * @return true if the value was set, false otherwise.
204 : : */
205 : : bool deserialize(const std::string& str);
206 : : /** Set the option's value from an input stream
207 : : * @param iss: An input stream reference.
208 : : * @return the stream reference for chaining.
209 : : */
210 : : std::istream& in_stream(std::istream& iss);
211 : : friend GncOptionVariant& swig_get_option(GncOption*);
212 : : void set_widget_changed (std::any cb) { m_widget_changed = cb; }
213 : 0 : std::any& get_widget_changed () { return m_widget_changed; }
214 : : private:
215 : : inline static const std::string c_empty_string{""};
216 : : GncOptionVariantPtr m_option;
217 : : GncOptionUIItemPtr m_ui_item{nullptr};
218 : : std::any m_widget_changed{};
219 : : };
220 : :
221 : : inline bool
222 : 1299842 : operator<(const GncOption& right, const GncOption& left)
223 : : {
224 : 1299842 : return right.get_key() < left.get_key();
225 : : }
226 : :
227 : : inline std::ostream&
228 : 0 : operator<<(std::ostream& oss, const GncOption& opt)
229 : : {
230 : 0 : oss << opt.serialize();
231 : 0 : return oss;
232 : : }
233 : :
234 : : inline std::istream&
235 : 0 : operator>>(std::istream& iss, GncOption& opt)
236 : : {
237 : 0 : return opt.in_stream(iss);
238 : : }
239 : :
240 : : inline std::ostream&
241 : : output_color_value(std::ostream& oss, const std::string& value)
242 : : {
243 : : oss << "'(";
244 : : oss << std::fixed << std::showpoint << std::setprecision(1);
245 : : auto len{value.length() > 8 ? 8 : value.length()};
246 : : for (size_t i{}; i < len; i += 2)
247 : : {
248 : : oss << static_cast<float>(stoi(value.substr(i, 2), nullptr, 16));
249 : : if (i < 6)
250 : : oss << " ";
251 : : }
252 : : if (len < 8)
253 : : oss << 256.0;
254 : : oss << ")";
255 : : return oss;
256 : : }
257 : :
258 : : /**
259 : : * Free function wrapping GncOption's constructor. The type of GncOptionValue to
260 : : * create is determined from the UI type. Some GncOptionValue types require more
261 : : * parameters for their constructors and can't be created with this function.
262 : : */
263 : : template<typename ValueType> GncOption*
264 : 2 : gnc_make_option(const char* section, const char* name,
265 : : const char* key, const char* doc_string,
266 : : ValueType value, GncOptionUIType ui_type)
267 : : {
268 : 2 : return new GncOption(section, name, key, doc_string, value, ui_type);
269 : : }
270 : :
271 : : #endif //GNC_OPTION_HPP_
272 : :
273 : : /** @}
274 : : @} */
|