aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-03 13:07:55 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-05 12:57:37 +0000
commit76f410452dd09489cc48197a0dd4d0bf95699647 (patch)
tree5043cab4d63676405668c1064bbfa5f6eda8882d /src/qml
parent1261fb2b89a8fa147f92c40d2476196d2745ca3f (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>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/qml/qqmlimport.cpp20
-rw-r--r--src/qml/qml/qqmlimport_p.h1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp46
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
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);