From 74e0bf397f6346ff5400e4f4015a482b71a67beb Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Fri, 28 Apr 2017 02:42:50 +0200 Subject: [PATCH] Ref T42, application classes * GUI classes allow retry * longer timeouts * accept unknow accessibility (QAM) * QAM now as pointer, which would allow to replace QAM When QAM becomes disconnected, then connect again it is in unknown state --- src/blackcore/application.cpp | 61 +++++++++++++++++++++-------- src/blackcore/application.h | 43 ++++++++++++-------- src/blackgui/guiapplication.cpp | 46 ++++++++-------------- src/blackgui/guiapplication.h | 4 +- src/swiftlauncher/swiftlauncher.cpp | 2 +- 5 files changed, 90 insertions(+), 66 deletions(-) diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index b7416d162..288f4a15c 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -96,7 +96,8 @@ namespace BlackCore { } CApplication::CApplication(const QString &applicationName, CApplicationInfo::Application application, bool init) : - m_cookieManager( {}, this), m_applicationName(applicationName), m_application(application), m_coreFacadeConfig(CCoreFacadeConfig::allEmpty()) + m_accessManager(new QNetworkAccessManager(this)), + m_application(application), m_cookieManager( {}, this), m_applicationName(applicationName), m_coreFacadeConfig(CCoreFacadeConfig::allEmpty()) { Q_ASSERT_X(!sApp, Q_FUNC_INFO, "already initialized"); Q_ASSERT_X(QCoreApplication::instance(), Q_FUNC_INFO, "no application object"); @@ -139,9 +140,11 @@ namespace BlackCore QCoreApplication::instance()->installTranslator(&translator); // Init network - this->m_cookieManager.setParent(&this->m_accessManager); - this->m_accessManager.setCookieJar(&this->m_cookieManager); - connect(&this->m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, this, &CApplication::ps_networkAccessibleChanged); + Q_ASSERT_X(m_accessManager, Q_FUNC_INFO, "Need QAM"); + this->m_cookieManager.setParent(this->m_accessManager); + this->m_accessManager->setCookieJar(&this->m_cookieManager); + connect(this->m_accessManager, &QNetworkAccessManager::networkAccessibleChanged, this, &CApplication::ps_networkAccessibleChanged); + CLogMessage::preformatted(CNetworkUtils::createNetworkReport(this->m_accessManager)); // global setup sApp = this; @@ -149,7 +152,7 @@ namespace BlackCore connect(this->m_setupReader.data(), &CSetupReader::setupHandlingCompleted, this, &CApplication::ps_setupHandlingCompleted); connect(this->m_setupReader.data(), &CSetupReader::distributionInfoAvailable, this, &CApplication::distributionInfoAvailable); - this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions()); + this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions()); // add options from reader // startup done connect(this, &CApplication::startUpCompleted, this, &CApplication::ps_startupCompleted); @@ -176,6 +179,15 @@ namespace BlackCore return QCoreApplication::exec(); } + void CApplication::restartApplication() + { + this->gracefulShutdown(); + const QString prg = QCoreApplication::applicationFilePath(); + const QStringList args = CApplication::arguments(); + QProcess::startDetached(prg, args); + this->exit(0); + } + CApplication::~CApplication() { this->gracefulShutdown(); @@ -380,7 +392,7 @@ namespace BlackCore CStatusMessageList CApplication::waitForSetup() { if (!this->m_setupReader) { return CStatusMessage(this).error("No setup reader"); } - CEventLoop::processEventsUntil(this, &CApplication::setupHandlingCompleted, 5000, [this] + CEventLoop::processEventsUntil(this, &CApplication::setupHandlingCompleted, CNetworkUtils::getLongTimeoutMs(), [this] { return this->m_setupReader->isSetupAvailable(); }); @@ -567,9 +579,9 @@ namespace BlackCore QNetworkReply *CApplication::postToNetwork(const QNetworkRequest &request, QHttpMultiPart *multiPart, const CSlot &callback) { if (!this->isNetworkAccessible()) { return nullptr; } - if (QThread::currentThread() != this->m_accessManager.thread()) + if (QThread::currentThread() != this->m_accessManager->thread()) { - multiPart->moveToThread(this->m_accessManager.thread()); + multiPart->moveToThread(this->m_accessManager->thread()); } return httpRequestImpl(request, callback, -1, [ this, multiPart ](QNetworkAccessManager & nam, const QNetworkRequest & request) @@ -598,7 +610,12 @@ namespace BlackCore bool CApplication::isNetworkAccessible() const { - return this->m_accessManager.networkAccessible() == QNetworkAccessManager::Accessible; + if (!this->m_accessManager) return false; + const QNetworkAccessManager::NetworkAccessibility a = this->m_accessManager->networkAccessible(); + if (a == QNetworkAccessManager::Accessible) return true; + + // currently I also accept unknown + return a == QNetworkAccessManager::UnknownAccessibility; } bool CApplication::hasSetupReader() const @@ -847,6 +864,7 @@ namespace BlackCore switch (accessible) { case QNetworkAccessManager::Accessible: + this->m_accessManager->setNetworkAccessible(accessible); // for some reasons the queried value still is unknown CLogMessage(this).info("Network is accessible"); break; case QNetworkAccessManager::NotAccessible: @@ -947,6 +965,11 @@ namespace BlackCore return this->m_parser.isSet(option); } + bool CApplication::isInstallerOptionSet() const + { + return this->isParserOptionSet("installer"); + } + bool CApplication::isParserOptionSet(const QCommandLineOption &option) const { return this->m_parser.isSet(option); @@ -1011,20 +1034,24 @@ namespace BlackCore return true; } - void CApplication::cmdLineErrorMessage(const QString &errorMessage) const + bool CApplication::cmdLineErrorMessage(const QString &errorMessage, bool retry) const { + Q_UNUSED(retry); // onyl works with UI version fputs(qPrintable(errorMessage), stderr); fputs("\n\n", stderr); fputs(qPrintable(this->m_parser.helpText()), stderr); + return false; } - void CApplication::cmdLineErrorMessage(const CStatusMessageList &msgs) const + bool CApplication::cmdLineErrorMessage(const CStatusMessageList &msgs, bool retry) const { - if (msgs.isEmpty()) { return; } - if (!msgs.hasErrorMessages()) { return; } + Q_UNUSED(retry); // onyl works with UI version + if (msgs.isEmpty()) { return false; } + if (!msgs.hasErrorMessages()) { return false; } CApplication::cmdLineErrorMessage( msgs.toFormattedQString(true) ); + return false; } void CApplication::cmdLineHelpMessage() @@ -1206,14 +1233,14 @@ namespace BlackCore if (this->m_shutdown) { return nullptr; } if (!this->isNetworkAccessible()) { return nullptr; } QWriteLocker locker(&m_accessManagerLock); - Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); - if (QThread::currentThread() != this->m_accessManager.thread()) + Q_ASSERT_X(QCoreApplication::instance()->thread() == m_accessManager->thread(), Q_FUNC_INFO, "Network manager supposed to be in main thread"); + if (QThread::currentThread() != this->m_accessManager->thread()) { QTimer::singleShot(0, this, std::bind(&CApplication::httpRequestImpl, this, request, callback, maxRedirects, requestOrPostMethod)); return nullptr; // not yet started } - Q_ASSERT_X(QThread::currentThread() == m_accessManager.thread(), Q_FUNC_INFO, "Network manager thread mismatch"); + Q_ASSERT_X(QThread::currentThread() == m_accessManager->thread(), Q_FUNC_INFO, "Network manager thread mismatch"); QNetworkRequest copiedRequest(request); // no QObject CNetworkUtils::ignoreSslVerification(copiedRequest); CNetworkUtils::setSwiftUserAgent(copiedRequest); @@ -1221,7 +1248,7 @@ namespace BlackCore // If URL is one of the shared urls, add swift client SSL certificate CNetworkUtils::setSwiftClientSslCertificate(copiedRequest, getGlobalSetup().getSwiftSharedUrls()); - QNetworkReply *reply = requestOrPostMethod(this->m_accessManager, copiedRequest); + QNetworkReply *reply = requestOrPostMethod(*this->m_accessManager, copiedRequest); reply->setProperty("started", QVariant(QDateTime::currentMSecsSinceEpoch())); if (callback) { diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 048e4dacf..a578d218c 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -12,19 +12,6 @@ #ifndef BLACKCORE_APPLICATION_H #define BLACKCORE_APPLICATION_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "blackcore/blackcoreexport.h" #include "blackcore/cookiemanager.h" #include "blackcore/corefacadeconfig.h" @@ -38,6 +25,19 @@ #include "blackmisc/applicationinfolist.h" #include "blackmisc/statusmessagelist.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #if defined(Q_CC_MSVC) || defined(Q_OS_OSX) // Crashpad only supported on MSVC and MacOS/X #define BLACK_USE_CRASHPAD #endif @@ -159,6 +159,9 @@ namespace BlackCore //! Network accessible? bool isNetworkAccessible() const; + //! Access to access manager + const QNetworkAccessManager *getNetworkAccessManager() const { return m_accessManager; } + //! Setup reader? bool hasSetupReader() const; @@ -221,6 +224,9 @@ namespace BlackCore //! Directory for temporary files QString getTemporaryDirectory() const; + //! Stop and restart application + void restartApplication(); + //! Register as running //! \note Normally done automatically when CApplication::exec is called static bool registerAsRunning(); @@ -268,6 +274,9 @@ namespace BlackCore //! Delegates to QCommandLineParser::isSet bool isParserOptionSet(const QString &option) const; + //! Installer called? + bool isInstallerOptionSet() const; + //! Delegates to QCommandLineParser::isSet bool isParserOptionSet(const QCommandLineOption &option) const; @@ -285,10 +294,10 @@ namespace BlackCore //! @} //! Display error message - virtual void cmdLineErrorMessage(const QString &cmdLineErrorMessage) const; + virtual bool cmdLineErrorMessage(const QString &cmdLineErrorMessage, bool retry = false) const; //! Display error message - virtual void cmdLineErrorMessage(const BlackMisc::CStatusMessageList &msgs) const; + virtual bool cmdLineErrorMessage(const BlackMisc::CStatusMessageList &msgs, bool retry = false) const; // ----------------------- contexts ---------------------------------------- @@ -479,14 +488,14 @@ namespace BlackCore int maxRedirects, std::function requestOrPostMethod); + QNetworkAccessManager *m_accessManager = nullptr; //!< single network access manager + BlackMisc::CApplicationInfo::Application m_application = BlackMisc::CApplicationInfo::Unknown; //!< Application if specified QScopedPointer m_coreFacade; //!< core facade if any QScopedPointer m_setupReader; //!< setup reader QScopedPointer m_webDataServices; //!< web data services QScopedPointer m_fileLogger; //!< file logger - QNetworkAccessManager m_accessManager { this }; //!< single network access manager CCookieManager m_cookieManager; //!< single cookie manager for our access manager QString m_applicationName; //!< application name - BlackMisc::CApplicationInfo::Application m_application = BlackMisc::CApplicationInfo::Unknown; //!< Application if specified QReadWriteLock m_accessManagerLock; //!< lock to make access manager access threadsafe CCoreFacadeConfig m_coreFacadeConfig; //!< Core facade config if any CWebReaderFlags::WebReader m_webReadersUsed; //!< Readers to be used diff --git a/src/blackgui/guiapplication.cpp b/src/blackgui/guiapplication.cpp index 6810db02e..cdfb518ec 100644 --- a/src/blackgui/guiapplication.cpp +++ b/src/blackgui/guiapplication.cpp @@ -259,39 +259,27 @@ namespace BlackGui return html; } - void CGuiApplication::cmdLineErrorMessage(const QString &errorMessage) const + bool CGuiApplication::cmdLineErrorMessage(const QString &errorMessage, bool retry) const { - if (CBuildConfig::isRunningOnWindowsNtPlatform()) - { - const QString helpText(beautifyHelpMessage(this->m_parser.helpText())); - QMessageBox::warning(nullptr, - QGuiApplication::applicationDisplayName(), - "

" + errorMessage + "


" + helpText + ""); - } - else - { - CApplication::cmdLineErrorMessage(errorMessage); - } + const QString helpText(beautifyHelpMessage(this->m_parser.helpText())); + const int r = QMessageBox::warning(nullptr, + QGuiApplication::applicationDisplayName(), + "

" + errorMessage + "


" + helpText + "", QMessageBox::Abort, retry ? QMessageBox::Retry : QMessageBox::NoButton); + return (r == QMessageBox::Retry); } - void CGuiApplication::cmdLineErrorMessage(const CStatusMessageList &msgs) const + bool CGuiApplication::cmdLineErrorMessage(const CStatusMessageList &msgs, bool retry) const { - if (msgs.isEmpty()) { return; } - if (!msgs.hasErrorMessages()) { return; } - if (CBuildConfig::isRunningOnWindowsNtPlatform()) - { - static const CPropertyIndexList propertiesSingle({ CStatusMessage::IndexMessage }); - static const CPropertyIndexList propertiesMulti({ CStatusMessage::IndexSeverityAsString, CStatusMessage::IndexMessage }); - const QString helpText(CGuiApplication::beautifyHelpMessage(this->m_parser.helpText())); - const QString msgsHtml = msgs.toHtml(msgs.size() > 1 ? propertiesMulti : propertiesSingle); - QMessageBox::critical(nullptr, - QGuiApplication::applicationDisplayName(), - "" + msgsHtml + "

" + helpText + ""); - } - else - { - CApplication::cmdLineErrorMessage(msgs); - } + if (msgs.isEmpty()) { return false; } + if (!msgs.hasErrorMessages()) { return false; } + static const CPropertyIndexList propertiesSingle({ CStatusMessage::IndexMessage }); + static const CPropertyIndexList propertiesMulti({ CStatusMessage::IndexSeverityAsString, CStatusMessage::IndexMessage }); + const QString helpText(CGuiApplication::beautifyHelpMessage(this->m_parser.helpText())); + const QString msgsHtml = msgs.toHtml(msgs.size() > 1 ? propertiesMulti : propertiesSingle); + const int r = QMessageBox::critical(nullptr, + QGuiApplication::applicationDisplayName(), + "" + msgsHtml + "

" + helpText + "", QMessageBox::Abort, retry ? QMessageBox::Retry : QMessageBox::NoButton); + return (r == QMessageBox::Retry); } bool CGuiApplication::displayInStatusBar(const CStatusMessage &message) diff --git a/src/blackgui/guiapplication.h b/src/blackgui/guiapplication.h index cf091548f..ff4b30fbd 100644 --- a/src/blackgui/guiapplication.h +++ b/src/blackgui/guiapplication.h @@ -111,8 +111,8 @@ namespace BlackGui //! \name print messages generated during parsing / cmd handling //! @{ - virtual void cmdLineErrorMessage(const QString &cmdLineErrorMessage) const override; - virtual void cmdLineErrorMessage(const BlackMisc::CStatusMessageList &msgs) const override; + virtual bool cmdLineErrorMessage(const QString &cmdLineErrorMessage, bool retry = false) const override; + virtual bool cmdLineErrorMessage(const BlackMisc::CStatusMessageList &msgs, bool retry = false) const override; //! @} //! \name direct access to main application window diff --git a/src/swiftlauncher/swiftlauncher.cpp b/src/swiftlauncher/swiftlauncher.cpp index 54d016275..f31140b93 100644 --- a/src/swiftlauncher/swiftlauncher.cpp +++ b/src/swiftlauncher/swiftlauncher.cpp @@ -70,7 +70,7 @@ CSwiftLauncher::CSwiftLauncher(QWidget *parent) : m_checkTimer.start(); // auto launch wizard - if (sGui->isParserOptionSet("installer")) + if (sGui->isInstallerOptionSet()) { QTimer::singleShot(2500, this, &CSwiftLauncher::ps_startWizard); }