Skip to content

Commit c7c0613

Browse files
committed
Add CheckboxDropdownOption.
1 parent 0215f32 commit c7c0613

File tree

11 files changed

+569
-16
lines changed

11 files changed

+569
-16
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* Checkbox Dropdown Database
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
* A database that goes with a checkbox dropdown menu.
6+
*
7+
* This database contains information about the enum such as the display names
8+
* and serialization slugs.
9+
*
10+
* This database is used to initialize an CheckboxDropdownCell/Option.
11+
*
12+
*/
13+
14+
#ifndef PokemonAutomation_Options_CheckboxDropdownDatabase_H
15+
#define PokemonAutomation_Options_CheckboxDropdownDatabase_H
16+
17+
#include <vector>
18+
#include <map>
19+
#include "Common/Cpp/Exceptions.h"
20+
21+
namespace PokemonAutomation{
22+
23+
24+
25+
template <typename FlagEnum>
26+
struct FlagEnumEntry{
27+
FlagEnum value;
28+
std::string slug;
29+
std::string display;
30+
};
31+
32+
33+
template <typename FlagEnum>
34+
class CheckboxDropdownDatabase{
35+
using FlagEnumEntry = FlagEnumEntry<FlagEnum>;
36+
37+
public:
38+
CheckboxDropdownDatabase() = default;
39+
CheckboxDropdownDatabase(std::initializer_list<FlagEnumEntry> list){
40+
for (auto iter = list.begin(); iter != list.end(); ++iter){
41+
add(iter->value, std::move(iter->slug), std::move(iter->display));
42+
}
43+
}
44+
45+
// Warning, these functions do not have strong exception safety!
46+
// If these throw, this class will be in a bad state.
47+
void add(FlagEnumEntry entry){
48+
FlagEnumEntry& e = m_list.emplace_back(std::move(entry));
49+
50+
auto ret = m_slug_to_enum.emplace(e.slug, &e);
51+
if (!ret.second){
52+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "Duplicate Enum Slug: " + e.value);
53+
}
54+
}
55+
void add(FlagEnum value, std::string slug, std::string display){
56+
add(FlagEnumEntry{value, std::move(slug), std::move(display)});
57+
}
58+
59+
60+
public:
61+
size_t size() const{
62+
return m_list.size();
63+
}
64+
const FlagEnumEntry& operator[](size_t index) const{
65+
return m_list[index];
66+
}
67+
const FlagEnum* find_slug(const std::string& slug) const{
68+
auto iter = m_slug_to_enum.find(slug);
69+
if (iter == m_slug_to_enum.end()){
70+
return nullptr;
71+
}
72+
return &iter->second->value;
73+
}
74+
75+
public:
76+
auto begin() const{
77+
return m_list.begin();
78+
}
79+
auto end() const{
80+
return m_list.end();
81+
}
82+
83+
84+
private:
85+
std::vector<FlagEnumEntry> m_list;
86+
std::map<std::string, const FlagEnumEntry*> m_slug_to_enum;
87+
};
88+
89+
90+
91+
92+
}
93+
#endif
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/* Checkbox Dropdown Option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
* Same as EnumDropdown, but allows multiple selections.
6+
*
7+
*/
8+
9+
#ifndef PokemonAutomation_Options_CheckboxDropdownOption_H
10+
#define PokemonAutomation_Options_CheckboxDropdownOption_H
11+
12+
#include "Common/Cpp/Concurrency/SpinLock.h"
13+
#include "ConfigOption.h"
14+
15+
namespace PokemonAutomation{
16+
17+
18+
template <typename FlagEnum>
19+
class CheckboxDropdownDatabase;
20+
21+
22+
class CheckboxDropdownBase : public ConfigOption{
23+
public:
24+
CheckboxDropdownBase(std::string label)
25+
: m_label(std::move(label))
26+
{}
27+
28+
const std::string& label() const{
29+
return m_label;
30+
}
31+
virtual size_t size() const = 0;
32+
virtual const std::string& name_at_index(size_t index) const = 0;
33+
34+
virtual bool operator[](size_t index) const = 0;
35+
virtual void set_index(size_t index) = 0;
36+
virtual void clear_index(size_t index) = 0;
37+
virtual void toggle_index(size_t index) = 0;
38+
39+
virtual ConfigWidget* make_QtWidget(QWidget& parent) override;
40+
41+
private:
42+
std::string m_label;
43+
};
44+
45+
46+
47+
template <typename FlagEnum>
48+
class CheckboxDropdownCell : public CheckboxDropdownBase{
49+
using CheckboxDropdownDatabase = CheckboxDropdownDatabase<FlagEnum>;
50+
51+
public:
52+
CheckboxDropdownCell(
53+
std::string label,
54+
const CheckboxDropdownDatabase& database,
55+
LockMode lock_while_running,
56+
FlagEnum default_value
57+
);
58+
CheckboxDropdownCell(
59+
std::string label,
60+
const CheckboxDropdownDatabase& database,
61+
LockMode lock_while_running,
62+
FlagEnum default_value, FlagEnum current_value
63+
);
64+
CheckboxDropdownCell(
65+
std::string label,
66+
CheckboxDropdownDatabase&& database,
67+
LockMode lock_while_running,
68+
FlagEnum default_value
69+
) = delete;
70+
CheckboxDropdownCell(
71+
std::string label,
72+
CheckboxDropdownDatabase&& database,
73+
LockMode lock_while_running,
74+
FlagEnum default_value, FlagEnum current_value
75+
) = delete;
76+
77+
FlagEnum default_value() const{
78+
return m_default;
79+
}
80+
FlagEnum current_value() const;
81+
82+
83+
public:
84+
bool is_set(FlagEnum value) const;
85+
void set_flag(FlagEnum value);
86+
void clear_flag(FlagEnum value);
87+
void toggle_flag(FlagEnum value);
88+
89+
90+
public:
91+
virtual size_t size() const override;
92+
virtual const std::string& name_at_index(size_t index) const override;
93+
94+
virtual bool operator[](size_t index) const override;
95+
virtual void set_index(size_t index) override;
96+
virtual void clear_index(size_t index) override;
97+
virtual void toggle_index(size_t index) override;
98+
99+
100+
public:
101+
virtual void load_json(const JsonValue& json) override;
102+
virtual JsonValue to_json() const override;
103+
104+
virtual void restore_defaults() override;
105+
106+
107+
private:
108+
const CheckboxDropdownDatabase& m_database;
109+
const FlagEnum m_default;
110+
111+
mutable SpinLock m_lock;
112+
FlagEnum m_current;
113+
};
114+
115+
116+
117+
118+
}
119+
#endif
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/* Checkbox Dropdown Option
2+
*
3+
* From: https://github.com/PokemonAutomation/
4+
*
5+
* Same as EnumDropdown, but allows multiple selections.
6+
*
7+
*/
8+
9+
#ifndef PokemonAutomation_Options_CheckboxDropdownOption_TPP
10+
#define PokemonAutomation_Options_CheckboxDropdownOption_TPP
11+
12+
#include "Common/Cpp/Json/JsonArray.h"
13+
#include "CheckboxDropdownDatabase.h"
14+
#include "CheckboxDropdownOption.h"
15+
16+
namespace PokemonAutomation{
17+
18+
19+
20+
template <typename FlagEnum>
21+
CheckboxDropdownCell<FlagEnum>::CheckboxDropdownCell(
22+
std::string label,
23+
const CheckboxDropdownDatabase& database,
24+
LockMode lock_while_running,
25+
FlagEnum default_value
26+
)
27+
: CheckboxDropdownBase(std::move(label))
28+
, m_database(database)
29+
, m_default(default_value)
30+
, m_current(default_value)
31+
{}
32+
template <typename FlagEnum>
33+
CheckboxDropdownCell<FlagEnum>::CheckboxDropdownCell(
34+
std::string label,
35+
const CheckboxDropdownDatabase& database,
36+
LockMode lock_while_running,
37+
FlagEnum default_value, FlagEnum current_value
38+
)
39+
: CheckboxDropdownBase(std::move(label))
40+
, m_database(database)
41+
, m_default(default_value)
42+
, m_current(current_value)
43+
{}
44+
45+
46+
template <typename FlagEnum>
47+
FlagEnum CheckboxDropdownCell<FlagEnum>::current_value() const{
48+
ReadSpinLock lg(m_lock);
49+
return m_current;
50+
}
51+
52+
template <typename FlagEnum>
53+
bool CheckboxDropdownCell<FlagEnum>::is_set(FlagEnum value) const{
54+
ReadSpinLock lg(m_lock);
55+
return !is_empty(value & m_current);
56+
}
57+
template <typename FlagEnum>
58+
void CheckboxDropdownCell<FlagEnum>::set_flag(FlagEnum value){
59+
{
60+
WriteSpinLock lg(m_lock);
61+
if (!is_empty(m_current & value)){
62+
return;
63+
}
64+
m_current |= value;
65+
}
66+
report_value_changed(this);
67+
}
68+
template <typename FlagEnum>
69+
void CheckboxDropdownCell<FlagEnum>::clear_flag(FlagEnum value){
70+
{
71+
WriteSpinLock lg(m_lock);
72+
if (is_empty(m_current & value)){
73+
return;
74+
}
75+
m_current |= value;
76+
m_current ^= value;
77+
}
78+
report_value_changed(this);
79+
}
80+
template <typename FlagEnum>
81+
void CheckboxDropdownCell<FlagEnum>::toggle_flag(FlagEnum value){
82+
{
83+
WriteSpinLock lg(m_lock);
84+
m_current ^= value;
85+
}
86+
report_value_changed(this);
87+
}
88+
89+
template <typename FlagEnum>
90+
size_t CheckboxDropdownCell<FlagEnum>::size() const{
91+
return m_database.size();
92+
}
93+
template <typename FlagEnum>
94+
const std::string& CheckboxDropdownCell<FlagEnum>::name_at_index(size_t index) const{
95+
return m_database[index].display;
96+
}
97+
template <typename FlagEnum>
98+
bool CheckboxDropdownCell<FlagEnum>::operator[](size_t index) const{
99+
return is_set(m_database[index].value);
100+
}
101+
template <typename FlagEnum>
102+
void CheckboxDropdownCell<FlagEnum>::set_index(size_t index){
103+
set_flag(m_database[index].value);
104+
}
105+
template <typename FlagEnum>
106+
void CheckboxDropdownCell<FlagEnum>::clear_index(size_t index){
107+
clear_flag(m_database[index].value);
108+
}
109+
template <typename FlagEnum>
110+
void CheckboxDropdownCell<FlagEnum>::toggle_index(size_t index){
111+
toggle_flag(m_database[index].value);
112+
}
113+
114+
115+
116+
117+
template <typename FlagEnum>
118+
void CheckboxDropdownCell<FlagEnum>::load_json(const JsonValue& json){
119+
m_current = empty_value((FlagEnum*)nullptr);
120+
const JsonArray& array = json.to_array_throw();
121+
for (const JsonValue& item : array){
122+
const std::string slug = item.to_string_throw();
123+
const FlagEnum* flag = m_database.find_slug(slug);
124+
if (flag){
125+
m_current |= *flag;
126+
}
127+
}
128+
}
129+
template <typename FlagEnum>
130+
JsonValue CheckboxDropdownCell<FlagEnum>::to_json() const{
131+
JsonArray ret;
132+
for (const FlagEnumEntry<FlagEnum>& value : m_database){
133+
if (is_set(value.value)){
134+
ret.push_back(value.slug);
135+
}
136+
}
137+
return ret;
138+
}
139+
140+
template <typename FlagEnum>
141+
void CheckboxDropdownCell<FlagEnum>::restore_defaults(){
142+
WriteSpinLock lg(m_lock);
143+
m_current = m_default;
144+
}
145+
146+
147+
148+
149+
150+
151+
}
152+
#endif

Common/Qt/CheckboxDropdown.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class CheckboxDropdownItem : public QObject, public QStandardItem{
2626
this->setCheckState(Qt::Unchecked);
2727
}
2828
}
29+
bool checked() const{
30+
return this->checkState() == Qt::Checked;
31+
}
2932

3033
signals:
3134
void checkStateChanged(Qt::CheckState state);
@@ -57,6 +60,15 @@ class CheckboxDropdown : public QComboBox{
5760
return item;
5861
}
5962

63+
64+
public:
65+
size_t size() const{
66+
return m_items.size();
67+
}
68+
CheckboxDropdownItem* operator[](size_t index) const{
69+
return m_items[index];
70+
}
71+
6072
virtual bool eventFilter(QObject* obj, QEvent* event) override{
6173
// cout << "eventFilter()" << endl;
6274
if (event->type() != QEvent::MouseButtonRelease){

0 commit comments

Comments
 (0)