diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp index dc57f340bd42219e6077ca4bb1917e098fd8cd12..23b64be3c3bbbb61b35ffddf9190c1831622aceb 100644 --- a/src/windeployqt/main.cpp +++ b/src/windeployqt/main.cpp @@ -746,8 +746,8 @@ static DeployResult deploy(const Options &options, } if (optVerboseLevel >= 1) { std::fputs("QML imports:\n", stdout); - foreach (const QString &mod, qmlScanResult.modulesDirectories) - std::printf(" %s\n", qPrintable(QDir::toNativeSeparators(mod))); + foreach (const QmlImportScanResult::Module &mod, qmlScanResult.modules) + std::printf(" '%s' %s\n", qPrintable(mod.name), qPrintable(QDir::toNativeSeparators(mod.sourcePath))); if (optVerboseLevel >= 2) { std::fputs("QML plugins:\n", stdout); foreach (const QString &p, qmlScanResult.plugins) @@ -851,8 +851,14 @@ static DeployResult deploy(const Options &options, if (options.quickImports && (usesQuick1 || usesQml2)) { const QmlDirectoryFileEntryFunction qmlFileEntryFunction(options.platform, isDebug); if (usesQml2) { - foreach (const QString &module, qmlScanResult.modulesDirectories) { - if (!updateFile(module, qmlFileEntryFunction, options.directory, options.updateFileFlags, options.json, errorMessage)) + foreach (const QmlImportScanResult::Module &module, qmlScanResult.modules) { + const QString installPath = module.installPath(options.directory); + if (optVerboseLevel > 1) + std::printf("Installing: '%s' from %s to %s\n", + qPrintable(module.name), qPrintable(module.sourcePath), qPrintable(QDir::toNativeSeparators(installPath))); + if (installPath != options.directory && !createDirectory(installPath, errorMessage)) + return result; + if (!updateFile(module.sourcePath, qmlFileEntryFunction, installPath, options.updateFileFlags, options.json, errorMessage)) return result; } } // Quick 2 diff --git a/src/windeployqt/qmlutils.cpp b/src/windeployqt/qmlutils.cpp index 1a2ea60b438b6449e0c7a8397bd0ffcb24513f82..aef73636493c2a47b875c7b01bbd126651b47f6a 100644 --- a/src/windeployqt/qmlutils.cpp +++ b/src/windeployqt/qmlutils.cpp @@ -52,6 +52,41 @@ QT_BEGIN_NAMESPACE +// Return the relative install path, that is, for example for +// module "QtQuick.Controls.Styles" in "path/qtbase/qml/QtQuick/Controls/Styles.3" +// --> "QtQuick/Controls" suitable for updateFile() (cp -r semantics). +QString QmlImportScanResult::Module::relativeInstallPath() const +{ + const QChar dot = QLatin1Char('.'); + const QChar slash = QLatin1Char('/'); + + // Find relative path by module name. + if (!name.contains(dot)) + return QString(); // "QtQuick.2" -> flat folder. + QString result = sourcePath; + QString pathComponent = name; + pathComponent.replace(dot, slash); + const int pos = result.lastIndexOf(pathComponent); + if (pos < 0) + return QString(); + result.remove(0, pos); + // return base name. + const int lastSlash = result.lastIndexOf(slash); + if (lastSlash >= 0) + result.truncate(lastSlash); + return result; +} + +QString QmlImportScanResult::Module::installPath(const QString &root) const +{ + QString result = root; + const QString relPath = relativeInstallPath(); + if (!relPath.isEmpty()) + result += QLatin1Char('/'); + result += relPath; + return result; +} + static QString qmlDirectoryRecursion(Platform platform, const QString &path) { QDir dir(path); @@ -119,7 +154,11 @@ QmlImportScanResult runQmlImportScanner(const QString &directory, const QString if (object.value(QStringLiteral("type")).toString() == QLatin1String("module")) { const QString path = object.value(QStringLiteral("path")).toString(); if (!path.isEmpty()) { - result.modulesDirectories.append(path); + QmlImportScanResult::Module module; + module.name = object.value(QStringLiteral("name")).toString(); + module.className = object.value(QStringLiteral("classname")).toString(); + module.sourcePath = path; + result.modules.append(module); findFileRecursion(QDir(path), Platform(platform), debug, &result.plugins); } } @@ -128,11 +167,20 @@ QmlImportScanResult runQmlImportScanner(const QString &directory, const QString return result; } +static inline bool contains(const QList<QmlImportScanResult::Module> &modules, const QString &name) +{ + foreach (const QmlImportScanResult::Module &m, modules) { + if (m.name == name) + return true; + } + return false; +} + void QmlImportScanResult::append(const QmlImportScanResult &other) { - foreach (const QString &module, other.modulesDirectories) { - if (!modulesDirectories.contains(module)) - modulesDirectories.append(module); + foreach (const QmlImportScanResult::Module &module, other.modules) { + if (!contains(modules, module.name)) + modules.append(module); } foreach (const QString &plugin, other.plugins) { if (!plugins.contains(plugin)) diff --git a/src/windeployqt/qmlutils.h b/src/windeployqt/qmlutils.h index ea8c7747da40925c171a54932bbac907db19c48e..1752d2717099406e47079161778322d549c18c75 100644 --- a/src/windeployqt/qmlutils.h +++ b/src/windeployqt/qmlutils.h @@ -49,11 +49,20 @@ QT_BEGIN_NAMESPACE QString findQmlDirectory(int platform, const QString &startDirectoryName); struct QmlImportScanResult { + struct Module { + QString relativeInstallPath() const; + QString installPath(const QString &root) const; + + QString name; + QString className; + QString sourcePath; + }; + QmlImportScanResult() : ok(false) {} void append(const QmlImportScanResult &other); bool ok; - QStringList modulesDirectories; + QList<Module> modules; QStringList plugins; };