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;
912 int index = data->moduleApiCount++;
914 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
915 if (iter == data->moduleApis.end()) {
916 QQmlMetaTypeData::ModuleApiList apis;
917 apis.moduleApis << import;
918 data->moduleApis.insert(uri, apis);
920 iter->moduleApis << import;
921 iter->sorted = false;
929 This method is "over generalized" to allow us to (potentially) register more types of things in
930 the future without adding exported symbols.
932 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
934 if (type == TypeRegistration) {
935 return registerType(*reinterpret_cast<RegisterType *>(data));
936 } else if (type == InterfaceRegistration) {
937 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
938 } else if (type == AutoParentRegistration) {
939 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
940 } else if (type == ModuleApiRegistration) {
941 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
947 Returns true if a module \a uri of any version is installed.
949 bool QQmlMetaType::isAnyModule(const QString &uri)
951 QReadLocker lock(metaTypeDataLock());
952 QQmlMetaTypeData *data = metaTypeData();
954 for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
955 iter != data->uriToModule.end(); ++iter) {
956 if ((*iter)->module() == uri)
964 Returns true if any type or API has been registered for the given \a module with at least
965 versionMajor.versionMinor, or if types have been registered for \a module with at most
966 versionMajor.versionMinor.
968 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.
970 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
972 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
973 QReadLocker lock(metaTypeDataLock());
975 QQmlMetaTypeData *data = metaTypeData();
977 // first, check Types
979 data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
980 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
983 // then, check ModuleApis
984 foreach (const QQmlMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
985 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
992 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
994 QReadLocker lock(metaTypeDataLock());
995 QQmlMetaTypeData *data = metaTypeData();
996 return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
999 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1001 QReadLocker lock(metaTypeDataLock());
1002 QQmlMetaTypeData *data = metaTypeData();
1003 return data->parentFunctions;
1006 static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs)
1008 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1011 QQmlMetaType::ModuleApi
1012 QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
1014 QReadLocker lock(metaTypeDataLock());
1015 QQmlMetaTypeData *data = metaTypeData();
1017 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
1018 if (iter == data->moduleApis.end())
1021 if (iter->sorted == false) {
1022 qSort(iter->moduleApis.begin(), iter->moduleApis.end());
1023 iter->sorted = true;
1026 for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) {
1027 const ModuleApi &import = iter->moduleApis.at(ii);
1028 if (import.major == versionMajor && import.minor <= versionMinor)
1035 QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis()
1037 QReadLocker lock(metaTypeDataLock());
1038 QQmlMetaTypeData *data = metaTypeData();
1040 QHash<QString, QList<ModuleApi> > moduleApis;
1041 QHashIterator<QString, QQmlMetaTypeData::ModuleApiList> it(data->moduleApis);
1042 while (it.hasNext()) {
1044 moduleApis[it.key()] = it.value().moduleApis;
1050 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1052 if (!isQObject(v.userType())) {
1053 if (ok) *ok = false;
1059 return *(QObject **)v.constData();
1062 bool QQmlMetaType::isQObject(int userType)
1064 if (userType == QMetaType::QObjectStar)
1067 QReadLocker lock(metaTypeDataLock());
1068 QQmlMetaTypeData *data = metaTypeData();
1069 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1073 Returns the item type for a list of type \a id.
1075 int QQmlMetaType::listType(int id)
1077 QReadLocker lock(metaTypeDataLock());
1078 QQmlMetaTypeData *data = metaTypeData();
1079 QQmlType *type = data->idToType.value(id);
1080 if (type && type->qListTypeId() == id)
1081 return type->typeId();
1086 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1088 QReadLocker lock(metaTypeDataLock());
1089 QQmlMetaTypeData *data = metaTypeData();
1091 QQmlType *type = data->metaObjectToType.value(mo);
1092 if (type && type->attachedPropertiesFunction())
1093 return type->attachedPropertiesId();
1098 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1102 QReadLocker lock(metaTypeDataLock());
1103 QQmlMetaTypeData *data = metaTypeData();
1104 return data->types.at(id)->attachedPropertiesFunction();
1107 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1109 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1111 return QMetaProperty();
1113 QMetaClassInfo info = metaObject->classInfo(idx);
1115 return QMetaProperty();
1117 idx = metaObject->indexOfProperty(info.value());
1119 return QMetaProperty();
1121 return metaObject->property(idx);
1124 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1127 return QMetaProperty();
1129 const QMetaObject *metaObject = obj->metaObject();
1130 return defaultProperty(metaObject);
1133 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1135 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1137 return QMetaMethod();
1139 QMetaClassInfo info = metaObject->classInfo(idx);
1141 return QMetaMethod();
1143 idx = metaObject->indexOfMethod(info.value());
1145 return QMetaMethod();
1147 return metaObject->method(idx);
1150 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1153 return QMetaMethod();
1155 const QMetaObject *metaObject = obj->metaObject();
1156 return defaultMethod(metaObject);
1159 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1163 if (userType == QMetaType::QObjectStar)
1166 QReadLocker lock(metaTypeDataLock());
1167 QQmlMetaTypeData *data = metaTypeData();
1168 if (userType < data->objects.size() && data->objects.testBit(userType))
1170 else if (userType < data->lists.size() && data->lists.testBit(userType))
1176 bool QQmlMetaType::isInterface(int userType)
1178 QReadLocker lock(metaTypeDataLock());
1179 QQmlMetaTypeData *data = metaTypeData();
1180 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1183 const char *QQmlMetaType::interfaceIId(int userType)
1185 QReadLocker lock(metaTypeDataLock());
1186 QQmlMetaTypeData *data = metaTypeData();
1187 QQmlType *type = data->idToType.value(userType);
1189 if (type && type->isInterface() && type->typeId() == userType)
1190 return type->interfaceIId();
1195 bool QQmlMetaType::isList(int userType)
1197 QReadLocker lock(metaTypeDataLock());
1198 QQmlMetaTypeData *data = metaTypeData();
1199 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1203 A custom string convertor allows you to specify a function pointer that
1204 returns a variant of \a type. For example, if you have written your own icon
1205 class that you want to support as an object property assignable in QML:
1208 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1209 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1212 The function pointer must be of the form:
1214 QVariant (*StringConverter)(const QString &);
1217 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1219 QWriteLocker lock(metaTypeDataLock());
1221 QQmlMetaTypeData *data = metaTypeData();
1222 if (data->stringConverters.contains(type))
1224 data->stringConverters.insert(type, converter);
1228 Return the custom string converter for \a type, previously installed through
1229 registerCustomStringConverter()
1231 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1233 QReadLocker lock(metaTypeDataLock());
1235 QQmlMetaTypeData *data = metaTypeData();
1236 return data->stringConverters.value(type);
1240 Returns the type (if any) of URI-qualified named \a name in version specified
1241 by \a version_major and \a version_minor.
1243 QQmlType *QQmlMetaType::qmlType(const QString &name, int version_major, int version_minor)
1245 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1246 QReadLocker lock(metaTypeDataLock());
1247 QQmlMetaTypeData *data = metaTypeData();
1249 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1250 while (it != data->nameToType.end()) {
1251 // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1252 if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor)))
1261 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1264 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1266 QReadLocker lock(metaTypeDataLock());
1267 QQmlMetaTypeData *data = metaTypeData();
1269 return data->metaObjectToType.value(metaObject);
1273 Returns the type (if any) that corresponds to the \a metaObject in version specified
1274 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1277 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor)
1279 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1280 QReadLocker lock(metaTypeDataLock());
1281 QQmlMetaTypeData *data = metaTypeData();
1283 QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1284 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1286 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1295 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1296 Returns null if no type is registered.
1298 QQmlType *QQmlMetaType::qmlType(int userType)
1300 QReadLocker lock(metaTypeDataLock());
1301 QQmlMetaTypeData *data = metaTypeData();
1303 QQmlType *type = data->idToType.value(userType);
1304 if (type && type->typeId() == userType)
1311 Returns the list of registered QML type names.
1313 QList<QString> QQmlMetaType::qmlTypeNames()
1315 QReadLocker lock(metaTypeDataLock());
1316 QQmlMetaTypeData *data = metaTypeData();
1318 return data->nameToType.keys();
1322 Returns the list of registered QML types.
1324 QList<QQmlType*> QQmlMetaType::qmlTypes()
1326 QReadLocker lock(metaTypeDataLock());
1327 QQmlMetaTypeData *data = metaTypeData();
1329 return data->nameToType.values();
1332 int QQmlMetaType::QQuickAnchorLineMetaTypeId()
1336 id = QMetaType::type("QQuickAnchorLine");
1341 QQmlMetaType::CompareFunction QQmlMetaType::anchorLineCompareFunction = 0;
1343 void QQmlMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1345 anchorLineCompareFunction = fun;
1348 bool QQmlMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1350 Q_ASSERT(anchorLineCompareFunction != 0);
1351 return anchorLineCompareFunction(p1, p2);