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