1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28
29 #include "qdesigner_introspection_p.h"
30
31 #include <QtCore/qmetaobject.h>
32 #include <QtCore/qstringlist.h>
33 #include <QtCore/qvector.h>
34
35 QT_BEGIN_NAMESPACE
36
37 // Qt Implementation
byteArrayListToStringList(const QByteArrayList & l)38 static QStringList byteArrayListToStringList(const QByteArrayList &l)
39 {
40 if (l.isEmpty())
41 return QStringList();
42 QStringList rc;
43 for (const QByteArray &b : l)
44 rc += QString::fromUtf8(b);
45 return rc;
46 }
47
charToQString(const char * c)48 static inline QString charToQString(const char *c)
49 {
50 if (!c)
51 return QString();
52 return QString::fromUtf8(c);
53 }
54
55 namespace {
56 // ------- QDesignerMetaEnum
57 class QDesignerMetaEnum : public QDesignerMetaEnumInterface {
58 public:
59 QDesignerMetaEnum(const QMetaEnum &qEnum);
isFlag() const60 bool isFlag() const override { return m_enum.isFlag(); }
key(int index) const61 QString key(int index) const override { return charToQString(m_enum.key(index)); }
keyCount() const62 int keyCount() const override { return m_enum.keyCount(); }
keyToValue(const QString & key) const63 int keyToValue(const QString &key) const override { return m_enum.keyToValue(key.toUtf8()); }
keysToValue(const QString & keys) const64 int keysToValue(const QString &keys) const override { return m_enum.keysToValue(keys.toUtf8()); }
name() const65 QString name() const override { return m_name; }
scope() const66 QString scope() const override { return m_scope; }
67 QString separator() const override;
value(int index) const68 int value(int index) const override { return m_enum.value(index); }
valueToKey(int value) const69 QString valueToKey(int value) const override { return charToQString(m_enum.valueToKey(value)); }
valueToKeys(int value) const70 QString valueToKeys(int value) const override { return charToQString(m_enum.valueToKeys(value)); }
71
72 private:
73 const QMetaEnum m_enum;
74 const QString m_name;
75 const QString m_scope;
76 };
77
QDesignerMetaEnum(const QMetaEnum & qEnum)78 QDesignerMetaEnum::QDesignerMetaEnum(const QMetaEnum &qEnum) :
79 m_enum(qEnum),
80 m_name(charToQString(m_enum.name())),
81 m_scope(charToQString(m_enum.scope()))
82 {
83 }
84
separator() const85 QString QDesignerMetaEnum::separator() const
86 {
87 static const QString rc = QStringLiteral("::");
88 return rc;
89 }
90
91 // ------- QDesignerMetaProperty
92 class QDesignerMetaProperty : public QDesignerMetaPropertyInterface {
93 public:
94 QDesignerMetaProperty(const QMetaProperty &property);
95 ~QDesignerMetaProperty() override;
96
enumerator() const97 const QDesignerMetaEnumInterface *enumerator() const override { return m_enumerator; }
98
kind() const99 Kind kind() const override { return m_kind; }
100
accessFlags() const101 AccessFlags accessFlags() const override { return m_access; }
102 Attributes attributes(const QObject *object = nullptr) const override;
103
type() const104 QVariant::Type type() const override { return m_property.type(); }
name() const105 QString name() const override { return m_name; }
typeName() const106 QString typeName() const override { return m_typeName; }
userType() const107 int userType() const override { return m_property.userType(); }
hasSetter() const108 bool hasSetter() const override { return m_property.hasStdCppSet(); }
109
read(const QObject * object) const110 QVariant read(const QObject *object) const override { return m_property.read(object); }
reset(QObject * object) const111 bool reset(QObject *object) const override { return m_property.reset(object); }
write(QObject * object,const QVariant & value) const112 bool write(QObject *object, const QVariant &value) const override { return m_property.write(object, value); }
113
114 private:
115 const QMetaProperty m_property;
116 const QString m_name;
117 const QString m_typeName;
118 Kind m_kind;
119 AccessFlags m_access;
120 Attributes m_defaultAttributes;
121 QDesignerMetaEnumInterface *m_enumerator;
122 };
123
QDesignerMetaProperty(const QMetaProperty & property)124 QDesignerMetaProperty::QDesignerMetaProperty(const QMetaProperty &property) :
125 m_property(property),
126 m_name(charToQString(m_property.name())),
127 m_typeName(charToQString(m_property.typeName())),
128 m_kind(OtherKind),
129 m_enumerator(nullptr)
130 {
131 if (m_property.isFlagType() || m_property.isEnumType()) {
132 const QMetaEnum metaEnum = m_property.enumerator();
133 Q_ASSERT(metaEnum.isValid());
134 m_enumerator = new QDesignerMetaEnum(metaEnum);
135 }
136 // kind
137 if (m_property.isFlagType())
138 m_kind = FlagKind;
139 else
140 if (m_property.isEnumType())
141 m_kind = EnumKind;
142 // flags and attributes
143 if (m_property.isReadable())
144 m_access |= ReadAccess;
145 if (m_property.isWritable())
146 m_access |= WriteAccess;
147 if (m_property.isResettable())
148 m_access |= ResetAccess;
149
150 if (m_property.isDesignable())
151 m_defaultAttributes |= DesignableAttribute;
152 if (m_property.isScriptable())
153 m_defaultAttributes |= ScriptableAttribute;
154 if (m_property.isStored())
155 m_defaultAttributes |= StoredAttribute;
156 if (m_property.isUser())
157 m_defaultAttributes |= UserAttribute;
158 }
159
~QDesignerMetaProperty()160 QDesignerMetaProperty::~QDesignerMetaProperty()
161 {
162 delete m_enumerator;
163 }
164
attributes(const QObject * object) const165 QDesignerMetaProperty::Attributes QDesignerMetaProperty::attributes(const QObject *object) const
166 {
167 if (!object)
168 return m_defaultAttributes;
169 Attributes rc;
170 if (m_property.isDesignable(object))
171 rc |= DesignableAttribute;
172 if (m_property.isScriptable(object))
173 rc |= ScriptableAttribute;
174 if (m_property.isStored(object))
175 rc |= StoredAttribute;
176 if (m_property.isUser(object))
177 rc |= UserAttribute;
178 return rc;
179 }
180
181 // -------------- QDesignerMetaMethod
182
183 class QDesignerMetaMethod : public QDesignerMetaMethodInterface {
184 public:
185 QDesignerMetaMethod(const QMetaMethod &method);
186
access() const187 Access access() const override { return m_access; }
methodType() const188 MethodType methodType() const override { return m_methodType; }
parameterNames() const189 QStringList parameterNames() const override { return m_parameterNames; }
parameterTypes() const190 QStringList parameterTypes() const override { return m_parameterTypes; }
signature() const191 QString signature() const override { return m_signature; }
normalizedSignature() const192 QString normalizedSignature() const override { return m_normalizedSignature; }
tag() const193 QString tag() const override { return m_tag; }
typeName() const194 QString typeName() const override { return m_typeName; }
195
196 private:
197 Access m_access;
198 MethodType m_methodType;
199 const QStringList m_parameterNames;
200 const QStringList m_parameterTypes;
201 const QString m_signature;
202 const QString m_normalizedSignature;
203 const QString m_tag;
204 const QString m_typeName;
205 };
206
QDesignerMetaMethod(const QMetaMethod & method)207 QDesignerMetaMethod::QDesignerMetaMethod(const QMetaMethod &method) :
208 m_parameterNames(byteArrayListToStringList(method.parameterNames())),
209 m_parameterTypes(byteArrayListToStringList(method.parameterTypes())),
210 m_signature(QString::fromLatin1(method.methodSignature())),
211 m_normalizedSignature(QString::fromLatin1(QMetaObject::normalizedSignature(method.methodSignature().constData()))),
212 m_tag(charToQString(method.tag())),
213 m_typeName(charToQString(method.typeName()))
214 {
215 switch (method.access()) {
216 case QMetaMethod::Public:
217 m_access = Public;
218 break;
219 case QMetaMethod::Protected:
220 m_access = Protected;
221 break;
222 case QMetaMethod::Private:
223 m_access = Private;
224 break;
225
226 }
227 switch (method.methodType()) {
228 case QMetaMethod::Constructor:
229 m_methodType = Constructor;
230 break;
231 case QMetaMethod::Method:
232 m_methodType = Method;
233 break;
234 case QMetaMethod::Signal:
235 m_methodType = Signal;
236 break;
237
238 case QMetaMethod::Slot:
239 m_methodType = Slot;
240 break;
241 }
242 }
243
244 // ------------- QDesignerMetaObject
245 class QDesignerMetaObject : public QDesignerMetaObjectInterface {
246 public:
247 QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject);
248 ~QDesignerMetaObject() override;
249
className() const250 QString className() const override { return m_className; }
enumerator(int index) const251 const QDesignerMetaEnumInterface *enumerator(int index) const override
252 { return m_enumerators[index]; }
enumeratorCount() const253 int enumeratorCount() const override { return m_enumerators.size(); }
enumeratorOffset() const254 int enumeratorOffset() const override { return m_metaObject->enumeratorOffset(); }
255
indexOfEnumerator(const QString & name) const256 int indexOfEnumerator(const QString &name) const override
257 { return m_metaObject->indexOfEnumerator(name.toUtf8()); }
indexOfMethod(const QString & method) const258 int indexOfMethod(const QString &method) const override
259 { return m_metaObject->indexOfMethod(method.toUtf8()); }
indexOfProperty(const QString & name) const260 int indexOfProperty(const QString &name) const override
261 { return m_metaObject->indexOfProperty(name.toUtf8()); }
indexOfSignal(const QString & signal) const262 int indexOfSignal(const QString &signal) const override
263 { return m_metaObject->indexOfSignal(signal.toUtf8()); }
indexOfSlot(const QString & slot) const264 int indexOfSlot(const QString &slot) const override
265 { return m_metaObject->indexOfSlot(slot.toUtf8()); }
266
method(int index) const267 const QDesignerMetaMethodInterface *method(int index) const override
268 { return m_methods[index]; }
methodCount() const269 int methodCount() const override { return m_methods.size(); }
methodOffset() const270 int methodOffset() const override { return m_metaObject->methodOffset(); }
271
property(int index) const272 const QDesignerMetaPropertyInterface *property(int index) const override
273 { return m_properties[index]; }
propertyCount() const274 int propertyCount() const override { return m_properties.size(); }
propertyOffset() const275 int propertyOffset() const override { return m_metaObject->propertyOffset(); }
276
277 const QDesignerMetaObjectInterface *superClass() const override;
userProperty() const278 const QDesignerMetaPropertyInterface *userProperty() const override
279 { return m_userProperty; }
280
281 private:
282 const QString m_className;
283 const qdesigner_internal::QDesignerIntrospection *m_introspection;
284 const QMetaObject *m_metaObject;
285
286 using Enumerators = QVector<QDesignerMetaEnumInterface *>;
287 Enumerators m_enumerators;
288
289 using Methods = QVector<QDesignerMetaMethodInterface *>;
290 Methods m_methods;
291
292 using Properties = QVector<QDesignerMetaPropertyInterface *>;
293 Properties m_properties;
294
295 QDesignerMetaPropertyInterface *m_userProperty;
296 };
297
QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection * introspection,const QMetaObject * metaObject)298 QDesignerMetaObject::QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject) :
299 m_className(charToQString(metaObject->className())),
300 m_introspection(introspection),
301 m_metaObject(metaObject),
302 m_userProperty(nullptr)
303 {
304 const int numEnumerators = metaObject->enumeratorCount();
305 m_enumerators.reserve(numEnumerators);
306 for (int i = 0; i < numEnumerators; i++)
307 m_enumerators.push_back(new QDesignerMetaEnum(metaObject->enumerator(i)));
308 const int numMethods = metaObject->methodCount();
309 m_methods.reserve(numMethods);
310 for (int i = 0; i < numMethods; i++)
311 m_methods.push_back(new QDesignerMetaMethod(metaObject->method(i)));
312
313 const int numProperties = metaObject->propertyCount();
314 m_properties.reserve(numProperties);
315 for (int i = 0; i < numProperties; i++)
316 m_properties.push_back(new QDesignerMetaProperty(metaObject->property(i)));
317
318 const QMetaProperty userProperty = metaObject->userProperty();
319 if (userProperty.isValid())
320 m_userProperty = new QDesignerMetaProperty(userProperty);
321 }
322
~QDesignerMetaObject()323 QDesignerMetaObject::~QDesignerMetaObject()
324 {
325 qDeleteAll(m_enumerators);
326 qDeleteAll(m_methods);
327 qDeleteAll(m_properties);
328 delete m_userProperty;
329 }
330
superClass() const331 const QDesignerMetaObjectInterface *QDesignerMetaObject::superClass() const
332 {
333 const QMetaObject *qSuperClass = m_metaObject->superClass();
334 if (!qSuperClass)
335 return nullptr;
336 return m_introspection->metaObjectForQMetaObject(qSuperClass);
337 }
338
339 }
340
341 namespace qdesigner_internal {
342
343 QDesignerIntrospection::QDesignerIntrospection() = default;
344
~QDesignerIntrospection()345 QDesignerIntrospection::~QDesignerIntrospection()
346 {
347 qDeleteAll(m_metaObjectMap.values());
348 }
349
metaObject(const QObject * object) const350 const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObject(const QObject *object) const
351 {
352 return metaObjectForQMetaObject(object->metaObject());
353 }
354
metaObjectForQMetaObject(const QMetaObject * metaObject) const355 const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObjectForQMetaObject(const QMetaObject *metaObject) const
356 {
357 MetaObjectMap::iterator it = m_metaObjectMap.find(metaObject);
358 if (it == m_metaObjectMap.end())
359 it = m_metaObjectMap.insert(metaObject, new QDesignerMetaObject(this, metaObject));
360 return it.value();
361 }
362 }
363
364 QT_END_NAMESPACE
365