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
35QT_BEGIN_NAMESPACE
36
37// Qt Implementation
38static 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(str: b);
45 return rc;
46}
47
48static inline QString charToQString(const char *c)
49{
50 if (!c)
51 return QString();
52 return QString::fromUtf8(str: c);
53}
54
55namespace {
56 // ------- QDesignerMetaEnum
57 class QDesignerMetaEnum : public QDesignerMetaEnumInterface {
58 public:
59 QDesignerMetaEnum(const QMetaEnum &qEnum);
60 bool isFlag() const override { return m_enum.isFlag(); }
61 QString key(int index) const override { return charToQString(c: m_enum.key(index)); }
62 int keyCount() const override { return m_enum.keyCount(); }
63 int keyToValue(const QString &key) const override { return m_enum.keyToValue(key: key.toUtf8()); }
64 int keysToValue(const QString &keys) const override { return m_enum.keysToValue(keys: keys.toUtf8()); }
65 QString name() const override { return m_name; }
66 QString scope() const override { return m_scope; }
67 QString separator() const override;
68 int value(int index) const override { return m_enum.value(index); }
69 QString valueToKey(int value) const override { return charToQString(c: m_enum.valueToKey(value)); }
70 QString valueToKeys(int value) const override { return charToQString(c: m_enum.valueToKeys(value)); }
71
72 private:
73 const QMetaEnum m_enum;
74 const QString m_name;
75 const QString m_scope;
76 };
77
78 QDesignerMetaEnum::QDesignerMetaEnum(const QMetaEnum &qEnum) :
79 m_enum(qEnum),
80 m_name(charToQString(c: m_enum.name())),
81 m_scope(charToQString(c: m_enum.scope()))
82 {
83 }
84
85 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
97 const QDesignerMetaEnumInterface *enumerator() const override { return m_enumerator; }
98
99 Kind kind() const override { return m_kind; }
100
101 AccessFlags accessFlags() const override { return m_access; }
102 Attributes attributes(const QObject *object = nullptr) const override;
103
104 QVariant::Type type() const override { return m_property.type(); }
105 QString name() const override { return m_name; }
106 QString typeName() const override { return m_typeName; }
107 int userType() const override { return m_property.userType(); }
108 bool hasSetter() const override { return m_property.hasStdCppSet(); }
109
110 QVariant read(const QObject *object) const override { return m_property.read(obj: object); }
111 bool reset(QObject *object) const override { return m_property.reset(obj: object); }
112 bool write(QObject *object, const QVariant &value) const override { return m_property.write(obj: 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
124 QDesignerMetaProperty::QDesignerMetaProperty(const QMetaProperty &property) :
125 m_property(property),
126 m_name(charToQString(c: m_property.name())),
127 m_typeName(charToQString(c: 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
160 QDesignerMetaProperty::~QDesignerMetaProperty()
161 {
162 delete m_enumerator;
163 }
164
165 QDesignerMetaProperty::Attributes QDesignerMetaProperty::attributes(const QObject *object) const
166 {
167 if (!object)
168 return m_defaultAttributes;
169 Attributes rc;
170 if (m_property.isDesignable(obj: object))
171 rc |= DesignableAttribute;
172 if (m_property.isScriptable(obj: object))
173 rc |= ScriptableAttribute;
174 if (m_property.isStored(obj: object))
175 rc |= StoredAttribute;
176 if (m_property.isUser(obj: 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
187 Access access() const override { return m_access; }
188 MethodType methodType() const override { return m_methodType; }
189 QStringList parameterNames() const override { return m_parameterNames; }
190 QStringList parameterTypes() const override { return m_parameterTypes; }
191 QString signature() const override { return m_signature; }
192 QString normalizedSignature() const override { return m_normalizedSignature; }
193 QString tag() const override { return m_tag; }
194 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
207 QDesignerMetaMethod::QDesignerMetaMethod(const QMetaMethod &method) :
208 m_parameterNames(byteArrayListToStringList(l: method.parameterNames())),
209 m_parameterTypes(byteArrayListToStringList(l: method.parameterTypes())),
210 m_signature(QString::fromLatin1(str: method.methodSignature())),
211 m_normalizedSignature(QString::fromLatin1(str: QMetaObject::normalizedSignature(method: method.methodSignature().constData()))),
212 m_tag(charToQString(c: method.tag())),
213 m_typeName(charToQString(c: 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
250 QString className() const override { return m_className; }
251 const QDesignerMetaEnumInterface *enumerator(int index) const override
252 { return m_enumerators[index]; }
253 int enumeratorCount() const override { return m_enumerators.size(); }
254 int enumeratorOffset() const override { return m_metaObject->enumeratorOffset(); }
255
256 int indexOfEnumerator(const QString &name) const override
257 { return m_metaObject->indexOfEnumerator(name: name.toUtf8()); }
258 int indexOfMethod(const QString &method) const override
259 { return m_metaObject->indexOfMethod(method: method.toUtf8()); }
260 int indexOfProperty(const QString &name) const override
261 { return m_metaObject->indexOfProperty(name: name.toUtf8()); }
262 int indexOfSignal(const QString &signal) const override
263 { return m_metaObject->indexOfSignal(signal: signal.toUtf8()); }
264 int indexOfSlot(const QString &slot) const override
265 { return m_metaObject->indexOfSlot(slot: slot.toUtf8()); }
266
267 const QDesignerMetaMethodInterface *method(int index) const override
268 { return m_methods[index]; }
269 int methodCount() const override { return m_methods.size(); }
270 int methodOffset() const override { return m_metaObject->methodOffset(); }
271
272 const QDesignerMetaPropertyInterface *property(int index) const override
273 { return m_properties[index]; }
274 int propertyCount() const override { return m_properties.size(); }
275 int propertyOffset() const override { return m_metaObject->propertyOffset(); }
276
277 const QDesignerMetaObjectInterface *superClass() const override;
278 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
298 QDesignerMetaObject::QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject) :
299 m_className(charToQString(c: 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(asize: numEnumerators);
306 for (int i = 0; i < numEnumerators; i++)
307 m_enumerators.push_back(t: new QDesignerMetaEnum(metaObject->enumerator(index: i)));
308 const int numMethods = metaObject->methodCount();
309 m_methods.reserve(asize: numMethods);
310 for (int i = 0; i < numMethods; i++)
311 m_methods.push_back(t: new QDesignerMetaMethod(metaObject->method(index: i)));
312
313 const int numProperties = metaObject->propertyCount();
314 m_properties.reserve(asize: numProperties);
315 for (int i = 0; i < numProperties; i++)
316 m_properties.push_back(t: new QDesignerMetaProperty(metaObject->property(index: i)));
317
318 const QMetaProperty userProperty = metaObject->userProperty();
319 if (userProperty.isValid())
320 m_userProperty = new QDesignerMetaProperty(userProperty);
321 }
322
323 QDesignerMetaObject::~QDesignerMetaObject()
324 {
325 qDeleteAll(c: m_enumerators);
326 qDeleteAll(c: m_methods);
327 qDeleteAll(c: m_properties);
328 delete m_userProperty;
329 }
330
331 const QDesignerMetaObjectInterface *QDesignerMetaObject::superClass() const
332 {
333 const QMetaObject *qSuperClass = m_metaObject->superClass();
334 if (!qSuperClass)
335 return nullptr;
336 return m_introspection->metaObjectForQMetaObject(metaObject: qSuperClass);
337 }
338
339}
340
341namespace qdesigner_internal {
342
343 QDesignerIntrospection::QDesignerIntrospection() = default;
344
345 QDesignerIntrospection::~QDesignerIntrospection()
346 {
347 qDeleteAll(c: m_metaObjectMap.values());
348 }
349
350 const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObject(const QObject *object) const
351 {
352 return metaObjectForQMetaObject(metaObject: object->metaObject());
353 }
354
355 const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObjectForQMetaObject(const QMetaObject *metaObject) const
356 {
357 MetaObjectMap::iterator it = m_metaObjectMap.find(akey: metaObject);
358 if (it == m_metaObjectMap.end())
359 it = m_metaObjectMap.insert(akey: metaObject, avalue: new QDesignerMetaObject(this, metaObject));
360 return it.value();
361 }
362}
363
364QT_END_NAMESPACE
365

source code of qttools/src/designer/src/lib/shared/qdesigner_introspection.cpp