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.signature();
344 int parenIdx = name.indexOf('(');
345 if (parenIdx != -1) name = name.left(parenIdx);
350 for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount();
351 !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount();
354 QMetaMethod other = ignoreEnd->method(ii);
355 QByteArray othername = other.signature();
356 int parenIdx = othername.indexOf('(');
357 if (parenIdx != -1) othername = othername.left(parenIdx);
359 found = name == othername;
362 QMetaMethodBuilder m = builder.addMethod(method);
364 m.setAccess(QMetaMethod::Private);
368 for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) {
369 QMetaEnum enumerator = mo->enumerator(ii);
371 int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name());
372 if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) {
375 builder.addEnumerator(enumerator);
380 static bool isPropertyRevisioned(const QMetaObject *mo, int index)
383 i -= mo->propertyOffset();
384 if (i < 0 && mo->d.superdata)
385 return isPropertyRevisioned(mo->d.superdata, index);
387 const QMetaObjectPrivate *mop = reinterpret_cast<const QMetaObjectPrivate*>(mo->d.data);
388 if (i >= 0 && i < mop->propertyCount) {
389 int handle = mop->propertyData + 3*i;
390 int flags = mo->d.data[handle + 2];
392 return (flags & Revisioned);
398 void QQmlTypePrivate::init() const
400 if (m_isSetup) return;
402 QWriteLocker lock(metaTypeDataLock());
406 // Setup extended meta object
407 // XXX - very inefficient
408 const QMetaObject *mo = m_baseMetaObject;
410 QMetaObjectBuilder builder;
411 clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject);
412 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
413 QMetaObject *mmo = builder.toMetaObject();
414 mmo->d.superdata = mo;
415 QQmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
416 m_metaObjects << data;
419 mo = mo->d.superdata;
421 QQmlType *t = metaTypeData()->metaObjectToType.value(mo);
423 if (t->d->m_extFunc) {
424 QMetaObjectBuilder builder;
425 clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject);
426 builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
427 QMetaObject *mmo = builder.toMetaObject();
428 mmo->d.superdata = m_baseMetaObject;
429 if (!m_metaObjects.isEmpty())
430 m_metaObjects.last().metaObject->d.superdata = mmo;
431 QQmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
432 m_metaObjects << data;
435 mo = mo->d.superdata;
438 for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
439 m_metaObjects[ii].propertyOffset =
440 m_metaObjects.at(ii).metaObject->propertyOffset();
441 m_metaObjects[ii].methodOffset =
442 m_metaObjects.at(ii).metaObject->methodOffset();
445 // Check for revisioned details
447 const QMetaObject *mo = 0;
448 if (m_metaObjects.isEmpty())
449 mo = m_baseMetaObject;
451 mo = m_metaObjects.first().metaObject;
453 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
454 if (isPropertyRevisioned(mo, ii))
455 m_containsRevisionedAttributes = true;
458 for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) {
459 if (mo->method(ii).revision() != 0)
460 m_containsRevisionedAttributes = true;
468 void QQmlTypePrivate::initEnums() const
470 if (m_isEnumSetup) return;
474 QWriteLocker lock(metaTypeDataLock());
475 if (m_isEnumSetup) return;
477 const QMetaObject *metaObject = m_baseMetaObject;
478 for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
480 QMetaEnum e = metaObject->enumerator(ii);
482 for (int jj = 0; jj < e.keyCount(); ++jj)
483 m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
486 m_isEnumSetup = true;
489 QByteArray QQmlType::typeName() const
491 if (d->m_baseMetaObject)
492 return d->m_baseMetaObject->className();
497 const QString &QQmlType::elementName() const
499 if (d->m_elementName.isEmpty()) {
500 QString n = qmlTypeName();
501 int idx = n.lastIndexOf(QLatin1Char('/'));
502 d->m_elementName = n.mid(idx + 1);
504 return d->m_elementName;
507 const QString &QQmlType::qmlTypeName() const
512 QObject *QQmlType::create() const
516 QObject *rv = (QObject *)operator new(d->m_allocationSize);
519 if (rv && !d->m_metaObjects.isEmpty())
520 (void *)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
525 void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) const
529 QObject *rv = (QObject *)operator new(d->m_allocationSize + additionalMemory);
532 if (rv && !d->m_metaObjects.isEmpty())
533 (void *)new QQmlProxyMetaObject(rv, &d->m_metaObjects);
536 *memory = ((char *)rv) + d->m_allocationSize;
539 QQmlCustomParser *QQmlType::customParser() const
541 return d->m_customParser;
544 QQmlType::CreateFunc QQmlType::createFunction() const
549 QString QQmlType::noCreationReason() const
551 return d->m_noCreationReason;
554 int QQmlType::createSize() const
556 return d->m_allocationSize;
559 bool QQmlType::isCreatable() const
561 return d->m_newFunc != 0;
564 bool QQmlType::isExtendedType() const
568 return !d->m_metaObjects.isEmpty();
571 bool QQmlType::isInterface() const
573 return d->m_isInterface;
576 int QQmlType::typeId() const
581 int QQmlType::qListTypeId() const
586 const QMetaObject *QQmlType::metaObject() const
590 if (d->m_metaObjects.isEmpty())
591 return d->m_baseMetaObject;
593 return d->m_metaObjects.first().metaObject;
597 const QMetaObject *QQmlType::baseMetaObject() const
599 return d->m_baseMetaObject;
602 bool QQmlType::containsRevisionedAttributes() const
606 return d->m_containsRevisionedAttributes;
609 int QQmlType::metaObjectRevision() const
611 return d->m_revision;
614 QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction() const
616 return d->m_attachedPropertiesFunc;
619 const QMetaObject *QQmlType::attachedPropertiesType() const
621 return d->m_attachedPropertiesType;
625 This is the id passed to qmlAttachedPropertiesById(). This is different from the index
626 for the case that a single class is registered under two or more names (eg. Item in
627 Qt 4.7 and QtQuick 1.0).
629 int QQmlType::attachedPropertiesId() const
631 return d->m_attachedPropertiesId;
634 int QQmlType::parserStatusCast() const
636 return d->m_parserStatusCast;
639 int QQmlType::propertyValueSourceCast() const
641 return d->m_propertyValueSourceCast;
644 int QQmlType::propertyValueInterceptorCast() const
646 return d->m_propertyValueInterceptorCast;
649 const char *QQmlType::interfaceIId() const
654 int QQmlType::index() const
659 int QQmlType::enumValue(const QHashedStringRef &name) const
663 int *rv = d->m_enums.value(name);
667 int QQmlType::enumValue(const QHashedV8String &name) const
671 int *rv = d->m_enums.value(name);
675 QQmlTypeModule::QQmlTypeModule()
676 : d(new QQmlTypeModulePrivate)
680 QQmlTypeModule::~QQmlTypeModule()
685 QString QQmlTypeModule::module() const
690 int QQmlTypeModule::majorVersion() const
692 return d->uri.majorVersion;
695 int QQmlTypeModule::minimumMinorVersion() const
697 return d->minMinorVersion;
700 int QQmlTypeModule::maximumMinorVersion() const
702 return d->maxMinorVersion;
705 void QQmlTypeModulePrivate::add(QQmlType *type)
709 minMinorVersion = qMin(minMinorVersion, type->minorVersion());
710 maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
712 QList<QQmlType *> &list = typeHash[type->elementName()];
713 for (int ii = 0; ii < list.count(); ++ii) {
714 if (list.at(ii)->minorVersion() < type->minorVersion()) {
715 list.insert(ii, type);
722 QList<QQmlType *> QQmlTypeModule::types()
724 QList<QQmlType *> rv;
725 QReadLocker lock(metaTypeDataLock());
730 QList<QQmlType *> QQmlTypeModule::type(const QString &name)
732 QReadLocker lock(metaTypeDataLock());
733 QList<QQmlType *> rv;
734 for (int ii = 0; ii < d->types.count(); ++ii) {
735 if (d->types.at(ii)->elementName() == name)
736 rv << d->types.at(ii);
741 QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor)
743 QReadLocker lock(metaTypeDataLock());
745 QList<QQmlType *> *types = d->typeHash.value(name);
746 if (!types) return 0;
748 for (int ii = 0; ii < types->count(); ++ii)
749 if (types->at(ii)->minorVersion() <= minor)
750 return types->at(ii);
755 QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor)
757 QReadLocker lock(metaTypeDataLock());
759 QList<QQmlType *> *types = d->typeHash.value(name);
760 if (!types) return 0;
762 for (int ii = 0; ii < types->count(); ++ii)
763 if (types->at(ii)->minorVersion() <= minor)
764 return types->at(ii);
770 QQmlTypeModuleVersion::QQmlTypeModuleVersion()
771 : m_module(0), m_minor(0)
775 QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
776 : m_module(module), m_minor(minor)
779 Q_ASSERT(m_minor >= 0);
782 QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
783 : m_module(o.m_module), m_minor(o.m_minor)
787 QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVersion &o)
789 m_module = o.m_module;
794 QQmlTypeModule *QQmlTypeModuleVersion::module() const
799 int QQmlTypeModuleVersion::minorVersion() const
804 QQmlType *QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
806 if (m_module) return m_module->type(name, m_minor);
810 QQmlType *QQmlTypeModuleVersion::type(const QHashedV8String &name) const
812 if (m_module) return m_module->type(name, m_minor);
817 int registerAutoParentFunction(QQmlPrivate::RegisterAutoParent &autoparent)
819 QWriteLocker lock(metaTypeDataLock());
820 QQmlMetaTypeData *data = metaTypeData();
822 data->parentFunctions.append(autoparent.function);
824 return data->parentFunctions.count() - 1;
827 int registerInterface(const QQmlPrivate::RegisterInterface &interface)
829 if (interface.version > 0)
830 qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
832 QWriteLocker lock(metaTypeDataLock());
833 QQmlMetaTypeData *data = metaTypeData();
835 int index = data->types.count();
837 QQmlType *type = new QQmlType(index, interface);
839 data->types.append(type);
840 data->idToType.insert(type->typeId(), type);
841 data->idToType.insert(type->qListTypeId(), type);
842 // XXX No insertMulti, so no multi-version interfaces?
843 if (!type->qmlTypeName().isEmpty())
844 data->nameToType.insert(type->qmlTypeName(), type);
846 if (data->interfaces.size() <= interface.typeId)
847 data->interfaces.resize(interface.typeId + 16);
848 if (data->lists.size() <= interface.listId)
849 data->lists.resize(interface.listId + 16);
850 data->interfaces.setBit(interface.typeId, true);
851 data->lists.setBit(interface.listId, true);
856 int registerType(const QQmlPrivate::RegisterType &type)
858 if (type.elementName) {
859 for (int ii = 0; type.elementName[ii]; ++ii) {
860 if (!isalnum(type.elementName[ii])) {
861 qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName);
867 QWriteLocker lock(metaTypeDataLock());
868 QQmlMetaTypeData *data = metaTypeData();
869 int index = data->types.count();
871 QQmlType *dtype = new QQmlType(index, type);
873 data->types.append(dtype);
874 data->idToType.insert(dtype->typeId(), dtype);
875 if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype);
877 if (!dtype->qmlTypeName().isEmpty())
878 data->nameToType.insertMulti(dtype->qmlTypeName(), dtype);
880 data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype);
882 if (data->objects.size() <= type.typeId)
883 data->objects.resize(type.typeId + 16);
884 if (data->lists.size() <= type.listId)
885 data->lists.resize(type.listId + 16);
886 data->objects.setBit(type.typeId, true);
887 if (type.listId) data->lists.setBit(type.listId, true);
890 QString mod = QString::fromUtf8(type.uri);
892 QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
893 QQmlTypeModule *module = data->uriToModule.value(versionedUri);
895 module = new QQmlTypeModule;
896 module->d->uri = versionedUri;
897 data->uriToModule.insert(versionedUri, module);
899 module->d->add(dtype);
905 int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api)
907 QWriteLocker lock(metaTypeDataLock());
909 QQmlMetaTypeData *data = metaTypeData();
910 QString uri = QString::fromUtf8(api.uri);
911 QQmlMetaType::ModuleApi import;
912 import.major = api.versionMajor;
913 import.minor = api.versionMinor;
914 import.script = api.scriptApi;
915 import.qobject = api.qobjectApi;
917 int index = data->moduleApiCount++;
919 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
920 if (iter == data->moduleApis.end()) {
921 QQmlMetaTypeData::ModuleApiList apis;
922 apis.moduleApis << import;
923 data->moduleApis.insert(uri, apis);
925 iter->moduleApis << import;
926 iter->sorted = false;
934 This method is "over generalized" to allow us to (potentially) register more types of things in
935 the future without adding exported symbols.
937 int QQmlPrivate::qmlregister(RegistrationType type, void *data)
939 if (type == TypeRegistration) {
940 return registerType(*reinterpret_cast<RegisterType *>(data));
941 } else if (type == InterfaceRegistration) {
942 return registerInterface(*reinterpret_cast<RegisterInterface *>(data));
943 } else if (type == AutoParentRegistration) {
944 return registerAutoParentFunction(*reinterpret_cast<RegisterAutoParent *>(data));
945 } else if (type == ModuleApiRegistration) {
946 return registerModuleApi(*reinterpret_cast<RegisterModuleApi *>(data));
952 Returns true if a module \a uri of any version is installed.
954 bool QQmlMetaType::isAnyModule(const QString &uri)
956 QReadLocker lock(metaTypeDataLock());
957 QQmlMetaTypeData *data = metaTypeData();
959 for (QQmlMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
960 iter != data->uriToModule.end(); ++iter) {
961 if ((*iter)->module() == uri)
969 Returns true if any type or API has been registered for the given \a module with at least
970 versionMajor.versionMinor, or if types have been registered for \a module with at most
971 versionMajor.versionMinor.
973 So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10.
975 bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
977 Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
978 QReadLocker lock(metaTypeDataLock());
980 QQmlMetaTypeData *data = metaTypeData();
982 // first, check Types
984 data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
985 if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
988 // then, check ModuleApis
989 foreach (const QQmlMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
990 if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
997 QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
999 QReadLocker lock(metaTypeDataLock());
1000 QQmlMetaTypeData *data = metaTypeData();
1001 return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
1004 QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
1006 QReadLocker lock(metaTypeDataLock());
1007 QQmlMetaTypeData *data = metaTypeData();
1008 return data->parentFunctions;
1011 static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs)
1013 return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor);
1016 QQmlMetaType::ModuleApi
1017 QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor)
1019 QReadLocker lock(metaTypeDataLock());
1020 QQmlMetaTypeData *data = metaTypeData();
1022 QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri);
1023 if (iter == data->moduleApis.end())
1026 if (iter->sorted == false) {
1027 qSort(iter->moduleApis.begin(), iter->moduleApis.end());
1028 iter->sorted = true;
1031 for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) {
1032 const ModuleApi &import = iter->moduleApis.at(ii);
1033 if (import.major == versionMajor && import.minor <= versionMinor)
1040 QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis()
1042 QReadLocker lock(metaTypeDataLock());
1043 QQmlMetaTypeData *data = metaTypeData();
1045 QHash<QString, QList<ModuleApi> > moduleApis;
1046 QHashIterator<QString, QQmlMetaTypeData::ModuleApiList> it(data->moduleApis);
1047 while (it.hasNext()) {
1049 moduleApis[it.key()] = it.value().moduleApis;
1055 QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok)
1057 if (!isQObject(v.userType())) {
1058 if (ok) *ok = false;
1064 return *(QObject **)v.constData();
1067 bool QQmlMetaType::isQObject(int userType)
1069 if (userType == QMetaType::QObjectStar)
1072 QReadLocker lock(metaTypeDataLock());
1073 QQmlMetaTypeData *data = metaTypeData();
1074 return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
1078 Returns the item type for a list of type \a id.
1080 int QQmlMetaType::listType(int id)
1082 QReadLocker lock(metaTypeDataLock());
1083 QQmlMetaTypeData *data = metaTypeData();
1084 QQmlType *type = data->idToType.value(id);
1085 if (type && type->qListTypeId() == id)
1086 return type->typeId();
1091 int QQmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
1093 QReadLocker lock(metaTypeDataLock());
1094 QQmlMetaTypeData *data = metaTypeData();
1096 QQmlType *type = data->metaObjectToType.value(mo);
1097 if (type && type->attachedPropertiesFunction())
1098 return type->attachedPropertiesId();
1103 QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(int id)
1107 QReadLocker lock(metaTypeDataLock());
1108 QQmlMetaTypeData *data = metaTypeData();
1109 return data->types.at(id)->attachedPropertiesFunction();
1112 QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
1114 int idx = metaObject->indexOfClassInfo("DefaultProperty");
1116 return QMetaProperty();
1118 QMetaClassInfo info = metaObject->classInfo(idx);
1120 return QMetaProperty();
1122 idx = metaObject->indexOfProperty(info.value());
1124 return QMetaProperty();
1126 return metaObject->property(idx);
1129 QMetaProperty QQmlMetaType::defaultProperty(QObject *obj)
1132 return QMetaProperty();
1134 const QMetaObject *metaObject = obj->metaObject();
1135 return defaultProperty(metaObject);
1138 QMetaMethod QQmlMetaType::defaultMethod(const QMetaObject *metaObject)
1140 int idx = metaObject->indexOfClassInfo("DefaultMethod");
1142 return QMetaMethod();
1144 QMetaClassInfo info = metaObject->classInfo(idx);
1146 return QMetaMethod();
1148 idx = metaObject->indexOfMethod(info.value());
1150 return QMetaMethod();
1152 return metaObject->method(idx);
1155 QMetaMethod QQmlMetaType::defaultMethod(QObject *obj)
1158 return QMetaMethod();
1160 const QMetaObject *metaObject = obj->metaObject();
1161 return defaultMethod(metaObject);
1164 QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
1168 if (userType == QMetaType::QObjectStar)
1171 QReadLocker lock(metaTypeDataLock());
1172 QQmlMetaTypeData *data = metaTypeData();
1173 if (userType < data->objects.size() && data->objects.testBit(userType))
1175 else if (userType < data->lists.size() && data->lists.testBit(userType))
1181 bool QQmlMetaType::isInterface(int userType)
1183 QReadLocker lock(metaTypeDataLock());
1184 QQmlMetaTypeData *data = metaTypeData();
1185 return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
1188 const char *QQmlMetaType::interfaceIId(int userType)
1190 QReadLocker lock(metaTypeDataLock());
1191 QQmlMetaTypeData *data = metaTypeData();
1192 QQmlType *type = data->idToType.value(userType);
1194 if (type && type->isInterface() && type->typeId() == userType)
1195 return type->interfaceIId();
1200 bool QQmlMetaType::isList(int userType)
1202 QReadLocker lock(metaTypeDataLock());
1203 QQmlMetaTypeData *data = metaTypeData();
1204 return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
1208 A custom string convertor allows you to specify a function pointer that
1209 returns a variant of \a type. For example, if you have written your own icon
1210 class that you want to support as an object property assignable in QML:
1213 int type = qRegisterMetaType<SuperIcon>("SuperIcon");
1214 QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
1217 The function pointer must be of the form:
1219 QVariant (*StringConverter)(const QString &);
1222 void QQmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
1224 QWriteLocker lock(metaTypeDataLock());
1226 QQmlMetaTypeData *data = metaTypeData();
1227 if (data->stringConverters.contains(type))
1229 data->stringConverters.insert(type, converter);
1233 Return the custom string converter for \a type, previously installed through
1234 registerCustomStringConverter()
1236 QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
1238 QReadLocker lock(metaTypeDataLock());
1240 QQmlMetaTypeData *data = metaTypeData();
1241 return data->stringConverters.value(type);
1245 Returns the type (if any) of URI-qualified named \a name in version specified
1246 by \a version_major and \a version_minor.
1248 QQmlType *QQmlMetaType::qmlType(const QString &name, int version_major, int version_minor)
1250 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1251 QReadLocker lock(metaTypeDataLock());
1252 QQmlMetaTypeData *data = metaTypeData();
1254 QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name);
1255 while (it != data->nameToType.end()) {
1256 // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
1257 if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor)))
1266 Returns the type (if any) that corresponds to the \a metaObject. Returns null if no
1269 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject)
1271 QReadLocker lock(metaTypeDataLock());
1272 QQmlMetaTypeData *data = metaTypeData();
1274 return data->metaObjectToType.value(metaObject);
1278 Returns the type (if any) that corresponds to the \a metaObject in version specified
1279 by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
1282 QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor)
1284 Q_ASSERT(version_major >= 0 && version_minor >= 0);
1285 QReadLocker lock(metaTypeDataLock());
1286 QQmlMetaTypeData *data = metaTypeData();
1288 QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject);
1289 while (it != data->metaObjectToType.end() && it.key() == metaObject) {
1291 if (version_major < 0 || t->availableInVersion(module, version_major,version_minor))
1300 Returns the type (if any) that corresponds to the QVariant::Type \a userType.
1301 Returns null if no type is registered.
1303 QQmlType *QQmlMetaType::qmlType(int userType)
1305 QReadLocker lock(metaTypeDataLock());
1306 QQmlMetaTypeData *data = metaTypeData();
1308 QQmlType *type = data->idToType.value(userType);
1309 if (type && type->typeId() == userType)
1316 Returns the list of registered QML type names.
1318 QList<QString> QQmlMetaType::qmlTypeNames()
1320 QReadLocker lock(metaTypeDataLock());
1321 QQmlMetaTypeData *data = metaTypeData();
1323 return data->nameToType.keys();
1327 Returns the list of registered QML types.
1329 QList<QQmlType*> QQmlMetaType::qmlTypes()
1331 QReadLocker lock(metaTypeDataLock());
1332 QQmlMetaTypeData *data = metaTypeData();
1334 return data->nameToType.values();
1337 int QQmlMetaType::QQuickAnchorLineMetaTypeId()
1341 id = QMetaType::type("QQuickAnchorLine");
1346 QQmlMetaType::CompareFunction QQmlMetaType::anchorLineCompareFunction = 0;
1348 void QQmlMetaType::setQQuickAnchorLineCompareFunction(CompareFunction fun)
1350 anchorLineCompareFunction = fun;
1353 bool QQmlMetaType::QQuickAnchorLineCompare(const void *p1, const void *p2)
1355 Q_ASSERT(anchorLineCompareFunction != 0);
1356 return anchorLineCompareFunction(p1, p2);