diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-12-23 15:37:49 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2013-12-23 15:37:49 +0100 |
commit | f3d5a7307bb232218c098b6c44defab5f182d647 (patch) | |
tree | d0c87cd16bca80dad42f6ef46271bb4a9bdc2546 /src | |
parent | 9a816664b1eafdce52fab9e2d5ec535fc28a782c (diff) | |
parent | 856ba53f77bc3d7b39c5e35d0249ead595dc0439 (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Change-Id: I788baca1c05b6293c295f7842347bf0100d9d48c
Diffstat (limited to 'src')
-rw-r--r-- | src/androiddeployqt/main.cpp | 168 | ||||
-rw-r--r-- | src/designer/src/components/formeditor/formwindow.cpp | 1 | ||||
-rw-r--r-- | src/designer/src/components/formeditor/qdesignerundostack.cpp | 6 | ||||
-rw-r--r-- | src/designer/src/components/formeditor/qdesignerundostack.h | 1 | ||||
-rw-r--r-- | src/macdeployqt/macchangeqt/main.cpp | 2 | ||||
-rw-r--r-- | src/qdbus/qdbus/qdbus.cpp | 12 | ||||
-rw-r--r-- | src/windeployqt/main.cpp | 58 | ||||
-rw-r--r-- | src/windeployqt/qmlutils.cpp | 58 | ||||
-rw-r--r-- | src/windeployqt/qmlutils.h | 11 | ||||
-rw-r--r-- | src/windeployqt/utils.cpp | 8 |
10 files changed, 250 insertions, 75 deletions
diff --git a/src/androiddeployqt/main.cpp b/src/androiddeployqt/main.cpp index 9d3cf507b..9c4071547 100644 --- a/src/androiddeployqt/main.cpp +++ b/src/androiddeployqt/main.cpp @@ -51,6 +51,7 @@ #include <QDateTime> #include <QStandardPaths> #include <QUuid> +#include <QDirIterator> #include <algorithm> static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output @@ -77,6 +78,7 @@ struct Options Options() : helpRequested(false) , verbose(false) + , timing(false) , minimumAndroidVersion(9) , targetAndroidVersion(10) , deploymentMechanism(Bundled) @@ -105,6 +107,8 @@ struct Options bool helpRequested; bool verbose; + bool timing; + QTime timer; // External tools QString sdkPath; @@ -164,7 +168,7 @@ struct Options QStringList initClasses; QString temporaryDirectoryName; bool fetchedRemoteModificationDates; - QHash<QString, QDateTime> remoteModificationDates; + QDateTime remoteModificationDate; QStringList permissions; QStringList features; }; @@ -302,6 +306,8 @@ Options parseOptions() if (options.inputFileName.isEmpty()) options.inputFileName = QString::fromLatin1("android-lib%1.so-deployment-settings.json").arg(QDir::current().dirName()); + options.timing = qEnvironmentVariableIsSet("ANDROIDDEPLOYQT_TIMING_OUTPUT"); + return options; } @@ -1389,11 +1395,9 @@ bool fetchRemoteModifications(Options *options, const QString &directory) options->fetchedRemoteModificationDates = true; FILE *adbCommand = runAdb(*options, QLatin1String(" ls ") + directory); - QHash<QString, QDateTime> ret; if (adbCommand == 0) return false; - QStringList possibleDirectoriesToTry; char buffer[512]; while (fgets(buffer, sizeof(buffer), adbCommand) != 0) { QByteArray line = QByteArray::fromRawData(buffer, qstrlen(buffer)); @@ -1405,24 +1409,27 @@ bool fetchRemoteModifications(Options *options, const QString &directory) || line.at(26) != ' ') { continue; } + QString fileName = QString::fromLocal8Bit(line.mid(27)).trimmed(); + if (fileName != QLatin1String("modification.txt")) + continue; bool ok; int time = line.mid(18, 8).toUInt(&ok, 16); if (!ok) continue; - QString fileName = QString::fromLocal8Bit(line.mid(27)).trimmed(); - - ret[directory + QLatin1Char('/') + fileName] = QDateTime::fromTime_t(time); - - if (fileName != QLatin1String("..") && fileName != QLatin1String(".") && !fileName.isEmpty()) - possibleDirectoriesToTry.append(directory + QLatin1Char('/') + fileName); + options->remoteModificationDate = QDateTime::fromTime_t(time); + break; } - foreach (QString possibleDirectoryToTry, possibleDirectoriesToTry) - fetchRemoteModifications(options, possibleDirectoryToTry); - pclose(adbCommand); - options->remoteModificationDates.unite(ret); + + { + QFile file(options->temporaryDirectoryName + QLatin1String("/modification.txt")); + if (!file.open(QIODevice::WriteOnly)) { + fprintf(stderr, "Cannot create modification timestamp.\n"); + return false; + } + } return true; } @@ -1451,20 +1458,10 @@ bool deployToLocalTmp(Options *options, QFileInfo fileInfo(options->qtInstallDirectory + QLatin1Char('/') + qtDependency); - QStringList unmetDependencies; - if (!goodToCopy(options, fileInfo.absoluteFilePath(), &unmetDependencies)) { - if (options->verbose) - fprintf(stdout, " -- Skipping %s. It has unmet dependencies: %s.\n", - qPrintable(fileInfo.absoluteFilePath()), - qPrintable(unmetDependencies.join(QLatin1Char(',')))); - return true; - } - // Make sure precision is the same as what we get from Android QDateTime sourceModified = QDateTime::fromTime_t(fileInfo.lastModified().toTime_t()); - QDateTime destinationModified = options->remoteModificationDates.value(QLatin1String("/data/local/tmp/qt/") + qtDependency); - if (destinationModified.isNull() || destinationModified < sourceModified) { + if (options->remoteModificationDate.isNull() || options->remoteModificationDate < sourceModified) { if (!copyFileIfNewer(options->qtInstallDirectory + QLatin1Char('/') + qtDependency, options->temporaryDirectoryName + QLatin1Char('/') + qtDependency, options->verbose)) { @@ -1475,26 +1472,6 @@ bool deployToLocalTmp(Options *options, && !stripFile(*options, options->temporaryDirectoryName + QLatin1Char('/') + qtDependency)) { return false; } - - FILE *adbCommand = runAdb(*options, - QString::fromLatin1(" push %1 %2") - .arg(options->temporaryDirectoryName + QLatin1Char('/') + qtDependency) - .arg(QLatin1String("/data/local/tmp/qt/") + qtDependency)); - if (adbCommand == 0) - return false; - - if (options->verbose) { - fprintf(stdout, " -- Deploying %s to device.\n", qPrintable(qtDependency)); - char buffer[512]; - while (fgets(buffer, sizeof(buffer), adbCommand) != 0) - fprintf(stdout, "%s", buffer); - } - - int errorCode = pclose(adbCommand); - if (errorCode != 0) { - fprintf(stderr, "Copying file to device failed!\n"); - return false; - } } return true; @@ -1517,12 +1494,29 @@ bool copyQtFiles(Options *options) } if (options->deploymentMechanism == Options::Debug) { - foreach (QString qtDependency, options->qtDependencies) { - if (!deployToLocalTmp(options, qtDependency)) - return false; + // For debug deployment, we copy all libraries and plugins + QDirIterator dirIterator(options->qtInstallDirectory, QDirIterator::Subdirectories); + while (dirIterator.hasNext()) { + QFileInfo info = dirIterator.fileInfo(); + if (!info.isDir()) { + QString relativePath = info.absoluteFilePath().mid(options->qtInstallDirectory.length()); + if (relativePath.startsWith(QLatin1Char('/'))) + relativePath.remove(0, 1); + if ((relativePath.startsWith("lib/") && relativePath.endsWith(".so")) + || relativePath.startsWith("jar/") + || relativePath.startsWith("plugins/") + || relativePath.startsWith("imports/") + || relativePath.startsWith("qml/") + || relativePath.startsWith("plugins/")) { + if (!deployToLocalTmp(options, relativePath)) + return false; + } + } + dirIterator.next(); + } + foreach (QString qtDependency, options->qtDependencies) options->bundledFiles += qMakePair(qtDependency, qtDependency); - } } else { QString libsDirectory = QLatin1String("libs/"); @@ -1954,6 +1948,30 @@ bool copyGdbServer(const Options &options) return true; } +bool deployAllToLocalTmp(const Options &options) +{ + FILE *adbCommand = runAdb(options, + QString::fromLatin1(" push %1 /data/local/tmp/qt/") + .arg(options.temporaryDirectoryName + QLatin1Char('/'))); + if (adbCommand == 0) + return false; + + if (options.verbose) { + fprintf(stdout, " -- Deploying Qt files to device.\n"); + char buffer[512]; + while (fgets(buffer, sizeof(buffer), adbCommand) != 0) + fprintf(stdout, "%s", buffer); + } + + int errorCode = pclose(adbCommand); + if (errorCode != 0) { + fprintf(stderr, "Copying files to device failed!\n"); + return false; + } + + return true; +} + enum ErrorCode { Success, @@ -1972,7 +1990,8 @@ enum ErrorCode CannotCreateAndroidProject = 13, CannotBuildAndroidProject = 14, CannotSignPackage = 15, - CannotInstallApk = 16 + CannotInstallApk = 16, + CannotDeployAllToLocalTmp = 17 }; int main(int argc, char *argv[]) @@ -1985,9 +2004,15 @@ int main(int argc, char *argv[]) return SyntaxErrorOrHelpRequested; } + if (Q_UNLIKELY(options.timing)) + options.timer.start(); + if (!readInputFile(&options)) return CannotReadInputFile; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Read input file\n", options.timer.elapsed()); + fprintf(stdout, // "012345678901234567890123456789012345678901234567890123456789012345678901" "Generating Android Package\n" @@ -2008,45 +2033,90 @@ int main(int argc, char *argv[]) if (!copyAndroidTemplate(options)) return CannotCopyAndroidTemplate; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied Android template\n", options.timer.elapsed()); + if (!readDependencies(&options)) return CannotReadDependencies; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Read dependencies\n", options.timer.elapsed()); + if (options.deploymentMechanism != Options::Ministro && !copyGnuStl(&options)) return CannotCopyGnuStl; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied GNU STL\n", options.timer.elapsed()); + if (!copyQtFiles(&options)) return CannotCopyQtFiles; + if (options.deploymentMechanism == Options::Debug && !deployAllToLocalTmp(options)) + return CannotDeployAllToLocalTmp; + + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied Qt files\n", options.timer.elapsed()); + if (!containsApplicationBinary(options)) return CannotFindApplicationBinary; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Checked for application binary\n", options.timer.elapsed()); + if (!options.releasePackage && !copyGdbServer(options)) return CannotCopyGdbServer; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied GDB server\n", options.timer.elapsed()); + if (!stripLibraries(options)) return CannotStripLibraries; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Stripped libraries\n", options.timer.elapsed()); + if (!copyAndroidExtraLibs(options)) return CannotCopyAndroidExtraLibs; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied extra libs\n", options.timer.elapsed()); + if (!copyAndroidSources(options)) return CannotCopyAndroidSources; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Copied android sources\n", options.timer.elapsed()); + if (!updateAndroidFiles(options)) return CannotUpdateAndroidFiles; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Updated files\n", options.timer.elapsed()); + if (!createAndroidProject(options)) return CannotCreateAndroidProject; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Created project\n", options.timer.elapsed()); + if (!buildAndroidProject(options)) return CannotBuildAndroidProject; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Built project\n", options.timer.elapsed()); + if (!options.keyStore.isEmpty() && !signPackage(options)) return CannotSignPackage; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Signed package\n", options.timer.elapsed()); + if (options.installApk && !installApk(options)) return CannotInstallApk; + if (Q_UNLIKELY(options.timing)) + fprintf(stdout, "[TIMING] %d ms: Installed APK\n", options.timer.elapsed()); + fprintf(stdout, "Android package built successfully.\n"); if (options.installApk) diff --git a/src/designer/src/components/formeditor/formwindow.cpp b/src/designer/src/components/formeditor/formwindow.cpp index 9ac7fb55b..d26b5d5ba 100644 --- a/src/designer/src/components/formeditor/formwindow.cpp +++ b/src/designer/src/components/formeditor/formwindow.cpp @@ -2159,6 +2159,7 @@ bool FormWindow::setContents(QIODevice *dev, QString *errorMessageIn /* = 0 */) // The main container is cleared as otherwise // the names of the newly loaded objects will be unified. clearMainContainer(); + m_undoStack.clear(); emit changed(); QDesignerResource r(this); diff --git a/src/designer/src/components/formeditor/qdesignerundostack.cpp b/src/designer/src/components/formeditor/qdesignerundostack.cpp index 48c36fc5f..cc533f9b6 100644 --- a/src/designer/src/components/formeditor/qdesignerundostack.cpp +++ b/src/designer/src/components/formeditor/qdesignerundostack.cpp @@ -60,6 +60,12 @@ QDesignerUndoStack::~QDesignerUndoStack() { // QUndoStack is managed by the QUndoGroup } +void QDesignerUndoStack::clear() +{ + m_fakeDirty = false; + m_undoStack->clear(); +} + void QDesignerUndoStack::push(QUndoCommand * cmd) { m_undoStack->push(cmd); diff --git a/src/designer/src/components/formeditor/qdesignerundostack.h b/src/designer/src/components/formeditor/qdesignerundostack.h index 01f3d29e3..84d56184e 100644 --- a/src/designer/src/components/formeditor/qdesignerundostack.h +++ b/src/designer/src/components/formeditor/qdesignerundostack.h @@ -62,6 +62,7 @@ public: explicit QDesignerUndoStack(QObject *parent = 0); virtual ~QDesignerUndoStack(); + void clear(); void push(QUndoCommand * cmd); void beginMacro(const QString &text); void endMacro(); diff --git a/src/macdeployqt/macchangeqt/main.cpp b/src/macdeployqt/macchangeqt/main.cpp index 341f1c248..495c305d1 100644 --- a/src/macdeployqt/macchangeqt/main.cpp +++ b/src/macdeployqt/macchangeqt/main.cpp @@ -65,7 +65,7 @@ int main(int argc, char **argv) } if (argc != (3 + optionsSpecified)) { - qDebug() << "Changeqt: changes witch Qt frameworks an application links against."; + qDebug() << "Changeqt: changes which Qt frameworks an application links against."; qDebug() << "Usage: changeqt app-bundle qt-dir <-verbose=[0-3]>"; return 0; } diff --git a/src/qdbus/qdbus/qdbus.cpp b/src/qdbus/qdbus/qdbus.cpp index 0349c6008..b03c14319 100644 --- a/src/qdbus/qdbus/qdbus.cpp +++ b/src/qdbus/qdbus/qdbus.cpp @@ -479,9 +479,15 @@ int main(int argc, char **argv) connection = QDBusConnection::sessionBus(); if (!connection.isConnected()) { - fprintf(stderr, "Could not connect to D-Bus server: %s: %s\n", - qPrintable(connection.lastError().name()), - qPrintable(connection.lastError().message())); + const QDBusError lastError = connection.lastError(); + if (lastError.isValid()) { + fprintf(stderr, "Could not connect to D-Bus server: %s: %s\n", + qPrintable(lastError.name()), + qPrintable(lastError.message())); + } else { + // an invalid last error means that we were not able to even load the D-Bus library + fprintf(stderr, "Could not connect to D-Bus server: Unable to load dbus libraries\n"); + } return 1; } diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp index dc57f340b..a5e5a9283 100644 --- a/src/windeployqt/main.cpp +++ b/src/windeployqt/main.cpp @@ -182,7 +182,7 @@ bool optHelp = false; int optWebKit2 = 0; struct Options { - Options() : plugins(true), libraries(true), quickImports(true), translations(true) + Options() : plugins(true), libraries(true), quickImports(true), translations(true), systemD3dCompiler(true) , platform(Windows), additionalLibraries(0), disabledLibraries(0) , updateFileFlags(0), json(0) {} @@ -190,6 +190,7 @@ struct Options { bool libraries; bool quickImports; bool translations; + bool systemD3dCompiler; Platform platform; unsigned additionalLibraries; unsigned disabledLibraries; @@ -266,6 +267,10 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse QStringLiteral("Skip deployment of translations.")); parser->addOption(noTranslationOption); + QCommandLineOption noSystemD3DCompilerOption(QStringLiteral("no-system-d3d-compiler"), + QStringLiteral("Skip deployment of the system D3D compiler.")); + parser->addOption(noSystemD3DCompilerOption); + QCommandLineOption webKitOption(QStringLiteral("webkit2"), QStringLiteral("Deployment of WebKit2 (web process).")); parser->addOption(webKitOption); @@ -316,6 +321,7 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse options->plugins = !parser->isSet(noPluginsOption); options->libraries = !parser->isSet(noLibraryOption); options->translations = !parser->isSet(noTranslationOption); + options->systemD3dCompiler = !parser->isSet(noSystemD3DCompilerOption); options->quickImports = !parser->isSet(noQuickImportOption); if (parser->isSet(forceOption)) options->updateFileFlags |= ForceUpdateFile; @@ -480,7 +486,7 @@ private: class QmlDirectoryFileEntryFunction { public: explicit QmlDirectoryFileEntryFunction(Platform platform, bool debug) - : m_qmlNameFilter(QStringList() << QStringLiteral("*.js") << QStringLiteral("qmldir") << QStringLiteral("*.qmltypes") << QStringLiteral("*.png")) + : m_qmlNameFilter(QStringList() << QStringLiteral("*.js") << QStringLiteral("qmldir") << QStringLiteral("*.qml") << QStringLiteral("*.qmltypes") << QStringLiteral("*.png")) , m_dllFilter(platform, debug) {} @@ -652,6 +658,16 @@ static QString libraryPath(const QString &libraryLocation, const char *name, Pla return result; } +static inline int qtVersion(const QMap<QString, QString> &qmakeVariables) +{ + const QString versionString = qmakeVariables.value(QStringLiteral("QT_VERSION")); + const QChar dot = QLatin1Char('.'); + const int majorVersion = versionString.section(dot, 0, 0).toInt(); + const int minorVersion = versionString.section(dot, 1, 1).toInt(); + const int patchVersion = versionString.section(dot, 2, 2).toInt(); + return (majorVersion << 16) | (minorVersion << 8) | patchVersion; +} + static DeployResult deploy(const Options &options, const QMap<QString, QString> &qmakeVariables, QString *errorMessage) @@ -662,6 +678,7 @@ static DeployResult deploy(const Options &options, const QString qtBinDir = qmakeVariables.value(QStringLiteral("QT_INSTALL_BINS")); const QString libraryLocation = options.platform == Unix ? qmakeVariables.value(QStringLiteral("QT_INSTALL_LIBS")) : qtBinDir; + const int version = qtVersion(qmakeVariables); if (optVerboseLevel > 1) std::printf("Qt binaries in %s\n", qPrintable(QDir::toNativeSeparators(qtBinDir))); @@ -746,8 +763,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) @@ -804,12 +821,23 @@ static DeployResult deploy(const Options &options, const QString libGLESv2FullPath = qtBinDir + slash + QFileInfo(libGLESv2.front()).fileName(); deployedQtLibraries.push_back(libGLESv2FullPath); } - // Find the D3d Compiler matching the D3D library. - const QString d3dCompiler = findD3dCompiler(options.platform, wordSize); - if (d3dCompiler.isEmpty()) { - std::fprintf(stderr, "Warning: Cannot find any version of the d3dcompiler DLL.\n"); - } else { - deployedQtLibraries.push_back(d3dCompiler); + // Find the system D3d Compiler matching the D3D library. + if (options.systemD3dCompiler && options.platform != WinPhoneArm && options.platform != WinPhoneIntel) { + const QString d3dCompiler = findD3dCompiler(options.platform, wordSize); + if (d3dCompiler.isEmpty()) { + std::fprintf(stderr, "Warning: Cannot find any version of the d3dcompiler DLL.\n"); + } else { + deployedQtLibraries.push_back(d3dCompiler); + } + } + // Deploy Qt's D3D compiler starting from 5.3 onwards. + if (version >= 0x050300) { + QString d3dCompilerQt = qtBinDir + QStringLiteral("/d3dcompiler_qt"); + if (isDebug) + d3dCompilerQt += QLatin1Char('d'); + d3dCompilerQt += QLatin1String(windowsSharedLibrarySuffix); + if (QFileInfo(d3dCompilerQt).exists()) + deployedQtLibraries.push_back(d3dCompilerQt); } } // !libEgl.isEmpty() } // Windows @@ -851,8 +879,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 8e16a9526..aef736364 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,14 +167,23 @@ 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 (!plugin.contains(plugin)) + if (!plugins.contains(plugin)) plugins.append(plugin); } } diff --git a/src/windeployqt/qmlutils.h b/src/windeployqt/qmlutils.h index ea8c7747d..1752d2717 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; }; diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp index 36edf5e35..527a6e9d0 100644 --- a/src/windeployqt/utils.cpp +++ b/src/windeployqt/utils.cpp @@ -474,14 +474,14 @@ QMap<QString, QString> queryQMakeAll(QString *errorMessage) } const QString output = QString::fromLocal8Bit(stdOut).trimmed().remove(QLatin1Char('\r')); QMap<QString, QString> result; - int pos = 0; - while (true) { + const int size = output.size(); + for (int pos = 0; pos < size; ) { const int colonPos = output.indexOf(QLatin1Char(':'), pos); if (colonPos < 0) break; - const int endPos = output.indexOf(QLatin1Char('\n'), colonPos + 1); + int endPos = output.indexOf(QLatin1Char('\n'), colonPos + 1); if (endPos < 0) - break; + endPos = size; const QString key = output.mid(pos, colonPos - pos); const QString value = output.mid(colonPos + 1, endPos - colonPos - 1); result.insert(key, value); |