X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fqml%2Fqml%2Fqqmlmetatype.cpp;h=595f9e8de028f9c2c0cb44b9e6d24e84663dc7e5;hb=48b2d386399341307027efb151f59873c5372407;hp=4af08c28bf77710835f63374330eef90d9699e79;hpb=0655209fdad022bd0f6eb20ce85522cb56506bf0;p=profile%2Fivi%2Fqtdeclarative.git diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 4af08c2..595f9e8 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1,38 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** ** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ @@ -73,7 +73,7 @@ struct QQmlMetaTypeData QList types; typedef QHash Ids; Ids idToType; - typedef QHash Names; + typedef QHash Names; Names nameToType; typedef QHash MetaObjects; MetaObjects metaObjectToType; @@ -83,31 +83,27 @@ struct QQmlMetaTypeData struct VersionedUri { VersionedUri() : majorVersion(0) {} - VersionedUri(const QString &uri, int majorVersion) + VersionedUri(const QHashedString &uri, int majorVersion) : uri(uri), majorVersion(majorVersion) {} bool operator==(const VersionedUri &other) const { return other.majorVersion == majorVersion && other.uri == uri; } - QString uri; + QHashedString uri; int majorVersion; }; typedef QHash TypeModules; TypeModules uriToModule; - struct ModuleApiList { - ModuleApiList() : sorted(true) {} - QList moduleApis; - bool sorted; - }; - typedef QHash ModuleApis; - ModuleApis moduleApis; - int moduleApiCount; - QBitArray objects; QBitArray interfaces; QBitArray lists; QList parentFunctions; + + QSet protectedNamespaces; + + QString typeRegistrationNamespace; + QStringList typeRegistrationFailures; }; class QQmlTypeModulePrivate @@ -128,15 +124,14 @@ public: }; Q_GLOBAL_STATIC(QQmlMetaTypeData, metaTypeData) -Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) +Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, metaTypeDataLock, (QReadWriteLock::Recursive)) static uint qHash(const QQmlMetaTypeData::VersionedUri &v) { - return qHash(v.uri) ^ qHash(v.majorVersion); + return v.uri.hash() ^ qHash(v.majorVersion); } QQmlMetaTypeData::QQmlMetaTypeData() -: moduleApiCount(0) { } @@ -144,19 +139,25 @@ QQmlMetaTypeData::~QQmlMetaTypeData() { for (int i = 0; i < types.count(); ++i) delete types.at(i); + + TypeModules::const_iterator i = uriToModule.constBegin(); + for (; i != uriToModule.constEnd(); ++i) + delete *i; } class QQmlTypePrivate { public: QQmlTypePrivate(); + ~QQmlTypePrivate(); void init() const; void initEnums() const; + void insertEnums(const QMetaObject *metaObject) const; bool m_isInterface : 1; const char *m_iid; - QString m_module; + QHashedString m_module; QString m_name; QString m_elementName; int m_version_maj; @@ -186,10 +187,69 @@ public: mutable bool m_haveSuperType:1; mutable QList m_metaObjects; mutable QStringHash m_enums; + QQmlType::SingletonInstanceInfo *m_singletonInstanceInfo; static QHash m_attachedPropertyIds; }; +// Avoid multiple fromUtf8(), copies and hashing of the module name. +// This is only called when metaTypeDataLock is locked. +static QHashedString moduleFromUtf8(const char *module) +{ + if (!module) + return QHashedString(); + + static const char *lastModule = 0; + static QHashedString lastModuleStr; + + // Separate plugins may have different strings at the same address + QHashedCStringRef currentModule(module, ::strlen(module)); + if ((lastModule != module) || (lastModuleStr.hash() != currentModule.hash())) { + lastModuleStr = QString::fromUtf8(module); + lastModuleStr.hash(); + lastModule = module; + } + + return lastModuleStr; +} + +void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) +{ + if (scriptCallback && scriptApi(e).isUndefined()) { + setScriptApi(e, scriptCallback(e, e)); + } else if (qobjectCallback && !qobjectApi(e)) { + setQObjectApi(e, qobjectCallback(e, e)); + } +} + +void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e) +{ + // cleans up the engine-specific singleton instances if they exist. + scriptApis.remove(e); + QObject *o = qobjectApis.take(e); + delete o; +} + +void QQmlType::SingletonInstanceInfo::setQObjectApi(QQmlEngine *e, QObject *o) +{ + qobjectApis.insert(e, o); +} + +QObject *QQmlType::SingletonInstanceInfo::qobjectApi(QQmlEngine *e) const +{ + return qobjectApis.value(e); +} + +void QQmlType::SingletonInstanceInfo::setScriptApi(QQmlEngine *e, QJSValue v) +{ + scriptApis.insert(e, v); +} + +QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const +{ + return scriptApis.value(e); +} + QHash QQmlTypePrivate::m_attachedPropertyIds; QQmlTypePrivate::QQmlTypePrivate() @@ -197,10 +257,14 @@ QQmlTypePrivate::QQmlTypePrivate() m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), - m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false) + m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false), m_singletonInstanceInfo(0) { } +QQmlTypePrivate::~QQmlTypePrivate() +{ + delete m_singletonInstanceInfo; +} QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) : d(new QQmlTypePrivate) @@ -216,15 +280,40 @@ QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) d->m_version_min = 0; } -QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type) +QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterSingletonType &type) : d(new QQmlTypePrivate) { - QString name = QString::fromUtf8(type.uri); - if (type.uri) name += QLatin1Char('/'); - name += QString::fromUtf8(type.elementName); + d->m_elementName = elementName; + d->m_module = moduleFromUtf8(type.uri); + + d->m_version_maj = type.versionMajor; + d->m_version_min = type.versionMinor; + + if (type.qobjectApi) { + if (type.version >= 1) // static metaobject added in version 1 + d->m_baseMetaObject = type.instanceMetaObject; + if (type.version >= 2) // typeId added in version 2 + d->m_typeId = type.typeId; + if (type.version >= 2) // revisions added in version 2 + d->m_revision = type.revision; + } + + d->m_newFunc = 0; + d->m_index = index; + + d->m_singletonInstanceInfo = new SingletonInstanceInfo; + d->m_singletonInstanceInfo->scriptCallback = type.scriptApi; + d->m_singletonInstanceInfo->qobjectCallback = type.qobjectApi; + d->m_singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName); + d->m_singletonInstanceInfo->instanceMetaObject = (type.qobjectApi && type.version >= 1) ? type.instanceMetaObject : 0; +} + +QQmlType::QQmlType(int index, const QString &elementName, const QQmlPrivate::RegisterType &type) +: d(new QQmlTypePrivate) +{ + d->m_elementName = elementName; + d->m_module = moduleFromUtf8(type.uri); - d->m_module = QString::fromUtf8(type.uri); - d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; if (type.version >= 1) // revisions added in version 1 @@ -262,7 +351,7 @@ QQmlType::~QQmlType() delete d; } -QString QQmlType::module() const +const QHashedString &QQmlType::module() const { return d->m_module; } @@ -283,7 +372,7 @@ bool QQmlType::availableInVersion(int vmajor, int vminor) const return vmajor == d->m_version_maj && vminor >= d->m_version_min; } -bool QQmlType::availableInVersion(const QString &module, int vmajor, int vminor) const +bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const { Q_ASSERT(vmajor >= 0 && vminor >= 0); return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min; @@ -292,7 +381,7 @@ bool QQmlType::availableInVersion(const QString &module, int vmajor, int vminor) // returns the nearest _registered_ super class QQmlType *QQmlType::superType() const { - if (!d->m_haveSuperType) { + if (!d->m_haveSuperType && d->m_baseMetaObject) { const QMetaObject *mo = d->m_baseMetaObject->superClass(); while (mo && !d->m_superType) { d->m_superType = QQmlMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min); @@ -398,9 +487,14 @@ void QQmlTypePrivate::init() const if (m_isSetup) return; + const QMetaObject *mo = m_baseMetaObject; + if (!mo) { + // singleton type without metaobject information + return; + } + // Setup extended meta object // XXX - very inefficient - const QMetaObject *mo = m_baseMetaObject; if (m_extFunc) { QMetaObjectBuilder builder; clone(builder, m_extMetaObject, m_extMetaObject, m_extMetaObject); @@ -469,20 +563,35 @@ void QQmlTypePrivate::initEnums() const QWriteLocker lock(metaTypeDataLock()); if (m_isEnumSetup) return; - const QMetaObject *metaObject = m_baseMetaObject; - for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + if (m_baseMetaObject) // could be singleton type without metaobject + insertEnums(m_baseMetaObject); - QMetaEnum e = metaObject->enumerator(ii); + m_isEnumSetup = true; +} - for (int jj = 0; jj < e.keyCount(); ++jj) - m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); +void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const +{ + // Add any enum values defined by 'related' classes + if (metaObject->d.relatedMetaObjects) { + const QMetaObject **related = metaObject->d.relatedMetaObjects; + if (related) { + while (*related) + insertEnums(*related++); + } } - m_isEnumSetup = true; + // Add any enum values defined by this class, overwriting any inherited values + for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { + QMetaEnum e = metaObject->enumerator(ii); + for (int jj = 0; jj < e.keyCount(); ++jj) + m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + } } QByteArray QQmlType::typeName() const { + if (d->m_singletonInstanceInfo) + return d->m_singletonInstanceInfo->typeName.toUtf8(); if (d->m_baseMetaObject) return d->m_baseMetaObject->className(); else @@ -491,16 +600,18 @@ QByteArray QQmlType::typeName() const const QString &QQmlType::elementName() const { - if (d->m_elementName.isEmpty()) { - QString n = qmlTypeName(); - int idx = n.lastIndexOf(QLatin1Char('/')); - d->m_elementName = n.mid(idx + 1); - } return d->m_elementName; } const QString &QQmlType::qmlTypeName() const { + if (d->m_name.isEmpty()) { + if (!d->m_module.isEmpty()) + d->m_name = static_cast(d->m_module) + QLatin1Char('/') + d->m_elementName; + else + d->m_name = d->m_elementName; + } + return d->m_name; } @@ -531,6 +642,11 @@ void QQmlType::create(QObject **out, void **memory, size_t additionalMemory) con *memory = ((char *)rv) + d->m_allocationSize; } +QQmlType::SingletonInstanceInfo *QQmlType::singletonInstanceInfo() const +{ + return d->m_singletonInstanceInfo; +} + QQmlCustomParser *QQmlType::customParser() const { return d->m_customParser; @@ -563,6 +679,11 @@ bool QQmlType::isExtendedType() const return !d->m_metaObjects.isEmpty(); } +bool QQmlType::isSingleton() const +{ + return d->m_singletonInstanceInfo != 0; +} + bool QQmlType::isInterface() const { return d->m_isInterface; @@ -651,20 +772,49 @@ int QQmlType::index() const return d->m_index; } -int QQmlType::enumValue(const QHashedStringRef &name) const +int QQmlType::enumValue(const QHashedStringRef &name, bool *ok) const { + Q_ASSERT(ok); + *ok = true; + d->initEnums(); int *rv = d->m_enums.value(name); - return rv?*rv:-1; + if (rv) + return *rv; + + *ok = false; + return -1; } -int QQmlType::enumValue(const QHashedV8String &name) const +int QQmlType::enumValue(const QHashedCStringRef &name, bool *ok) const { + Q_ASSERT(ok); + *ok = true; + d->initEnums(); int *rv = d->m_enums.value(name); - return rv?*rv:-1; + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::enumValue(const QHashedV8String &name, bool *ok) const +{ + Q_ASSERT(ok); + *ok = true; + + d->initEnums(); + + int *rv = d->m_enums.value(name); + if (rv) + return *rv; + + *ok = false; + return -1; } QQmlTypeModule::QQmlTypeModule() @@ -699,8 +849,6 @@ int QQmlTypeModule::maximumMinorVersion() const void QQmlTypeModulePrivate::add(QQmlType *type) { - types << type; - minMinorVersion = qMin(minMinorVersion, type->minorVersion()); maxMinorVersion = qMax(maxMinorVersion, type->minorVersion()); @@ -714,25 +862,6 @@ void QQmlTypeModulePrivate::add(QQmlType *type) list.append(type); } -QList QQmlTypeModule::types() -{ - QList rv; - QReadLocker lock(metaTypeDataLock()); - rv = d->types; - return rv; -} - -QList QQmlTypeModule::type(const QString &name) -{ - QReadLocker lock(metaTypeDataLock()); - QList rv; - for (int ii = 0; ii < d->types.count(); ++ii) { - if (d->types.at(ii)->elementName() == name) - rv << d->types.at(ii); - } - return rv; -} - QQmlType *QQmlTypeModule::type(const QHashedStringRef &name, int minor) { QReadLocker lock(metaTypeDataLock()); @@ -761,6 +890,20 @@ QQmlType *QQmlTypeModule::type(const QHashedV8String &name, int minor) return 0; } +QList QQmlTypeModule::singletonTypes(int minor) const +{ + QReadLocker lock(metaTypeDataLock()); + + QList retn; + for (int ii = 0; ii < d->types.count(); ++ii) { + QQmlType *curr = d->types.at(ii); + if (curr->isSingleton() && curr->minorVersion() <= minor) + retn.append(curr); + } + + return retn; +} + QQmlTypeModuleVersion::QQmlTypeModuleVersion() : m_module(0), m_minor(0) @@ -835,8 +978,8 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface) data->idToType.insert(type->typeId(), type); data->idToType.insert(type->qListTypeId(), type); // XXX No insertMulti, so no multi-version interfaces? - if (!type->qmlTypeName().isEmpty()) - data->nameToType.insert(type->qmlTypeName(), type); + if (!type->elementName().isEmpty()) + data->nameToType.insert(type->elementName(), type); if (data->interfaces.size() <= interface.typeId) data->interfaces.resize(interface.typeId + 16); @@ -848,29 +991,73 @@ int registerInterface(const QQmlPrivate::RegisterInterface &interface) return index; } -int registerType(const QQmlPrivate::RegisterType &type) +QString registrationTypeString(QQmlType::RegistrationType typeType) +{ + QString typeStr; + if (typeType == QQmlType::CppType) + typeStr = QStringLiteral("element"); + else if (typeType == QQmlType::SingletonType) + typeStr = QStringLiteral("singleton type"); + return typeStr; +} + +// NOTE: caller must hold a QWriteLocker on "data" +bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName) { - if (type.elementName) { - for (int ii = 0; type.elementName[ii]; ++ii) { - if (!isalnum(type.elementName[ii])) { - qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName); - return -1; + if (!typeName.isEmpty()) { + int typeNameLen = typeName.length(); + for (int ii = 0; ii < typeNameLen; ++ii) { + if (!typeName.at(ii).isLetterOrNumber()) { + QString failure(QCoreApplication::translate("qmlRegisterType", "Invalid QML %1 name \"%2\"")); + data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName)); + return false; } } } + if (uri && !typeName.isEmpty()) { + QString nameSpace = moduleFromUtf8(uri); + + if (!data->typeRegistrationNamespace.isEmpty()) { + // We can only install types into the registered namespace + if (nameSpace != data->typeRegistrationNamespace) { + QString failure(QCoreApplication::translate("qmlRegisterType", + "Cannot install %1 '%2' into unregistered namespace '%3'")); + data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace)); + return false; + } + } else if (data->typeRegistrationNamespace != nameSpace) { + // Is the target namespace protected against further registrations? + if (data->protectedNamespaces.contains(nameSpace)) { + QString failure(QCoreApplication::translate("qmlRegisterType", + "Cannot install %1 '%2' into protected namespace '%3'")); + data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace)); + return false; + } + } + } + + return true; +} + +int registerType(const QQmlPrivate::RegisterType &type) +{ QWriteLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); + QString elementName = QString::fromUtf8(type.elementName); + if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName)) + return -1; + int index = data->types.count(); - QQmlType *dtype = new QQmlType(index, type); + QQmlType *dtype = new QQmlType(index, elementName, type); data->types.append(dtype); data->idToType.insert(dtype->typeId(), dtype); if (dtype->qListTypeId()) data->idToType.insert(dtype->qListTypeId(), dtype); - if (!dtype->qmlTypeName().isEmpty()) - data->nameToType.insertMulti(dtype->qmlTypeName(), dtype); + if (!dtype->elementName().isEmpty()) + data->nameToType.insertMulti(dtype->elementName(), dtype); data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype); @@ -881,8 +1068,8 @@ int registerType(const QQmlPrivate::RegisterType &type) data->objects.setBit(type.typeId, true); if (type.listId) data->lists.setBit(type.listId, true); - if (type.uri) { - QString mod = QString::fromUtf8(type.uri); + if (!dtype->module().isEmpty()) { + const QHashedString &mod = dtype->module(); QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor); QQmlTypeModule *module = data->uriToModule.value(versionedUri); @@ -897,28 +1084,44 @@ int registerType(const QQmlPrivate::RegisterType &type) return index; } -int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api) +int registerSingletonType(const QQmlPrivate::RegisterSingletonType &type) { QWriteLocker lock(metaTypeDataLock()); - QQmlMetaTypeData *data = metaTypeData(); - QString uri = QString::fromUtf8(api.uri); - QQmlMetaType::ModuleApi import; - import.major = api.versionMajor; - import.minor = api.versionMinor; - import.script = api.scriptApi; - import.qobject = api.qobjectApi; - - int index = data->moduleApiCount++; - - QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri); - if (iter == data->moduleApis.end()) { - QQmlMetaTypeData::ModuleApiList apis; - apis.moduleApis << import; - data->moduleApis.insert(uri, apis); - } else { - iter->moduleApis << import; - iter->sorted = false; + QString typeName = QString::fromUtf8(type.typeName); + if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName)) + return -1; + + int index = data->types.count(); + + QQmlType *dtype = new QQmlType(index, typeName, type); + + data->types.append(dtype); + data->idToType.insert(dtype->typeId(), dtype); + + if (!dtype->elementName().isEmpty()) + data->nameToType.insertMulti(dtype->elementName(), dtype); + + if (dtype->baseMetaObject()) + data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype); + + if (type.typeId) { + if (data->objects.size() <= type.typeId) + data->objects.resize(type.typeId + 16); + data->objects.setBit(type.typeId, true); + } + + if (!dtype->module().isEmpty()) { + const QHashedString &mod = dtype->module(); + + QQmlMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor); + QQmlTypeModule *module = data->uriToModule.value(versionedUri); + if (!module) { + module = new QQmlTypeModule; + module->d->uri = versionedUri; + data->uriToModule.insert(versionedUri, module); + } + module->d->add(dtype); } return index; @@ -937,12 +1140,52 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data) return registerInterface(*reinterpret_cast(data)); } else if (type == AutoParentRegistration) { return registerAutoParentFunction(*reinterpret_cast(data)); - } else if (type == ModuleApiRegistration) { - return registerModuleApi(*reinterpret_cast(data)); + } else if (type == SingletonRegistration) { + return registerSingletonType(*reinterpret_cast(data)); } return -1; } +bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + // Has any type previously been installed to this namespace? + QHashedString nameSpace(uri); + foreach (const QQmlType *type, data->types) + if (type->module() == nameSpace) + return true; + + return false; +} + +void QQmlMetaType::protectNamespace(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + data->protectedNamespaces.insert(uri); +} + +void QQmlMetaType::setTypeRegistrationNamespace(const QString &uri) +{ + QQmlMetaTypeData *data = metaTypeData(); + + data->typeRegistrationNamespace = uri; + data->typeRegistrationFailures.clear(); +} + +QStringList QQmlMetaType::typeRegistrationFailures() +{ + QQmlMetaTypeData *data = metaTypeData(); + + return data->typeRegistrationFailures; +} + +QReadWriteLock *QQmlMetaType::typeRegistrationLock() +{ + return metaTypeDataLock(); +} + /* Returns true if a module \a uri of any version is installed. */ @@ -980,12 +1223,6 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor) return true; - // then, check ModuleApis - foreach (const QQmlMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) { - if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct? - return true; - } - return false; } @@ -1003,50 +1240,6 @@ QList QQmlMetaType::parentFunctions() return data->parentFunctions; } -static bool operator<(const QQmlMetaType::ModuleApi &lhs, const QQmlMetaType::ModuleApi &rhs) -{ - return lhs.major < rhs.major || (lhs.major == rhs.major && lhs.minor < rhs.minor); -} - -QQmlMetaType::ModuleApi -QQmlMetaType::moduleApi(const QString &uri, int versionMajor, int versionMinor) -{ - QReadLocker lock(metaTypeDataLock()); - QQmlMetaTypeData *data = metaTypeData(); - - QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri); - if (iter == data->moduleApis.end()) - return ModuleApi(); - - if (iter->sorted == false) { - qSort(iter->moduleApis.begin(), iter->moduleApis.end()); - iter->sorted = true; - } - - for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) { - const ModuleApi &import = iter->moduleApis.at(ii); - if (import.major == versionMajor && import.minor <= versionMinor) - return import; - } - - return ModuleApi(); -} - -QHash > QQmlMetaType::moduleApis() -{ - QReadLocker lock(metaTypeDataLock()); - QQmlMetaTypeData *data = metaTypeData(); - - QHash > moduleApis; - QHashIterator it(data->moduleApis); - while (it.hasNext()) { - it.next(); - moduleApis[it.key()] = it.value().moduleApis; - } - - return moduleApis; -} - QObject *QQmlMetaType::toQObject(const QVariant &v, bool *ok) { if (!isQObject(v.userType())) { @@ -1237,19 +1430,35 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type) } /*! - Returns the type (if any) of URI-qualified named \a name in version specified + Returns the type (if any) of URI-qualified named \a qualifiedName and version specified + by \a version_major and \a version_minor. +*/ +QQmlType *QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor) +{ + int slash = qualifiedName.indexOf(QLatin1Char('/')); + if (slash <= 0) + return 0; + + QHashedStringRef module(qualifiedName.constData(), slash); + QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1); + + return qmlType(name, module, version_major, version_minor); +} + +/*! + Returns the type (if any) of \a name in \a module and version specified by \a version_major and \a version_minor. */ -QQmlType *QQmlMetaType::qmlType(const QString &name, int version_major, int version_minor) +QQmlType *QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.find(name); - while (it != data->nameToType.end()) { + while (it != data->nameToType.end() && it.key() == name) { // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty - if (it.key() == name && (version_major<0 || (*it)->availableInVersion(version_major,version_minor))) + if (version_major < 0 || (*it)->availableInVersion(module, version_major,version_minor)) return (*it); ++it; } @@ -1274,7 +1483,7 @@ QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject) by \a version_major and \a version_minor in module specified by \a uri. Returns null if no type is registered. */ -QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor) +QQmlType *QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor) { Q_ASSERT(version_major >= 0 && version_minor >= 0); QReadLocker lock(metaTypeDataLock()); @@ -1315,7 +1524,14 @@ QList QQmlMetaType::qmlTypeNames() QReadLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - return data->nameToType.keys(); + QList names; + QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin(); + while (it != data->nameToType.end()) { + names += (*it)->qmlTypeName(); + ++it; + } + + return names; } /*! @@ -1329,6 +1545,25 @@ QList QQmlMetaType::qmlTypes() return data->nameToType.values(); } +/*! + Returns the list of registered QML singleton types. +*/ +QList QQmlMetaType::qmlSingletonTypes() +{ + QReadLocker lock(metaTypeDataLock()); + QQmlMetaTypeData *data = metaTypeData(); + + QList alltypes = data->nameToType.values(); + QList retn; + foreach (QQmlType* t, alltypes) { + if (t->isSingleton()) { + retn.append(t); + } + } + + return retn; +} + int QQmlMetaType::QQuickAnchorLineMetaTypeId() { static int id = 0;