Skip to content

Commit

Permalink
Change the type of OptionUIItem's m_ui_item from void* to GncOptionUI…
Browse files Browse the repository at this point in the history
…Item.

A locally-opaque class wrapping whatever sort of widget ptr one needs.
Thanks, warlord!
  • Loading branch information
jralls committed Jul 11, 2021
1 parent 3296212 commit c5fac51
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 25 deletions.
20 changes: 11 additions & 9 deletions libgnucash/app-utils/gnc-option.hpp
Expand Up @@ -125,6 +125,8 @@ struct OptionClassifier
using GncMultiChoiceOptionEntry = std::pair<std::string, std::string>;
using GncMultiChoiceOptionChoices = std::vector<GncMultiChoiceOptionEntry>;

class GncOptionUIItem;

/**
* 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
Expand All @@ -140,9 +142,9 @@ class OptionUIItem
{
public:
GncOptionUIType get_ui_type() { return m_ui_type; }
void* const get_ui_item() {return m_ui_item; }
GncOptionUIItem* const get_ui_item() {return m_ui_item; }
void clear_ui_item() { m_ui_item = nullptr; }
void set_ui_item(void* ui_item)
void set_ui_item(GncOptionUIItem* ui_item)
{
if (m_ui_type == GncOptionUIType::INTERNAL)
{
Expand All @@ -169,7 +171,7 @@ class OptionUIItem
OptionUIItem& operator=(const OptionUIItem&) = default;
OptionUIItem& operator=(OptionUIItem&&) = default;
private:
void* m_ui_item;
GncOptionUIItem* m_ui_item;
GncOptionUIType m_ui_type;
};

Expand Down Expand Up @@ -359,15 +361,15 @@ class GncOption
{
return boost::apply_visitor(GetDocstringVisitor(), m_option);
}
void set_ui_item(void* ui_elem)
void set_ui_item(GncOptionUIItem* ui_elem)
{
return boost::apply_visitor(SetUIItemVisitor(ui_elem), m_option);
}
const GncOptionUIType get_ui_type()
{
return boost::apply_visitor(GetUITypeVisitor(), m_option);
}
void* const get_ui_item()
GncOptionUIItem* const get_ui_item()
{
return boost::apply_visitor(GetUIItemVisitor(), m_option);
}
Expand Down Expand Up @@ -465,13 +467,13 @@ class GncOption
};
struct SetUIItemVisitor : public boost::static_visitor<>
{
SetUIItemVisitor(void* ui_item) : m_ui_item{ui_item} {}
SetUIItemVisitor(GncOptionUIItem* 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;
GncOptionUIItem* m_ui_item;
};
struct GetUITypeVisitor :
public boost::static_visitor<GncOptionUIType>
Expand All @@ -482,10 +484,10 @@ class GncOption
}
};
struct GetUIItemVisitor :
public boost::static_visitor<void* const >
public boost::static_visitor<GncOptionUIItem* const >
{
template <class OptionType>
void* const operator()(OptionType& option) const {
GncOptionUIItem* const operator()(OptionType& option) const {
return option.get_ui_item();
}
};
Expand Down
5 changes: 3 additions & 2 deletions libgnucash/app-utils/gnc-optiondb.cpp
Expand Up @@ -80,14 +80,15 @@ GncOptionDB::get_default_section() const noexcept
}

void
GncOptionDB::set_ui_item(const char* section, const char* name, void* ui_item)
GncOptionDB::set_ui_item(const char* section, const char* name,
GncOptionUIItem* ui_item)
{
auto option = find_option(section, name);
if (!option) return;
option->set_ui_item(ui_item);
}

void* const
GncOptionUIItem* const
GncOptionDB::get_ui_item(const char* section, const char* name)
{
auto option = find_option(section, name);
Expand Down
8 changes: 4 additions & 4 deletions libgnucash/app-utils/gnc-optiondb.hpp
Expand Up @@ -52,8 +52,8 @@ class GncOptionDB
void unregister_option(const char* section, const char* name);
void set_default_section(const char* section);
const GncOptionSection* const get_default_section() const noexcept;
void set_ui_item(const char* section, const char* name, void* ui_item);
void* const get_ui_item(const char* section, const char* name);
void set_ui_item(const char* section, const char* name, GncOptionUIItem* ui_item);
GncOptionUIItem* const get_ui_item(const char* section, const char* name);
GncOptionUIType get_ui_type(const char* section, const char* name);
void set_ui_from_option(const char* section, const char* name,
std::function<void(GncOption&)> func);
Expand All @@ -74,8 +74,8 @@ class GncOptionDB
std::vector<GncOptionSection> m_sections;
bool m_dirty = false;

std::function<void*()> m_get_ui_value;
std::function<void(void*)> m_set_ui_value;
std::function<GncOptionUIItem*()> m_get_ui_value;
std::function<void(GncOptionUIItem*)> m_set_ui_value;
};

using GncOptionDBPtr = std::unique_ptr<GncOptionDB>;
Expand Down
12 changes: 10 additions & 2 deletions libgnucash/app-utils/test/gtest-gnc-option.cpp
Expand Up @@ -202,6 +202,13 @@ class GncUIItem
std::string m_value;
};

class GncOptionUIItem
{
public:
GncOptionUIItem(GncUIItem* widget) : m_widget{widget} {}
GncUIItem* m_widget;
};

class GncOptionUITest : public ::testing::Test
{
protected:
Expand All @@ -222,6 +229,7 @@ TEST_F(GncOptionUI, test_option_ui_type)
TEST_F(GncOptionUI, test_set_option_ui_item)
{
GncUIItem ui_item;
m_option.set_ui_item(&ui_item);
EXPECT_EQ(&ui_item, static_cast<const GncUIItem*>(m_option.get_ui_item()));
GncOptionUIItem option_ui_item{&ui_item};
m_option.set_ui_item(&option_ui_item);
EXPECT_EQ(&ui_item, m_option.get_ui_item()->m_widget);
}
36 changes: 28 additions & 8 deletions libgnucash/app-utils/test/gtest-gnc-optiondb.cpp
Expand Up @@ -78,6 +78,23 @@ class GncUIType
std::string m_value;
};

class GncOptionUIItem
{
public:
GncOptionUIItem(GncUIType* widget) : m_widget{widget} {}
GncUIType* m_widget;
};

class GncOptionUITest : public ::testing::Test
{
protected:
GncOptionUITest() :
m_option{"foo", "bar", "baz", "Phony Option", std::string{"waldo"},
GncOptionUIType::STRING} {}

GncOption m_option;
};

class GncOptionDBUITest : public ::testing::Test
{
protected:
Expand All @@ -99,31 +116,34 @@ class GncOptionDBUITest : public ::testing::Test
TEST_F(GncOptionDBUITest, test_set_ui_item)
{
GncUIType entry;
m_db->set_ui_item("foo", "bar", &entry);
EXPECT_EQ(&entry, static_cast<GncUIType*>(m_db->get_ui_item("foo", "bar")));
GncOptionUIItem ui_item(&entry);
m_db->set_ui_item("foo", "bar", &ui_item);
EXPECT_EQ(&entry, m_db->get_ui_item("foo", "bar")->m_widget);
}

TEST_F(GncOptionDBUITest, test_ui_value_from_option)
{
GncUIType entry;
GncOptionUIItem ui_item(&entry);
const char* value{"waldo"};
m_db->set_ui_item("foo", "bar", &entry);
m_db->set_ui_item("foo", "bar", &ui_item);
m_db->set_ui_from_option("foo", "bar", [](GncOption& option){
auto ui_item = static_cast<GncUIType* const>(option.get_ui_item());
ui_item->set_value(option.get_value<std::string>());
auto new_ui_item = option.get_ui_item();
new_ui_item->m_widget->set_value(option.get_value<std::string>());
});
EXPECT_STREQ(value, entry.get_value().c_str());
}

TEST_F(GncOptionDBUITest, test_option_value_from_ui)
{
GncUIType entry;
GncOptionUIItem ui_item(&entry);
const char* value{"pepper"};
m_db->set_ui_item("foo", "bar", &entry);
m_db->set_ui_item("foo", "bar", &ui_item);
entry.set_value(value);
m_db->set_option_from_ui("foo", "bar", [](GncOption& option){
auto ui_item = static_cast<GncUIType* const>(option.get_ui_item());
option.set_value(ui_item->get_value());
auto new_ui_item = option.get_ui_item()->m_widget;
option.set_value(new_ui_item->get_value());
});
EXPECT_STREQ(value, m_db->lookup_string_option("foo", "bar").c_str());
}

0 comments on commit c5fac51

Please sign in to comment.