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;
157 bool m_isInterface : 1;
159 QHashedString m_module;
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 d->m_module = QString::fromUtf8(type.uri);
223 d->m_elementName = QString::fromUtf8(type.elementName);
225 if (!d->m_module.isEmpty())
226 d->m_name = static_cast<QString>(d->m_module) + QLatin1Char('/') + d->m_elementName;
228 d->m_name = d->m_elementName;
230 d->m_version_maj = type.versionMajor;
231 d->m_version_min = type.versionMinor;
232 if (type.version >= 1) // revisions added in version 1
233 d->m_revision = type.revision;
234 d->m_typeId = type.typeId;
235 d->m_listId = type.listId;
236 d->m_allocationSize = type.objectSize;
237 d->m_newFunc = type.create;
238 d->m_noCreationReason = type.noCreationReason;
239 d->m_baseMetaObject = type.metaObject;
240 d->m_attachedPropertiesFunc = type.attachedPropertiesFunction;
241 d->m_attachedPropertiesType = type.attachedPropertiesMetaObject;
242 if (d->m_attachedPropertiesType) {
243 QHash<const QMetaObject *, int>::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject);
244 if (iter == d->m_attachedPropertyIds.end())
245 iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index);
246 d->m_attachedPropertiesId = *iter;
248 d->m_attachedPropertiesId = -1;
250 d->m_parserStatusCast = type.parserStatusCast;
251 d->m_propertyValueSourceCast = type.valueSourceCast;
252 d->m_propertyValueInterceptorCast = type.valueInterceptorCast;
253 d->m_extFunc = type.extensionObjectCreate;
255 d->m_customParser = type.customParser;
257 if (type.extensionMetaObject)
258 d->m_extMetaObject = type.extensionMetaObject;
261 QQmlType::~QQmlType()
263 delete d->m_customParser;
267 const QHashedString &QQmlType::module() const
272 int QQmlType::majorVersion() const
274 return d->m_version_maj;
277 int QQmlType::minorVersion() const
279 return d->m_version_min;
282 bool QQmlType::availableInVersion(int vmajor, int vminor) const
284 Q_ASSERT(vmajor >= 0 && vminor >= 0);
285 return vmajor == d->m_version_maj && vminor >= d->m_version_min;
288 bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
290 Q_ASSERT(vmajor >= 0 && vminor >= 0);
291 return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
294 // returns the nearest _registered_ super class
295 QQmlType *QQmlType::superType() const
297 if (!d->m_haveSuperType) {
298 const QMetaObject *mo = d->m_baseMetaObject->superClass();
299 while (mo && !d->m_superType) {
300 d->m_superType = QQmlMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min);
301 mo = mo->superClass();
303 d->m_haveSuperType = true;
306 return d->m_superType;
309 static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
310 const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd)
313 builder.setClassName(ignoreEnd->className());
316 for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) {
317 QMetaClassInfo info = mo->classInfo(ii);
319 int otherIndex = ignoreEnd->indexOfClassInfo(info.name());
320 if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) {
323 builder.addClassInfo(info.name(), info.value());
328 for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) {
329 QMetaProperty property = mo->property(ii);
331 int otherIndex = ignoreEnd->indexOfProperty(property.name());
332 if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) {
333 builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void"));
336 builder.addProperty(property);
341 for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) {
342 QMetaMethod method = mo->method(ii);
344 // More complex - need to search name
345 QByteArray name = method.name();
350 for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
351 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
354 QMetaMethod other = ignoreEnd->method(ii);
356 found = name == other.name();
359 QMetaMethodBuilder m = builder.addMethod(method);
361 m.setAccess(QMetaMethod::Private);
365 for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
366 QMetaEnum enumerator = mo->enumerator(ii);
368 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
369 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
372 builder.addEnumerator(enumerator);
377 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
380 i -= mo->propertyOffset();
381 if (i < 0 && mo->d.superdata)
382 return isPropertyRevisioned(mo->d.superdata, index);
384 const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
385 if (i >= 0 && i < mop->propertyCount) {
386 int handle = mop->propertyData + 3*i;
387 int flags = mo->d.data[handle + 2];
389 return (flags & Revisioned);
395 void QQmlTypePrivate::init() const
397 if (m_isSetup) return;
399 QWriteLocker lock(metaTypeDataLock());
403 // Setup extended meta object
404 // XXX - very inefficient
405 const QMetaObject *mo = m_baseMetaObject;
407 QMetaObjectBuilder builder;
408 clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
409 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
410 QMetaObject *mmo = builder.toMetaObject();
411 mmo->d.superdata = mo;
412 QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
413 m_metaObjects << data;
416 mo = mo->d.superdata;
418 QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
420 if (t->d->m_extFunc) {
421 QMetaObjectBuilder builder;
422 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
423 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
424 QMetaObject *mmo = builder.toMetaObject();
425 mmo->d.superdata = m_baseMetaObject;
426 if (!m_metaObjects.isEmpty())
427 m_metaObjects.last().metaObject->d.superdata = mmo;
428 QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
429 m_metaObjects << data;
432 mo = mo->d.superdata;
435 for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
436 m_metaObjects[ii].propertyOffset =
437 m_metaObjects.at(ii).metaObject->propertyOffset();
438 m_metaObjects[ii].methodOffset =
439 m_metaObjects.at(ii).metaObject->methodOffset();
442 // Check for revisioned details
444 const QMetaObject *mo = 0;
445 if (m_metaObjects.isEmpty())
446 mo = m_baseMetaObject;
448 mo = m_metaObjects.first().metaObject;
450 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
451 if (isPropertyRevisioned(mo, ii))
452 m_containsRevisionedAttributes = true;
455 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
456 if (mo->method(ii).revision() != 0)
457 m_containsRevisionedAttributes = true;
465 void QQmlTypePrivate::initEnums() const
467 if (m_isEnumSetup) return;
471 QWriteLocker lock(metaTypeDataLock());
472 if (m_isEnumSetup) return;
474 const QMetaObject *metaObject = m_baseMetaObject;
475 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
477 QMetaEnum e = metaObject->enumerator(ii);
479 for (int jj = 0; jj < e.keyCount(); ++jj)
480 m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
483 m_isEnumSetup = true;
486 QByteArray QQmlType::typeName() const
488 if (d->m_baseMetaObject)
489 return d->m_baseMetaObject->className();
494 const QString &QQmlType::elementName() const
496 return d->m_elementName;
499 const QString &QQmlType::qmlTypeName() const
504 QObject *QQmlType::create() const
508 QObject *rv = (QObject *)operator new(d->m_allocationSize);
511 if (rv && !d->m_metaObjects.isEmpty())
512 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
517 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
521 QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
524 if (rv && !d->m_metaObjects.isEmpty())
525 (void)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
528 *memory = ((char *)rv) + d->m_allocationSize;
531 QQmlCustomParser *QQmlType::customParser() const
533 return d->m_customParser;
536 QQmlType::CreateFunc QQmlType::createFunction() const
541 QString QQmlType::noCreationReason() const
543 return d->m_noCreationReason;
546 int QQmlType::createSize() const
548 return d->m_allocationSize;
551 bool QQmlType::isCreatable() const
553 return d->m_newFunc != 0;
556 bool QQmlType::isExtendedType() const
560 return !d->m_metaObjects.isEmpty();
563 bool QQmlType::isInterface() const
565 return d->m_isInterface;
568 int QQmlType::typeId() const
573 int QQmlType::qListTypeId() const
578 const QMetaObject *QQmlType::metaObject() const
582 if (d->m_metaObjects.isEmpty())
583 return d->m_baseMetaObject;
585 return d->m_metaObjects.first().metaObject;
589 const QMetaObject *QQmlType::baseMetaObject() const
591 return d->m_baseMetaObject;
594 bool QQmlType::containsRevisionedAttributes() const
598 return d->m_containsRevisionedAttributes;
601 int QQmlType::metaObjectRevision() const
603 return d->m_revision;
606 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
608 return d->m_attachedPropertiesFunc;
611 const QMetaObject *QQmlType::attachedPropertiesType() const
613 return d->m_attachedPropertiesType;
617 This is the id passed to qmlAttachedPropertiesById(). This is different from the index
618 for the case that a single class is registered under two or more names (eg. Item in
619 Qt 4.7 and QtQuick 1.0).
621 int QQmlType::attachedPropertiesId() const
623 return d->m_attachedPropertiesId;
626 int QQmlType::parserStatusCast() const
628 return d->m_parserStatusCast;
631 int QQmlType::propertyValueSourceCast() const
633 return d->m_propertyValueSourceCast;
636 int QQmlType::propertyValueInterceptorCast() const
638 return d->m_propertyValueInterceptorCast;
641 const char *QQmlType::interfaceIId() const
646 int QQmlType::index() const
651 int QQmlType::enumValue(const QHashedStringRef &name) const
655 int *rv = d->m_enums.value(name);
659 int QQmlType::enumValue(const QHashedV8String &name) const
663 int *rv = d->m_enums.value(name);
667 QQmlTypeModule::QQmlTypeModule()
668 : d(new QQmlTypeModulePrivate)
672 QQmlTypeModule::~QQmlTypeModule()
677 QString QQmlTypeModule::module() const
682 int QQmlTypeModule::majorVersion() const
684 return d->uri.majorVersion;
687 int QQmlTypeModule::minimumMinorVersion() const
689 return d->minMinorVersion;
692 int QQmlTypeModule::maximumMinorVersion() const
694 return d->maxMinorVersion;
697 void QQmlTypeModulePrivate::add(QQmlType *type)
699 minMinorVersion = qMin(minMinorVersion, type->minorVersion());
700 maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
702 QList<QQmlType *> &list = typeHash[type->elementName()];
703 for (int ii = 0; ii < list.count(); ++ii) {
704 if (list.at(ii)->minorVersion() < type->minorVersion()) {
705 list.insert(ii, type);
712 QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
714 QReadLocker lock(metaTypeDataLock());
716 QList<QQmlType *> *types = d->typeHash.value(name);
717 if (!types) return 0;
719 for (int ii = 0; ii < types->count(); ++ii)
720 if (types->at(ii)->minorVersion() <= minor)
721 return types->at(ii);
726 QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor)
728 QReadLocker lock(metaTypeDataLock());
730 QList<QQmlType *> *types = d->typeHash.value(name);
731 if (!types) return 0;
733 for (int ii = 0; ii < types->count(); ++ii)
734 if (types->at(ii)->minorVersion() <= minor)
735 return types->at(ii);
741 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
742 : m_module(0), m_minor(0)
746 QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
747 : m_module(module), m_minor(minor)
750 Q_ASSERT(m_minor >= 0);
753 QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
754 : m_module(o.m_module), m_minor(o.m_minor)
758 QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
760 m_module = o.m_module;
765 QQmlTypeModule *QQmlTypeModuleVersion::module() const
770 int QQmlTypeModuleVersion::minorVersion() const
775 QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
777 if (m_module) return m_module->type(name, m_minor);
781 QQmlType *QQmlTypeModuleVersion::type(const QHashedV8String &name) const
783 if (m_module) return m_module->type(name, m_minor);
788 int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
790 QWriteLocker lock(metaTypeDataLock());
791 QQmlMetaTypeData *data = metaTypeData();
793 data->parentFunctions.append(autoparent.function);
795 return data->parentFunctions.count() - 1;
798 int registerInterface(const QQmlPrivate::RegisterInterface &interface)
800 if (interface.version > 0)
801 qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
803 QWriteLocker lock(metaTypeDataLock());
804 QQmlMetaTypeData *data = metaTypeData();
806 int index = data->types.count();
808 QQmlType *type = new QQmlType(index, interface);
810 data->types.append(type);
811 data->idToType.insert(type->typeId(), type);
812 data->idToType.insert(type->qListTypeId(), type);
813 // XXX No insertMulti, so no multi-version interfaces?
814 if (!type->elementName().isEmpty())
815 data->nameToType.insert(type->elementName(), type);
817 if (data->interfaces.size() <= interface.typeId)
818 data->interfaces.resize(interface.typeId + 16);
819 if (data->lists.size() <= interface.listId)
820 data->lists.resize(interface.listId + 16);
821 data->interfaces.setBit(interface.typeId, true);
822 data->lists.setBit(interface.listId, true);
827 int registerType(const QQmlPrivate::RegisterType &type)
829 if (type.elementName) {
830 for (int ii = 0; type.elementName[ii]; ++ii) {
831 if (!isalnum(type.elementName[ii])) {
832 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
838 QWriteLocker lock(metaTypeDataLock());
839 QQmlMetaTypeData *data = metaTypeData();
840 int index = data->types.count();
842 QQmlType *dtype = new QQmlType(index, type);
844 data->types.append(dtype);
845 data->idToType.insert(dtype->typeId(), dtype);
846 if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
848 if (!dtype->elementName().isEmpty())
849 data->nameToType.insertMulti(dtype->elementName(), dtype);
851 data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
853 if (data->objects.size() <= type.typeId)
854 data->objects.resize(type.typeId + 16);
855 if (data->lists.size() <= type.listId)
856 data->lists.resize(type.listId + 16);
857 data->objects.setBit(type.typeId, true);
858 if (type.listId) data->lists.setBit(type.listId, true);
860 if (!dtype->module().isEmpty()) {
861 const QHashedString &mod = dtype->module();
863 QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
864 QQmlTypeModule *module = data->uriToModule.value(versionedUri);
866 module = new QQmlTypeModule;
867 module->d->uri = versionedUri;
868 data->uriToModule.insert(versionedUri, module);
870 module->d->add(dtype);
876 int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api)
878 QWriteLocker lock(metaTypeDataLock());
880 QQmlMetaTypeData *data = metaTypeData();
881 QString uri = QString::fromUtf8(api.uri);
882 QQmlMetaType::ModuleApi import;
883 import.major = api.versionMajor;
884 import.minor = api.versionMinor;
885 import.script = api.scriptApi;
886 import.qobject = api.qobjectApi;
887 import.instanceMetaObject = (api.qobjectApi && api.version >= 1) ? api.instanceMetaObject : 0; // BC with version 0.
889 if (import.qobject && !import.instanceMetaObject) // BC - check import.iMO rather than api.iMO.
890 qWarning() << "qmlRegisterModuleApi(): sub-optimal: use the templated version of this function instead!";
892 int index = data->moduleApiCount++;
894 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri);
896 QQmlMetaTypeData::ModuleApiList apis;
897 apis.moduleApis << import;
898 data->moduleApis.insert(uri, apis);
900 apiList->moduleApis << import;
901 apiList->sorted = false;
909 This method is "over generalized" to allow us to (potentially) register more types of things in
910 the future without adding exported symbols.
912 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
914 if (type == TypeRegistration) {
915 return registerType(*reinterpret_cast<RegisterType *>(data));
916 } else if (type == InterfaceRegistration) {
917 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
918 } else if (type == AutoParentRegistration) {
919 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
920 } else if (type == ModuleApiRegistration) {
921 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
927 Returns true if a module \a uri of any version is installed.
929 bool QQmlMetaType::isAnyModule(const QString &uri)
931 QReadLocker lock(metaTypeDataLock());
932 QQmlMetaTypeData *data = metaTypeData();
934 for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
935 iter != data->uriToModule.end(); ++iter) {
936 if ((*iter)->module() == uri)
944 Returns true if any type or API has been registered for the given \a module with at least
945 versionMajor.versionMinor, or if types have been registered for \a module with at most
946 versionMajor.versionMinor.
948 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.
950 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
952 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
953 QReadLocker lock(metaTypeDataLock());
955 QQmlMetaTypeData *data = metaTypeData();
957 // first, check Types
959 data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
960 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
963 // then, check ModuleApis
964 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(module);
966 foreach (const QQmlMetaType::ModuleApi &mApi, apiList->moduleApis) {
967 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
975 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
977 QReadLocker lock(metaTypeDataLock());
978 QQmlMetaTypeData *data = metaTypeData();
979 return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
982 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
984 QReadLocker lock(metaTypeDataLock());
985 QQmlMetaTypeData *data = metaTypeData();
986 return data->parentFunctions;
989 static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs)
991 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
994 QQmlMetaType::ModuleApi
995 QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
997 QReadLocker lock(metaTypeDataLock());
998 QQmlMetaTypeData *data = metaTypeData();
1000 QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri);
1004 if (apiList->sorted == false) {
1005 qSort(apiList->moduleApis.begin(), apiList->moduleApis.end());
1006 apiList->sorted = true;
1009 for (int ii = apiList->moduleApis.count() - 1; ii >= 0; --ii) {
1010 const ModuleApi &import = apiList->moduleApis.at(ii);
1011 if (import.major == versionMajor && import.minor <= versionMinor)
1018 QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis()
1020 QReadLocker lock(metaTypeDataLock());
1021 QQmlMetaTypeData *data = metaTypeData();
1023 QHash<QString, QList<ModuleApi> > moduleApis;
1024 QStringHash<QQmlMetaTypeData::ModuleApiList>::ConstIterator it = data->moduleApis.begin();
1025 for (; it != data->moduleApis.end(); ++it)
1026 moduleApis[it.key()] = it.value().moduleApis;
1031 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1033 if (!isQObject(v.userType())) {
1034 if (ok) *ok = false;
1040 return *(QObject **)v.constData();
1043 bool QQmlMetaType::isQObject(int userType)
1045 if (userType == QMetaType::QObjectStar)
1048 QReadLocker lock(metaTypeDataLock());
1049 QQmlMetaTypeData *data = metaTypeData();
1050 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1054 Returns the item type for a list of type \a id.
1056 int QQmlMetaType::listType(int id)
1058 QReadLocker lock(metaTypeDataLock());
1059 QQmlMetaTypeData *data = metaTypeData();
1060 QQmlType *type = data->idToType.value(id);
1061 if (type && type->qListTypeId() == id)
1062 return type->typeId();
1067 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1069 QReadLocker lock(metaTypeDataLock());
1070 QQmlMetaTypeData *data = metaTypeData();
1072 QQmlType *type = data->metaObjectToType.value(mo);
1073 if (type && type->attachedPropertiesFunction())
1074 return type->attachedPropertiesId();
1079 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1083 QReadLocker lock(metaTypeDataLock());
1084 QQmlMetaTypeData *data = metaTypeData();
1085 return data->types.at(id)->attachedPropertiesFunction();
1088 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1090 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1092 return QMetaProperty();
1094 QMetaClassInfo info = metaObject->classInfo(idx);
1096 return QMetaProperty();
1098 idx = metaObject->indexOfProperty(info.value());
1100 return QMetaProperty();
1102 return metaObject->property(idx);
1105 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1108 return QMetaProperty();
1110 const QMetaObject *metaObject = obj->metaObject();
1111 return defaultProperty(metaObject);
1114 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1116 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1118 return QMetaMethod();
1120 QMetaClassInfo info = metaObject->classInfo(idx);
1122 return QMetaMethod();
1124 idx = metaObject->indexOfMethod(info.value());
1126 return QMetaMethod();
1128 return metaObject->method(idx);
1131 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1134 return QMetaMethod();
1136 const QMetaObject *metaObject = obj->metaObject();
1137 return defaultMethod(metaObject);
1140 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1144 if (userType == QMetaType::QObjectStar)
1147 QReadLocker lock(metaTypeDataLock());
1148 QQmlMetaTypeData *data = metaTypeData();
1149 if (userType < data->objects.size() && data->objects.testBit(userType))
1151 else if (userType < data->lists.size() && data->lists.testBit(userType))
1157 bool QQmlMetaType::isInterface(int userType)
1159 QReadLocker lock(metaTypeDataLock());
1160 QQmlMetaTypeData *data = metaTypeData();
1161 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1164 const char *QQmlMetaType::interfaceIId(int userType)
1166 QReadLocker lock(metaTypeDataLock());
1167 QQmlMetaTypeData *data = metaTypeData();
1168 QQmlType *type = data->idToType.value(userType);
1170 if (type && type->isInterface() && type->typeId() == userType)
1171 return type->interfaceIId();
1176 bool QQmlMetaType::isList(int userType)
1178 QReadLocker lock(metaTypeDataLock());
1179 QQmlMetaTypeData *data = metaTypeData();
1180 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1184 A custom string convertor allows you to specify a function pointer that
1185 returns a variant of \a type. For example, if you have written your own icon
1186 class that you want to support as an object property assignable in QML:
1189 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1190 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1193 The function pointer must be of the form:
1195 QVariant (*StringConverter)(const QString &);
1198 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1200 QWriteLocker lock(metaTypeDataLock());
1202 QQmlMetaTypeData *data = metaTypeData();
1203 if (data->stringConverters.contains(type))
1205 data->stringConverters.insert(type, converter);
1209 Return the custom string converter for \a type, previously installed through
1210 registerCustomStringConverter()
1212 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1214 QReadLocker lock(metaTypeDataLock());
1216 QQmlMetaTypeData *data = metaTypeData();
1217 return data->stringConverters.value(type);
1221 Returns the type (if any) of URI-qualified named \a qualifiedName and version specified
1222 by \a version_major and \a version_minor.
1224 QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
1226 int slash = qualifiedName.indexOf(QLatin1Char('/'));
1230 QHashedStringRef module(qualifiedName.constData(), slash);
1231 QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1);
1233 return qmlType(name, module, version_major, version_minor);
1237 Returns the type (if any) of \a name in \a module and version specified
1238 by \a version_major and \a version_minor.
1240 QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
1242 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1243 QReadLocker lock(metaTypeDataLock());
1244 QQmlMetaTypeData *data = metaTypeData();
1246 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1247 while (it != data->nameToType.end() && it.key() == name) {
1248 // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1249 if (version_major < 0 || (*it)->availableInVersion(module, version_major,version_minor))
1258 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1261 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1263 QReadLocker lock(metaTypeDataLock());
1264 QQmlMetaTypeData *data = metaTypeData();
1266 return data->metaObjectToType.value(metaObject);
1270 Returns the type (if any) that corresponds to the \a metaObject in version specified
1271 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1274 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
1276 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1277 QReadLocker lock(metaTypeDataLock());
1278 QQmlMetaTypeData *data = metaTypeData();
1280 QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1281 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1283 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1292 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1293 Returns null if no type is registered.
1295 QQmlType *QQmlMetaType::qmlType(int userType)
1297 QReadLocker lock(metaTypeDataLock());
1298 QQmlMetaTypeData *data = metaTypeData();
1300 QQmlType *type = data->idToType.value(userType);
1301 if (type && type->typeId() == userType)
1308 Returns the list of registered QML type names.
1310 QList<QString> QQmlMetaType::qmlTypeNames()
1312 QReadLocker lock(metaTypeDataLock());
1313 QQmlMetaTypeData *data = metaTypeData();
1315 QList<QString> names;
1316 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin();
1317 while (it != data->nameToType.end()) {
1318 names += (*it)->qmlTypeName();
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);