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