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