1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativeprivate.h>
43 #include "qdeclarativemetatype_p.h"
45 #include <private/qdeclarativeproxymetaobject_p.h>
46 #include <private/qdeclarativecustomparser_p.h>
47 #include <private/qdeclarativeguard_p.h>
48 #include <private/qhashedstring_p.h>
50 #include <QtCore/qdebug.h>
51 #include <QtCore/qstringlist.h>
52 #include <QtCore/qmetaobject.h>
53 #include <QtCore/qbitarray.h>
54 #include <QtCore/qreadwritelock.h>
55 #include <QtCore/private/qmetaobject_p.h>
57 #include <qmetatype.h>
58 #include <qobjectdefs.h>
59 #include <qbytearray.h>
60 #include <qreadwritelock.h>
62 #include <qstringlist.h>
69 struct QDeclarativeMetaTypeData
71 QDeclarativeMetaTypeData();
72 ~QDeclarativeMetaTypeData();
73 QList<QDeclarativeType *> types;
74 typedef QHash<int, QDeclarativeType *> Ids;
76 typedef QHash<QString, QDeclarativeType *> Names;
78 typedef QHash<const QMetaObject *, QDeclarativeType *> MetaObjects;
79 MetaObjects metaObjectToType;
80 typedef QHash<int, QDeclarativeMetaType::StringConverter> StringConverters;
81 StringConverters stringConverters;
86 VersionedUri(const QString &uri, int majorVersion)
87 : uri(uri), majorVersion(majorVersion) {}
88 bool operator==(const VersionedUri &other) const {
89 return other.majorVersion == majorVersion && other.uri == uri;
94 typedef QHash<VersionedUri, QDeclarativeTypeModule *> TypeModules;
95 TypeModules uriToModule;
97 struct ModuleApiList {
98 ModuleApiList() : sorted(true) {}
99 QList<QDeclarativeMetaType::ModuleApi> moduleApis;
102 typedef QHash<QString, ModuleApiList> ModuleApis;
103 ModuleApis moduleApis;
107 QBitArray interfaces;
110 QList<QDeclarativePrivate::AutoParentFunction> parentFunctions;
113 class QDeclarativeTypeModulePrivate
116 QDeclarativeTypeModulePrivate()
117 : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
119 QDeclarativeMetaTypeData::VersionedUri uri;
124 void add(QDeclarativeType *);
126 QStringHash<QList<QDeclarativeType *> > typeHash;
127 QList<QDeclarativeType *> types;
130 Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData)
131 Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
133 static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v)
135 return qHash(v.uri) ^ qHash(v.majorVersion);
138 QDeclarativeMetaTypeData::QDeclarativeMetaTypeData()
143 QDeclarativeMetaTypeData::~QDeclarativeMetaTypeData()
145 for (int i = 0; i < types.count(); ++i)
149 class QDeclarativeTypePrivate
152 QDeclarativeTypePrivate();
155 void initEnums() const;
157 bool m_isInterface : 1;
161 QString m_elementName;
164 int m_typeId; int m_listId;
166 mutable bool m_containsRevisionedAttributes;
167 mutable QDeclarativeType *m_superType;
169 int m_allocationSize;
170 void (*m_newFunc)(void *);
171 QString m_noCreationReason;
173 const QMetaObject *m_baseMetaObject;
174 QDeclarativeAttachedPropertiesFunc m_attachedPropertiesFunc;
175 const QMetaObject *m_attachedPropertiesType;
176 int m_attachedPropertiesId;
177 int m_parserStatusCast;
178 int m_propertyValueSourceCast;
179 int m_propertyValueInterceptorCast;
180 QObject *(*m_extFunc)(QObject *);
181 const QMetaObject *m_extMetaObject;
183 QDeclarativeCustomParser *m_customParser;
184 mutable volatile bool m_isSetup:1;
185 mutable volatile bool m_isEnumSetup:1;
186 mutable bool m_haveSuperType:1;
187 mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects;
188 mutable QStringHash<int> m_enums;
190 static QHash<const QMetaObject *, int> m_attachedPropertyIds;
193 QHash<const QMetaObject *, int> QDeclarativeTypePrivate::m_attachedPropertyIds;
195 QDeclarativeTypePrivate::QDeclarativeTypePrivate()
196 : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false),
197 m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
198 m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1),
199 m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0),
200 m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
205 QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::RegisterInterface &interface)
206 : d(new QDeclarativeTypePrivate)
208 d->m_isInterface = true;
209 d->m_iid = interface.iid;
210 d->m_typeId = interface.typeId;
211 d->m_listId = interface.listId;
215 d->m_version_maj = 0;
216 d->m_version_min = 0;
219 QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::RegisterType &type)
220 : d(new QDeclarativeTypePrivate)
222 QString name = QString::fromUtf8(type.uri);
223 if (type.uri) name += QLatin1Char('/');
224 name += QString::fromUtf8(type.elementName);
226 d->m_module = QString::fromUtf8(type.uri);
228 d->m_version_maj = type.versionMajor;
229 d->m_version_min = type.versionMinor;
230 if (type.version >= 1) // revisions added in version 1
231 d->m_revision = type.revision;
232 d->m_typeId = type.typeId;
233 d->m_listId = type.listId;
234 d->m_allocationSize = type.objectSize;
235 d->m_newFunc = type.create;
236 d->m_noCreationReason = type.noCreationReason;
237 d->m_baseMetaObject = type.metaObject;
238 d->m_attachedPropertiesFunc = type.attachedPropertiesFunction;
239 d->m_attachedPropertiesType = type.attachedPropertiesMetaObject;
240 if (d->m_attachedPropertiesType) {
241 QHash<const QMetaObject *, int>::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject);
242 if (iter == d->m_attachedPropertyIds.end())
243 iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index);
244 d->m_attachedPropertiesId = *iter;
246 d->m_attachedPropertiesId = -1;
248 d->m_parserStatusCast = type.parserStatusCast;
249 d->m_propertyValueSourceCast = type.valueSourceCast;
250 d->m_propertyValueInterceptorCast = type.valueInterceptorCast;
251 d->m_extFunc = type.extensionObjectCreate;
253 d->m_customParser = type.customParser;
255 if (type.extensionMetaObject)
256 d->m_extMetaObject = type.extensionMetaObject;
259 QDeclarativeType::~QDeclarativeType()
261 delete d->m_customParser;
265 QString QDeclarativeType::module() const
270 int QDeclarativeType::majorVersion() const
272 return d->m_version_maj;
275 int QDeclarativeType::minorVersion() const
277 return d->m_version_min;
280 bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const
282 Q_ASSERT(vmajor >= 0 && vminor >= 0);
283 return vmajor == d->m_version_maj && vminor >= d->m_version_min;
286 bool QDeclarativeType::availableInVersion(const QString &module, int vmajor, int vminor) const
288 Q_ASSERT(vmajor >= 0 && vminor >= 0);
289 return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
292 // returns the nearest _registered_ super class
293 QDeclarativeType *QDeclarativeType::superType() const
295 if (!d->m_haveSuperType) {
296 const QMetaObject *mo = d->m_baseMetaObject->superClass();
297 while (mo && !d->m_superType) {
298 d->m_superType = QDeclarativeMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min);
299 mo = mo->superClass();
301 d->m_haveSuperType = true;
304 return d->m_superType;
307 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
308 const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
311 builder.setClassName(ignoreEnd->className());
314 for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
315 QMetaClassInfo info = mo->classInfo(ii);
317 int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
318 if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
321 builder.addClassInfo(info.name(), info.value());
326 for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
327 QMetaProperty property = mo->property(ii);
329 int otherIndex = ignoreEnd->indexOfProperty(property.name());
330 if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
331 builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
334 builder.addProperty(property);
339 for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
340 QMetaMethod method = mo->method(ii);
342 // More complex - need to search name
343 QByteArray name = method.signature();
344 int parenIdx = name.indexOf('(');
345 if (parenIdx != -1) name = name.left(parenIdx);
350 for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
351 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
354 QMetaMethod other = ignoreEnd->method(ii);
355 QByteArray othername = other.signature();
356 int parenIdx = othername.indexOf('(');
357 if (parenIdx != -1) othername = othername.left(parenIdx);
359 found = name == othername;
362 QMetaMethodBuilder m = builder.addMethod(method);
364 m.setAccess(QMetaMethod::Private);
368 for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
369 QMetaEnum enumerator = mo->enumerator(ii);
371 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
372 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
375 builder.addEnumerator(enumerator);
380 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
383 i -= mo->propertyOffset();
384 if (i < 0 && mo->d.superdata)
385 return isPropertyRevisioned(mo->d.superdata, index);
387 const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
388 if (i >= 0 && i < mop->propertyCount) {
389 int handle = mop->propertyData + 3*i;
390 int flags = mo->d.data[handle + 2];
392 return (flags & Revisioned);
398 void QDeclarativeTypePrivate::init() const
400 if (m_isSetup) return;
402 QWriteLocker lock(metaTypeDataLock());
406 // Setup extended meta object
407 // XXX - very inefficient
408 const QMetaObject *mo = m_baseMetaObject;
410 QMetaObjectBuilder builder;
411 clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
412 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
413 QMetaObject *mmo = builder.toMetaObject();
414 mmo->d.superdata = mo;
415 QDeclarativeProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
416 m_metaObjects << data;
419 mo = mo->d.superdata;
421 QDeclarativeType *t = metaTypeData()->metaObjectToType.value(mo);
423 if (t->d->m_extFunc) {
424 QMetaObjectBuilder builder;
425 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
426 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
427 QMetaObject *mmo = builder.toMetaObject();
428 mmo->d.superdata = m_baseMetaObject;
429 if (!m_metaObjects.isEmpty())
430 m_metaObjects.last().metaObject->d.superdata = mmo;
431 QDeclarativeProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
432 m_metaObjects << data;
435 mo = mo->d.superdata;
438 for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
439 m_metaObjects[ii].propertyOffset =
440 m_metaObjects.at(ii).metaObject->propertyOffset();
441 m_metaObjects[ii].methodOffset =
442 m_metaObjects.at(ii).metaObject->methodOffset();
445 // Check for revisioned details
447 const QMetaObject *mo = 0;
448 if (m_metaObjects.isEmpty())
449 mo = m_baseMetaObject;
451 mo = m_metaObjects.first().metaObject;
453 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
454 if (isPropertyRevisioned(mo, ii))
455 m_containsRevisionedAttributes = true;
458 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
459 if (mo->method(ii).revision() != 0)
460 m_containsRevisionedAttributes = true;
468 void QDeclarativeTypePrivate::initEnums() const
470 if (m_isEnumSetup) return;
474 QWriteLocker lock(metaTypeDataLock());
475 if (m_isEnumSetup) return;
477 const QMetaObject *metaObject = m_baseMetaObject;
478 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
480 QMetaEnum e = metaObject->enumerator(ii);
482 for (int jj = 0; jj < e.keyCount(); ++jj)
483 m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
486 m_isEnumSetup = true;
489 QByteArray QDeclarativeType::typeName() const
491 if (d->m_baseMetaObject)
492 return d->m_baseMetaObject->className();
497 const QString &QDeclarativeType::elementName() const
499 if (d->m_elementName.isEmpty()) {
500 QString n = qmlTypeName();
501 int idx = n.lastIndexOf(QLatin1Char('/'));
502 d->m_elementName = n.mid(idx + 1);
504 return d->m_elementName;
507 const QString &QDeclarativeType::qmlTypeName() const
512 QObject *QDeclarativeType::create() const
516 QObject *rv = (QObject *)operator new(d->m_allocationSize);
519 if (rv && !d->m_metaObjects.isEmpty())
520 (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects);
525 void QDeclarativeType::create(QObject **out, void **memory, size_t additionalMemory) const
529 QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
532 if (rv && !d->m_metaObjects.isEmpty())
533 (void *)new QDeclarativeProxyMetaObject(rv, &d->m_metaObjects);
536 *memory = ((char *)rv) + d->m_allocationSize;
539 QDeclarativeCustomParser *QDeclarativeType::customParser() const
541 return d->m_customParser;
544 QDeclarativeType::CreateFunc QDeclarativeType::createFunction() const
549 QString QDeclarativeType::noCreationReason() const
551 return d->m_noCreationReason;
554 int QDeclarativeType::createSize() const
556 return d->m_allocationSize;
559 bool QDeclarativeType::isCreatable() const
561 return d->m_newFunc != 0;
564 bool QDeclarativeType::isExtendedType() const
568 return !d->m_metaObjects.isEmpty();
571 bool QDeclarativeType::isInterface() const
573 return d->m_isInterface;
576 int QDeclarativeType::typeId() const
581 int QDeclarativeType::qListTypeId() const
586 const QMetaObject *QDeclarativeType::metaObject() const
590 if (d->m_metaObjects.isEmpty())
591 return d->m_baseMetaObject;
593 return d->m_metaObjects.first().metaObject;
597 const QMetaObject *QDeclarativeType::baseMetaObject() const
599 return d->m_baseMetaObject;
602 bool QDeclarativeType::containsRevisionedAttributes() const
606 return d->m_containsRevisionedAttributes;
609 int QDeclarativeType::metaObjectRevision() const
611 return d->m_revision;
614 QDeclarativeAttachedPropertiesFunc QDeclarativeType::attachedPropertiesFunction() const
616 return d->m_attachedPropertiesFunc;
619 const QMetaObject *QDeclarativeType::attachedPropertiesType() const
621 return d->m_attachedPropertiesType;
625 This is the id passed to qmlAttachedPropertiesById(). This is different from the index
626 for the case that a single class is registered under two or more names (eg. Item in
627 Qt 4.7 and QtQuick 1.0).
629 int QDeclarativeType::attachedPropertiesId() const
631 return d->m_attachedPropertiesId;
634 int QDeclarativeType::parserStatusCast() const
636 return d->m_parserStatusCast;
639 int QDeclarativeType::propertyValueSourceCast() const
641 return d->m_propertyValueSourceCast;
644 int QDeclarativeType::propertyValueInterceptorCast() const
646 return d->m_propertyValueInterceptorCast;
649 const char *QDeclarativeType::interfaceIId() const
654 int QDeclarativeType::index() const
659 int QDeclarativeType::enumValue(const QHashedStringRef &name) const
663 int *rv = d->m_enums.value(name);
667 int QDeclarativeType::enumValue(const QHashedV8String &name) const
671 int *rv = d->m_enums.value(name);
675 QDeclarativeTypeModule::QDeclarativeTypeModule()
676 : d(new QDeclarativeTypeModulePrivate)
680 QDeclarativeTypeModule::~QDeclarativeTypeModule()
685 QString QDeclarativeTypeModule::module() const
690 int QDeclarativeTypeModule::majorVersion() const
692 return d->uri.majorVersion;
695 int QDeclarativeTypeModule::minimumMinorVersion() const
697 return d->minMinorVersion;
700 int QDeclarativeTypeModule::maximumMinorVersion() const
702 return d->maxMinorVersion;
705 void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type)
709 minMinorVersion = qMin(minMinorVersion, type->minorVersion());
710 maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
712 QList<QDeclarativeType *> &list = typeHash[type->elementName()];
713 for (int ii = 0; ii < list.count(); ++ii) {
714 if (list.at(ii)->minorVersion() < type->minorVersion()) {
715 list.insert(ii, type);
722 QList<QDeclarativeType *> QDeclarativeTypeModule::types()
724 QList<QDeclarativeType *> rv;
725 QReadLocker lock(metaTypeDataLock());
730 QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name)
732 QReadLocker lock(metaTypeDataLock());
733 QList<QDeclarativeType *> rv;
734 for (int ii = 0; ii < d->types.count(); ++ii) {
735 if (d->types.at(ii)->elementName() == name)
736 rv << d->types.at(ii);
741 QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor)
743 QReadLocker lock(metaTypeDataLock());
745 QList<QDeclarativeType *> *types = d->typeHash.value(name);
746 if (!types) return 0;
748 for (int ii = 0; ii < types->count(); ++ii)
749 if (types->at(ii)->minorVersion() <= minor)
750 return types->at(ii);
755 QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor)
757 QReadLocker lock(metaTypeDataLock());
759 QList<QDeclarativeType *> *types = d->typeHash.value(name);
760 if (!types) return 0;
762 for (int ii = 0; ii < types->count(); ++ii)
763 if (types->at(ii)->minorVersion() <= minor)
764 return types->at(ii);
770 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion()
771 : m_module(0), m_minor(0)
775 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor)
776 : m_module(module), m_minor(minor)
779 Q_ASSERT(m_minor >= 0);
782 QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o)
783 : m_module(o.m_module), m_minor(o.m_minor)
787 QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o)
789 m_module = o.m_module;
794 QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const
799 int QDeclarativeTypeModuleVersion::minorVersion() const
804 QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const
806 if (m_module) return m_module->type(name, m_minor);
810 QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const
812 if (m_module) return m_module->type(name, m_minor);
817 int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent)
819 QWriteLocker lock(metaTypeDataLock());
820 QDeclarativeMetaTypeData *data = metaTypeData();
822 data->parentFunctions.append(autoparent.function);
824 return data->parentFunctions.count() - 1;
827 int registerInterface(const QDeclarativePrivate::RegisterInterface &interface)
829 if (interface.version > 0)
830 qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
832 QWriteLocker lock(metaTypeDataLock());
833 QDeclarativeMetaTypeData *data = metaTypeData();
835 int index = data->types.count();
837 QDeclarativeType *type = new QDeclarativeType(index, interface);
839 data->types.append(type);
840 data->idToType.insert(type->typeId(), type);
841 data->idToType.insert(type->qListTypeId(), type);
842 // XXX No insertMulti, so no multi-version interfaces?
843 if (!type->qmlTypeName().isEmpty())
844 data->nameToType.insert(type->qmlTypeName(), type);
846 if (data->interfaces.size() <= interface.typeId)
847 data->interfaces.resize(interface.typeId + 16);
848 if (data->lists.size() <= interface.listId)
849 data->lists.resize(interface.listId + 16);
850 data->interfaces.setBit(interface.typeId, true);
851 data->lists.setBit(interface.listId, true);
856 int registerType(const QDeclarativePrivate::RegisterType &type)
858 if (type.elementName) {
859 for (int ii = 0; type.elementName[ii]; ++ii) {
860 if (!isalnum(type.elementName[ii])) {
861 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
867 QWriteLocker lock(metaTypeDataLock());
868 QDeclarativeMetaTypeData *data = metaTypeData();
869 int index = data->types.count();
871 QDeclarativeType *dtype = new QDeclarativeType(index, type);
873 data->types.append(dtype);
874 data->idToType.insert(dtype->typeId(), dtype);
875 if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
877 if (!dtype->qmlTypeName().isEmpty())
878 data->nameToType.insertMulti(dtype->qmlTypeName(), dtype);
880 data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
882 if (data->objects.size() <= type.typeId)
883 data->objects.resize(type.typeId + 16);
884 if (data->lists.size() <= type.listId)
885 data->lists.resize(type.listId + 16);
886 data->objects.setBit(type.typeId, true);
887 if (type.listId) data->lists.setBit(type.listId, true);
890 QString mod = QString::fromUtf8(type.uri);
892 QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
893 QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri);
895 module = new QDeclarativeTypeModule;
896 module->d->uri = versionedUri;
897 data->uriToModule.insert(versionedUri, module);
899 module->d->add(dtype);
905 int registerModuleApi(const QDeclarativePrivate::RegisterModuleApi &api)
907 QWriteLocker lock(metaTypeDataLock());
909 QDeclarativeMetaTypeData *data = metaTypeData();
910 QString uri = QString::fromUtf8(api.uri);
911 QDeclarativeMetaType::ModuleApi import;
912 import.major = api.versionMajor;
913 import.minor = api.versionMinor;
914 import.script = api.scriptApi;
915 import.qobject = api.qobjectApi;
917 int index = data->moduleApiCount++;
919 QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
920 if (iter == data->moduleApis.end()) {
921 QDeclarativeMetaTypeData::ModuleApiList apis;
922 apis.moduleApis << import;
923 data->moduleApis.insert(uri, apis);
925 iter->moduleApis << import;
926 iter->sorted = false;
934 This method is "over generalized" to allow us to (potentially) register more types of things in
935 the future without adding exported symbols.
937 int QDeclarativePrivate::qmlregister(RegistrationType type, void *data)
939 if (type == TypeRegistration) {
940 return registerType(*reinterpret_cast<RegisterType *>(data));
941 } else if (type == InterfaceRegistration) {
942 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
943 } else if (type == AutoParentRegistration) {
944 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
945 } else if (type == ModuleApiRegistration) {
946 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
952 Returns true if a module \a uri of any version is installed.
954 bool QDeclarativeMetaType::isAnyModule(const QString &uri)
956 QReadLocker lock(metaTypeDataLock());
957 QDeclarativeMetaTypeData *data = metaTypeData();
959 for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
960 iter != data->uriToModule.end(); ++iter) {
961 if ((*iter)->module() == uri)
969 Returns true if any type or API has been registered for the given \a module with at least
970 versionMajor.versionMinor, or if types have been registered for \a module with at most
971 versionMajor.versionMinor.
973 So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10.
975 bool QDeclarativeMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
977 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
978 QReadLocker lock(metaTypeDataLock());
980 QDeclarativeMetaTypeData *data = metaTypeData();
982 // first, check Types
983 QDeclarativeTypeModule *tm =
984 data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor));
985 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
988 // then, check ModuleApis
989 foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
990 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
997 QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QString &uri, int majorVersion)
999 QReadLocker lock(metaTypeDataLock());
1000 QDeclarativeMetaTypeData *data = metaTypeData();
1001 return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion));
1004 QList<QDeclarativePrivate::AutoParentFunction> QDeclarativeMetaType::parentFunctions()
1006 QReadLocker lock(metaTypeDataLock());
1007 QDeclarativeMetaTypeData *data = metaTypeData();
1008 return data->parentFunctions;
1011 static bool operator<(const QDeclarativeMetaType::ModuleApi &lhs, const QDeclarativeMetaType::ModuleApi &rhs)
1013 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1016 QDeclarativeMetaType::ModuleApi
1017 QDeclarativeMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
1019 QReadLocker lock(metaTypeDataLock());
1020 QDeclarativeMetaTypeData *data = metaTypeData();
1022 QDeclarativeMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
1023 if (iter == data->moduleApis.end())
1026 if (iter->sorted == false) {
1027 qSort(iter->moduleApis.begin(), iter->moduleApis.end());
1028 iter->sorted = true;
1031 for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) {
1032 const ModuleApi &import = iter->moduleApis.at(ii);
1033 if (import.major == versionMajor && import.minor <= versionMinor)
1040 QHash<QString, QList<QDeclarativeMetaType::ModuleApi> > QDeclarativeMetaType::moduleApis()
1042 QReadLocker lock(metaTypeDataLock());
1043 QDeclarativeMetaTypeData *data = metaTypeData();
1045 QHash<QString, QList<ModuleApi> > moduleApis;
1046 QHashIterator<QString, QDeclarativeMetaTypeData::ModuleApiList> it(data->moduleApis);
1047 while (it.hasNext()) {
1049 moduleApis[it.key()] = it.value().moduleApis;
1055 QObject *QDeclarativeMetaType::toQObject(const QVariant &v, bool *ok)
1057 if (!isQObject(v.userType())) {
1058 if (ok) *ok = false;
1064 return *(QObject **)v.constData();
1067 bool QDeclarativeMetaType::isQObject(int userType)
1069 if (userType == QMetaType::QObjectStar)
1072 QReadLocker lock(metaTypeDataLock());
1073 QDeclarativeMetaTypeData *data = metaTypeData();
1074 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1078 Returns the item type for a list of type \a id.
1080 int QDeclarativeMetaType::listType(int id)
1082 QReadLocker lock(metaTypeDataLock());
1083 QDeclarativeMetaTypeData *data = metaTypeData();
1084 QDeclarativeType *type = data->idToType.value(id);
1085 if (type && type->qListTypeId() == id)
1086 return type->typeId();
1091 int QDeclarativeMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1093 QReadLocker lock(metaTypeDataLock());
1094 QDeclarativeMetaTypeData *data = metaTypeData();
1096 QDeclarativeType *type = data->metaObjectToType.value(mo);
1097 if (type && type->attachedPropertiesFunction())
1098 return type->attachedPropertiesId();
1103 QDeclarativeAttachedPropertiesFunc QDeclarativeMetaType::attachedPropertiesFuncById(int id)
1107 QReadLocker lock(metaTypeDataLock());
1108 QDeclarativeMetaTypeData *data = metaTypeData();
1109 return data->types.at(id)->attachedPropertiesFunction();
1112 QMetaProperty QDeclarativeMetaType::defaultProperty(const QMetaObject *metaObject)
1114 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1116 return QMetaProperty();
1118 QMetaClassInfo info = metaObject->classInfo(idx);
1120 return QMetaProperty();
1122 idx = metaObject->indexOfProperty(info.value());
1124 return QMetaProperty();
1126 return metaObject->property(idx);
1129 QMetaProperty QDeclarativeMetaType::defaultProperty(QObject *obj)
1132 return QMetaProperty();
1134 const QMetaObject *metaObject = obj->metaObject();
1135 return defaultProperty(metaObject);
1138 QMetaMethod QDeclarativeMetaType::defaultMethod(const QMetaObject *metaObject)
1140 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1142 return QMetaMethod();
1144 QMetaClassInfo info = metaObject->classInfo(idx);
1146 return QMetaMethod();
1148 idx = metaObject->indexOfMethod(info.value());
1150 return QMetaMethod();
1152 return metaObject->method(idx);
1155 QMetaMethod QDeclarativeMetaType::defaultMethod(QObject *obj)
1158 return QMetaMethod();
1160 const QMetaObject *metaObject = obj->metaObject();
1161 return defaultMethod(metaObject);
1164 QDeclarativeMetaType::TypeCategory QDeclarativeMetaType::typeCategory(int userType)
1168 if (userType == QMetaType::QObjectStar)
1171 QReadLocker lock(metaTypeDataLock());
1172 QDeclarativeMetaTypeData *data = metaTypeData();
1173 if (userType < data->objects.size() && data->objects.testBit(userType))
1175 else if (userType < data->lists.size() && data->lists.testBit(userType))
1181 bool QDeclarativeMetaType::isInterface(int userType)
1183 QReadLocker lock(metaTypeDataLock());
1184 QDeclarativeMetaTypeData *data = metaTypeData();
1185 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1188 const char *QDeclarativeMetaType::interfaceIId(int userType)
1190 QReadLocker lock(metaTypeDataLock());
1191 QDeclarativeMetaTypeData *data = metaTypeData();
1192 QDeclarativeType *type = data->idToType.value(userType);
1194 if (type && type->isInterface() && type->typeId() == userType)
1195 return type->interfaceIId();
1200 bool QDeclarativeMetaType::isList(int userType)
1202 QReadLocker lock(metaTypeDataLock());
1203 QDeclarativeMetaTypeData *data = metaTypeData();
1204 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1208 A custom string convertor allows you to specify a function pointer that
1209 returns a variant of \a type. For example, if you have written your own icon
1210 class that you want to support as an object property assignable in QML:
1213 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1214 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1217 The function pointer must be of the form:
1219 QVariant (*StringConverter)(const QString &);
1222 void QDeclarativeMetaType::registerCustomStringConverter(int type, StringConverter converter)
1224 QWriteLocker lock(metaTypeDataLock());
1226 QDeclarativeMetaTypeData *data = metaTypeData();
1227 if (data->stringConverters.contains(type))
1229 data->stringConverters.insert(type, converter);
1233 Return the custom string converter for \a type, previously installed through
1234 registerCustomStringConverter()
1236 QDeclarativeMetaType::StringConverter QDeclarativeMetaType::customStringConverter(int type)
1238 QReadLocker lock(metaTypeDataLock());
1240 QDeclarativeMetaTypeData *data = metaTypeData();
1241 return data->stringConverters.value(type);
1245 Returns the type (if any) of URI-qualified named \a name in version specified
1246 by \a version_major and \a version_minor.
1248 QDeclarativeType *QDeclarativeMetaType::qmlType(const QString &name, int version_major, int version_minor)
1250 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1251 QReadLocker lock(metaTypeDataLock());
1252 QDeclarativeMetaTypeData *data = metaTypeData();
1254 QDeclarativeMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1255 while (it != data->nameToType.end()) {
1256 // XXX version_major<0 just a kludge for QDeclarativePropertyPrivate::initProperty
1257 if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor)))
1266 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1269 QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject)
1271 QReadLocker lock(metaTypeDataLock());
1272 QDeclarativeMetaTypeData *data = metaTypeData();
1274 return data->metaObjectToType.value(metaObject);
1278 Returns the type (if any) that corresponds to the \a metaObject in version specified
1279 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1282 QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor)
1284 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1285 QReadLocker lock(metaTypeDataLock());
1286 QDeclarativeMetaTypeData *data = metaTypeData();
1288 QDeclarativeMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1289 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1290 QDeclarativeType *t = *it;
1291 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1300 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1301 Returns null if no type is registered.
1303 QDeclarativeType *QDeclarativeMetaType::qmlType(int userType)
1305 QReadLocker lock(metaTypeDataLock());
1306 QDeclarativeMetaTypeData *data = metaTypeData();
1308 QDeclarativeType *type = data->idToType.value(userType);
1309 if (type && type->typeId() == userType)
1316 Returns the list of registered QML type names.
1318 QList<QString> QDeclarativeMetaType::qmlTypeNames()
1320 QReadLocker lock(metaTypeDataLock());
1321 QDeclarativeMetaTypeData *data = metaTypeData();
1323 return data->nameToType.keys();
1327 Returns the list of registered QML types.
1329 QList<QDeclarativeType*> QDeclarativeMetaType::qmlTypes()
1331 QReadLocker lock(metaTypeDataLock());
1332 QDeclarativeMetaTypeData *data = metaTypeData();
1334 return data->nameToType.values();
1337 int QDeclarativeMetaType::QQuickAnchorLineMetaTypeId()
1341 id = QMetaType::type("QQuickAnchorLine");
1346 QDeclarativeMetaType::CompareFunction QDeclarativeMetaType::anchorLineCompareFunction = 0;
1348 void QDeclarativeMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1350 anchorLineCompareFunction = fun;
1353 bool QDeclarativeMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1355 Q_ASSERT(anchorLineCompareFunction != 0);
1356 return anchorLineCompareFunction(p1, p2);