1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtQml/qqmlprivate.h>
43 #include "qqmlmetatype_p.h"
45 #include <private/qqmlproxymetaobject_p.h>
46 #include <private/qqmlcustomparser_p.h>
47 #include <private/qqmlguard_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 QQmlMetaTypeData
73 QList<QQmlType *> types;
74 typedef QHash<int, QQmlType *> Ids;
76 typedef QHash<QHashedStringRef,QQmlType *> Names;
78 typedef QHash<const QMetaObject *, QQmlType *> MetaObjects;
79 MetaObjects metaObjectToType;
80 typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
81 StringConverters stringConverters;
86 VersionedUri(const QHashedString &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, QQmlTypeModule *> TypeModules;
95 TypeModules uriToModule;
97 struct ModuleApiList {
98 ModuleApiList() : sorted(true) {}
99 QList<QQmlMetaType::ModuleApi> moduleApis;
102 typedef QStringHash<ModuleApiList> ModuleApis;
103 ModuleApis moduleApis;
107 QBitArray interfaces;
110 QList<QQmlPrivate::AutoParentFunction> parentFunctions;
113 class QQmlTypeModulePrivate
116 QQmlTypeModulePrivate()
117 : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
119 QQmlMetaTypeData::VersionedUri uri;
124 void add(QQmlType *);
126 QStringHash<QList<QQmlType *> > typeHash;
127 QList<QQmlType *> types;
130 Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData)
131 Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
133 static uint qHash(const QQmlMetaTypeData::VersionedUri &v)
135 return v.uri.hash() ^ qHash(v.majorVersion);
138 QQmlMetaTypeData::QQmlMetaTypeData()
143 QQmlMetaTypeData::~QQmlMetaTypeData()
145 for (int i = 0; i < types.count(); ++i)
149 class QQmlTypePrivate
155 void initEnums() const;
156 void insertEnums(const QMetaObject *metaObject) const;
158 bool m_isInterface : 1;
160 QHashedString m_module;
162 QString m_elementName;
165 int m_typeId; int m_listId;
167 mutable bool m_containsRevisionedAttributes;
168 mutable QQmlType *m_superType;
170 int m_allocationSize;
171 void (*m_newFunc)(void *);
172 QString m_noCreationReason;
174 const QMetaObject *m_baseMetaObject;
175 QQmlAttachedPropertiesFunc m_attachedPropertiesFunc;
176 const QMetaObject *m_attachedPropertiesType;
177 int m_attachedPropertiesId;
178 int m_parserStatusCast;
179 int m_propertyValueSourceCast;
180 int m_propertyValueInterceptorCast;
181 QObject *(*m_extFunc)(QObject *);
182 const QMetaObject *m_extMetaObject;
184 QQmlCustomParser *m_customParser;
185 mutable volatile bool m_isSetup:1;
186 mutable volatile bool m_isEnumSetup:1;
187 mutable bool m_haveSuperType:1;
188 mutable QList<QQmlProxyMetaObject::ProxyData> m_metaObjects;
189 mutable QStringHash<int> m_enums;
191 static QHash<const QMetaObject *, int> m_attachedPropertyIds;
194 // Avoid multiple fromUtf8(), copies and hashing of the module name.
195 // This is only called when metaTypeDataLock is locked.
196 static QHashedString moduletoUtf8(const char *module)
199 return QHashedString();
201 static const char *lastModule = 0;
202 static QHashedString lastModuleStr;
204 // Separate plugins may have different strings at the same address
205 QHashedCStringRef currentModule(module, ::strlen(module));
206 if ((lastModule != module) || (lastModuleStr.hash() != currentModule.hash())) {
207 lastModuleStr = QString::fromUtf8(module);
208 lastModuleStr.hash();
212 return lastModuleStr;
215 QHash<const QMetaObject *, int> QQmlTypePrivate::m_attachedPropertyIds;
217 QQmlTypePrivate::QQmlTypePrivate()
218 : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false),
219 m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
220 m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1),
221 m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0),
222 m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
227 QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface)
228 : d(new QQmlTypePrivate)
230 d->m_isInterface = true;
231 d->m_iid = interface.iid;
232 d->m_typeId = interface.typeId;
233 d->m_listId = interface.listId;
237 d->m_version_maj = 0;
238 d->m_version_min = 0;
241 QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type)
242 : d(new QQmlTypePrivate)
244 d->m_module = moduletoUtf8(type.uri);
245 d->m_elementName = QString::fromUtf8(type.elementName);
247 d->m_version_maj = type.versionMajor;
248 d->m_version_min = type.versionMinor;
249 if (type.version >= 1) // revisions added in version 1
250 d->m_revision = type.revision;
251 d->m_typeId = type.typeId;
252 d->m_listId = type.listId;
253 d->m_allocationSize = type.objectSize;
254 d->m_newFunc = type.create;
255 d->m_noCreationReason = type.noCreationReason;
256 d->m_baseMetaObject = type.metaObject;
257 d->m_attachedPropertiesFunc = type.attachedPropertiesFunction;
258 d->m_attachedPropertiesType = type.attachedPropertiesMetaObject;
259 if (d->m_attachedPropertiesType) {
260 QHash<const QMetaObject *, int>::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject);
261 if (iter == d->m_attachedPropertyIds.end())
262 iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index);
263 d->m_attachedPropertiesId = *iter;
265 d->m_attachedPropertiesId = -1;
267 d->m_parserStatusCast = type.parserStatusCast;
268 d->m_propertyValueSourceCast = type.valueSourceCast;
269 d->m_propertyValueInterceptorCast = type.valueInterceptorCast;
270 d->m_extFunc = type.extensionObjectCreate;
272 d->m_customParser = type.customParser;
274 if (type.extensionMetaObject)
275 d->m_extMetaObject = type.extensionMetaObject;
278 QQmlType::~QQmlType()
280 delete d->m_customParser;
284 const QHashedString &QQmlType::module() const
289 int QQmlType::majorVersion() const
291 return d->m_version_maj;
294 int QQmlType::minorVersion() const
296 return d->m_version_min;
299 bool QQmlType::availableInVersion(int vmajor, int vminor) const
301 Q_ASSERT(vmajor >= 0 && vminor >= 0);
302 return vmajor == d->m_version_maj && vminor >= d->m_version_min;
305 bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
307 Q_ASSERT(vmajor >= 0 && vminor >= 0);
308 return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
311 // returns the nearest _registered_ super class
312 QQmlType *QQmlType::superType() const
314 if (!d->m_haveSuperType) {
315 const QMetaObject *mo = d->m_baseMetaObject->superClass();
316 while (mo && !d->m_superType) {
317 d->m_superType = QQmlMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min);
318 mo = mo->superClass();
320 d->m_haveSuperType = true;
323 return d->m_superType;
326 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
327 const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
330 builder.setClassName(ignoreEnd->className());
333 for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
334 QMetaClassInfo info = mo->classInfo(ii);
336 int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
337 if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
340 builder.addClassInfo(info.name(), info.value());
345 for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
346 QMetaProperty property = mo->property(ii);
348 int otherIndex = ignoreEnd->indexOfProperty(property.name());
349 if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
350 builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
353 builder.addProperty(property);
358 for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
359 QMetaMethod method = mo->method(ii);
361 // More complex - need to search name
362 QByteArray name = method.name();
367 for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
368 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
371 QMetaMethod other = ignoreEnd->method(ii);
373 found = name == other.name();
376 QMetaMethodBuilder m = builder.addMethod(method);
378 m.setAccess(QMetaMethod::Private);
382 for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
383 QMetaEnum enumerator = mo->enumerator(ii);
385 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
386 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
389 builder.addEnumerator(enumerator);
394 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
397 i -= mo->propertyOffset();
398 if (i < 0 && mo->d.superdata)
399 return isPropertyRevisioned(mo->d.superdata, index);
401 const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
402 if (i >= 0 && i < mop->propertyCount) {
403 int handle = mop->propertyData + 3*i;
404 int flags = mo->d.data[handle + 2];
406 return (flags & Revisioned);
412 void QQmlTypePrivate::init() const
414 if (m_isSetup) return;
416 QWriteLocker lock(metaTypeDataLock());
420 // Setup extended meta object
421 // XXX - very inefficient
422 const QMetaObject *mo = m_baseMetaObject;
424 QMetaObjectBuilder builder;
425 clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
426 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
427 QMetaObject *mmo = builder.toMetaObject();
428 mmo->d.superdata = mo;
429 QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
430 m_metaObjects << data;
433 mo = mo->d.superdata;
435 QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
437 if (t->d->m_extFunc) {
438 QMetaObjectBuilder builder;
439 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
440 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
441 QMetaObject *mmo = builder.toMetaObject();
442 mmo->d.superdata = m_baseMetaObject;
443 if (!m_metaObjects.isEmpty())
444 m_metaObjects.last().metaObject->d.superdata = mmo;
445 QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
446 m_metaObjects << data;
449 mo = mo->d.superdata;
452 for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
453 m_metaObjects[ii].propertyOffset =
454 m_metaObjects.at(ii).metaObject->propertyOffset();
455 m_metaObjects[ii].methodOffset =
456 m_metaObjects.at(ii).metaObject->methodOffset();
459 // Check for revisioned details
461 const QMetaObject *mo = 0;
462 if (m_metaObjects.isEmpty())
463 mo = m_baseMetaObject;
465 mo = m_metaObjects.first().metaObject;
467 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
468 if (isPropertyRevisioned(mo, ii))
469 m_containsRevisionedAttributes = true;
472 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
473 if (mo->method(ii).revision() != 0)
474 m_containsRevisionedAttributes = true;
482 void QQmlTypePrivate::initEnums() const
484 if (m_isEnumSetup) return;
488 QWriteLocker lock(metaTypeDataLock());
489 if (m_isEnumSetup) return;
491 insertEnums(m_baseMetaObject);
493 m_isEnumSetup = true;
496 void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
498 // Add any enum values defined by 'related' classes
499 if (metaObject->d.relatedMetaObjects) {
500 const QMetaObject **related = metaObject->d.relatedMetaObjects;
503 insertEnums(*related++);
507 // Add any enum values defined by this class, overwriting any inherited values
508 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
509 QMetaEnum e = metaObject->enumerator(ii);
510 for (int jj = 0; jj < e.keyCount(); ++jj)
511 m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
515 QByteArray QQmlType::typeName() const
517 if (d->m_baseMetaObject)
518 return d->m_baseMetaObject->className();
523 const QString &QQmlType::elementName() const
525 return d->m_elementName;
528 const QString &QQmlType::qmlTypeName() const
530 if (d->m_name.isEmpty()) {
531 if (!d->m_module.isEmpty())
532 d->m_name = static_cast<QString>(d->m_module) + QLatin1Char('/') + d->m_elementName;
534 d->m_name = d->m_elementName;
540 QObject *QQmlType::create() const
544 QObject *rv = (QObject *)operator new(d->m_allocationSize);
547 if (rv && !d->m_metaObjects.isEmpty())
548 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
553 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
557 QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
560 if (rv && !d->m_metaObjects.isEmpty())
561 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
564 *memory = ((char *)rv) + d->m_allocationSize;
567 QQmlCustomParser *QQmlType::customParser() const
569 return d->m_customParser;
572 QQmlType::CreateFunc QQmlType::createFunction() const
577 QString QQmlType::noCreationReason() const
579 return d->m_noCreationReason;
582 int QQmlType::createSize() const
584 return d->m_allocationSize;
587 bool QQmlType::isCreatable() const
589 return d->m_newFunc != 0;
592 bool QQmlType::isExtendedType() const
596 return !d->m_metaObjects.isEmpty();
599 bool QQmlType::isInterface() const
601 return d->m_isInterface;
604 int QQmlType::typeId() const
609 int QQmlType::qListTypeId() const
614 const QMetaObject *QQmlType::metaObject() const
618 if (d->m_metaObjects.isEmpty())
619 return d->m_baseMetaObject;
621 return d->m_metaObjects.first().metaObject;
625 const QMetaObject *QQmlType::baseMetaObject() const
627 return d->m_baseMetaObject;
630 bool QQmlType::containsRevisionedAttributes() const
634 return d->m_containsRevisionedAttributes;
637 int QQmlType::metaObjectRevision() const
639 return d->m_revision;
642 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
644 return d->m_attachedPropertiesFunc;
647 const QMetaObject *QQmlType::attachedPropertiesType() const
649 return d->m_attachedPropertiesType;
653 This is the id passed to qmlAttachedPropertiesById(). This is different from the index
654 for the case that a single class is registered under two or more names (eg. Item in
655 Qt 4.7 and QtQuick 1.0).
657 int QQmlType::attachedPropertiesId() const
659 return d->m_attachedPropertiesId;
662 int QQmlType::parserStatusCast() const
664 return d->m_parserStatusCast;
667 int QQmlType::propertyValueSourceCast() const
669 return d->m_propertyValueSourceCast;
672 int QQmlType::propertyValueInterceptorCast() const
674 return d->m_propertyValueInterceptorCast;
677 const char *QQmlType::interfaceIId() const
682 int QQmlType::index() const
687 int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const
694 int *rv = d->m_enums.value(name);
702 int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const
709 int *rv = d->m_enums.value(name);
717 int QQmlType::enumValue(const QHashedV8String &name, bool *ok) const
724 int *rv = d->m_enums.value(name);
732 QQmlTypeModule::QQmlTypeModule()
733 : d(new QQmlTypeModulePrivate)
737 QQmlTypeModule::~QQmlTypeModule()
742 QString QQmlTypeModule::module() const
747 int QQmlTypeModule::majorVersion() const
749 return d->uri.majorVersion;
752 int QQmlTypeModule::minimumMinorVersion() const
754 return d->minMinorVersion;
757 int QQmlTypeModule::maximumMinorVersion() const
759 return d->maxMinorVersion;
762 void QQmlTypeModulePrivate::add(QQmlType *type)
764 minMinorVersion = qMin(minMinorVersion, type->minorVersion());
765 maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
767 QList<QQmlType *> &list = typeHash[type->elementName()];
768 for (int ii = 0; ii < list.count(); ++ii) {
769 if (list.at(ii)->minorVersion() < type->minorVersion()) {
770 list.insert(ii, type);
777 QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
779 QReadLocker lock(metaTypeDataLock());
781 QList<QQmlType *> *types = d->typeHash.value(name);
782 if (!types) return 0;
784 for (int ii = 0; ii < types->count(); ++ii)
785 if (types->at(ii)->minorVersion() <= minor)
786 return types->at(ii);
791 QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor)
793 QReadLocker lock(metaTypeDataLock());
795 QList<QQmlType *> *types = d->typeHash.value(name);
796 if (!types) return 0;
798 for (int ii = 0; ii < types->count(); ++ii)
799 if (types->at(ii)->minorVersion() <= minor)
800 return types->at(ii);
806 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
807 : m_module(0), m_minor(0)
811 QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
812 : m_module(module), m_minor(minor)
815 Q_ASSERT(m_minor >= 0);
818 QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
819 : m_module(o.m_module), m_minor(o.m_minor)
823 QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
825 m_module = o.m_module;
830 QQmlTypeModule *QQmlTypeModuleVersion::module() const
835 int QQmlTypeModuleVersion::minorVersion() const
840 QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
842 if (m_module) return m_module->type(name, m_minor);
846 QQmlType *QQmlTypeModuleVersion::type(const QHashedV8String &name) const
848 if (m_module) return m_module->type(name, m_minor);
853 int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
855 QWriteLocker lock(metaTypeDataLock());
856 QQmlMetaTypeData *data = metaTypeData();
858 data->parentFunctions.append(autoparent.function);
860 return data->parentFunctions.count() - 1;
863 int registerInterface(const QQmlPrivate::RegisterInterface &interface)
865 if (interface.version > 0)
866 qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
868 QWriteLocker lock(metaTypeDataLock());
869 QQmlMetaTypeData *data = metaTypeData();
871 int index = data->types.count();
873 QQmlType *type = new QQmlType(index, interface);
875 data->types.append(type);
876 data->idToType.insert(type->typeId(), type);
877 data->idToType.insert(type->qListTypeId(), type);
878 // XXX No insertMulti, so no multi-version interfaces?
879 if (!type->elementName().isEmpty())
880 data->nameToType.insert(type->elementName(), type);
882 if (data->interfaces.size() <= interface.typeId)
883 data->interfaces.resize(interface.typeId + 16);
884 if (data->lists.size() <= interface.listId)
885 data->lists.resize(interface.listId + 16);
886 data->interfaces.setBit(interface.typeId, true);
887 data->lists.setBit(interface.listId, true);
892 int registerType(const QQmlPrivate::RegisterType &type)
894 if (type.elementName) {
895 for (int ii = 0; type.elementName[ii]; ++ii) {
896 if (!isalnum(type.elementName[ii])) {
897 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
903 QWriteLocker lock(metaTypeDataLock());
904 QQmlMetaTypeData *data = metaTypeData();
905 int index = data->types.count();
907 QQmlType *dtype = new QQmlType(index, type);
909 data->types.append(dtype);
910 data->idToType.insert(dtype->typeId(), dtype);
911 if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
913 if (!dtype->elementName().isEmpty())
914 data->nameToType.insertMulti(dtype->elementName(), dtype);
916 data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
918 if (data->objects.size() <= type.typeId)
919 data->objects.resize(type.typeId + 16);
920 if (data->lists.size() <= type.listId)
921 data->lists.resize(type.listId + 16);
922 data->objects.setBit(type.typeId, true);
923 if (type.listId) data->lists.setBit(type.listId, true);
925 if (!dtype->module().isEmpty()) {
926 const QHashedString &mod = dtype->module();
928 QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
929 QQmlTypeModule *module = data->uriToModule.value(versionedUri);
931 module = new QQmlTypeModule;
932 module->d->uri = versionedUri;
933 data->uriToModule.insert(versionedUri, module);
935 module->d->add(dtype);
941 int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api)
943 QWriteLocker lock(metaTypeDataLock());
945 QQmlMetaTypeData *data = metaTypeData();
946 QString uri = QString::fromUtf8(api.uri);
947 QQmlMetaType::ModuleApi import;
948 import.major = api.versionMajor;
949 import.minor = api.versionMinor;
950 import.script = api.scriptApi;
951 import.qobject = api.qobjectApi;
952 import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0.
954 int index = data->moduleApiCount++;
956 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri);
958 QQmlMetaTypeData::ModuleApiList apis;
959 apis.moduleApis << import;
960 data->moduleApis.insert(uri, apis);
962 apiList->moduleApis << import;
963 apiList->sorted = false;
971 This method is "over generalized" to allow us to (potentially) register more types of things in
972 the future without adding exported symbols.
974 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
976 if (type == TypeRegistration) {
977 return registerType(*reinterpret_cast<RegisterType *>(data));
978 } else if (type == InterfaceRegistration) {
979 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
980 } else if (type == AutoParentRegistration) {
981 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
982 } else if (type == ModuleApiRegistration) {
983 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
989 Returns true if a module \a uri of any version is installed.
991 bool QQmlMetaType::isAnyModule(const QString &uri)
993 QReadLocker lock(metaTypeDataLock());
994 QQmlMetaTypeData *data = metaTypeData();
996 // first, check Types
997 for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
998 iter != data->uriToModule.end(); ++iter) {
999 if ((*iter)->module() == uri)
1003 // then, check ModuleApis
1004 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri);
1012 Returns true if any type or API has been registered for the given \a module with at least
1013 versionMajor.versionMinor, or if types have been registered for \a module with at most
1014 versionMajor.versionMinor.
1016 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.
1018 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
1020 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
1021 QReadLocker lock(metaTypeDataLock());
1023 QQmlMetaTypeData *data = metaTypeData();
1025 // first, check Types
1026 QQmlTypeModule *tm =
1027 data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
1028 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
1031 // then, check ModuleApis
1032 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(module);
1034 foreach (const QQmlMetaType::ModuleApi &mApi, apiList->moduleApis) {
1035 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
1043 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
1045 QReadLocker lock(metaTypeDataLock());
1046 QQmlMetaTypeData *data = metaTypeData();
1047 return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
1050 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1052 QReadLocker lock(metaTypeDataLock());
1053 QQmlMetaTypeData *data = metaTypeData();
1054 return data->parentFunctions;
1057 static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs)
1059 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1062 QQmlMetaType::ModuleApi
1063 QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
1065 QReadLocker lock(metaTypeDataLock());
1066 QQmlMetaTypeData *data = metaTypeData();
1068 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri);
1072 if (apiList->sorted == false) {
1073 qSort(apiList->moduleApis.begin(), apiList->moduleApis.end());
1074 apiList->sorted = true;
1077 for (int ii = apiList->moduleApis.count() - 1; ii >= 0; --ii) {
1078 const ModuleApi &import = apiList->moduleApis.at(ii);
1079 if (import.major == versionMajor && import.minor <= versionMinor)
1086 QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis()
1088 QReadLocker lock(metaTypeDataLock());
1089 QQmlMetaTypeData *data = metaTypeData();
1091 QHash<QString, QList<ModuleApi> > moduleApis;
1092 QStringHash<QQmlMetaTypeData::ModuleApiList>::ConstIterator it = data->moduleApis.begin();
1093 for (; it != data->moduleApis.end(); ++it)
1094 moduleApis[it.key()] = it.value().moduleApis;
1099 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1101 if (!isQObject(v.userType())) {
1102 if (ok) *ok = false;
1108 return *(QObject **)v.constData();
1111 bool QQmlMetaType::isQObject(int userType)
1113 if (userType == QMetaType::QObjectStar)
1116 QReadLocker lock(metaTypeDataLock());
1117 QQmlMetaTypeData *data = metaTypeData();
1118 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1122 Returns the item type for a list of type \a id.
1124 int QQmlMetaType::listType(int id)
1126 QReadLocker lock(metaTypeDataLock());
1127 QQmlMetaTypeData *data = metaTypeData();
1128 QQmlType *type = data->idToType.value(id);
1129 if (type && type->qListTypeId() == id)
1130 return type->typeId();
1135 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1137 QReadLocker lock(metaTypeDataLock());
1138 QQmlMetaTypeData *data = metaTypeData();
1140 QQmlType *type = data->metaObjectToType.value(mo);
1141 if (type && type->attachedPropertiesFunction())
1142 return type->attachedPropertiesId();
1147 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1151 QReadLocker lock(metaTypeDataLock());
1152 QQmlMetaTypeData *data = metaTypeData();
1153 return data->types.at(id)->attachedPropertiesFunction();
1156 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1158 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1160 return QMetaProperty();
1162 QMetaClassInfo info = metaObject->classInfo(idx);
1164 return QMetaProperty();
1166 idx = metaObject->indexOfProperty(info.value());
1168 return QMetaProperty();
1170 return metaObject->property(idx);
1173 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1176 return QMetaProperty();
1178 const QMetaObject *metaObject = obj->metaObject();
1179 return defaultProperty(metaObject);
1182 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1184 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1186 return QMetaMethod();
1188 QMetaClassInfo info = metaObject->classInfo(idx);
1190 return QMetaMethod();
1192 idx = metaObject->indexOfMethod(info.value());
1194 return QMetaMethod();
1196 return metaObject->method(idx);
1199 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1202 return QMetaMethod();
1204 const QMetaObject *metaObject = obj->metaObject();
1205 return defaultMethod(metaObject);
1208 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1212 if (userType == QMetaType::QObjectStar)
1215 QReadLocker lock(metaTypeDataLock());
1216 QQmlMetaTypeData *data = metaTypeData();
1217 if (userType < data->objects.size() && data->objects.testBit(userType))
1219 else if (userType < data->lists.size() && data->lists.testBit(userType))
1225 bool QQmlMetaType::isInterface(int userType)
1227 QReadLocker lock(metaTypeDataLock());
1228 QQmlMetaTypeData *data = metaTypeData();
1229 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1232 const char *QQmlMetaType::interfaceIId(int userType)
1234 QReadLocker lock(metaTypeDataLock());
1235 QQmlMetaTypeData *data = metaTypeData();
1236 QQmlType *type = data->idToType.value(userType);
1238 if (type && type->isInterface() && type->typeId() == userType)
1239 return type->interfaceIId();
1244 bool QQmlMetaType::isList(int userType)
1246 QReadLocker lock(metaTypeDataLock());
1247 QQmlMetaTypeData *data = metaTypeData();
1248 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1252 A custom string convertor allows you to specify a function pointer that
1253 returns a variant of \a type. For example, if you have written your own icon
1254 class that you want to support as an object property assignable in QML:
1257 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1258 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1261 The function pointer must be of the form:
1263 QVariant (*StringConverter)(const QString &);
1266 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1268 QWriteLocker lock(metaTypeDataLock());
1270 QQmlMetaTypeData *data = metaTypeData();
1271 if (data->stringConverters.contains(type))
1273 data->stringConverters.insert(type, converter);
1277 Return the custom string converter for \a type, previously installed through
1278 registerCustomStringConverter()
1280 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1282 QReadLocker lock(metaTypeDataLock());
1284 QQmlMetaTypeData *data = metaTypeData();
1285 return data->stringConverters.value(type);
1289 Returns the type (if any) of URI-qualified named \a qualifiedName and version specified
1290 by \a version_major and \a version_minor.
1292 QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
1294 int slash = qualifiedName.indexOf(QLatin1Char('/'));
1298 QHashedStringRef module(qualifiedName.constData(), slash);
1299 QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1);
1301 return qmlType(name, module, version_major, version_minor);
1305 Returns the type (if any) of \a name in \a module and version specified
1306 by \a version_major and \a version_minor.
1308 QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
1310 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1311 QReadLocker lock(metaTypeDataLock());
1312 QQmlMetaTypeData *data = metaTypeData();
1314 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1315 while (it != data->nameToType.end() && it.key() == name) {
1316 // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1317 if (version_major < 0 || (*it)->availableInVersion(module, version_major,version_minor))
1326 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1329 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1331 QReadLocker lock(metaTypeDataLock());
1332 QQmlMetaTypeData *data = metaTypeData();
1334 return data->metaObjectToType.value(metaObject);
1338 Returns the type (if any) that corresponds to the \a metaObject in version specified
1339 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1342 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
1344 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1345 QReadLocker lock(metaTypeDataLock());
1346 QQmlMetaTypeData *data = metaTypeData();
1348 QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1349 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1351 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1360 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1361 Returns null if no type is registered.
1363 QQmlType *QQmlMetaType::qmlType(int userType)
1365 QReadLocker lock(metaTypeDataLock());
1366 QQmlMetaTypeData *data = metaTypeData();
1368 QQmlType *type = data->idToType.value(userType);
1369 if (type && type->typeId() == userType)
1376 Returns the list of registered QML type names.
1378 QList<QString> QQmlMetaType::qmlTypeNames()
1380 QReadLocker lock(metaTypeDataLock());
1381 QQmlMetaTypeData *data = metaTypeData();
1383 QList<QString> names;
1384 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
1385 while (it != data->nameToType.end()) {
1386 names += (*it)->qmlTypeName();
1394 Returns the list of registered QML types.
1396 QList<QQmlType*> QQmlMetaType::qmlTypes()
1398 QReadLocker lock(metaTypeDataLock());
1399 QQmlMetaTypeData *data = metaTypeData();
1401 return data->nameToType.values();
1404 int QQmlMetaType::QQuickAnchorLineMetaTypeId()
1408 id = QMetaType::type("QQuickAnchorLine");
1413 QQmlMetaType::CompareFunction QQmlMetaType::anchorLineCompareFunction = 0;
1415 void QQmlMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1417 anchorLineCompareFunction = fun;
1420 bool QQmlMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1422 Q_ASSERT(anchorLineCompareFunction != 0);
1423 return anchorLineCompareFunction(p1, p2);