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 53 : GncOption(OptionType option) :
144 53 : 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 67952 : operator<(const GncOption& right, const GncOption& left)
223 : {
224 67952 : 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 0 : 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 0 : return new GncOption(section, name, key, doc_string, value, ui_type);
269 : }
270 :
271 : #endif //GNC_OPTION_HPP_
272 :
273 : /** @}
274 : @} */
|