2019-07-09 11:40:29 -05:00
|
|
|
/********************************************************************\
|
|
|
|
* gnc-option.hpp -- Application options system *
|
2020-01-27 15:40:39 -06:00
|
|
|
* Copyright (C) 2020 John Ralls <jralls@ceridwen.us> *
|
2019-07-09 11:40:29 -05:00
|
|
|
* *
|
|
|
|
* 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 *
|
|
|
|
* *
|
|
|
|
\********************************************************************/
|
2021-11-10 20:01:55 -06:00
|
|
|
/** @addtogroup Engine
|
|
|
|
@{ */
|
|
|
|
/** @addtogroup Options
|
|
|
|
@{ */
|
|
|
|
|
|
|
|
/** @file gnc-option.hpp
|
|
|
|
@brief C++ Public interface for individual options.
|
|
|
|
@author Copyright 2020-2021 John Ralls <jralls@ceridwen.us>
|
|
|
|
*/
|
2019-07-09 11:40:29 -05:00
|
|
|
|
|
|
|
#ifndef GNC_OPTION_HPP_
|
|
|
|
#define GNC_OPTION_HPP_
|
|
|
|
|
2020-02-18 16:27:41 -06:00
|
|
|
#include <glib.h>
|
2020-10-09 16:08:18 -05:00
|
|
|
#include <libguile.h>
|
2019-07-09 11:40:29 -05:00
|
|
|
#include <string>
|
2019-11-22 17:45:42 -06:00
|
|
|
#include <iostream>
|
2021-08-18 15:38:06 -05:00
|
|
|
#include <iomanip>
|
2020-01-27 15:40:39 -06:00
|
|
|
#include <variant>
|
|
|
|
#include <memory>
|
2020-12-22 18:24:15 -06:00
|
|
|
#include "gnc-option-ui.hpp"
|
2020-03-05 20:06:46 -06:00
|
|
|
#include "gnc-option-date.hpp"
|
2019-07-09 11:40:29 -05:00
|
|
|
|
2021-01-04 19:19:02 -06:00
|
|
|
struct OptionClassifier;
|
2019-10-03 15:30:49 -05:00
|
|
|
class GncOptionUIItem;
|
2020-02-11 15:35:27 -06:00
|
|
|
using GncOptionUIItemPtr = std::unique_ptr<GncOptionUIItem>;
|
2021-07-30 15:19:17 -05:00
|
|
|
#ifndef SWIG //SWIG pulls in GncOwner from swig-engine.
|
|
|
|
struct _gncOwner;
|
|
|
|
using GncOwner = _gncOwner;
|
|
|
|
#endif
|
2021-03-11 20:03:36 -06:00
|
|
|
struct _QofQuery;
|
|
|
|
using QofQuery = _QofQuery;
|
2020-01-27 15:40:39 -06:00
|
|
|
struct QofInstance_s;
|
|
|
|
using QofInstance = QofInstance_s;
|
|
|
|
template <typename ValueType> class GncOptionValue;
|
2021-12-30 14:21:56 -06:00
|
|
|
class GncOptionQofInstanceValue;
|
2021-07-31 19:43:48 -05:00
|
|
|
class GncOptionAccountListValue;
|
|
|
|
class GncOptionAccountSelValue;
|
2020-01-27 15:40:39 -06:00
|
|
|
class GncOptionMultichoiceValue;
|
|
|
|
template <typename ValueType> class GncOptionRangeValue;
|
2022-01-03 16:47:18 -06:00
|
|
|
class GncOptionCommodityValue;
|
2020-01-27 15:40:39 -06:00
|
|
|
class GncOptionDateValue;
|
2019-10-03 15:30:49 -05:00
|
|
|
|
2021-08-25 14:16:15 -05:00
|
|
|
template <typename T>
|
|
|
|
struct is_OptionClassifier
|
|
|
|
{
|
|
|
|
static constexpr bool value =
|
|
|
|
std::is_base_of_v<OptionClassifier, std::decay_t<T>>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T> inline constexpr bool
|
|
|
|
is_OptionClassifier_v = is_OptionClassifier<T>::value;
|
|
|
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
struct is_same_decayed
|
|
|
|
{
|
|
|
|
static constexpr bool value = std::is_same_v<std::decay_t<T>,
|
|
|
|
std::decay_t<U>>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename U> inline constexpr bool
|
|
|
|
is_same_decayed_v = is_same_decayed<T, U>::value;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct is_RangeValue
|
|
|
|
{
|
|
|
|
static constexpr bool value =
|
|
|
|
(is_same_decayed_v<T, GncOptionRangeValue<int>> ||
|
|
|
|
is_same_decayed_v<T, GncOptionRangeValue<double>>);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T> inline constexpr bool
|
|
|
|
is_RangeValue_v = is_RangeValue<T>::value;
|
|
|
|
|
|
|
|
|
2020-01-27 15:40:39 -06:00
|
|
|
using GncOptionVariant = std::variant<GncOptionValue<std::string>,
|
|
|
|
GncOptionValue<bool>,
|
|
|
|
GncOptionValue<int64_t>,
|
2021-12-30 14:21:56 -06:00
|
|
|
GncOptionQofInstanceValue,
|
2021-03-11 20:03:36 -06:00
|
|
|
GncOptionValue<const QofQuery*>,
|
2021-07-30 15:19:17 -05:00
|
|
|
GncOptionValue<const GncOwner*>,
|
2020-10-09 16:08:18 -05:00
|
|
|
GncOptionValue<SCM>,
|
2021-07-31 19:43:48 -05:00
|
|
|
GncOptionAccountListValue,
|
|
|
|
GncOptionAccountSelValue,
|
2020-01-27 15:40:39 -06:00
|
|
|
GncOptionMultichoiceValue,
|
|
|
|
GncOptionRangeValue<int>,
|
|
|
|
GncOptionRangeValue<double>,
|
2022-01-03 16:47:18 -06:00
|
|
|
GncOptionCommodityValue,
|
2020-01-27 15:40:39 -06:00
|
|
|
GncOptionDateValue>;
|
2019-12-05 19:47:30 -06:00
|
|
|
|
2020-01-27 15:40:39 -06:00
|
|
|
using GncOptionVariantPtr = std::unique_ptr<GncOptionVariant>;
|
2019-07-09 11:40:29 -05:00
|
|
|
|
2021-02-18 19:10:16 -06:00
|
|
|
enum class GncOptionMultichoiceKeyType
|
|
|
|
{
|
|
|
|
SYMBOL,
|
|
|
|
STRING,
|
|
|
|
NUMBER,
|
|
|
|
};
|
|
|
|
|
2021-11-10 20:01:55 -06:00
|
|
|
/** @class GncOption
|
|
|
|
* @brief Represents the public interface for an option.
|
|
|
|
* Polymorphism is provided by a std::variant member containing GncOptionValue
|
|
|
|
* types.
|
|
|
|
*/
|
|
|
|
|
2020-01-27 15:40:39 -06:00
|
|
|
class GncOption
|
2019-07-09 11:40:29 -05:00
|
|
|
{
|
|
|
|
public:
|
2021-01-04 19:19:02 -06:00
|
|
|
template <typename OptionType,
|
2021-08-25 14:16:15 -05:00
|
|
|
typename std::enable_if_t<is_OptionClassifier_v<OptionType>,
|
2021-01-04 19:19:02 -06:00
|
|
|
int> = 0>
|
2021-08-25 14:16:15 -05:00
|
|
|
|
2020-01-27 15:40:39 -06:00
|
|
|
GncOption(OptionType option) :
|
|
|
|
m_option{std::make_unique<GncOptionVariant>(option)} {}
|
2021-01-04 19:19:02 -06:00
|
|
|
template <typename ValueType,
|
2021-08-25 14:16:15 -05:00
|
|
|
typename std::enable_if_t<!is_OptionClassifier_v<ValueType>,
|
2021-01-04 19:19:02 -06:00
|
|
|
int> = 0>
|
2020-01-27 15:40:39 -06:00
|
|
|
GncOption(const char* section, const char* name,
|
|
|
|
const char* key, const char* doc_string,
|
|
|
|
ValueType value,
|
|
|
|
GncOptionUIType ui_type = GncOptionUIType::INTERNAL);
|
|
|
|
template <typename ValueType> void set_value(ValueType value);
|
2021-03-05 17:56:34 -06:00
|
|
|
template <typename ValueType> void set_default_value(ValueType value);
|
2020-01-27 15:40:39 -06:00
|
|
|
template <typename ValueType> ValueType get_default_value() const;
|
|
|
|
template <typename ValueType> ValueType get_value() const;
|
2020-04-05 11:07:34 -05:00
|
|
|
void reset_default_value();
|
2020-01-27 15:40:39 -06:00
|
|
|
|
|
|
|
const std::string& get_section() const;
|
|
|
|
const std::string& get_name() const;
|
|
|
|
const std::string& get_key() const;
|
|
|
|
const std::string& get_docstring() const;
|
2020-02-11 15:35:27 -06:00
|
|
|
void set_ui_item(GncOptionUIItemPtr&& ui_elem);
|
2020-01-27 15:40:39 -06:00
|
|
|
const GncOptionUIType get_ui_type() const;
|
2021-02-18 19:13:09 -06:00
|
|
|
void set_ui_item_selectable(bool) const noexcept;
|
2020-03-24 13:06:57 -05:00
|
|
|
GncOptionUIItem* const get_ui_item() const;
|
2020-02-11 15:35:27 -06:00
|
|
|
void set_ui_item_from_option();
|
|
|
|
void set_option_from_ui_item();
|
2020-01-27 15:40:39 -06:00
|
|
|
void make_internal();
|
|
|
|
bool is_changed() const noexcept;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** @returns false unless m_option contains a GncOptionMultiselectValue or
|
|
|
|
* GncOptionAccountListValue for which multiple selections have been enabled.
|
|
|
|
*/
|
2020-03-10 16:48:06 -05:00
|
|
|
bool is_multiselect() const noexcept;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionNumericRange */
|
2020-03-15 15:39:34 -05:00
|
|
|
template <typename ValueType> void get_limits(ValueType&, ValueType&,
|
|
|
|
ValueType&) const noexcept;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Not implemented for GncOptionValue. */
|
2020-01-27 15:40:39 -06:00
|
|
|
template <typename ValueType> bool validate(ValueType value) const;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionMultiselectValue. */
|
2020-01-27 15:40:39 -06:00
|
|
|
std::size_t num_permissible_values() const;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionMultiselectValue. */
|
2020-03-05 19:55:15 -06:00
|
|
|
std::size_t permissible_value_index(const char* value) const;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionMultiselectValue. */
|
2020-03-05 19:55:15 -06:00
|
|
|
const char* permissible_value(std::size_t index) const;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionMultiselectValue. */
|
2020-03-05 19:55:15 -06:00
|
|
|
const char* permissible_value_name(std::size_t index) const;
|
2021-11-10 20:01:55 -06:00
|
|
|
/** Implemented only for GncOptionAccountListValue. */
|
2020-02-18 16:27:41 -06:00
|
|
|
GList* account_type_list() const noexcept;
|
2020-03-16 12:27:59 -05:00
|
|
|
bool is_alternate() const noexcept;
|
|
|
|
void set_alternate(bool) noexcept;
|
2021-12-02 17:04:49 -06:00
|
|
|
/** 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.
|
|
|
|
*/
|
2020-01-27 15:40:39 -06:00
|
|
|
std::istream& in_stream(std::istream& iss);
|
2020-02-20 14:09:21 -06:00
|
|
|
friend GncOptionVariant& swig_get_option(GncOption*);
|
|
|
|
|
2019-07-09 11:40:29 -05:00
|
|
|
private:
|
2020-01-27 15:40:39 -06:00
|
|
|
inline static const std::string c_empty_string{""};
|
|
|
|
GncOptionVariantPtr m_option;
|
2020-02-11 15:35:27 -06:00
|
|
|
GncOptionUIItemPtr m_ui_item{nullptr};
|
2019-07-09 11:40:29 -05:00
|
|
|
};
|
|
|
|
|
2021-08-18 16:37:20 -05:00
|
|
|
inline bool
|
|
|
|
operator<(const GncOption& right, const GncOption& left)
|
|
|
|
{
|
|
|
|
return right.get_key() < left.get_key();
|
|
|
|
}
|
|
|
|
|
2019-12-03 13:14:06 -06:00
|
|
|
inline std::ostream&
|
2020-01-27 15:40:39 -06:00
|
|
|
operator<<(std::ostream& oss, const GncOption& opt)
|
2019-12-03 13:14:06 -06:00
|
|
|
{
|
2021-12-02 17:04:49 -06:00
|
|
|
oss << opt.serialize();
|
|
|
|
return oss;
|
2019-12-03 13:14:06 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
inline std::istream&
|
2020-01-27 15:40:39 -06:00
|
|
|
operator>>(std::istream& iss, GncOption& opt)
|
2019-12-03 13:14:06 -06:00
|
|
|
{
|
2020-01-27 15:40:39 -06:00
|
|
|
return opt.in_stream(iss);
|
2019-11-22 17:45:42 -06:00
|
|
|
}
|
2019-10-29 18:34:44 -05:00
|
|
|
|
2021-08-18 15:38:06 -05:00
|
|
|
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<float>(stoi(value.substr(i, 2), nullptr, 16));
|
|
|
|
if (i < 6)
|
|
|
|
oss << " ";
|
|
|
|
}
|
|
|
|
if (len < 8)
|
|
|
|
oss << 256.0;
|
|
|
|
oss << ")";
|
|
|
|
return oss;
|
|
|
|
}
|
|
|
|
|
2021-11-10 20:01:55 -06:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-01-04 19:21:31 -06:00
|
|
|
template<typename ValueType> 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);
|
|
|
|
}
|
2019-11-22 17:45:42 -06:00
|
|
|
|
2021-11-10 20:01:55 -06:00
|
|
|
/**
|
|
|
|
* Free function wrapping GncOption's constructor using an SCM value.
|
|
|
|
* To work around SWIG_Guile's typedef of SCM to unsigned long
|
|
|
|
*/
|
2021-03-02 16:24:15 -06:00
|
|
|
GncOption* gnc_make_SCM_option(const char* section, const char* name,
|
|
|
|
const char* key, const char* doc_string,
|
|
|
|
SCM value, GncOptionUIType ui_type);
|
|
|
|
|
2019-07-09 11:40:29 -05:00
|
|
|
#endif //GNC_OPTION_HPP_
|
2021-11-10 20:01:55 -06:00
|
|
|
|
|
|
|
/** @}
|
|
|
|
@} */
|