1 // Copyright 2015-2016 the openage authors. See copying.md for legal info.
2
3 #include "gui_property_map.h"
4
5 #include <algorithm>
6 #include <typeinfo>
7 #include <cassert>
8
9 #include <QVariant>
10 #include <QRegExp>
11
12 #include <QCoreApplication>
13
14 #include "../link/gui_property_map_impl.h"
15
16 namespace qtsdl {
17
GuiPropertyMap()18 GuiPropertyMap::GuiPropertyMap()
19 :
20 impl{std::make_unique<GuiPropertyMapImpl>()} {
21
22 assert(QCoreApplication::instance());
23 }
24
~GuiPropertyMap()25 GuiPropertyMap::~GuiPropertyMap() {
26 }
27
28 namespace {
29 template<typename T>
getter(const QObject & map,const char * name)30 T getter(const QObject &map, const char *name) {
31 auto v = map.property(name);
32
33 if (!v.isValid())
34 return T();
35
36 using namespace std::string_literals;
37
38 if (!v.canConvert<T>())
39 throw std::runtime_error("Can't interpret a property '"s + name + "' of type '"s + v.typeName() + "' as '"s + typeid(T).name() + "'."s);
40
41 return v.value<T>();
42 }
43
44 template<typename T>
setter(QObject & map,const char * name,T v)45 void setter(QObject &map, const char *name, T v) {
46 map.setProperty(name, QVariant::fromValue(v));
47 }
48
49 template<>
setter(QObject & map,const char * name,const char * v)50 void setter<const char*>(QObject &map, const char *name, const char *v) {
51 map.setProperty(name, v);
52 }
53
strings_to_vector(const QStringList & strings)54 std::vector<std::string> strings_to_vector(const QStringList &strings) {
55 std::vector<std::string> result(strings.size());
56 std::transform(std::begin(strings), std::end(strings), std::begin(result), [] (const QString &s) {return s.toStdString();});
57
58 return result;
59 }
60
vector_to_strings(const std::vector<std::string> & v)61 QStringList vector_to_strings(const std::vector<std::string> &v) {
62 QStringList strings;
63 std::transform(std::begin(v), std::end(v), std::back_inserter(strings), [] (const std::string &s) {return QString::fromStdString(s);});
64
65 return strings;
66 }
67 }
68
69 template<>
getv(const char * name) const70 bool GuiPropertyMap::getv<bool>(const char *name) const {
71 return getter<bool>(*this->impl, name);
72 }
73
74 template<>
setv(const char * name,bool v)75 void GuiPropertyMap::setv<bool>(const char *name, bool v) {
76 setter(*this->impl, name, v);
77 }
78
79 template<>
getv(const char * name) const80 int GuiPropertyMap::getv<int>(const char *name) const {
81 return getter<int>(*this->impl, name);
82 }
83
84 template<>
setv(const char * name,int v)85 void GuiPropertyMap::setv<int>(const char *name, int v) {
86 setter(*this->impl, name, v);
87 }
88
89 template<>
getv(const char * name) const90 double GuiPropertyMap::getv<double>(const char *name) const {
91 return getter<double>(*this->impl, name);
92 }
93
94 template<>
setv(const char * name,double v)95 void GuiPropertyMap::setv<double>(const char *name, double v) {
96 setter(*this->impl, name, v);
97 }
98
99 template<>
getv(const char * name) const100 std::string GuiPropertyMap::getv<std::string>(const char *name) const {
101 return getter<QString>(*this->impl, name).toStdString();
102 }
103
104 template<>
setv(const char * name,const std::string & v)105 void GuiPropertyMap::setv<const std::string&>(const char *name, const std::string &v) {
106 setter(*this->impl, name, QString::fromStdString(v));
107 }
108
109 template<>
setv(const char * name,const char * v)110 void GuiPropertyMap::setv<const char*>(const char *name, const char *v) {
111 setter(*this->impl, name, v);
112 }
113
114 template<>
getv(const char * name) const115 std::vector<std::string> GuiPropertyMap::getv<std::vector<std::string>>(const char *name) const {
116 return strings_to_vector(getter<QStringList>(*this->impl, name));
117 }
118
119 template<>
setv(const char * name,const std::vector<std::string> & v)120 void GuiPropertyMap::setv<const std::vector<std::string>&>(const char *name, const std::vector<std::string> &v) {
121 setter(*this->impl, name, vector_to_strings(v));
122 }
123
124 template<>
getv(const char * name) const125 QString GuiPropertyMap::getv<QString>(const char *name) const {
126 return getter<QString>(*this->impl, name);
127 }
128
129 template<>
setv(const char * name,const QString & v)130 void GuiPropertyMap::setv<const QString&>(const char *name, const QString &v) {
131 setter(*this->impl, name, v);
132 }
133
134 template<>
getv(const char * name) const135 QStringList GuiPropertyMap::getv<QStringList>(const char *name) const {
136 return getter<QStringList>(*this->impl, name);
137 }
138
139 template<>
setv(const char * name,const QStringList & v)140 void GuiPropertyMap::setv<const QStringList&>(const char *name, const QStringList &v) {
141 setter(*this->impl, name, v);
142 }
143
setv(const char * name,const std::string & v)144 void GuiPropertyMap::setv(const char *name, const std::string &v) {
145 this->setv<const std::string&>(name, v);
146 }
147
setv(const std::string & name,const std::string & v)148 void GuiPropertyMap::setv(const std::string &name, const std::string &v) {
149 this->setv<const std::string&>(name.c_str(), v);
150 }
151
setv(const char * name,const std::vector<std::string> & v)152 void GuiPropertyMap::setv(const char *name, const std::vector<std::string> &v) {
153 this->setv<const std::vector<std::string>&>(name, v);
154 }
155
setv(const std::string & name,const std::vector<std::string> & v)156 void GuiPropertyMap::setv(const std::string &name, const std::vector<std::string> &v) {
157 this->setv<const std::vector<std::string>&>(name.c_str(), v);
158 }
159
get_csv(const char * name) const160 std::vector<std::string> GuiPropertyMap::get_csv(const char *name) const {
161 return strings_to_vector(getter<QString>(*this->impl, name).split(QRegExp("\\s*,\\s*")));
162 }
163
set_csv(const char * name,const std::vector<std::string> & v)164 void GuiPropertyMap::set_csv(const char *name, const std::vector<std::string> &v) {
165 setter(*this->impl, name, vector_to_strings(v).join(", "));
166 }
167
168 } // namespace qtsdl
169