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 |
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(str: b); |
45 | return rc; |
46 | } |
47 | |
48 | static inline QString charToQString(const char *c) |
49 | { |
50 | if (!c) |
51 | return QString(); |
52 | return QString::fromUtf8(str: c); |
53 | } |
54 | |
55 | namespace { |
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 = 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 | |
341 | namespace 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 | |
364 | QT_END_NAMESPACE |
365 | |