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<QString, 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 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, QQmlTypeModule *> TypeModules;
95 TypeModules uriToModule;
97 struct ModuleApiList {
98 ModuleApiList() : sorted(true) {}
99 QList<QQmlMetaType::ModuleApi> moduleApis;
102 typedef QHash<QString, 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 qHash(v.uri) ^ 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;
157 bool m_isInterface : 1;
161 QString m_elementName;
164 int m_typeId; int m_listId;
166 mutable bool m_containsRevisionedAttributes;
167 mutable QQmlType *m_superType;
169 int m_allocationSize;
170 void (*m_newFunc)(void *);
171 QString m_noCreationReason;
173 const QMetaObject *m_baseMetaObject;
174 QQmlAttachedPropertiesFunc 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 QQmlCustomParser *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<QQmlProxyMetaObject::ProxyData> m_metaObjects;
188 mutable QStringHash<int> m_enums;
190 static QHash<const QMetaObject *, int> m_attachedPropertyIds;
193 QHash<const QMetaObject *, int> QQmlTypePrivate::m_attachedPropertyIds;
195 QQmlTypePrivate::QQmlTypePrivate()
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 QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface)
206 : d(new QQmlTypePrivate)
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 QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type)
220 : d(new QQmlTypePrivate)
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 QQmlType::~QQmlType()
261 delete d->m_customParser;
265 QString QQmlType::module() const
270 int QQmlType::majorVersion() const
272 return d->m_version_maj;
275 int QQmlType::minorVersion() const
277 return d->m_version_min;
280 bool QQmlType::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 QQmlType::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 QQmlType *QQmlType::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 = QQmlMetaType::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.name();
348 for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
349 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
352 QMetaMethod other = ignoreEnd->method(ii);
354 found = name == other.name();
357 QMetaMethodBuilder m = builder.addMethod(method);
359 m.setAccess(QMetaMethod::Private);
363 for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
364 QMetaEnum enumerator = mo->enumerator(ii);
366 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
367 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
370 builder.addEnumerator(enumerator);
375 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
378 i -= mo->propertyOffset();
379 if (i < 0 && mo->d.superdata)
380 return isPropertyRevisioned(mo->d.superdata, index);
382 const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
383 if (i >= 0 && i < mop->propertyCount) {
384 int handle = mop->propertyData + 3*i;
385 int flags = mo->d.data[handle + 2];
387 return (flags & Revisioned);
393 void QQmlTypePrivate::init() const
395 if (m_isSetup) return;
397 QWriteLocker lock(metaTypeDataLock());
401 // Setup extended meta object
402 // XXX - very inefficient
403 const QMetaObject *mo = m_baseMetaObject;
405 QMetaObjectBuilder builder;
406 clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
407 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
408 QMetaObject *mmo = builder.toMetaObject();
409 mmo->d.superdata = mo;
410 QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
411 m_metaObjects << data;
414 mo = mo->d.superdata;
416 QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
418 if (t->d->m_extFunc) {
419 QMetaObjectBuilder builder;
420 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
421 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
422 QMetaObject *mmo = builder.toMetaObject();
423 mmo->d.superdata = m_baseMetaObject;
424 if (!m_metaObjects.isEmpty())
425 m_metaObjects.last().metaObject->d.superdata = mmo;
426 QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
427 m_metaObjects << data;
430 mo = mo->d.superdata;
433 for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
434 m_metaObjects[ii].propertyOffset =
435 m_metaObjects.at(ii).metaObject->propertyOffset();
436 m_metaObjects[ii].methodOffset =
437 m_metaObjects.at(ii).metaObject->methodOffset();
440 // Check for revisioned details
442 const QMetaObject *mo = 0;
443 if (m_metaObjects.isEmpty())
444 mo = m_baseMetaObject;
446 mo = m_metaObjects.first().metaObject;
448 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
449 if (isPropertyRevisioned(mo, ii))
450 m_containsRevisionedAttributes = true;
453 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
454 if (mo->method(ii).revision() != 0)
455 m_containsRevisionedAttributes = true;
463 void QQmlTypePrivate::initEnums() const
465 if (m_isEnumSetup) return;
469 QWriteLocker lock(metaTypeDataLock());
470 if (m_isEnumSetup) return;
472 const QMetaObject *metaObject = m_baseMetaObject;
473 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
475 QMetaEnum e = metaObject->enumerator(ii);
477 for (int jj = 0; jj < e.keyCount(); ++jj)
478 m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
481 m_isEnumSetup = true;
484 QByteArray QQmlType::typeName() const
486 if (d->m_baseMetaObject)
487 return d->m_baseMetaObject->className();
492 const QString &QQmlType::elementName() const
494 if (d->m_elementName.isEmpty()) {
495 QString n = qmlTypeName();
496 int idx = n.lastIndexOf(QLatin1Char('/'));
497 d->m_elementName = n.mid(idx + 1);
499 return d->m_elementName;
502 const QString &QQmlType::qmlTypeName() const
507 QObject *QQmlType::create() const
511 QObject *rv = (QObject *)operator new(d->m_allocationSize);
514 if (rv && !d->m_metaObjects.isEmpty())
515 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
520 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
524 QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
527 if (rv && !d->m_metaObjects.isEmpty())
528 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
531 *memory = ((char *)rv) + d->m_allocationSize;
534 QQmlCustomParser *QQmlType::customParser() const
536 return d->m_customParser;
539 QQmlType::CreateFunc QQmlType::createFunction() const
544 QString QQmlType::noCreationReason() const
546 return d->m_noCreationReason;
549 int QQmlType::createSize() const
551 return d->m_allocationSize;
554 bool QQmlType::isCreatable() const
556 return d->m_newFunc != 0;
559 bool QQmlType::isExtendedType() const
563 return !d->m_metaObjects.isEmpty();
566 bool QQmlType::isInterface() const
568 return d->m_isInterface;
571 int QQmlType::typeId() const
576 int QQmlType::qListTypeId() const
581 const QMetaObject *QQmlType::metaObject() const
585 if (d->m_metaObjects.isEmpty())
586 return d->m_baseMetaObject;
588 return d->m_metaObjects.first().metaObject;
592 const QMetaObject *QQmlType::baseMetaObject() const
594 return d->m_baseMetaObject;
597 bool QQmlType::containsRevisionedAttributes() const
601 return d->m_containsRevisionedAttributes;
604 int QQmlType::metaObjectRevision() const
606 return d->m_revision;
609 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
611 return d->m_attachedPropertiesFunc;
614 const QMetaObject *QQmlType::attachedPropertiesType() const
616 return d->m_attachedPropertiesType;
620 This is the id passed to qmlAttachedPropertiesById(). This is different from the index
621 for the case that a single class is registered under two or more names (eg. Item in
622 Qt 4.7 and QtQuick 1.0).
624 int QQmlType::attachedPropertiesId() const
626 return d->m_attachedPropertiesId;
629 int QQmlType::parserStatusCast() const
631 return d->m_parserStatusCast;
634 int QQmlType::propertyValueSourceCast() const
636 return d->m_propertyValueSourceCast;
639 int QQmlType::propertyValueInterceptorCast() const
641 return d->m_propertyValueInterceptorCast;
644 const char *QQmlType::interfaceIId() const
649 int QQmlType::index() const
654 int QQmlType::enumValue(const QHashedStringRef &name) const
658 int *rv = d->m_enums.value(name);
662 int QQmlType::enumValue(const QHashedV8String &name) const
666 int *rv = d->m_enums.value(name);
670 QQmlTypeModule::QQmlTypeModule()
671 : d(new QQmlTypeModulePrivate)
675 QQmlTypeModule::~QQmlTypeModule()
680 QString QQmlTypeModule::module() const
685 int QQmlTypeModule::majorVersion() const
687 return d->uri.majorVersion;
690 int QQmlTypeModule::minimumMinorVersion() const
692 return d->minMinorVersion;
695 int QQmlTypeModule::maximumMinorVersion() const
697 return d->maxMinorVersion;
700 void QQmlTypeModulePrivate::add(QQmlType *type)
704 minMinorVersion = qMin(minMinorVersion, type->minorVersion());
705 maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
707 QList<QQmlType *> &list = typeHash[type->elementName()];
708 for (int ii = 0; ii < list.count(); ++ii) {
709 if (list.at(ii)->minorVersion() < type->minorVersion()) {
710 list.insert(ii, type);
717 QList<QQmlType *> QQmlTypeModule::types()
719 QList<QQmlType *> rv;
720 QReadLocker lock(metaTypeDataLock());
725 QList<QQmlType *> QQmlTypeModule::type(const QString &name)
727 QReadLocker lock(metaTypeDataLock());
728 QList<QQmlType *> rv;
729 for (int ii = 0; ii < d->types.count(); ++ii) {
730 if (d->types.at(ii)->elementName() == name)
731 rv << d->types.at(ii);
736 QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
738 QReadLocker lock(metaTypeDataLock());
740 QList<QQmlType *> *types = d->typeHash.value(name);
741 if (!types) return 0;
743 for (int ii = 0; ii < types->count(); ++ii)
744 if (types->at(ii)->minorVersion() <= minor)
745 return types->at(ii);
750 QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor)
752 QReadLocker lock(metaTypeDataLock());
754 QList<QQmlType *> *types = d->typeHash.value(name);
755 if (!types) return 0;
757 for (int ii = 0; ii < types->count(); ++ii)
758 if (types->at(ii)->minorVersion() <= minor)
759 return types->at(ii);
765 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
766 : m_module(0), m_minor(0)
770 QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
771 : m_module(module), m_minor(minor)
774 Q_ASSERT(m_minor >= 0);
777 QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
778 : m_module(o.m_module), m_minor(o.m_minor)
782 QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
784 m_module = o.m_module;
789 QQmlTypeModule *QQmlTypeModuleVersion::module() const
794 int QQmlTypeModuleVersion::minorVersion() const
799 QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
801 if (m_module) return m_module->type(name, m_minor);
805 QQmlType *QQmlTypeModuleVersion::type(const QHashedV8String &name) const
807 if (m_module) return m_module->type(name, m_minor);
812 int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
814 QWriteLocker lock(metaTypeDataLock());
815 QQmlMetaTypeData *data = metaTypeData();
817 data->parentFunctions.append(autoparent.function);
819 return data->parentFunctions.count() - 1;
822 int registerInterface(const QQmlPrivate::RegisterInterface &interface)
824 if (interface.version > 0)
825 qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
827 QWriteLocker lock(metaTypeDataLock());
828 QQmlMetaTypeData *data = metaTypeData();
830 int index = data->types.count();
832 QQmlType *type = new QQmlType(index, interface);
834 data->types.append(type);
835 data->idToType.insert(type->typeId(), type);
836 data->idToType.insert(type->qListTypeId(), type);
837 // XXX No insertMulti, so no multi-version interfaces?
838 if (!type->qmlTypeName().isEmpty())
839 data->nameToType.insert(type->qmlTypeName(), type);
841 if (data->interfaces.size() <= interface.typeId)
842 data->interfaces.resize(interface.typeId + 16);
843 if (data->lists.size() <= interface.listId)
844 data->lists.resize(interface.listId + 16);
845 data->interfaces.setBit(interface.typeId, true);
846 data->lists.setBit(interface.listId, true);
851 int registerType(const QQmlPrivate::RegisterType &type)
853 if (type.elementName) {
854 for (int ii = 0; type.elementName[ii]; ++ii) {
855 if (!isalnum(type.elementName[ii])) {
856 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
862 QWriteLocker lock(metaTypeDataLock());
863 QQmlMetaTypeData *data = metaTypeData();
864 int index = data->types.count();
866 QQmlType *dtype = new QQmlType(index, type);
868 data->types.append(dtype);
869 data->idToType.insert(dtype->typeId(), dtype);
870 if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
872 if (!dtype->qmlTypeName().isEmpty())
873 data->nameToType.insertMulti(dtype->qmlTypeName(), dtype);
875 data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
877 if (data->objects.size() <= type.typeId)
878 data->objects.resize(type.typeId + 16);
879 if (data->lists.size() <= type.listId)
880 data->lists.resize(type.listId + 16);
881 data->objects.setBit(type.typeId, true);
882 if (type.listId) data->lists.setBit(type.listId, true);
885 QString mod = QString::fromUtf8(type.uri);
887 QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
888 QQmlTypeModule *module = data->uriToModule.value(versionedUri);
890 module = new QQmlTypeModule;
891 module->d->uri = versionedUri;
892 data->uriToModule.insert(versionedUri, module);
894 module->d->add(dtype);
900 int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api)
902 QWriteLocker lock(metaTypeDataLock());
904 QQmlMetaTypeData *data = metaTypeData();
905 QString uri = QString::fromUtf8(api.uri);
906 QQmlMetaType::ModuleApi import;
907 import.major = api.versionMajor;
908 import.minor = api.versionMinor;
909 import.script = api.scriptApi;
910 import.qobject = api.qobjectApi;
911 import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0.
913 if (import.qobject && !import.instanceMetaObject) // BC - check import.iMO rather than api.iMO.
914 qWarning() << "qmlRegisterModuleApi(): sub-optimal: use the templated version of this function instead!";
916 int index = data->moduleApiCount++;
918 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
919 if (iter == data->moduleApis.end()) {
920 QQmlMetaTypeData::ModuleApiList apis;
921 apis.moduleApis << import;
922 data->moduleApis.insert(uri, apis);
924 iter->moduleApis << import;
925 iter->sorted = false;
933 This method is "over generalized" to allow us to (potentially) register more types of things in
934 the future without adding exported symbols.
936 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
938 if (type == TypeRegistration) {
939 return registerType(*reinterpret_cast<RegisterType *>(data));
940 } else if (type == InterfaceRegistration) {
941 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
942 } else if (type == AutoParentRegistration) {
943 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
944 } else if (type == ModuleApiRegistration) {
945 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
951 Returns true if a module \a uri of any version is installed.
953 bool QQmlMetaType::isAnyModule(const QString &uri)
955 QReadLocker lock(metaTypeDataLock());
956 QQmlMetaTypeData *data = metaTypeData();
958 for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
959 iter != data->uriToModule.end(); ++iter) {
960 if ((*iter)->module() == uri)
968 Returns true if any type or API has been registered for the given \a module with at least
969 versionMajor.versionMinor, or if types have been registered for \a module with at most
970 versionMajor.versionMinor.
972 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.
974 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
976 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
977 QReadLocker lock(metaTypeDataLock());
979 QQmlMetaTypeData *data = metaTypeData();
981 // first, check Types
983 data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
984 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
987 // then, check ModuleApis
988 foreach (const QQmlMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
989 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
996 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
998 QReadLocker lock(metaTypeDataLock());
999 QQmlMetaTypeData *data = metaTypeData();
1000 return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
1003 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1005 QReadLocker lock(metaTypeDataLock());
1006 QQmlMetaTypeData *data = metaTypeData();
1007 return data->parentFunctions;
1010 static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs)
1012 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1015 QQmlMetaType::ModuleApi
1016 QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
1018 QReadLocker lock(metaTypeDataLock());
1019 QQmlMetaTypeData *data = metaTypeData();
1021 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
1022 if (iter == data->moduleApis.end())
1025 if (iter->sorted == false) {
1026 qSort(iter->moduleApis.begin(), iter->moduleApis.end());
1027 iter->sorted = true;
1030 for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) {
1031 const ModuleApi &import = iter->moduleApis.at(ii);
1032 if (import.major == versionMajor && import.minor <= versionMinor)
1039 QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis()
1041 QReadLocker lock(metaTypeDataLock());
1042 QQmlMetaTypeData *data = metaTypeData();
1044 QHash<QString, QList<ModuleApi> > moduleApis;
1045 QHashIterator<QString, QQmlMetaTypeData::ModuleApiList> it(data->moduleApis);
1046 while (it.hasNext()) {
1048 moduleApis[it.key()] = it.value().moduleApis;
1054 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1056 if (!isQObject(v.userType())) {
1057 if (ok) *ok = false;
1063 return *(QObject **)v.constData();
1066 bool QQmlMetaType::isQObject(int userType)
1068 if (userType == QMetaType::QObjectStar)
1071 QReadLocker lock(metaTypeDataLock());
1072 QQmlMetaTypeData *data = metaTypeData();
1073 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1077 Returns the item type for a list of type \a id.
1079 int QQmlMetaType::listType(int id)
1081 QReadLocker lock(metaTypeDataLock());
1082 QQmlMetaTypeData *data = metaTypeData();
1083 QQmlType *type = data->idToType.value(id);
1084 if (type && type->qListTypeId() == id)
1085 return type->typeId();
1090 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1092 QReadLocker lock(metaTypeDataLock());
1093 QQmlMetaTypeData *data = metaTypeData();
1095 QQmlType *type = data->metaObjectToType.value(mo);
1096 if (type && type->attachedPropertiesFunction())
1097 return type->attachedPropertiesId();
1102 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1106 QReadLocker lock(metaTypeDataLock());
1107 QQmlMetaTypeData *data = metaTypeData();
1108 return data->types.at(id)->attachedPropertiesFunction();
1111 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1113 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1115 return QMetaProperty();
1117 QMetaClassInfo info = metaObject->classInfo(idx);
1119 return QMetaProperty();
1121 idx = metaObject->indexOfProperty(info.value());
1123 return QMetaProperty();
1125 return metaObject->property(idx);
1128 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1131 return QMetaProperty();
1133 const QMetaObject *metaObject = obj->metaObject();
1134 return defaultProperty(metaObject);
1137 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1139 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1141 return QMetaMethod();
1143 QMetaClassInfo info = metaObject->classInfo(idx);
1145 return QMetaMethod();
1147 idx = metaObject->indexOfMethod(info.value());
1149 return QMetaMethod();
1151 return metaObject->method(idx);
1154 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1157 return QMetaMethod();
1159 const QMetaObject *metaObject = obj->metaObject();
1160 return defaultMethod(metaObject);
1163 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1167 if (userType == QMetaType::QObjectStar)
1170 QReadLocker lock(metaTypeDataLock());
1171 QQmlMetaTypeData *data = metaTypeData();
1172 if (userType < data->objects.size() && data->objects.testBit(userType))
1174 else if (userType < data->lists.size() && data->lists.testBit(userType))
1180 bool QQmlMetaType::isInterface(int userType)
1182 QReadLocker lock(metaTypeDataLock());
1183 QQmlMetaTypeData *data = metaTypeData();
1184 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1187 const char *QQmlMetaType::interfaceIId(int userType)
1189 QReadLocker lock(metaTypeDataLock());
1190 QQmlMetaTypeData *data = metaTypeData();
1191 QQmlType *type = data->idToType.value(userType);
1193 if (type && type->isInterface() && type->typeId() == userType)
1194 return type->interfaceIId();
1199 bool QQmlMetaType::isList(int userType)
1201 QReadLocker lock(metaTypeDataLock());
1202 QQmlMetaTypeData *data = metaTypeData();
1203 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1207 A custom string convertor allows you to specify a function pointer that
1208 returns a variant of \a type. For example, if you have written your own icon
1209 class that you want to support as an object property assignable in QML:
1212 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1213 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1216 The function pointer must be of the form:
1218 QVariant (*StringConverter)(const QString &);
1221 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1223 QWriteLocker lock(metaTypeDataLock());
1225 QQmlMetaTypeData *data = metaTypeData();
1226 if (data->stringConverters.contains(type))
1228 data->stringConverters.insert(type, converter);
1232 Return the custom string converter for \a type, previously installed through
1233 registerCustomStringConverter()
1235 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1237 QReadLocker lock(metaTypeDataLock());
1239 QQmlMetaTypeData *data = metaTypeData();
1240 return data->stringConverters.value(type);
1244 Returns the type (if any) of URI-qualified named \a name in version specified
1245 by \a version_major and \a version_minor.
1247 QQmlType *QQmlMetaType::qmlType(const QString &name, int version_major, int version_minor)
1249 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1250 QReadLocker lock(metaTypeDataLock());
1251 QQmlMetaTypeData *data = metaTypeData();
1253 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1254 while (it != data->nameToType.end()) {
1255 // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1256 if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor)))
1265 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1268 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1270 QReadLocker lock(metaTypeDataLock());
1271 QQmlMetaTypeData *data = metaTypeData();
1273 return data->metaObjectToType.value(metaObject);
1277 Returns the type (if any) that corresponds to the \a metaObject in version specified
1278 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1281 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor)
1283 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1284 QReadLocker lock(metaTypeDataLock());
1285 QQmlMetaTypeData *data = metaTypeData();
1287 QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1288 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1290 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1299 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1300 Returns null if no type is registered.
1302 QQmlType *QQmlMetaType::qmlType(int userType)
1304 QReadLocker lock(metaTypeDataLock());
1305 QQmlMetaTypeData *data = metaTypeData();
1307 QQmlType *type = data->idToType.value(userType);
1308 if (type && type->typeId() == userType)
1315 Returns the list of registered QML type names.
1317 QList<QString> QQmlMetaType::qmlTypeNames()
1319 QReadLocker lock(metaTypeDataLock());
1320 QQmlMetaTypeData *data = metaTypeData();
1322 return data->nameToType.keys();
1326 Returns the list of registered QML types.
1328 QList<QQmlType*> QQmlMetaType::qmlTypes()
1330 QReadLocker lock(metaTypeDataLock());
1331 QQmlMetaTypeData *data = metaTypeData();
1333 return data->nameToType.values();
1336 int QQmlMetaType::QQuickAnchorLineMetaTypeId()
1340 id = QMetaType::type("QQuickAnchorLine");
1345 QQmlMetaType::CompareFunction QQmlMetaType::anchorLineCompareFunction = 0;
1347 void QQmlMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1349 anchorLineCompareFunction = fun;
1352 bool QQmlMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1354 Q_ASSERT(anchorLineCompareFunction != 0);
1355 return anchorLineCompareFunction(p1, p2);