mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Add OptionUIItem composition class to GncOption.
Provides a type and a raw pointer member with accessors. The type is one of enum GncOptionIUType and is either VOID (for internal options that don't get UI items) or one of the widget types specified in dialog-option.c or business-options-gnome.c.
This commit is contained in:
parent
083e5b93df
commit
41ef2c5d44
@ -33,6 +33,7 @@ extern "C"
|
|||||||
}
|
}
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <exception>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -81,6 +82,34 @@ protected:
|
|||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum GncOptionUIType
|
||||||
|
{
|
||||||
|
INTERNAL,
|
||||||
|
BOOLEAN,
|
||||||
|
STRING,
|
||||||
|
TEXT,
|
||||||
|
CURRENCY,
|
||||||
|
COMMODITY,
|
||||||
|
MULTICHOICE,
|
||||||
|
DATE,
|
||||||
|
ACCOUNT_LIST,
|
||||||
|
ACCOUNT_SEL,
|
||||||
|
LIST,
|
||||||
|
NUMBER_RANGE,
|
||||||
|
COLOR,
|
||||||
|
FONT,
|
||||||
|
BUDGET,
|
||||||
|
PIXMAP,
|
||||||
|
RADIOBUTTON,
|
||||||
|
DATE_FORMAT,
|
||||||
|
OWNER,
|
||||||
|
CUSTOMER,
|
||||||
|
VENDOR,
|
||||||
|
EMPLOYEE,
|
||||||
|
INVOICE,
|
||||||
|
TAX_TABLE
|
||||||
|
};
|
||||||
|
|
||||||
struct OptionClassifier
|
struct OptionClassifier
|
||||||
{
|
{
|
||||||
std::string m_section;
|
std::string m_section;
|
||||||
@ -90,18 +119,59 @@ struct OptionClassifier
|
|||||||
std::string m_doc_string;
|
std::string m_doc_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a pointer to the UI item which will control the option and an enum
|
||||||
|
* representing the type of the option for dispatch purposes; all of that
|
||||||
|
* happens in gnucash/gnome-utils/dialog-options and
|
||||||
|
* gnucash/gnome/business-option-gnome.
|
||||||
|
*
|
||||||
|
* This class takes no ownership responsibility, so calling code is responsible
|
||||||
|
* for ensuring that the UI_Item is alive. For convenience the public
|
||||||
|
* clear_ui_item function can be used as a weak_ptr's destruction callback to
|
||||||
|
* ensure that if the ui_item is destroyed elsewhere the ptr will be nulled and
|
||||||
|
* the type reset to OptionUIType::INTERNAL.
|
||||||
|
*/
|
||||||
|
class OptionUIItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GncOptionUIType get_ui_type() { return m_ui_type; }
|
||||||
|
const void* get_ui_item() {return m_ui_item; }
|
||||||
|
void set_ui_item(void* ui_item)
|
||||||
|
{
|
||||||
|
if (m_ui_type == GncOptionUIType::INTERNAL)
|
||||||
|
{
|
||||||
|
std::string error{"Can't set ui item with void ui type."};
|
||||||
|
throw std::logic_error(std::move(error));
|
||||||
|
}
|
||||||
|
m_ui_item = ui_item;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
OptionUIItem(GncOptionUIType ui_type) :
|
||||||
|
m_ui_item{nullptr}, m_ui_type{ui_type} {}
|
||||||
|
OptionUIItem(const OptionUIItem&) = default;
|
||||||
|
OptionUIItem(OptionUIItem&&) = default;
|
||||||
|
~OptionUIItem() = default;
|
||||||
|
OptionUIItem& operator=(const OptionUIItem&) = default;
|
||||||
|
OptionUIItem& operator=(OptionUIItem&&) = default;
|
||||||
|
private:
|
||||||
|
void* m_ui_item;
|
||||||
|
GncOptionUIType m_ui_type;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
SCM scm_from_value(ValueType);
|
SCM scm_from_value(ValueType);
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
class GncOptionValue :
|
class GncOptionValue :
|
||||||
public OptionClassifier
|
public OptionClassifier, public OptionUIItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GncOptionValue<ValueType>(const char* section, const char* name,
|
GncOptionValue<ValueType>(const char* section, const char* name,
|
||||||
const char* key, const char* doc_string,
|
const char* key, const char* doc_string,
|
||||||
ValueType value) :
|
ValueType value,
|
||||||
|
GncOptionUIType ui_type = GncOptionUIType::INTERNAL) :
|
||||||
OptionClassifier{section, name, key, doc_string},
|
OptionClassifier{section, name, key, doc_string},
|
||||||
|
OptionUIItem(ui_type),
|
||||||
m_value{value}, m_default_value{value} {}
|
m_value{value}, m_default_value{value} {}
|
||||||
ValueType get_value() const { return m_value; }
|
ValueType get_value() const { return m_value; }
|
||||||
ValueType get_default_value() const { return m_default_value; }
|
ValueType get_default_value() const { return m_default_value; }
|
||||||
@ -121,14 +191,17 @@ private:
|
|||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
class GncOptionValidatedValue :
|
class GncOptionValidatedValue :
|
||||||
public OptionClassifier
|
public OptionClassifier, public OptionUIItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GncOptionValidatedValue<ValueType>(const char* section, const char* name,
|
GncOptionValidatedValue<ValueType>(const char* section, const char* name,
|
||||||
const char* key, const char* doc_string,
|
const char* key, const char* doc_string,
|
||||||
ValueType value,
|
ValueType value,
|
||||||
std::function<bool(ValueType)>validator) :
|
std::function<bool(ValueType)>validator,
|
||||||
|
GncOptionUIType ui_type = GncOptionUIType::INTERNAL
|
||||||
|
) :
|
||||||
OptionClassifier{section, name, key, doc_string},
|
OptionClassifier{section, name, key, doc_string},
|
||||||
|
OptionUIItem(ui_type),
|
||||||
m_value{value}, m_default_value{value}, m_validator{validator}
|
m_value{value}, m_default_value{value}, m_validator{validator}
|
||||||
{
|
{
|
||||||
if (!this->validate(value))
|
if (!this->validate(value))
|
||||||
@ -184,10 +257,10 @@ public:
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
GncOption(const char* section, const char* name,
|
GncOption(const char* section, const char* name,
|
||||||
const char* key, const char* doc_string,
|
const char* key, const char* doc_string,
|
||||||
ValueType value) :
|
ValueType value,
|
||||||
|
GncOptionUIType ui_type = GncOptionUIType::INTERNAL) :
|
||||||
m_option{GncOptionValue<ValueType> {
|
m_option{GncOptionValue<ValueType> {
|
||||||
section, name, key, doc_string, value
|
section, name, key, doc_string, value, ui_type}} {}
|
||||||
}} {}
|
|
||||||
|
|
||||||
template <typename ValueType> ValueType get_value() const
|
template <typename ValueType> ValueType get_value() const
|
||||||
{
|
{
|
||||||
@ -225,6 +298,18 @@ public:
|
|||||||
{
|
{
|
||||||
return boost::apply_visitor(GetDocstringVisitor(), m_option);
|
return boost::apply_visitor(GetDocstringVisitor(), m_option);
|
||||||
}
|
}
|
||||||
|
void set_ui_item(void* ui_elem)
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(SetUIItemVisitor(ui_elem), m_option);
|
||||||
|
}
|
||||||
|
const GncOptionUIType get_ui_type()
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(GetUITypeVisitor(), m_option);
|
||||||
|
}
|
||||||
|
const void* get_ui_item()
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(GetUIItemVisitor(), m_option);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
struct GetValueVisitor : public boost::static_visitor<ValueType>
|
struct GetValueVisitor : public boost::static_visitor<ValueType>
|
||||||
@ -313,6 +398,33 @@ private:
|
|||||||
return option.m_doc_string;
|
return option.m_doc_string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
struct SetUIItemVisitor : public boost::static_visitor<>
|
||||||
|
{
|
||||||
|
SetUIItemVisitor(void* ui_item) : m_ui_item{ui_item} {}
|
||||||
|
template <class OptionType>
|
||||||
|
void operator()(OptionType& option) const {
|
||||||
|
option.set_ui_item(m_ui_item);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void* m_ui_item;
|
||||||
|
};
|
||||||
|
struct GetUITypeVisitor :
|
||||||
|
public boost::static_visitor<GncOptionUIType>
|
||||||
|
{
|
||||||
|
template <class OptionType>
|
||||||
|
const GncOptionUIType operator()(OptionType& option) const {
|
||||||
|
return option.get_ui_type();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct GetUIItemVisitor :
|
||||||
|
public boost::static_visitor<const void*>
|
||||||
|
{
|
||||||
|
template <class OptionType>
|
||||||
|
const void* operator()(OptionType& option) const {
|
||||||
|
return option.get_ui_item();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
GncOptionVariant m_option;
|
GncOptionVariant m_option;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,3 +192,36 @@ TEST(GNCOption, test_currency_setter)
|
|||||||
gnc_commodity_table_destroy(table);
|
gnc_commodity_table_destroy(table);
|
||||||
qof_book_destroy(book);
|
qof_book_destroy(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GncUIItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void set_value(const std::string& value) { m_value = value; }
|
||||||
|
const std::string& get_value() { return m_value; }
|
||||||
|
private:
|
||||||
|
std::string m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GncOptionUITest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
GncOptionUITest() :
|
||||||
|
m_option{"foo", "bar", "baz", "Phony Option", std::string{"waldo"},
|
||||||
|
GncOptionUIType::STRING} {}
|
||||||
|
|
||||||
|
GncOption m_option;
|
||||||
|
};
|
||||||
|
|
||||||
|
using GncOptionUI = GncOptionUITest;
|
||||||
|
|
||||||
|
TEST_F(GncOptionUI, test_option_ui_type)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(GncOptionUIType::STRING, m_option.get_ui_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(GncOptionUI, test_set_option_ui_element)
|
||||||
|
{
|
||||||
|
GncUIItem ui_item;
|
||||||
|
m_option.set_ui_item(&ui_item);
|
||||||
|
EXPECT_EQ(&ui_item, static_cast<const GncUIItem*>(m_option.get_ui_item()));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user