diff options
author | Martin Jones <martin.jones@nokia.com> | 2012-05-16 17:49:32 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-05-17 13:42:27 +0200 |
commit | 8017cf63505f7ed477c658634ec882a12d3b3ddc (patch) | |
tree | 28d023fe7e8a2b2392c564a37ef7b891d2bb41b8 /src/qml/qml | |
parent | c556eecc25e24d6ee4f5c9965193a588c93b95fc (diff) |
Optimize type resolution
Faster qmlType() and resolveType() lookup.
Change-Id: I096439f23bf6071e8bfdf0cda366cc71e00293ba
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/ftw/qhashedstring.cpp | 21 | ||||
-rw-r--r-- | src/qml/qml/ftw/qhashedstring_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlcompiler.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmldirparser.cpp | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmldirparser_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 61 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 138 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 15 |
9 files changed, 147 insertions, 119 deletions
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp index 1f09d50ed3..2dc717b488 100644 --- a/src/qml/qml/ftw/qhashedstring.cpp +++ b/src/qml/qml/ftw/qhashedstring.cpp @@ -443,6 +443,27 @@ bool QHashedStringRef::startsWith(const QString &s) const QHashedString::compare(s.constData(), m_data, s.length()); } +static int findChar(const QChar *str, int len, QChar ch, int from) +{ + const ushort *s = (const ushort *)str; + ushort c = ch.unicode(); + if (from < 0) + from = qMax(from + len, 0); + if (from < len) { + const ushort *n = s + from - 1; + const ushort *e = s + len; + while (++n != e) + if (*n == c) + return n - s; + } + return -1; +} + +int QHashedStringRef::indexOf(const QChar &c, int from) const +{ + return findChar(m_data, m_length, c, from); +} + QString QHashedStringRef::toString() const { if (m_length == 0) diff --git a/src/qml/qml/ftw/qhashedstring_p.h b/src/qml/qml/ftw/qhashedstring_p.h index f058f21e98..f8099d508b 100644 --- a/src/qml/qml/ftw/qhashedstring_p.h +++ b/src/qml/qml/ftw/qhashedstring_p.h @@ -148,6 +148,7 @@ public: inline const QChar *constData() const; bool startsWith(const QString &) const; bool endsWith(const QString &) const; + int indexOf(const QChar &, int from=0) const; QHashedStringRef mid(int, int) const; inline bool isEmpty() const; diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp index c423d933d0..54035fcccf 100644 --- a/src/qml/qml/qqmlcompiler.cpp +++ b/src/qml/qml/qqmlcompiler.cpp @@ -90,7 +90,8 @@ using namespace QQmlCompilerTypes; static QString id_string(QLatin1String("id")); static QString on_string(QLatin1String("on")); static QString Changed_string(QLatin1String("Changed")); -static QString Component_import_string(QLatin1String("QML/Component")); +static QString Component_string(QLatin1String("Component")); +static QString Component_module_string(QLatin1String("QML")); static QString qsTr_string(QLatin1String("qsTr")); static QString qsTrId_string(QLatin1String("qsTrId")); @@ -1603,7 +1604,7 @@ bool QQmlCompiler::buildSubObject(QQmlScript::Object *obj, const BindingContext int QQmlCompiler::componentTypeRef() { if (cachedComponentTypeRef == -1) { - QQmlType *t = QQmlMetaType::qmlType(Component_import_string,1,0); + QQmlType *t = QQmlMetaType::qmlType(Component_string, Component_module_string, 1, 0); for (int ii = output->types.count() - 1; ii >= 0; --ii) { if (output->types.at(ii).type == t) { cachedComponentTypeRef = ii; @@ -1739,7 +1740,7 @@ bool QQmlCompiler::buildProperty(QQmlScript::Property *prop, QQmlType *type = 0; QQmlImportNamespace *typeNamespace = 0; - unit->imports().resolveType(prop->name().toString(), &type, 0, 0, 0, &typeNamespace); + unit->imports().resolveType(prop->name(), &type, 0, 0, 0, &typeNamespace); if (typeNamespace) { COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj, @@ -1861,7 +1862,7 @@ bool QQmlCompiler::buildPropertyInNamespace(QQmlImportNamespace *ns, // Setup attached property data QQmlType *type = 0; - unit->imports().resolveType(ns, prop->name().toString(), &type, 0, 0, 0); + unit->imports().resolveType(ns, prop->name(), &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); @@ -2875,7 +2876,7 @@ bool QQmlCompiler::buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mod QByteArray customTypeName; QQmlType *qmltype = 0; QString url; - if (!unit->imports().resolveType(p->customType.toString(), &qmltype, &url, 0, 0, 0)) + if (!unit->imports().resolveType(p->customType, &qmltype, &url, 0, 0, 0)) COMPILE_EXCEPTION(p, tr("Invalid property type")); if (!qmltype) { diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp index 2da4a3300b..2fb47cc008 100644 --- a/src/qml/qml/qqmldirparser.cpp +++ b/src/qml/qml/qqmldirparser.cpp @@ -156,7 +156,7 @@ bool QQmlDirParser::parse() } Component entry(sections[1], sections[2], -1, -1); entry.internal = true; - _components.append(entry); + _components.insertMulti(entry.typeName, entry); } else if (sections[0] == QLatin1String("typeinfo")) { if (sectionCount != 2) { reportError(lineNumber, -1, @@ -171,7 +171,7 @@ bool QQmlDirParser::parse() } else if (sectionCount == 2) { // No version specified (should only be used for relative qmldir files) const Component entry(sections[0], sections[1], -1, -1); - _components.append(entry); + _components.insertMulti(entry.typeName, entry); } else if (sectionCount == 3) { const QString &version = sections[1]; const int dotIndex = version.indexOf(QLatin1Char('.')); @@ -196,7 +196,7 @@ bool QQmlDirParser::parse() _scripts.append(entry); } else { const Component entry(sections[0], fileName, majorVersion, minorVersion); - _components.append(entry); + _components.insertMulti(entry.typeName, entry); } } } @@ -250,7 +250,7 @@ QList<QQmlDirParser::Plugin> QQmlDirParser::plugins() const return _plugins; } -QList<QQmlDirParser::Component> QQmlDirParser::components() const +QHash<QHashedStringRef,QQmlDirParser::Component> QQmlDirParser::components() const { return _components; } diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h index 77fe277a7e..4de39e04d9 100644 --- a/src/qml/qml/qqmldirparser_p.h +++ b/src/qml/qml/qqmldirparser_p.h @@ -56,6 +56,7 @@ #include <QtCore/QUrl> #include <QtCore/QHash> #include <QtCore/QDebug> +#include <private/qhashedstring_p.h> QT_BEGIN_NAMESPACE @@ -120,7 +121,7 @@ public: int minorVersion; }; - QList<Component> components() const; + QHash<QHashedStringRef,Component> components() const; QList<Script> scripts() const; QList<Plugin> plugins() const; @@ -143,7 +144,7 @@ private: private: QList<QQmlError> _errors; QString _source; - QList<Component> _components; + QHash<QHashedStringRef,Component> _components; // multi hash QList<Script> _scripts; QList<Plugin> _plugins; #ifdef QT_CREATOR @@ -152,7 +153,7 @@ private: unsigned _isParsed: 1; }; -typedef QList<QQmlDirParser::Component> QQmlDirComponents; +typedef QHash<QHashedStringRef,QQmlDirParser::Component> QQmlDirComponents; typedef QList<QQmlDirParser::Script> QQmlDirScripts; QDebug &operator<< (QDebug &, const QQmlDirParser::Component &); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 610257de38..9bdc67a0ac 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -125,20 +125,20 @@ public: QQmlDirComponents qmlDirComponents; QQmlDirScripts qmlDirScripts; - bool resolveType(QQmlTypeLoader *typeLoader, const QString& type, + bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QString *base = 0, bool *typeRecursionDetected = 0) const; }; QList<Import> imports; - bool resolveType(QQmlTypeLoader *typeLoader, const QString& type, + bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QString *base = 0, QList<QQmlError> *errors = 0); // Prefix when used as a qualified import. Otherwise empty. - QString prefix; + QHashedString prefix; // Used by QQmlImportsPrivate::qualifiedSets QQmlImportNamespace *nextNamespace; @@ -156,7 +156,7 @@ public: bool isImplicitImport, QQmlImportDatabase *database, QString *, QList<QQmlError> *errors); - bool resolveType(const QString& type, int *vmajor, int *vminor, + bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QList<QQmlError> *errors); @@ -166,7 +166,7 @@ public: QQmlImportNamespace unqualifiedset; - QQmlImportNamespace *findQualifiedNamespace(const QString &); + QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &); QFieldList<QQmlImportNamespace, &QQmlImportNamespace::nextNamespace> qualifiedSets; QQmlTypeLoader *typeLoader; @@ -325,7 +325,7 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const \sa addImport() */ -bool QQmlImports::resolveType(const QString& type, +bool QQmlImports::resolveType(const QHashedStringRef &type, QQmlType** type_return, QString* url_return, int *vmaj, int *vmin, QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const { @@ -339,7 +339,7 @@ bool QQmlImports::resolveType(const QString& type, if (d->resolveType(type,vmaj,vmin,type_return,url_return, errors)) { if (qmlImportTrace()) { #define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \ - << ')' << "::resolveType: " << type << " => " + << ')' << "::resolveType: " << type.toString() << " => " if (type_return && *type_return && url_return && !url_return->isEmpty()) RESOLVE_TYPE_DEBUG << (*type_return)->typeName() << ' ' << *url_return; @@ -366,7 +366,7 @@ bool QQmlImports::resolveType(const QString& type, If either return pointer is 0, the corresponding search is not done. */ -bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QString& type, +bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &type, QQmlType** type_return, QString* url_return, int *vmaj, int *vmin) const { @@ -374,13 +374,12 @@ bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QString& type, } bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, - const QString& type, int *vmajor, int *vminor, + const QHashedStringRef& type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QString *base, bool *typeRecursionDetected) const { if (majversion >= 0 && minversion >= 0) { - QString qt = uri + QLatin1Char('/') + type; - QQmlType *t = QQmlMetaType::qmlType(qt, majversion, minversion); + QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion); if (t) { if (vmajor) *vmajor = majversion; if (vminor) *vminor = minversion; @@ -392,14 +391,21 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, bool typeWasDeclaredInQmldir = false; if (!qmlDirComponents.isEmpty()) { - foreach (const QQmlDirParser::Component &c, qmlDirComponents) { - if (type == c.typeName) { - typeWasDeclaredInQmldir = true; + QQmlDirComponents::ConstIterator it = qmlDirComponents.find(type); + if (it != qmlDirComponents.end()) { + typeWasDeclaredInQmldir = true; + // first found is last inserted - process in reverse + QQmlDirComponents::ConstIterator begin = it; + while (++it != qmlDirComponents.end() && it.key() == type) {} + do { + --it; + const QQmlDirParser::Component &c = *it; + // importing version -1 means import ALL versions if ((majversion == -1) || (c.majorVersion == majversion && minversion >= c.minorVersion)) { - QString candidate = resolveLocalUrl(QString(url + type + dotqml_string), c.fileName); + QString candidate = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName); if (c.internal && base) { if (resolveLocalUrl(*base, c.fileName) != candidate) continue; // failed attempt to access an internal type @@ -413,19 +419,18 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, *url_return = candidate; return true; } - } + } while (it != begin); } } if (!typeWasDeclaredInQmldir && !isLibrary) { - QString qmlUrl = url + type + dotqml_string; + QString qmlUrl = url + QString::fromRawData(type.constData(), type.length()) + dotqml_string; bool exists = false; if (QQmlFile::isBundle(qmlUrl)) { exists = QQmlFile::bundleFileExists(qmlUrl, typeLoader->engine()); } else { - QString file = QQmlFile::urlToLocalFileOrQrc(qmlUrl); exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(qmlUrl)).isEmpty(); } @@ -444,19 +449,19 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, return false; } -bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vminor, +bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QList<QQmlError> *errors) { QQmlImportNamespace *s = 0; int dot = type.indexOf(QLatin1Char('.')); if (dot >= 0) { - QString namespaceName = type.left(dot); + QHashedStringRef namespaceName(type.constData(), dot); s = findQualifiedNamespace(namespaceName); if (!s) { if (errors) { QQmlError error; - error.setDescription(QQmlImportDatabase::tr("- %1 is not a namespace").arg(namespaceName)); + error.setDescription(QQmlImportDatabase::tr("- %1 is not a namespace").arg(namespaceName.toString())); errors->prepend(error); } return false; @@ -473,13 +478,13 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin } else { s = &unqualifiedset; } - QString unqualifiedtype = dot < 0 ? type : type.mid(dot+1, -1); + QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1); if (s) { if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return,url_return, &base, errors)) return true; if (s->imports.count() == 1 && !s->imports.at(0).isLibrary && url_return && s != &unqualifiedset) { // qualified, and only 1 url - *url_return = resolveLocalUrl(s->imports.at(0).url, unqualifiedtype + QLatin1String(".qml")); + *url_return = resolveLocalUrl(s->imports.at(0).url, unqualifiedtype.toString() + QLatin1String(".qml")); return true; } } @@ -487,7 +492,7 @@ bool QQmlImportsPrivate::resolveType(const QString& type, int *vmajor, int *vmin return false; } -bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QString& type, +bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, int *vmajor, int *vminor, QQmlType** type_return, QString* url_return, QString *base, QList<QQmlError> *errors) { @@ -560,7 +565,7 @@ QQmlImportsPrivate::~QQmlImportsPrivate() delete ns; } -QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QString &prefix) +QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStringRef &prefix) { for (QQmlImportNamespace *ns = qualifiedSets.first(); ns; ns = qualifiedSets.next(ns)) { if (prefix == ns->prefix) @@ -844,11 +849,11 @@ bool QQmlImportsPrivate::addImport(const QQmlDirComponents &qmldircomponentsnetw } else { int lowest_min = INT_MAX; int highest_min = INT_MIN; - typedef QList<QQmlDirParser::Component>::const_iterator ConstIterator; + typedef QQmlDirComponents::const_iterator ConstIterator; typedef QList<QQmlDirParser::Script>::const_iterator SConstIterator; - for (ConstIterator cit = qmldircomponents.constBegin(); - cit != qmldircomponents.constEnd(); ++cit) { + ConstIterator cend = qmldircomponents.end(); + for (ConstIterator cit = qmldircomponents.begin(); cit != cend; ++cit) { if (cit->majorVersion == vmaj) { lowest_min = qMin(lowest_min, cit->minorVersion); highest_min = qMax(highest_min, cit->minorVersion); diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index ad0bbc6cc6..111bf29641 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -83,13 +83,13 @@ public: void setBaseUrl(const QUrl &url, const QString &urlString = QString()); QUrl baseUrl() const; - bool resolveType(const QString& type, + bool resolveType(const QHashedStringRef &type, QQmlType** type_return, QString* url_return, int *version_major, int *version_minor, QQmlImportNamespace** ns_return, QList<QQmlError> *errors = 0) const; bool resolveType(QQmlImportNamespace*, - const QString& type, + const QHashedStringRef& type, QQmlType** type_return, QString* url_return, int *version_major, int *version_minor) const; diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 856f75fc16..1566d83a22 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -73,7 +73,7 @@ struct QQmlMetaTypeData QList<QQmlType *> types; typedef QHash<int, QQmlType *> Ids; Ids idToType; - typedef QHash<QString, QQmlType *> Names; + typedef QHash<QHashedStringRef,QQmlType *> Names; Names nameToType; typedef QHash<const QMetaObject *, QQmlType *> MetaObjects; MetaObjects metaObjectToType; @@ -83,12 +83,12 @@ 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<VersionedUri, QQmlTypeModule *> TypeModules; @@ -99,7 +99,7 @@ struct QQmlMetaTypeData QList<QQmlMetaType::ModuleApi> moduleApis; bool sorted; }; - typedef QHash<QString, ModuleApiList> ModuleApis; + typedef QStringHash<ModuleApiList> ModuleApis; ModuleApis moduleApis; int moduleApiCount; @@ -132,7 +132,7 @@ Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock) static uint qHash(const QQmlMetaTypeData::VersionedUri &v) { - return qHash(v.uri) ^ qHash(v.majorVersion); + return v.uri.hash() ^ qHash(v.majorVersion); } QQmlMetaTypeData::QQmlMetaTypeData() @@ -156,7 +156,7 @@ public: bool m_isInterface : 1; const char *m_iid; - QString m_module; + QHashedString m_module; QString m_name; QString m_elementName; int m_version_maj; @@ -219,12 +219,14 @@ QQmlType::QQmlType(int index, const QQmlPrivate::RegisterInterface &interface) QQmlType::QQmlType(int index, const QQmlPrivate::RegisterType &type) : d(new QQmlTypePrivate) { - QString name = QString::fromUtf8(type.uri); - if (type.uri) name += QLatin1Char('/'); - name += QString::fromUtf8(type.elementName); - d->m_module = QString::fromUtf8(type.uri); - d->m_name = name; + d->m_elementName = QString::fromUtf8(type.elementName); + + if (!d->m_module.isEmpty()) + d->m_name = static_cast<QString>(d->m_module) + QLatin1Char('/') + d->m_elementName; + else + d->m_name = d->m_elementName; + d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; if (type.version >= 1) // revisions added in version 1 @@ -262,7 +264,7 @@ QQmlType::~QQmlType() delete d; } -QString QQmlType::module() const +const QHashedString &QQmlType::module() const { return d->m_module; } @@ -283,7 +285,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; @@ -491,11 +493,6 @@ 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; } @@ -699,8 +696,6 @@ int QQmlTypeModule::maximumMinorVersion() const void QQmlTypeModulePrivate::add(QQmlType *type) { - types << type; - minMinorVersion = qMin(minMinorVersion, type->minorVersion()); maxMinorVersion = qMax(maxMinorVersion, type->minorVersion()); @@ -714,25 +709,6 @@ void QQmlTypeModulePrivate::add(QQmlType *type) list.append(type); } -QList<QQmlType *> QQmlTypeModule::types() -{ - QList<QQmlType *> rv; - QReadLocker lock(metaTypeDataLock()); - rv = d->types; - return rv; -} - -QList<QQmlType *> QQmlTypeModule::type(const QString &name) -{ - QReadLocker lock(metaTypeDataLock()); - QList<QQmlType *> 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()); @@ -835,8 +811,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); @@ -869,8 +845,8 @@ int registerType(const QQmlPrivate::RegisterType &type) 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 +857,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); @@ -915,14 +891,14 @@ int registerModuleApi(const QQmlPrivate::RegisterModuleApi &api) int index = data->moduleApiCount++; - QQmlMetaTypeData::ModuleApis::Iterator iter = data->moduleApis.find(uri); - if (iter == data->moduleApis.end()) { + QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri); + if (!apiList) { QQmlMetaTypeData::ModuleApiList apis; apis.moduleApis << import; data->moduleApis.insert(uri, apis); } else { - iter->moduleApis << import; - iter->sorted = false; + apiList->moduleApis << import; + apiList->sorted = false; } return index; @@ -985,9 +961,12 @@ bool QQmlMetaType::isModule(const QString &module, int versionMajor, int version 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; + QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(module); + if (apiList) { + foreach (const QQmlMetaType::ModuleApi &mApi, apiList->moduleApis) { + if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct? + return true; + } } return false; @@ -1018,17 +997,17 @@ 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()) + QQmlMetaTypeData::ModuleApiList *apiList = data->moduleApis.value(uri); + if (!apiList) return ModuleApi(); - if (iter->sorted == false) { - qSort(iter->moduleApis.begin(), iter->moduleApis.end()); - iter->sorted = true; + if (apiList->sorted == false) { + qSort(apiList->moduleApis.begin(), apiList->moduleApis.end()); + apiList->sorted = true; } - for (int ii = iter->moduleApis.count() - 1; ii >= 0; --ii) { - const ModuleApi &import = iter->moduleApis.at(ii); + for (int ii = apiList->moduleApis.count() - 1; ii >= 0; --ii) { + const ModuleApi &import = apiList->moduleApis.at(ii); if (import.major == versionMajor && import.minor <= versionMinor) return import; } @@ -1042,11 +1021,9 @@ QHash<QString, QList<QQmlMetaType::ModuleApi> > QQmlMetaType::moduleApis() QQmlMetaTypeData *data = metaTypeData(); QHash<QString, QList<ModuleApi> > moduleApis; - QHashIterator<QString, QQmlMetaTypeData::ModuleApiList> it(data->moduleApis); - while (it.hasNext()) { - it.next(); + QStringHash<QQmlMetaTypeData::ModuleApiList>::ConstIterator it = data->moduleApis.begin(); + for (; it != data->moduleApis.end(); ++it) moduleApis[it.key()] = it.value().moduleApis; - } return moduleApis; } @@ -1241,19 +1218,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 &name, int version_major, int 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 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; } @@ -1278,7 +1271,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()); @@ -1319,7 +1312,14 @@ QList<QString> QQmlMetaType::qmlTypeNames() QReadLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - return data->nameToType.keys(); + QList<QString> names; + QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.begin(); + while (it != data->nameToType.end()) { + names += (*it)->qmlTypeName(); + ++it; + } + + return names; } /*! diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 03017cafab..fbbc410c07 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -67,6 +67,8 @@ class QQmlType; class QQmlCustomParser; class QQmlTypePrivate; class QQmlTypeModule; +class QHashedString; +class QHashedStringRef; class Q_QML_PRIVATE_EXPORT QQmlMetaType { @@ -74,9 +76,10 @@ public: static QList<QString> qmlTypeNames(); static QList<QQmlType*> qmlTypes(); - static QQmlType *qmlType(const QString &, int, int); + static QQmlType *qmlType(const QString &qualifiedName, int, int); + static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int); static QQmlType *qmlType(const QMetaObject *); - static QQmlType *qmlType(const QMetaObject *metaObject, const QString &module, int version_major, int version_minor); + static QQmlType *qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor); static QQmlType *qmlType(int); static QMetaProperty defaultProperty(const QMetaObject *); @@ -140,7 +143,6 @@ private: static CompareFunction anchorLineCompareFunction; }; -class QHashedStringRef; class QHashedV8String; class Q_QML_PRIVATE_EXPORT QQmlType { @@ -149,12 +151,12 @@ public: const QString &qmlTypeName() const; const QString &elementName() const; - QString module() const; + const QHashedString &module() const; int majorVersion() const; int minorVersion() const; bool availableInVersion(int vmajor, int vminor) const; - bool availableInVersion(const QString &module, int vmajor, int vminor) const; + bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -214,9 +216,6 @@ public: int minimumMinorVersion() const; int maximumMinorVersion() const; - QList<QQmlType *> types(); - QList<QQmlType *> type(const QString &); - QQmlType *type(const QHashedStringRef &, int); QQmlType *type(const QHashedV8String &, int); |