1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdesigner_introspection_p.h"
43 
44 #include <QtCore/QMetaObject>
45 #include <QtCore/QMetaEnum>
46 #include <QtCore/QStringList>
47 #include <QtCore/QVector>
48 
49 QT_BEGIN_NAMESPACE
50 
51 // Qt Implementation
byteArrayListToStringList(const QList<QByteArray> & l)52 static QStringList byteArrayListToStringList(const QList<QByteArray> &l)
53 {
54     if (l.empty())
55         return QStringList();
56     QStringList rc;
57     const QList<QByteArray>::const_iterator cend = l.constEnd();
58     for (QList<QByteArray>::const_iterator it = l.constBegin(); it != cend; ++it)
59         rc += QString::fromUtf8(*it);
60     return rc;
61 }
62 
charToQString(const char * c)63 static inline QString charToQString(const char *c)
64 {
65     if (!c)
66         return QString();
67     return QString::fromUtf8(c);
68 }
69 
70 namespace  {
71     // ------- QDesignerMetaEnum
72     class QDesignerMetaEnum : public QDesignerMetaEnumInterface {
73     public:
74         QDesignerMetaEnum(const QMetaEnum &qEnum);
isFlag() const75         virtual bool isFlag() const                        {  return m_enum.isFlag(); }
key(int index) const76         virtual QString key(int index) const               { return charToQString(m_enum.key(index)); }
keyCount() const77         virtual int keyCount() const                       { return m_enum.keyCount(); }
keyToValue(const QString & key) const78         virtual int keyToValue(const QString &key) const   { return m_enum.keyToValue(key.toUtf8()); }
keysToValue(const QString & keys) const79         virtual int keysToValue(const QString &keys) const { return m_enum.keysToValue(keys.toUtf8()); }
name() const80         virtual QString name() const                       { return m_name; }
scope() const81         virtual QString scope() const                      { return m_scope; }
82         virtual QString separator() const;
value(int index) const83         virtual int value(int index) const                 { return m_enum.value(index); }
valueToKey(int value) const84         virtual QString valueToKey(int value) const        { return charToQString(m_enum.valueToKey(value)); }
valueToKeys(int value) const85         virtual QString valueToKeys(int value) const       { return charToQString(m_enum.valueToKeys(value)); }
86 
87     private:
88         const QMetaEnum m_enum;
89         const QString m_name;
90         const QString m_scope;
91     };
92 
QDesignerMetaEnum(const QMetaEnum & qEnum)93     QDesignerMetaEnum::QDesignerMetaEnum(const QMetaEnum &qEnum) :
94         m_enum(qEnum),
95         m_name(charToQString(m_enum.name())),
96         m_scope(charToQString(m_enum.scope()))
97     {
98     }
99 
separator() const100     QString QDesignerMetaEnum::separator() const
101     {
102         static const QString rc = QLatin1String("::");
103         return rc;
104     }
105 
106     // ------- QDesignerMetaProperty
107     class QDesignerMetaProperty : public QDesignerMetaPropertyInterface {
108     public:
109         QDesignerMetaProperty(const QMetaProperty &property);
110         virtual ~QDesignerMetaProperty();
111 
enumerator() const112         virtual const QDesignerMetaEnumInterface *enumerator() const { return m_enumerator; }
113 
kind() const114         virtual Kind kind() const { return m_kind; }
115 
accessFlags() const116         virtual AccessFlags accessFlags() const { return m_access; }
117         virtual Attributes attributes(const QObject *object = 0) const;
118 
type() const119         virtual QVariant::Type type() const { return m_property.type(); }
name() const120         virtual QString name() const        { return m_name; }
typeName() const121         virtual QString typeName() const    { return m_typeName; }
userType() const122         virtual int userType() const        { return m_property.userType(); }
hasSetter() const123         virtual bool hasSetter() const              { return m_property.hasStdCppSet(); }
124 
read(const QObject * object) const125         virtual QVariant read(const QObject *object) const { return m_property.read(object); }
reset(QObject * object) const126         virtual bool reset(QObject *object) const          { return m_property.reset(object); }
write(QObject * object,const QVariant & value) const127         virtual bool write(QObject *object, const QVariant &value) const { return m_property.write(object, value); }
128 
129     private:
130         const QMetaProperty m_property;
131         const QString m_name;
132         const QString m_typeName;
133         Kind m_kind;
134         AccessFlags m_access;
135         Attributes m_defaultAttributes;
136         QDesignerMetaEnumInterface *m_enumerator;
137     };
138 
QDesignerMetaProperty(const QMetaProperty & property)139     QDesignerMetaProperty::QDesignerMetaProperty(const QMetaProperty &property) :
140         m_property(property),
141         m_name(charToQString(m_property.name())),
142         m_typeName(charToQString(m_property.typeName())),
143         m_kind(OtherKind),
144         m_enumerator(0)
145     {
146         if (m_property.isFlagType() || m_property.isEnumType()) {
147             const QMetaEnum metaEnum = m_property.enumerator();
148             Q_ASSERT(metaEnum.isValid());
149             m_enumerator = new QDesignerMetaEnum(metaEnum);
150         }
151         // kind
152         if (m_property.isFlagType())
153             m_kind = FlagKind;
154         else
155             if (m_property.isEnumType())
156                 m_kind = EnumKind;
157         // flags and attributes
158         if (m_property.isReadable())
159             m_access |= ReadAccess;
160         if (m_property.isWritable())
161             m_access |= WriteAccess;
162         if (m_property.isResettable())
163             m_access |= ResetAccess;
164 
165         if (m_property.isDesignable())
166             m_defaultAttributes |= DesignableAttribute;
167         if (m_property.isScriptable())
168             m_defaultAttributes |= ScriptableAttribute;
169         if (m_property.isStored())
170             m_defaultAttributes |= StoredAttribute;
171         if (m_property.isUser())
172             m_defaultAttributes |= UserAttribute;
173     }
174 
~QDesignerMetaProperty()175     QDesignerMetaProperty::~QDesignerMetaProperty()
176     {
177         delete m_enumerator;
178     }
179 
attributes(const QObject * object) const180     QDesignerMetaProperty::Attributes QDesignerMetaProperty::attributes(const QObject *object) const
181     {
182         if (!object)
183             return m_defaultAttributes;
184         Attributes rc;
185         if (m_property.isDesignable(object))
186             rc |= DesignableAttribute;
187         if (m_property.isScriptable(object))
188             rc |= ScriptableAttribute;
189         if (m_property.isStored(object))
190             rc |= StoredAttribute;
191         if (m_property.isUser(object))
192             rc |= UserAttribute;
193         return rc;
194     }
195 
196     // -------------- QDesignerMetaMethod
197 
198     class QDesignerMetaMethod : public QDesignerMetaMethodInterface {
199     public:
200         QDesignerMetaMethod(const QMetaMethod &method);
201 
access() const202         virtual Access access() const               { return m_access; }
methodType() const203         virtual MethodType methodType() const       { return m_methodType; }
parameterNames() const204         virtual QStringList parameterNames() const  { return m_parameterNames; }
parameterTypes() const205         virtual QStringList parameterTypes() const  { return m_parameterTypes; }
signature() const206         virtual QString signature() const           { return m_signature; }
normalizedSignature() const207         virtual QString normalizedSignature() const { return m_normalizedSignature; }
tag() const208         virtual QString tag() const                 { return m_tag; }
typeName() const209         virtual QString typeName() const            { return m_typeName; }
210 
211     private:
212         Access m_access;
213         MethodType m_methodType;
214         const QStringList m_parameterNames;
215         const QStringList m_parameterTypes;
216         const QString m_signature;
217         const QString m_normalizedSignature;
218         const QString m_tag;
219         const QString m_typeName;
220     };
221 
QDesignerMetaMethod(const QMetaMethod & method)222     QDesignerMetaMethod::QDesignerMetaMethod(const QMetaMethod &method) :
223        m_parameterNames(byteArrayListToStringList(method.parameterNames())),
224        m_parameterTypes(byteArrayListToStringList(method.parameterTypes())),
225        m_signature(charToQString(method.signature())),
226        m_normalizedSignature(charToQString(QMetaObject::normalizedSignature(method.signature()))),
227        m_tag(charToQString(method.tag())),
228        m_typeName(charToQString(method.typeName()))
229     {
230         switch (method.access()) {
231         case QMetaMethod::Public:
232             m_access = Public;
233             break;
234         case QMetaMethod::Protected:
235             m_access = Protected;
236             break;
237         case QMetaMethod::Private:
238             m_access = Private;
239             break;
240 
241         }
242         switch (method.methodType()) {
243         case QMetaMethod::Constructor:
244             m_methodType = Constructor;
245             break;
246         case QMetaMethod::Method:
247             m_methodType = Method;
248             break;
249         case QMetaMethod::Signal:
250             m_methodType = Signal;
251             break;
252 
253         case QMetaMethod::Slot:
254             m_methodType = Slot;
255             break;
256         }
257     }
258 
259     // ------------- QDesignerMetaObject
260     class QDesignerMetaObject : public QDesignerMetaObjectInterface {
261     public:
262         QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject);
263         virtual ~QDesignerMetaObject();
264 
className() const265         virtual QString className() const { return m_className; }
enumerator(int index) const266         virtual const QDesignerMetaEnumInterface *enumerator(int index) const { return m_enumerators[index]; }
enumeratorCount() const267         virtual int enumeratorCount() const { return m_enumerators.size(); }
enumeratorOffset() const268         virtual int enumeratorOffset() const { return m_metaObject->enumeratorOffset(); }
269 
indexOfEnumerator(const QString & name) const270         virtual int indexOfEnumerator(const QString &name) const { return m_metaObject->indexOfEnumerator(name.toUtf8()); }
indexOfMethod(const QString & method) const271         virtual int indexOfMethod(const QString &method) const { return m_metaObject->indexOfMethod(method.toUtf8()); }
indexOfProperty(const QString & name) const272         virtual int indexOfProperty(const QString &name) const { return m_metaObject->indexOfProperty(name.toUtf8()); }
indexOfSignal(const QString & signal) const273         virtual int indexOfSignal(const QString &signal) const { return m_metaObject->indexOfSignal(signal.toUtf8());  }
indexOfSlot(const QString & slot) const274         virtual int indexOfSlot(const QString &slot) const { return m_metaObject->indexOfSlot(slot.toUtf8()); }
275 
method(int index) const276         virtual const QDesignerMetaMethodInterface *method(int index) const { return m_methods[index]; }
methodCount() const277         virtual int methodCount() const { return m_methods.size(); }
methodOffset() const278         virtual int methodOffset() const { return m_metaObject->methodOffset(); }
279 
property(int index) const280         virtual const QDesignerMetaPropertyInterface *property(int index) const { return m_properties[index]; }
propertyCount() const281         virtual int propertyCount() const { return m_properties.size(); }
propertyOffset() const282         virtual int propertyOffset() const { return m_metaObject->propertyOffset(); }
283 
284         const QDesignerMetaObjectInterface *superClass() const;
userProperty() const285         virtual const QDesignerMetaPropertyInterface *userProperty() const { return m_userProperty; }
286 
287     private:
288         const QString m_className;
289         const qdesigner_internal::QDesignerIntrospection *m_introspection;
290         const QMetaObject *m_metaObject;
291 
292         typedef QVector<QDesignerMetaEnumInterface *> Enumerators;
293         Enumerators m_enumerators;
294 
295         typedef QVector<QDesignerMetaMethodInterface *> Methods;
296         Methods m_methods;
297 
298         typedef QVector<QDesignerMetaPropertyInterface *> Properties;
299         Properties m_properties;
300 
301         QDesignerMetaPropertyInterface *m_userProperty;
302     };
303 
QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection * introspection,const QMetaObject * metaObject)304     QDesignerMetaObject::QDesignerMetaObject(const qdesigner_internal::QDesignerIntrospection *introspection, const QMetaObject *metaObject) :
305        m_className(charToQString(metaObject->className())),
306        m_introspection(introspection),
307        m_metaObject(metaObject),
308        m_userProperty(0)
309     {
310         const int numEnumerators = metaObject->enumeratorCount();
311         m_enumerators.reserve(numEnumerators);
312         for (int i = 0; i < numEnumerators; i++)
313             m_enumerators.push_back(new QDesignerMetaEnum(metaObject->enumerator(i)));
314         const int numMethods = metaObject->methodCount();
315         m_methods.reserve(numMethods);
316         for (int i = 0; i < numMethods; i++)
317             m_methods.push_back(new QDesignerMetaMethod(metaObject->method(i)));
318 
319         const int numProperties = metaObject->propertyCount();
320         m_properties.reserve(numProperties);
321         for (int i = 0; i < numProperties; i++)
322             m_properties.push_back(new QDesignerMetaProperty(metaObject->property(i)));
323 
324         const QMetaProperty userProperty = metaObject->userProperty();
325         if (userProperty.isValid())
326             m_userProperty = new QDesignerMetaProperty(userProperty);
327     }
328 
~QDesignerMetaObject()329     QDesignerMetaObject::~QDesignerMetaObject()
330     {
331         qDeleteAll(m_enumerators);
332         qDeleteAll(m_methods);
333         qDeleteAll(m_properties);
334         delete m_userProperty;
335     }
336 
superClass() const337     const QDesignerMetaObjectInterface *QDesignerMetaObject::superClass() const
338     {
339         const QMetaObject *qSuperClass = m_metaObject->superClass();
340         if (!qSuperClass)
341             return 0;
342         return m_introspection->metaObjectForQMetaObject(qSuperClass);
343     }
344 
345 }
346 
347 namespace qdesigner_internal {
348 
QDesignerIntrospection()349     QDesignerIntrospection::QDesignerIntrospection()
350     {
351     }
352 
~QDesignerIntrospection()353     QDesignerIntrospection::~QDesignerIntrospection()
354     {
355         qDeleteAll(m_metaObjectMap.values());
356     }
357 
metaObject(const QObject * object) const358     const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObject(const QObject *object) const
359     {
360         return metaObjectForQMetaObject(object->metaObject());
361     }
362 
metaObjectForQMetaObject(const QMetaObject * metaObject) const363     const QDesignerMetaObjectInterface* QDesignerIntrospection::metaObjectForQMetaObject(const QMetaObject *metaObject) const
364     {
365         MetaObjectMap::iterator it = m_metaObjectMap.find(metaObject);
366         if (it == m_metaObjectMap.end())
367             it = m_metaObjectMap.insert(metaObject, new QDesignerMetaObject(this, metaObject));
368         return it.value();
369     }
370 }
371 
372 QT_END_NAMESPACE
373