From 392c7b99348e2a96ef11adb5712095fbd13fb780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6sch?= Date: Thu, 24 Mar 2016 12:09:31 +0100 Subject: Instantiate static Qml plugins declaring QQmlExtensionInterface only When instantiating static plugins no check is done whether the QQmlExtensionInterface is declared. Therefore all user plugins are instantiated in the Qml thread, which may cause problems. Task-number: QTBUG-52012 Change-Id: Ia91ec5ec7b2a9721bd11e3648cdc161855b4454e Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/qml/qml/qqmlimport.cpp') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index d538199520..9fc01c8e35 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -850,8 +850,8 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &res // To avoid traversing all static plugins for all imports, we cut down // the list the first time called to only contain QML plugins: foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) { - if (qobject_cast(plugin.instance())) - plugins.append(plugin); + if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid)) + plugins.append(plugin); } } -- cgit v1.2.3 From 3c5e438890db63ecde98c84d221f87a3af52e1bf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 11 Apr 2016 17:17:19 +0200 Subject: Allow target path version in a parent module For example, the QML Engine is now able to locate QtQml.Models 2.x in both of the following target/installation paths: - QT_INSTALL_QML/QtQml/Models.2 - QT_INSTALL_QML/QtQml.2/Models This is required for QtQuick Controls 2. The target path of the module is QT_INSTALL_QML/QtQuick/Controls.2. The built-in styles are installed as sub-directories to be able to locate them from the controls module. Some of the built-in styles provide their own C++ extensions via style- specific imports (eg. the Material attached property is imported from QtQuick.Controls.Material 2.0). The problem is that the QML Engine does not find the module from QT_INSTALL_QML/QtQuick/Controls.2/Material, but requires it to be installed outside the main controls module ie. QT_INSTALL_QML/QtQuick/Controls/Material(.2). This makes it a) hard to locate the styles from the main controls module, and b) conflicts with the target path of QtQuick Controls 1. [ChangeLog][QtQml] Made the QML Engine capable of locating QML sub- modules from within a versioned parent module path. For example, QtQml.Models 2.x can be either in QT_INSTALL_QML/QtQml/Models.2 or in QT_INSTALL_QML/QtQml.2/Models. Change-Id: I2fe4bbdd6d04dd1e80cbe9b3e7e02617658a0756 Task-number: QTBUG-52556 Reviewed-by: J-P Nurmi Reviewed-by: Shawn Rutledge Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 99 +++++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 32 deletions(-) (limited to 'src/qml/qml/qqmlimport.cpp') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index d6c81bcc49..ec29e600ed 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -483,20 +483,58 @@ QList QQmlImports::resolvedScripts() const return scripts; } +static QString joinStringRefs(const QVector &refs, const QChar &sep) +{ + QString str; + for (auto it = refs.cbegin(); it != refs.cend(); ++it) { + if (it != refs.cbegin()) + str += sep; + str += *it; + } + return str; +} + /*! - Form a complete path to a qmldir file, from a base URL, a module URI and version specification. + Forms complete paths to a qmldir file, from a base URL, a module URI and version specification. + + For example, QtQml.Models 2.0: + - base/QtQml/Models.2.0/qmldir + - base/QtQml.2.0/Models/qmldir + - base/QtQml/Models.2/qmldir + - base/QtQml.2/Models/qmldir + - base/QtQml/Models/qmldir */ -QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin, - ImportVersion version) +QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin) { - QString url = uri; - url.replace(Dot, Slash); + const QVector parts = uri.splitRef(Dot, QString::SkipEmptyParts); + + QStringList qmlDirPathsPaths; + // fully & partially versioned parts + 1 unversioned for each base path + qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1)); - QString dir = base; - if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) - dir += Slash; + for (int version = FullyVersioned; version <= Unversioned; ++version) { + const QString ver = versionString(vmaj, vmin, static_cast(version)); - return dir + url + versionString(vmaj, vmin, version) + Slash_qmldir; + for (const QString &path : basePaths) { + QString dir = path; + if (!dir.endsWith(Slash) && !dir.endsWith(Backslash)) + dir += Slash; + + // append to the end + qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir; + + if (version != Unversioned) { + // insert in the middle + for (int index = parts.count() - 2; index >= 0; --index) { + qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash) + + ver + Slash + + joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir; + } + } + } + } + + return qmlDirPathsPaths; } QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version) @@ -1130,32 +1168,29 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local); // Search local import paths for a matching version - for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) { - foreach (const QString &path, localImportPaths) { - QString qmldirPath = QQmlImports::completeQmldirPath(uri, path, vmaj, vmin, static_cast(version)); - - QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); - if (!absoluteFilePath.isEmpty()) { - QString url; - QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); - if (absolutePath.at(0) == Colon) - url = QLatin1String("qrc://") + absolutePath.mid(1); - else - url = QUrl::fromLocalFile(absolutePath).toString(); + const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin); + for (const QString &qmldirPath : qmlDirPaths) { + QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); + if (!absoluteFilePath.isEmpty()) { + QString url; + QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); + if (absolutePath.at(0) == Colon) + url = QLatin1String("qrc://") + absolutePath.mid(1); + else + url = QUrl::fromLocalFile(absolutePath).toString(); - QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; - cache->versionMajor = vmaj; - cache->versionMinor = vmin; - cache->qmldirFilePath = absoluteFilePath; - cache->qmldirPathUrl = url; - cache->next = cacheHead; - database->qmldirCache.insert(uri, cache); + QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; + cache->versionMajor = vmaj; + cache->versionMinor = vmin; + cache->qmldirFilePath = absoluteFilePath; + cache->qmldirPathUrl = url; + cache->next = cacheHead; + database->qmldirCache.insert(uri, cache); - *outQmldirFilePath = absoluteFilePath; - *outQmldirPathUrl = url; + *outQmldirFilePath = absoluteFilePath; + *outQmldirPathUrl = url; - return true; - } + return true; } } -- cgit v1.2.3 From 1be53f4e143d417d60cd1f9a292193dab59b5b20 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Wed, 6 Apr 2016 15:23:58 +0300 Subject: Use QStringRef to optimize memory allocation Replace substring functions that return QString with corresponding functions that return QStringRef where it's possible. Create QString from QStringRef only where necessary. While touching the code, also port loops to C++11 style. Change-Id: I04c99b24ea6afd3715e3edf9ea00bfab838fd53c Reviewed-by: Ulf Hermann Reviewed-by: Simon Hausmann Reviewed-by: Frank Meerkoetter Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- src/qml/qml/qqmlimport.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/qml/qml/qqmlimport.cpp') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index ec29e600ed..2a1717f190 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -85,12 +85,11 @@ QString resolveLocalUrl(const QString &url, const QString &relative) } else if (relative.at(0) == Slash || !url.contains(Slash)) { return relative; } else { - QString base(url.left(url.lastIndexOf(Slash) + 1)); - + const QStringRef baseRef = url.leftRef(url.lastIndexOf(Slash) + 1); if (relative == QLatin1String(".")) - return base; + return baseRef.toString(); - base.append(relative); + QString base = baseRef + relative; // Remove any relative directory elements in the path int length = base.length(); @@ -815,11 +814,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS QString u1 = import->url; QString u2 = import2->url; if (base) { - QString b = *base; + QStringRef b(base); int dot = b.lastIndexOf(Dot); if (dot >= 0) { b = b.left(dot+1); - QString l = b.left(dot); + QStringRef l = b.left(dot); if (u1.startsWith(b)) u1 = u1.mid(b.count()); else if (u1 == l) @@ -1173,11 +1172,11 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath); if (!absoluteFilePath.isEmpty()) { QString url; - QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1); + const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1); if (absolutePath.at(0) == Colon) url = QLatin1String("qrc://") + absolutePath.mid(1); else - url = QUrl::fromLocalFile(absolutePath).toString(); + url = QUrl::fromLocalFile(absolutePath.toString()).toString(); QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache; cache->versionMajor = vmaj; -- cgit v1.2.3 From 6f59c91c51edd7207635c3fa2f0b2b1179e7aa6e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 6 May 2016 16:01:00 +0200 Subject: Revert parts of 392c7b99348e2a96ef11adb5712095fbd13fb780 Revert the plugin loading check for Qt 5.6.x. It turns out that making this check strict broke multiple static plugin builds beyond the qtdeclarative repository. Let's not cause unnecessary breakage in a patch release of Qt to fix a bug that has existed for much longer. I'll revert this change in the dev branch for Qt 5.8, together with an entry in the change log to inform the developers that a behavioral change in their code is necessary (the use of the interface id variable). Change-Id: I3c658433eaa125ac0d272806e3bbbf016cf6d3cb Reviewed-by: J-P Nurmi --- src/qml/qml/qqmlimport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/qml/qml/qqmlimport.cpp') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 9fc01c8e35..c4e0c7b778 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -850,7 +850,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector &res // To avoid traversing all static plugins for all imports, we cut down // the list the first time called to only contain QML plugins: foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) { - if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid)) + if (qobject_cast(plugin.instance())) plugins.append(plugin); } } -- cgit v1.2.3