diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-09-03 13:07:55 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-09-05 12:57:37 +0000 |
commit | 76f410452dd09489cc48197a0dd4d0bf95699647 (patch) | |
tree | 5043cab4d63676405668c1064bbfa5f6eda8882d | |
parent | 1261fb2b89a8fa147f92c40d2476196d2745ca3f (diff) |
Optimize QQmlImportInstance::resolveType()
Optimize the case where the import is not a library and
tries to find the type on disk.
Avoid lots of conversions to and from QUrl and related
string processing.
Change-Id: Ife247d8adf5ec63127596f2c5ba16a56562ab84a
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 20 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport_p.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 46 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader_p.h | 1 |
4 files changed, 60 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 035deea980..ee6484f0b7 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -674,6 +674,7 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQml { Q_ASSERT(resolvedUrl.endsWith(Slash)); url = resolvedUrl; + localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url); qmlDirComponents = qmldir.components(); @@ -811,21 +812,20 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt *type_return = returnType; return returnType.isValid(); } - } else if (!isLibrary) { + } else if (!isLibrary && !localDirectoryPath.isEmpty()) { QString qmlUrl; bool exists = false; const QString urlsToTry[2] = { - url + QString::fromRawData(type.constData(), type.length()) + dotqml_string, // Type -> Type.qml - url + QString::fromRawData(type.constData(), type.length()) + dotuidotqml_string // Type -> Type.ui.qml + typeStr + dotqml_string, // Type -> Type.qml + typeStr + dotuidotqml_string // Type -> Type.ui.qml }; for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) { - const QString url = urlsToTry[i]; - const QString localPath = QQmlFile::urlToLocalFileOrQrc(url); - exists = !typeLoader->absoluteFilePath(localPath).isEmpty(); + exists = typeLoader->fileExists(localDirectoryPath, urlsToTry[i]); if (exists) { +#if defined(Q_OS_MACOS) || defined(Q_OS_WIN) // don't let function.qml confuse the use of "new Function(...)" for example. - if (!QQml_isFileCaseCorrect(localPath)) { + if (!QQml_isFileCaseCorrect(localDirectoryPath + urlsToTry[i])) { exists = false; if (errors) { QQmlError caseError; @@ -834,7 +834,10 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt } break; } - qmlUrl = url; +#else + Q_UNUSED(errors); +#endif + qmlUrl = url + urlsToTry[i]; break; } } @@ -1433,6 +1436,7 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace QQmlImportInstance *import = new QQmlImportInstance; import->uri = uri; import->url = url; + import->localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url); import->majversion = vmaj; import->minversion = vmin; import->isLibrary = (type == QV4::CompiledData::Import::ImportLibrary); diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h index 283bd40660..f8c01ed876 100644 --- a/src/qml/qml/qqmlimport_p.h +++ b/src/qml/qml/qqmlimport_p.h @@ -78,6 +78,7 @@ struct QQmlImportInstance { QString uri; // e.g. QtQuick QString url; // the base path of the import + QString localDirectoryPath; // the base path of the import if it's a local file int majversion; // the major version imported int minversion; // the minor version imported bool isLibrary; // true means that this is not a file import diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index b0db031bf9..0b0ee9cb9a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1862,6 +1862,52 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) return absoluteFilePath; } +bool QQmlTypeLoader::fileExists(const QString &path, const QString &file) +{ + if (path.isEmpty()) + return false; + Q_ASSERT(path.endsWith(QLatin1Char('/'))); + if (path.at(0) == QLatin1Char(':')) { + // qrc resource + QFileInfo fileInfo(path + file); + return fileInfo.isFile(); + } else if (path.count() > 3 && path.at(3) == QLatin1Char(':') && + path.startsWith(QLatin1String("qrc"), Qt::CaseInsensitive)) { + // qrc resource url + QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)); + return fileInfo.isFile(); + } +#if defined(Q_OS_ANDROID) + else if (path.count() > 7 && path.at(6) == QLatin1Char(':') && path.at(7) == QLatin1Char('/') && + path.startsWith(QLatin1String("assets"), Qt::CaseInsensitive)) { + // assets resource url + QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)); + return fileInfo.isFile(); + } +#endif + + LockHolder<QQmlTypeLoader> holder(this); + if (!m_importDirCache.contains(path)) { + bool exists = QDir(path).exists(); + QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : nullptr; + m_importDirCache.insert(path, entry); + } + QCache<QString, bool> *fileSet = m_importDirCache.object(path); + if (!fileSet) + return false; + + QString absoluteFilePath; + + bool *value = fileSet->object(file); + if (value) { + return *value; + } else { + bool exists = QFile::exists(path + file); + fileSet->insert(file, new bool(exists)); + return exists; + } +} + /*! Returns true if the path is a directory via a directory cache. Cache is diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 5d85773be3..031554b330 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -313,6 +313,7 @@ public: QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &); QString absoluteFilePath(const QString &path); + bool fileExists(const QString &path, const QString &file); bool directoryExists(const QString &path); const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath); |