1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qbs.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "propertydeclaration.h"
41
42 #include "deprecationinfo.h"
43 #include <api/languageinfo.h>
44
45 #include <logging/translator.h>
46
47 #include <tools/error.h>
48 #include <tools/qttools.h>
49 #include <tools/stringconstants.h>
50
51 #include <QtCore/qmetatype.h>
52 #include <QtCore/qshareddata.h>
53 #include <QtCore/qstringlist.h>
54 #include <QtCore/qvariant.h>
55
56 namespace qbs {
57 namespace Internal {
58
59 // returns QMetaType::UnknownType for types that do not need conversion
variantType(PropertyDeclaration::Type t)60 static QMetaType::Type variantType(PropertyDeclaration::Type t)
61 {
62 switch (t) {
63 case PropertyDeclaration::UnknownType:
64 break;
65 case PropertyDeclaration::Boolean:
66 return QMetaType::Bool;
67 case PropertyDeclaration::Integer:
68 return QMetaType::Int;
69 case PropertyDeclaration::Path:
70 return QMetaType::QString;
71 case PropertyDeclaration::PathList:
72 return QMetaType::QStringList;
73 case PropertyDeclaration::String:
74 return QMetaType::QString;
75 case PropertyDeclaration::StringList:
76 return QMetaType::QStringList;
77 case PropertyDeclaration::VariantList:
78 return QMetaType::QVariantList;
79 case PropertyDeclaration::Variant:
80 break;
81 }
82 return QMetaType::UnknownType;
83 }
84
85 class PropertyDeclarationData : public QSharedData
86 {
87 public:
PropertyDeclarationData()88 PropertyDeclarationData()
89 : type(PropertyDeclaration::UnknownType)
90 , flags(PropertyDeclaration::DefaultFlags)
91 {
92 }
93
94 QString name;
95 PropertyDeclaration::Type type;
96 PropertyDeclaration::Flags flags;
97 QStringList allowedValues;
98 QString description;
99 QString initialValueSource;
100 QStringList functionArgumentNames;
101 DeprecationInfo deprecationInfo;
102 };
103
104
PropertyDeclaration()105 PropertyDeclaration::PropertyDeclaration()
106 : d(new PropertyDeclarationData)
107 {
108 }
109
PropertyDeclaration(const QString & name,Type type,const QString & initialValue,Flags flags)110 PropertyDeclaration::PropertyDeclaration(const QString &name, Type type,
111 const QString &initialValue, Flags flags)
112 : d(new PropertyDeclarationData)
113 {
114 d->name = name;
115 d->type = type;
116 d->initialValueSource = initialValue;
117 d->flags = flags;
118 }
119
120 PropertyDeclaration::PropertyDeclaration(const PropertyDeclaration &other) = default;
121
122 PropertyDeclaration::~PropertyDeclaration() = default;
123
124 PropertyDeclaration &PropertyDeclaration::operator=(const PropertyDeclaration &other) = default;
125
isValid() const126 bool PropertyDeclaration::isValid() const
127 {
128 return d && d->type != UnknownType;
129 }
130
isScalar() const131 bool PropertyDeclaration::isScalar() const
132 {
133 // ### Should be determined by a PropertyOption in the future.
134 return d->type != PathList && d->type != StringList && d->type != VariantList;
135 }
136
boolString()137 static QString boolString() { return QStringLiteral("bool"); }
intString()138 static QString intString() { return QStringLiteral("int"); }
pathListString()139 static QString pathListString() { return QStringLiteral("pathList"); }
stringString()140 static QString stringString() { return QStringLiteral("string"); }
stringListString()141 static QString stringListString() { return QStringLiteral("stringList"); }
varString()142 static QString varString() { return QStringLiteral("var"); }
variantString()143 static QString variantString() { return QStringLiteral("variant"); }
varListString()144 static QString varListString() { return QStringLiteral("varList"); }
145
propertyTypeFromString(const QString & typeName)146 PropertyDeclaration::Type PropertyDeclaration::propertyTypeFromString(const QString &typeName)
147 {
148 if (typeName == boolString())
149 return PropertyDeclaration::Boolean;
150 if (typeName == intString())
151 return PropertyDeclaration::Integer;
152 if (typeName == StringConstants::pathType())
153 return PropertyDeclaration::Path;
154 if (typeName == pathListString())
155 return PropertyDeclaration::PathList;
156 if (typeName == stringString())
157 return PropertyDeclaration::String;
158 if (typeName == stringListString())
159 return PropertyDeclaration::StringList;
160 if (typeName == varString() || typeName == variantString())
161 return PropertyDeclaration::Variant;
162 if (typeName == varListString())
163 return PropertyDeclaration::VariantList;
164 return PropertyDeclaration::UnknownType;
165 }
166
typeString() const167 QString PropertyDeclaration::typeString() const
168 {
169 return typeString(type());
170 }
171
typeString(PropertyDeclaration::Type t)172 QString PropertyDeclaration::typeString(PropertyDeclaration::Type t)
173 {
174 switch (t) {
175 case Boolean: return boolString();
176 case Integer: return intString();
177 case Path: return StringConstants::pathType();
178 case PathList: return pathListString();
179 case String: return stringString();
180 case StringList: return stringListString();
181 case Variant: return variantString();
182 case VariantList: return varListString();
183 case UnknownType: return QStringLiteral("unknown");
184 }
185 Q_UNREACHABLE(); // For stupid compilers.
186 }
187
name() const188 const QString &PropertyDeclaration::name() const
189 {
190 return d->name;
191 }
192
setName(const QString & name)193 void PropertyDeclaration::setName(const QString &name)
194 {
195 d->name = name;
196 }
197
type() const198 PropertyDeclaration::Type PropertyDeclaration::type() const
199 {
200 return d->type;
201 }
202
setType(PropertyDeclaration::Type t)203 void PropertyDeclaration::setType(PropertyDeclaration::Type t)
204 {
205 d->type = t;
206 }
207
flags() const208 PropertyDeclaration::Flags PropertyDeclaration::flags() const
209 {
210 return d->flags;
211 }
212
setFlags(Flags f)213 void PropertyDeclaration::setFlags(Flags f)
214 {
215 d->flags = f;
216 }
217
allowedValues() const218 const QStringList &PropertyDeclaration::allowedValues() const
219 {
220 return d->allowedValues;
221 }
222
setAllowedValues(const QStringList & v)223 void PropertyDeclaration::setAllowedValues(const QStringList &v)
224 {
225 d->allowedValues = v;
226 }
227
description() const228 const QString &PropertyDeclaration::description() const
229 {
230 return d->description;
231 }
232
setDescription(const QString & str)233 void PropertyDeclaration::setDescription(const QString &str)
234 {
235 d->description = str;
236 }
237
initialValueSource() const238 const QString &PropertyDeclaration::initialValueSource() const
239 {
240 return d->initialValueSource;
241 }
242
setInitialValueSource(const QString & str)243 void PropertyDeclaration::setInitialValueSource(const QString &str)
244 {
245 d->initialValueSource = str;
246 }
247
functionArgumentNames() const248 const QStringList &PropertyDeclaration::functionArgumentNames() const
249 {
250 return d->functionArgumentNames;
251 }
252
setFunctionArgumentNames(const QStringList & lst)253 void PropertyDeclaration::setFunctionArgumentNames(const QStringList &lst)
254 {
255 d->functionArgumentNames = lst;
256 }
257
isDeprecated() const258 bool PropertyDeclaration::isDeprecated() const
259 {
260 return d->deprecationInfo.isValid();
261 }
262
isExpired() const263 bool PropertyDeclaration::isExpired() const
264 {
265 return isDeprecated() && deprecationInfo().removalVersion() <= LanguageInfo::qbsVersion();
266 }
267
deprecationInfo() const268 const DeprecationInfo &PropertyDeclaration::deprecationInfo() const
269 {
270 return d->deprecationInfo;
271 }
272
setDeprecationInfo(const DeprecationInfo & deprecationInfo)273 void PropertyDeclaration::setDeprecationInfo(const DeprecationInfo &deprecationInfo)
274 {
275 d->deprecationInfo = deprecationInfo;
276 }
277
278 // see also: EvaluatorScriptClass::convertToPropertyType()
convertToPropertyType(const QVariant & v,Type t,const QStringList & namePrefix,const QString & key)279 QVariant PropertyDeclaration::convertToPropertyType(const QVariant &v, Type t,
280 const QStringList &namePrefix, const QString &key)
281 {
282 if (v.isNull() || !v.isValid())
283 return v;
284 const auto vt = variantType(t);
285 if (vt == QMetaType::UnknownType)
286 return v;
287
288 // Handle the foo,bar,bla stringlist syntax.
289 if (t == PropertyDeclaration::StringList && v.userType() == QMetaType::QString)
290 return v.toString().split(QLatin1Char(','));
291
292 QVariant c = v;
293 if (!qVariantConvert(c, vt)) {
294 QStringList name = namePrefix;
295 name << key;
296 throw ErrorInfo(Tr::tr("Value '%1' of property '%2' has incompatible type.")
297 .arg(v.toString(), name.join(QLatin1Char('.'))));
298 }
299 return c;
300 }
301
302 } // namespace Internal
303 } // namespace qbs
304