diff options
Diffstat (limited to 'src')
26 files changed, 188 insertions, 94 deletions
diff --git a/src/assistant/clucene/qclucene-config_p.h b/src/assistant/clucene/qclucene-config_p.h index 0b927a47d..781bec75e 100644 --- a/src/assistant/clucene/qclucene-config_p.h +++ b/src/assistant/clucene/qclucene-config_p.h @@ -54,6 +54,10 @@ #include <QtCore/qglobal.h> +#ifdef Q_OS_ANDROID +# include <android/api-level.h> +#endif + #ifndef _SRC_CLUCENE_CLUCENE_CONFIG_H #define _SRC_CLUCENE_CLUCENE_CONFIG_H 1 @@ -328,7 +332,7 @@ configure. #endif /* Define to 1 if you have the <sys/timeb.h> header file. */ -#if !defined(__OpenBSD__) +#if !defined(__OpenBSD__) && !defined(__ANDROID_API__) || __ANDROID_API__ < 21 # ifndef _CL_HAVE_SYS_TIMEB_H # define _CL_HAVE_SYS_TIMEB_H 1 # endif diff --git a/src/designer/src/components/formeditor/formwindow.cpp b/src/designer/src/components/formeditor/formwindow.cpp index 9204a4761..ba6712103 100644 --- a/src/designer/src/components/formeditor/formwindow.cpp +++ b/src/designer/src/components/formeditor/formwindow.cpp @@ -526,7 +526,7 @@ static inline unsigned mouseFlags(Qt::KeyboardModifiers mod) case Qt::ShiftModifier: return CycleParentModifier; break; -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS case Qt::AltModifier: // "Alt" or "option" key on Mac means copy return CopyDragModifier; #endif diff --git a/src/designer/src/components/formeditor/formwindowmanager.cpp b/src/designer/src/components/formeditor/formwindowmanager.cpp index 4a866527a..acdad8d1e 100644 --- a/src/designer/src/components/formeditor/formwindowmanager.cpp +++ b/src/designer/src/components/formeditor/formwindowmanager.cpp @@ -287,11 +287,9 @@ void FormWindowManager::removeFormWindow(QDesignerFormWindowInterface *w) if (formWindow == m_activeFormWindow) setActiveFormWindow(0); - if (m_formWindows.size() == 0 - && m_core->widgetBox()) { - // Make sure that widget box is enabled by default - m_core->widgetBox()->setEnabled(true); - } + // Make sure that widget box is enabled by default + if (m_formWindows.size() == 0 && m_core->widgetBox()) + m_core->widgetBox()->setEnabled(true); } diff --git a/src/designer/src/designer/assistantclient.cpp b/src/designer/src/designer/assistantclient.cpp index 9a54d04b9..ffceeff1d 100644 --- a/src/designer/src/designer/assistantclient.cpp +++ b/src/designer/src/designer/assistantclient.cpp @@ -100,7 +100,7 @@ bool AssistantClient::isRunning() const QString AssistantClient::binary() { QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator(); -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MACOS) app += QStringLiteral("assistant"); #else app += QStringLiteral("Assistant.app/Contents/MacOS/Assistant"); diff --git a/src/designer/src/designer/mainwindow.cpp b/src/designer/src/designer/mainwindow.cpp index 550fad91d..ecf92b5c6 100644 --- a/src/designer/src/designer/mainwindow.cpp +++ b/src/designer/src/designer/mainwindow.cpp @@ -82,7 +82,7 @@ MainWindowBase::MainWindowBase(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), m_policy(AcceptCloseEvents) { -#ifndef Q_OS_MAC +#ifndef Q_OS_MACOS setWindowIcon(qDesigner->windowIcon()); #endif } diff --git a/src/designer/src/designer/qdesigner_actions.cpp b/src/designer/src/designer/qdesigner_actions.cpp index 3cc70e57a..a25c8c349 100644 --- a/src/designer/src/designer/qdesigner_actions.cpp +++ b/src/designer/src/designer/qdesigner_actions.cpp @@ -97,7 +97,7 @@ using namespace qdesigner_internal; const char *QDesignerActions::defaultToolbarPropertyName = "__qt_defaultToolBarAction"; -//#ifdef Q_OS_MAC +//#ifdef Q_OS_MACOS # define NONMODAL_PREVIEW //#endif @@ -192,7 +192,7 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench) { typedef void (QDesignerActions::*VoidSlot)(); -#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) +#if defined (Q_OS_UNIX) && !defined(Q_OS_MACOS) m_newFormAction->setIcon(QIcon::fromTheme(QStringLiteral("document-new"), m_newFormAction->icon())); m_openFormAction->setIcon(QIcon::fromTheme(QStringLiteral("document-open"), m_openFormAction->icon())); m_saveFormAction->setIcon(QIcon::fromTheme(QStringLiteral("document-save"), m_saveFormAction->icon())); @@ -256,7 +256,7 @@ QDesignerActions::QDesignerActions(QDesignerWorkbench *workbench) connect(m_saveFormAsAction, &QAction::triggered, this, static_cast<VoidSlot>(&QDesignerActions::saveFormAs)); m_fileActions->addAction(m_saveFormAsAction); -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS m_saveAllFormsAction->setShortcut(tr("ALT+CTRL+S")); #else m_saveAllFormsAction->setShortcut(tr("CTRL+SHIFT+S")); // Commonly "Save As" on Mac diff --git a/src/designer/src/designer/qdesigner_settings.cpp b/src/designer/src/designer/qdesigner_settings.cpp index 0d0dbcbb4..cb1a9d20f 100644 --- a/src/designer/src/designer/qdesigner_settings.cpp +++ b/src/designer/src/designer/qdesigner_settings.cpp @@ -204,7 +204,7 @@ void QDesignerSettings::setUiMode(UIMode mode) UIMode QDesignerSettings::uiMode() const { -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS const UIMode defaultMode = TopLevelMode; #else const UIMode defaultMode = DockedMode; diff --git a/src/designer/src/designer/qdesigner_workbench.cpp b/src/designer/src/designer/qdesigner_workbench.cpp index 27eeb88d7..570815ec8 100644 --- a/src/designer/src/designer/qdesigner_workbench.cpp +++ b/src/designer/src/designer/qdesigner_workbench.cpp @@ -322,7 +322,7 @@ Qt::WindowFlags QDesignerWorkbench::magicalWindowFlags(const QWidget *widgetForF { switch (m_mode) { case TopLevelMode: { -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS if (qobject_cast<const QDesignerToolWindow *>(widgetForFlags)) return Qt::Tool; #else @@ -384,7 +384,7 @@ void QDesignerWorkbench::switchToNeutralMode() fw->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } -#ifndef Q_OS_MAC +#ifndef Q_OS_MACOS m_globalMenuBar->setParent(0); #endif @@ -402,14 +402,14 @@ void QDesignerWorkbench::switchToDockedMode() switchToNeutralMode(); -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MACOS) # if defined(Q_OS_UNIX) QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); # endif // Q_OS_UNIX QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); widgetBoxWrapper->action()->setVisible(true); widgetBoxWrapper->setWindowTitle(tr("Widget Box")); -#endif // !Q_OS_MAC +#endif // !Q_OS_MACOS m_mode = DockedMode; const QDesignerSettings settings(m_core); @@ -426,7 +426,7 @@ void QDesignerWorkbench::switchToDockedMode() m_core->setTopLevel(m_dockedMainWindow); -#ifndef Q_OS_MAC +#ifndef Q_OS_MACOS m_dockedMainWindow->setMenuBar(m_globalMenuBar); m_globalMenuBar->show(); #endif @@ -475,7 +475,7 @@ void QDesignerWorkbench::switchToTopLevelMode() // The widget box is special, it gets the menubar and gets to be the main widget. m_core->setTopLevel(widgetBoxWrapper); -#if !defined(Q_OS_MAC) +#if !defined(Q_OS_MACOS) # if defined(Q_OS_UNIX) // For now the appmenu protocol does not make it possible to associate a // menubar with all application windows. This means in top level mode you @@ -489,7 +489,7 @@ void QDesignerWorkbench::switchToTopLevelMode() widgetBoxWrapper->setCloseEventPolicy(MainWindowBase::EmitCloseEventSignal); qDesigner->setMainWindow(widgetBoxWrapper); widgetBoxWrapper->setWindowTitle(MainWindowBase::mainWindowTitle()); -#endif // !Q_OS_MAC +#endif // !Q_OS_MACOS const QDesignerSettings settings(m_core); m_topLevelData.toolbars = MainWindowBase::createToolBars(m_actionManager, false); diff --git a/src/designer/src/designer/versiondialog.cpp b/src/designer/src/designer/versiondialog.cpp index cc1ff2e7b..74c04b0a9 100644 --- a/src/designer/src/designer/versiondialog.cpp +++ b/src/designer/src/designer/versiondialog.cpp @@ -145,7 +145,7 @@ void VersionLabel::paintEvent(QPaintEvent *pe) VersionDialog::VersionDialog(QWidget *parent) : QDialog(parent -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS , Qt::Tool #endif ) diff --git a/src/designer/src/lib/sdk/abstractformeditor.cpp b/src/designer/src/lib/sdk/abstractformeditor.cpp index dc698ab27..21d58844e 100644 --- a/src/designer/src/lib/sdk/abstractformeditor.cpp +++ b/src/designer/src/lib/sdk/abstractformeditor.cpp @@ -546,7 +546,7 @@ void QDesignerFormEditorInterface::setIntrospection(QDesignerIntrospectionInterf */ QString QDesignerFormEditorInterface::resourceLocation() const { -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS return QStringLiteral(":/qt-project.org/formeditor/images/mac"); #else return QStringLiteral(":/qt-project.org/formeditor/images/win"); diff --git a/src/designer/src/lib/shared/dialoggui.cpp b/src/designer/src/lib/shared/dialoggui.cpp index 73d5e0514..be5f3a7f3 100644 --- a/src/designer/src/lib/shared/dialoggui.cpp +++ b/src/designer/src/lib/shared/dialoggui.cpp @@ -39,7 +39,7 @@ #include <QtCore/QSet> // QFileDialog on X11 does not provide an image preview. Display icons. -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) +#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) # define IMAGE_PREVIEW #endif diff --git a/src/designer/src/lib/shared/iconloader.cpp b/src/designer/src/lib/shared/iconloader.cpp index 4007f43f2..9ac8e96b9 100644 --- a/src/designer/src/lib/shared/iconloader.cpp +++ b/src/designer/src/lib/shared/iconloader.cpp @@ -40,7 +40,7 @@ QDESIGNER_SHARED_EXPORT QIcon createIconSet(const QString &name) { QStringList candidates = QStringList() << (QString::fromUtf8(":/qt-project.org/formeditor/images/") + name) -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS << (QString::fromUtf8(":/qt-project.org/formeditor/images/mac/") + name) #else << (QString::fromUtf8(":/qt-project.org/formeditor/images/win/") + name) diff --git a/src/designer/src/lib/shared/plugindialog.cpp b/src/designer/src/lib/shared/plugindialog.cpp index 998d23247..827dd8c68 100644 --- a/src/designer/src/lib/shared/plugindialog.cpp +++ b/src/designer/src/lib/shared/plugindialog.cpp @@ -48,7 +48,7 @@ namespace qdesigner_internal { PluginDialog::PluginDialog(QDesignerFormEditorInterface *core, QWidget *parent) : QDialog(parent -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS , Qt::Tool #endif ), m_core(core) diff --git a/src/designer/src/lib/shared/previewmanager.cpp b/src/designer/src/lib/shared/previewmanager.cpp index ba4d1ca8a..63520b0ec 100644 --- a/src/designer/src/lib/shared/previewmanager.cpp +++ b/src/designer/src/lib/shared/previewmanager.cpp @@ -865,7 +865,7 @@ bool PreviewManager::eventFilter(QObject *watched, QEvent *event) const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); const int key = keyEvent->key(); if ((key == Qt::Key_Escape -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS || (keyEvent->modifiers() == Qt::ControlModifier && key == Qt::Key_Period) #endif )) { diff --git a/src/designer/src/lib/shared/sheet_delegate.cpp b/src/designer/src/lib/shared/sheet_delegate.cpp index 255ce3b97..60a2cd963 100644 --- a/src/designer/src/lib/shared/sheet_delegate.cpp +++ b/src/designer/src/lib/shared/sheet_delegate.cpp @@ -53,7 +53,7 @@ void SheetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QStyleOptionButton buttonOption; buttonOption.state = option.state; -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS buttonOption.state |= QStyle::State_Raised; #endif buttonOption.state &= ~QStyle::State_HasFocus; diff --git a/src/designer/src/lib/shared/widgetfactory.cpp b/src/designer/src/lib/shared/widgetfactory.cpp index 30b5d8583..295665d00 100644 --- a/src/designer/src/lib/shared/widgetfactory.cpp +++ b/src/designer/src/lib/shared/widgetfactory.cpp @@ -110,8 +110,10 @@ bool ComboEventFilter::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::ChildPolished) { QComboBox *cb = static_cast<QComboBox*>(watched); - if (QLineEdit *le = cb->lineEdit()) + if (QLineEdit *le = cb->lineEdit()) { le->setFocusPolicy(Qt::NoFocus); + le->setCursor(Qt::ArrowCursor); + } } return QObject::eventFilter(watched, event); } diff --git a/src/designer/src/lib/uilib/abstractformbuilder.cpp b/src/designer/src/lib/uilib/abstractformbuilder.cpp index 79ced1632..43dfb0ec5 100644 --- a/src/designer/src/lib/uilib/abstractformbuilder.cpp +++ b/src/designer/src/lib/uilib/abstractformbuilder.cpp @@ -661,7 +661,7 @@ void QAbstractFormBuilder::layoutInfo(DomLayout *ui_layout, QObject *parent, int if (const DomProperty *p = properties.value(strings.spacingProperty, 0)) spac = p->elementNumber(); -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS // here we recognize UI file < 4.3 (no we don't store margin property) if (mar != INT_MIN) { const int defaultMargin = parent->inherits("QLayoutWidget") ? 0 : 9; diff --git a/src/linguist/linguist/messageeditorwidgets.cpp b/src/linguist/linguist/messageeditorwidgets.cpp index 6ea2a24b1..03f84a19a 100644 --- a/src/linguist/linguist/messageeditorwidgets.cpp +++ b/src/linguist/linguist/messageeditorwidgets.cpp @@ -334,17 +334,18 @@ void FormMultiWidget::updateLayout() layoutForPlusButtons->setMargin(0); for (int i = 0; i < m_plusButtons.count(); ++i) layoutForPlusButtons->addWidget(m_plusButtons.at(i), Qt::AlignTop); - layout->addLayout(layoutForPlusButtons, 1, 0); + layout->addLayout(layoutForPlusButtons, 1, 0, Qt::AlignTop); + const int minimumRowHeight = m_plusButtons.at(0)->sizeHint().height() / 2.0; QGridLayout *layoutForLabels = new QGridLayout; layoutForLabels->setMargin(0); - layoutForLabels->setRowMinimumHeight(0, m_plusButtons.at(0)->height()/2.0); + layoutForLabels->setRowMinimumHeight(0, minimumRowHeight); for (int j = 0; j < m_editors.count(); ++j) { layoutForLabels->addWidget(m_editors.at(j), 1 + j, 0, Qt::AlignVCenter); layoutForLabels->addWidget(m_minusButtons.at(j), 1 + j, 1, Qt::AlignVCenter); } - layoutForLabels->setRowMinimumHeight(m_editors.count() + 1, m_plusButtons.at(0)->height()/2.0); - layout->addLayout(layoutForLabels, 1, 1); + layoutForLabels->setRowMinimumHeight(m_editors.count() + 1, minimumRowHeight); + layout->addLayout(layoutForLabels, 1, 1, Qt::AlignTop); } else { for (int k = 0; k < m_editors.count(); ++k) layout->addWidget(m_editors.at(k), 1 + k, 0, Qt::AlignVCenter); diff --git a/src/linguist/lupdate/cpp.cpp b/src/linguist/lupdate/cpp.cpp index 5d160b7f9..31f1f7e91 100644 --- a/src/linguist/lupdate/cpp.cpp +++ b/src/linguist/lupdate/cpp.cpp @@ -561,10 +561,9 @@ CppParser::TokenType CppParser::getToken() // include do { yyCh = getChar(); - } while (yyCh != EOF && !isspace(yyCh)); - do { + } while (yyCh != EOF && !isspace(yyCh) && yyCh != '"' && yyCh != '<' ); + while (isspace(yyCh)) yyCh = getChar(); - } while (isspace(yyCh)); int tChar; if (yyCh == '"') tChar = '"'; diff --git a/src/macdeployqt/macdeployqt/main.cpp b/src/macdeployqt/macdeployqt/main.cpp index 2e6ad0c29..5488a5f61 100644 --- a/src/macdeployqt/macdeployqt/main.cpp +++ b/src/macdeployqt/macdeployqt/main.cpp @@ -52,6 +52,7 @@ int main(int argc, char **argv) qDebug() << " -always-overwrite : Copy files even if the target file exists"; qDebug() << " -codesign=<ident> : Run codesign with the given identity on all executables"; qDebug() << " -appstore-compliant: Skip deployment of components that use private API"; + qDebug() << " -libpath=<path> : Add the given path to the library search path"; qDebug() << ""; qDebug() << "macdeployqt takes an application bundle as input and makes it"; qDebug() << "self-contained by copying in the Qt frameworks and plugins that"; @@ -85,6 +86,7 @@ int main(int argc, char **argv) bool useDebugLibs = false; extern bool runStripEnabled; extern bool alwaysOwerwriteEnabled; + extern QStringList librarySearchPath; QStringList additionalExecutables; bool qmldirArgumentUsed = false; QStringList qmlDirs; @@ -132,6 +134,13 @@ int main(int argc, char **argv) LogError() << "Missing qml directory path"; else qmlDirs << argument.mid(index+1); + } else if (argument.startsWith(QByteArray("-libpath"))) { + LogDebug() << "Argument found:" << argument; + int index = argument.indexOf('='); + if (index == -1) + LogError() << "Missing library search path"; + else + librarySearchPath << argument.mid(index+1); } else if (argument == QByteArray("-always-overwrite")) { LogDebug() << "Argument found:" << argument; alwaysOwerwriteEnabled = true; diff --git a/src/macdeployqt/shared/shared.cpp b/src/macdeployqt/shared/shared.cpp index b9d71d11e..47bd70e17 100644 --- a/src/macdeployqt/shared/shared.cpp +++ b/src/macdeployqt/shared/shared.cpp @@ -51,6 +51,7 @@ bool runStripEnabled = true; bool alwaysOwerwriteEnabled = false; bool runCodesign = false; +QStringList librarySearchPath; QString codesignIdentiy; bool appstoreCompliant = false; int logLevel = 1; @@ -293,15 +294,26 @@ FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundl } else if (trimmed.startsWith("/") == false) { // If the line does not contain a full path, the app is using a binary Qt package. QStringList partsCopy = parts; partsCopy.removeLast(); + foreach (QString path, librarySearchPath) { + if (!path.endsWith("/")) + path += '/'; + QString nameInPath = path + parts.join("/"); + if (QFile::exists(nameInPath)) { + info.frameworkDirectory = path + partsCopy.join("/"); + break; + } + } if (currentPart.contains(".framework")) { - info.frameworkDirectory = "/Library/Frameworks/" + partsCopy.join("/"); + if (info.frameworkDirectory.isEmpty()) + info.frameworkDirectory = "/Library/Frameworks/" + partsCopy.join("/"); if (!info.frameworkDirectory.endsWith("/")) info.frameworkDirectory += "/"; state = FrameworkName; --part; continue; } else if (currentPart.contains(".dylib")) { - info.frameworkDirectory = "/usr/lib/" + partsCopy.join("/"); + if (info.frameworkDirectory.isEmpty()) + info.frameworkDirectory = "/usr/lib/" + partsCopy.join("/"); if (!info.frameworkDirectory.endsWith("/")) info.frameworkDirectory += "/"; state = DylibName; diff --git a/src/qtdiag/qtdiag.cpp b/src/qtdiag/qtdiag.cpp index b0914c4f6..d12dd691e 100644 --- a/src/qtdiag/qtdiag.cpp +++ b/src/qtdiag/qtdiag.cpp @@ -89,7 +89,7 @@ QTextStream &operator<<(QTextStream &str, const QDpi &d) QTextStream &operator<<(QTextStream &str, const QRect &r) { - str << r.size() << '+' << r.x() << '+' << r.y(); + str << r.size() << forcesign << r.x() << r.y() << noforcesign; return str; } diff --git a/src/windeployqt/main.cpp b/src/windeployqt/main.cpp index f9cabd253..41da5e6fc 100644 --- a/src/windeployqt/main.cpp +++ b/src/windeployqt/main.cpp @@ -249,7 +249,7 @@ struct Options { , angleDetection(AngleDetectionAuto), softwareRasterizer(true), platform(Windows) , additionalLibraries(0), disabledLibraries(0) , updateFileFlags(0), json(0), list(ListNone), debugDetection(DebugDetectionAuto) - , deployPdb(false) {} + , deployPdb(false), dryRun(false) {} bool plugins; bool libraries; @@ -273,6 +273,7 @@ struct Options { ListOption list; DebugDetection debugDetection; bool deployPdb; + bool dryRun; inline bool isWinRtOrWinPhone() const { return (platform == WinPhoneArm || platform == WinPhoneIntel @@ -523,8 +524,10 @@ static inline int parseArguments(const QStringList &arguments, QCommandLineParse if (parser->isSet(forceOption)) options->updateFileFlags |= ForceUpdateFile; - if (parser->isSet(dryRunOption)) + if (parser->isSet(dryRunOption)) { + options->dryRun = true; options->updateFileFlags |= SkipUpdateFile; + } for (size_t i = 0; i < qtModulesCount; ++i) { if (parser->isSet(*enabledModules.at(int(i)).first.data())) @@ -1345,6 +1348,33 @@ static DeployResult deploy(const Options &options, } } // Windows + // We need to copy ucrtbased.dll on WinRT as this library is not part of + // the c runtime package. VS 2015 does the same when deploying to a device + // or creating an appx. + if (isDebug && options.platform == WinRtArm + && qmakeVariables.value(QStringLiteral("QMAKE_XSPEC")).endsWith(QLatin1String("msvc2015"))) { + const QString extensionPath = QString::fromLocal8Bit(qgetenv("ExtensionSdkDir")); + const QString ucrtVersion = QString::fromLocal8Bit(qgetenv("UCRTVersion")); + if (extensionPath.isEmpty() || ucrtVersion.isEmpty()) { + std::wcerr << "Warning: Cannot find ucrtbased.dll as either " + << "ExtensionSdkDir or UCRTVersion is not set in " + << "your environment.\n"; + } else { + const QString ucrtbasedLib = extensionPath + + QStringLiteral("/Microsoft.UniversalCRT.Debug/") + + ucrtVersion + + QStringLiteral("/Redist/Debug/arm/ucrtbased.dll"); + const QFileInfo ucrtPath(ucrtbasedLib); + if (ucrtPath.exists() && ucrtPath.isFile()) { + deployedQtLibraries.append(ucrtPath.absoluteFilePath()); + } else { + std::wcerr << "Warning: Cannot find ucrtbased.dll at " + << QDir::toNativeSeparators(ucrtbasedLib) + << " or it is not a file.\n"; + } + } + } + // Update libraries if (options.libraries) { const QString targetPath = options.libraryDirectory.isEmpty() ? @@ -1357,7 +1387,7 @@ static DeployResult deploy(const Options &options, return result; } - if (!options.isWinRtOrWinPhone()) { + if (!options.isWinRtOrWinPhone() && !options.dryRun) { const QString qt5CoreName = QFileInfo(libraryPath(libraryLocation, "Qt5Core", qtLibInfix, options.platform, isDebug)).fileName(); @@ -1435,10 +1465,11 @@ static DeployResult deploy(const Options &options, } // optQuickImports if (options.translations) { - if (!createDirectory(options.translationsDirectory, errorMessage) - || !deployTranslations(qmakeVariables.value(QStringLiteral("QT_INSTALL_TRANSLATIONS")), - result.deployedQtLibraries, options.translationsDirectory, - options.updateFileFlags, errorMessage)) { + if (!options.dryRun && !createDirectory(options.translationsDirectory, errorMessage)) + return result; + if (!deployTranslations(qmakeVariables.value(QStringLiteral("QT_INSTALL_TRANSLATIONS")), + result.deployedQtLibraries, options.translationsDirectory, + options.updateFileFlags, errorMessage)) { return result; } } diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp index c74f7c4b4..dfdd7d0db 100644 --- a/src/winrtrunner/appxengine.cpp +++ b/src/winrtrunner/appxengine.cpp @@ -315,7 +315,7 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest) } // If it looks like an executable, check that manifest is next to it - if (fileName.endsWith(QStringLiteral(".exe"))) { + if (fileName.endsWith(QLatin1String(".exe"))) { QDir appDir = QFileInfo(fileName).absoluteDir(); QString manifestFileName = appDir.absoluteFilePath(QStringLiteral("AppxManifest.xml")); if (!QFile::exists(manifestFileName)) { @@ -328,7 +328,11 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest) return true; } - // TODO: handle already-built package as well + if (fileName.endsWith(QLatin1String(".appx"))) { + // For existing appx packages the manifest reader will be + // instantiated later. + return true; + } qCWarning(lcWinRtRunner) << "Appx: unable to determine manifest for" << fileName << "."; return false; @@ -375,12 +379,6 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) d->pid = -1; d->exitCode = UINT_MAX; - if (!getManifestFile(runner->app(), &d->manifest)) { - qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app(); - d->hasFatalError = true; - return; - } - HRESULT hr; hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), IID_PPV_ARGS(&d->uriFactory)); @@ -390,28 +388,57 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) IID_IAppxFactory, &d->packageFactory); CHECK_RESULT_FATAL("Failed to instantiate package factory.", return); - ComPtr<IStream> manifestStream; - hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); - CHECK_RESULT_FATAL("Failed to open manifest stream.", return); - - ComPtr<IAppxManifestReader> manifestReader; - hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader); - if (FAILED(hr)) { - qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate manifest reader. (0x" - << QByteArray::number(hr, 16).constData() - << ' ' << qt_error_string(hr) << ')'; - // ### TODO: read detailed error from event log directly - if (hr == APPX_E_INVALID_MANIFEST) { - qCWarning(lcWinRtRunner) << "More information on the error can " - "be found in the event log under " - "Microsoft\\Windows\\AppxPackagingOM"; + bool existingPackage = runner->app().endsWith(QLatin1String(".appx")); + + if (existingPackage) { + ComPtr<IStream> appxStream; + hr = SHCreateStreamOnFile(wchar(runner->app()), STGM_READ, &appxStream); + CHECK_RESULT_FATAL("Failed to open appx stream.", return); + + ComPtr<IAppxPackageReader> packageReader; + hr = d->packageFactory->CreatePackageReader(appxStream.Get(), &packageReader); + if (FAILED(hr)) { + qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate package reader. (0x" + << QByteArray::number(hr, 16).constData() + << ' ' << qt_error_string(hr) << ')'; + d->hasFatalError = true; + return; } - d->hasFatalError = true; - return; - } + hr = packageReader->GetManifest(&d->manifestReader); + if (FAILED(hr)) { + qCWarning(lcWinRtRunner).nospace() << "Failed to query manifext reader from package"; + d->hasFatalError = true; + return; + } + } else { + if (!getManifestFile(runner->app(), &d->manifest)) { + qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app(); + d->hasFatalError = true; + return; + } + + ComPtr<IStream> manifestStream; + hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); + CHECK_RESULT_FATAL("Failed to open manifest stream.", return); + + hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &d->manifestReader); + if (FAILED(hr)) { + qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate manifest reader. (0x" + << QByteArray::number(hr, 16).constData() + << ' ' << qt_error_string(hr) << ')'; + // ### TODO: read detailed error from event log directly + if (hr == APPX_E_INVALID_MANIFEST) { + qCWarning(lcWinRtRunner) << "More information on the error can " + "be found in the event log under " + "Microsoft\\Windows\\AppxPackagingOM"; + } + d->hasFatalError = true; + return; + } + } ComPtr<IAppxManifestPackageId> packageId; - hr = manifestReader->GetPackageId(&packageId); + hr = d->manifestReader->GetPackageId(&packageId); CHECK_RESULT_FATAL("Unable to obtain the package ID from the manifest.", return); APPX_PACKAGE_ARCHITECTURE arch; @@ -440,7 +467,7 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) #endif // _MSC_VER >= 1900 ComPtr<IAppxManifestApplicationsEnumerator> applications; - hr = manifestReader->GetApplications(&applications); + hr = d->manifestReader->GetApplications(&applications); CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return); BOOL hasCurrent; @@ -455,12 +482,12 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd) LPWSTR executable; application->GetStringValue(L"Executable", &executable); CHECK_RESULT_FATAL("Failed to retrieve the application executable from the manifest.", return); - d->executable = QFileInfo(d->manifest).absoluteDir() + d->executable = QFileInfo(runner->app()).absoluteDir() .absoluteFilePath(QString::fromWCharArray(executable)); CoTaskMemFree(executable); ComPtr<IAppxManifestPackageDependenciesEnumerator> dependencies; - hr = manifestReader->GetPackageDependencies(&dependencies); + hr = d->manifestReader->GetPackageDependencies(&dependencies); CHECK_RESULT_FATAL("Failed to retrieve the package dependencies from the manifest.", return); hr = dependencies->GetHasCurrent(&hasCurrent); diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h index 982c484b2..6ff41fed6 100644 --- a/src/winrtrunner/appxengine_p.h +++ b/src/winrtrunner/appxengine_p.h @@ -84,6 +84,7 @@ public: Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IUriRuntimeClassFactory> uriFactory; Microsoft::WRL::ComPtr<IAppxFactory> packageFactory; + Microsoft::WRL::ComPtr<IAppxManifestReader> manifestReader; }; #define wchar(str) reinterpret_cast<LPCWSTR>(str.utf16()) diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp index edbb58ea5..fb78e350b 100644 --- a/src/winrtrunner/appxphoneengine.cpp +++ b/src/winrtrunner/appxphoneengine.cpp @@ -224,8 +224,14 @@ AppxPhoneEngine::AppxPhoneEngine(Runner *runner) d->hasFatalError = true; ComPtr<IStream> manifestStream; - HRESULT hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); - RETURN_VOID_IF_FAILED("Failed to open manifest stream"); + HRESULT hr; + if (d->manifestReader) { + hr = d->manifestReader->GetStream(&manifestStream); + RETURN_VOID_IF_FAILED("Failed to query manifest stream from manifest reader."); + } else { + hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); + RETURN_VOID_IF_FAILED("Failed to open manifest stream"); + } if (!getPhoneProductId(manifestStream.Get(), &d->productId)) { qCWarning(lcWinRtRunner) << "Failed to read phone product ID from the manifest."; @@ -332,7 +338,12 @@ bool AppxPhoneEngine::installPackage(IAppxManifestReader *reader, const QString _bstr_t packagePath(wchar(QDir::toNativeSeparators(filePath))); hr = connection->InstallApplication(productId, productId, deploymentFlagsAsGenre, packageTypeAsIconPath, packagePath); - RETURN_FALSE_IF_FAILED("Failed to install the package"); + if (hr == 0x80073d06) { // No public E_* macro available + qCWarning(lcWinRtRunner) << "Found a newer version of " << filePath + << " on the target device, skipping..."; + } else { + RETURN_FALSE_IF_FAILED("Failed to install the package"); + } return true; } @@ -388,23 +399,22 @@ bool AppxPhoneEngine::install(bool removeFirst) if (!installDependencies()) return false; - const QDir base = QFileInfo(d->manifest).absoluteDir(); - const QString packageFileName = base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx")); - if (!createPackage(packageFileName)) - return false; - - if (!sign(packageFileName)) - return false; - - ComPtr<IStream> manifestStream; - hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream); - RETURN_FALSE_IF_FAILED("Failed to open manifest stream"); + const QDir base = QFileInfo(d->executable).absoluteDir(); + const bool existingPackage = d->runner->app().endsWith(QLatin1String(".appx")); + const QString packageFileName = existingPackage + ? d->runner->app() + : base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx")); + if (!existingPackage) { + if (!createPackage(packageFileName)) + return false; - ComPtr<IAppxManifestReader> manifestReader; - hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader); - RETURN_FALSE_IF_FAILED("Failed to create manifest reader for installation"); + if (!sign(packageFileName)) + return false; + } else { + qCDebug(lcWinRtRunner) << "Installing existing package."; + } - return installPackage(manifestReader.Get(), packageFileName); + return installPackage(d->manifestReader.Get(), packageFileName); } bool AppxPhoneEngine::remove() |