Ref T156, allow to interactively resolve setup issues

* interactivelySynchronizeSetup
* utility function parseAndSynchronizeSetup, explicit loading of setup
* removed m_startSetupReader;
This commit is contained in:
Klaus Basan
2017-09-24 19:44:06 +01:00
committed by Mathew Sutcliffe
parent 409a50e8a5
commit fedcd76a05
8 changed files with 138 additions and 51 deletions

View File

@@ -356,8 +356,8 @@ namespace BlackCore
}); });
} }
// load setup //! \fixme KB 9/17 waiting for setup reader here is supposed to be replaced by explicitly waiting for reader
if (m_startSetupReader && !m_setupReader->isSetupAvailable()) if (!m_setupReader->isSetupAvailable())
{ {
msgs = this->requestReloadOfSetupAndVersion(); msgs = this->requestReloadOfSetupAndVersion();
if (msgs.isFailure()) { break; } if (msgs.isFailure()) { break; }
@@ -396,14 +396,14 @@ namespace BlackCore
CLogMessage::preformatted(msgs); CLogMessage::preformatted(msgs);
} }
m_started = m_startSetupReader; // only if requested it will be started m_started = true;
return m_started; return m_started;
} }
CStatusMessageList CApplication::waitForSetup() CStatusMessageList CApplication::waitForSetup(int timeoutMs)
{ {
if (!m_setupReader) { return CStatusMessage(this).error("No setup reader"); } if (!m_setupReader) { return CStatusMessage(this).error("No setup reader"); }
CEventLoop::processEventsUntil(this, &CApplication::setupHandlingCompleted, CNetworkUtils::getLongTimeoutMs(), [this] CEventLoop::processEventsUntil(this, &CApplication::setupHandlingCompleted, timeoutMs, [this]
{ {
return m_setupReader->isSetupAvailable(); return m_setupReader->isSetupAvailable();
}); });
@@ -718,30 +718,12 @@ namespace BlackCore
return m_networkWatchDog && m_networkWatchDog->isSwiftDbAccessible(); return m_networkWatchDog && m_networkWatchDog->isSwiftDbAccessible();
} }
bool CApplication::hasSetupReader() const
{
// m_startSetupReader set to false, if something wrong with parsing
return m_setupReader && m_startSetupReader;
}
QString CApplication::getLastSuccesfulSetupUrl() const
{
if (!this->hasSetupReader()) { return ""; }
return m_setupReader->getLastSuccessfulSetupUrl();
}
CUrl CApplication::getWorkingSharedUrl() const CUrl CApplication::getWorkingSharedUrl() const
{ {
if (!m_networkWatchDog || !this->isNetworkAccessible()) { return CUrl(); } if (!m_networkWatchDog || !this->isNetworkAccessible()) { return CUrl(); }
return m_networkWatchDog->getWorkingSharedUrl(); return m_networkWatchDog->getWorkingSharedUrl();
} }
QString CApplication::getLastSuccesfulDistributionUrl() const
{
if (!this->hasSetupReader()) { return ""; }
return m_setupReader->getLastSuccessfulDistributionUrl();
}
void CApplication::exit(int retcode) void CApplication::exit(int retcode)
{ {
if (instance()) if (instance())
@@ -1183,11 +1165,17 @@ namespace BlackCore
if (!this->parsingHookIn()) { return false; } if (!this->parsingHookIn()) { return false; }
// setup reader // setup reader
m_startSetupReader = m_setupReader->parseCmdLineArguments(); m_setupReader->parseCmdLineArguments();
m_parsed = true; m_parsed = true;
return true; return true;
} }
bool CApplication::parseAndSynchronizeSetup(int timeoutMs)
{
if (!this->parseAndStartupCheck()) return false;
return !this->synchronizeSetup(timeoutMs).hasErrorMessages();
}
bool CApplication::cmdLineErrorMessage(const QString &errorMessage, bool retry) const bool CApplication::cmdLineErrorMessage(const QString &errorMessage, bool retry) const
{ {
Q_UNUSED(retry); // only works with UI version Q_UNUSED(retry); // only works with UI version
@@ -1220,6 +1208,14 @@ namespace BlackCore
return args; return args;
} }
QString CApplication::cmdLineArgumentsAsString(bool withExecutable)
{
QStringList args = QCoreApplication::arguments();
if (!withExecutable && !args.isEmpty()) args.removeFirst();
if (args.isEmpty()) return "";
return args.join(' ');
}
void CApplication::cmdLineHelpMessage() void CApplication::cmdLineHelpMessage()
{ {
m_parser.showHelp(); // terminates m_parser.showHelp(); // terminates
@@ -1307,6 +1303,34 @@ namespace BlackCore
// Setup // Setup
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
bool CApplication::hasSetupReader() const
{
return m_setupReader;
}
CSetupReader *CApplication::getSetupReader() const
{
return m_setupReader.data();
}
QString CApplication::getLastSuccesfulSetupUrl() const
{
if (!this->hasSetupReader()) { return ""; }
return m_setupReader->getLastSuccessfulSetupUrl();
}
QString CApplication::getLastSuccesfulDistributionUrl() const
{
if (!this->hasSetupReader()) { return ""; }
return m_setupReader->getLastSuccessfulDistributionUrl();
}
CStatusMessageList CApplication::synchronizeSetup(int timeoutMs)
{
this->requestReloadOfSetupAndVersion();
return this->waitForSetup(timeoutMs);
}
CUrlList CApplication::getVatsimMetarUrls() const CUrlList CApplication::getVatsimMetarUrls() const
{ {
if (m_shutdown) { return CUrlList(); } if (m_shutdown) { return CUrlList(); }

View File

@@ -181,9 +181,6 @@ namespace BlackCore
//! \remark supposed to be used only in special cases //! \remark supposed to be used only in special cases
const QNetworkAccessManager *getNetworkAccessManager() const { return m_accessManager; } const QNetworkAccessManager *getNetworkAccessManager() const { return m_accessManager; }
//! Setup reader?
bool hasSetupReader() const;
//! Last setup URL (successfully read) //! Last setup URL (successfully read)
//! \threadsafe //! \threadsafe
QString getLastSuccesfulSetupUrl() const; QString getLastSuccesfulSetupUrl() const;
@@ -192,9 +189,6 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
QString getLastSuccesfulDistributionUrl() const; QString getLastSuccesfulDistributionUrl() const;
//! Setup already synchronized
bool isSetupAvailable() const;
//! Reload setup and version //! Reload setup and version
BlackMisc::CStatusMessageList requestReloadOfSetupAndVersion(); BlackMisc::CStatusMessageList requestReloadOfSetupAndVersion();
@@ -312,7 +306,11 @@ namespace BlackCore
//! \sa parsingHookIn //! \sa parsingHookIn
//! \return true means to continue, false to stop //! \return true means to continue, false to stop
bool parseAndStartupCheck(); bool parseAndStartupCheck();
//! @}
//! Combined function
//! \see parseAndStartupCheck
//! \see synchronizeSetup
virtual bool parseAndSynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
//! Display error message //! Display error message
virtual bool cmdLineErrorMessage(const QString &cmdLineErrorMessage, bool retry = false) const; virtual bool cmdLineErrorMessage(const QString &cmdLineErrorMessage, bool retry = false) const;
@@ -323,6 +321,10 @@ namespace BlackCore
//! Arguments to be passed to another swift appplication //! Arguments to be passed to another swift appplication
QStringList inheritedArguments(bool withVatlibArgs = true) const; QStringList inheritedArguments(bool withVatlibArgs = true) const;
//! cmd line arguments as string
virtual QString cmdLineArgumentsAsString(bool withExecutable = true);
//! @}
// ----------------------- contexts ---------------------------------------- // ----------------------- contexts ----------------------------------------
//! \name Context / core facade related //! \name Context / core facade related
@@ -364,7 +366,20 @@ namespace BlackCore
Context::IContextSimulator *getIContextSimulator(); Context::IContextSimulator *getIContextSimulator();
//! @} //! @}
// ----------------------- direct access to some setup data --------------------------------- // ----------------------- setup data ---------------------------------
//! Read and wait for setup
//! \sa waitForSetup
BlackMisc::CStatusMessageList synchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
//! Setup reader?
bool hasSetupReader() const;
//! Access to setup reader
//! \remark supposed to be used only in special cases
BlackCore::CSetupReader *getSetupReader() const;
//! Setup already synchronized
bool isSetupAvailable() const;
//! Consolidated version of METAR URLs, either from CGlobalSetup or CVatsimSetup //! Consolidated version of METAR URLs, either from CGlobalSetup or CVatsimSetup
//! \threadsafe //! \threadsafe
@@ -374,15 +389,13 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
BlackMisc::Network::CUrlList getVatsimDataFileUrls() const; BlackMisc::Network::CUrlList getVatsimDataFileUrls() const;
public slots:
//! Graceful shutdown //! Graceful shutdown
virtual void gracefulShutdown(); virtual void gracefulShutdown();
//! Start services, if not yet parsed call CApplication::parse //! Start services, if not yet parsed call CApplication::parse
virtual bool start(); virtual bool start();
//! Wait for setup data by calling the event loop and waiting until everything is ready // ------------------------- network -----------------------------------------------
BlackMisc::CStatusMessageList waitForSetup();
public: public:
static constexpr int NoRedirects = -1; //!< network request not allowing redirects static constexpr int NoRedirects = -1; //!< network request not allowing redirects
@@ -463,11 +476,12 @@ namespace BlackCore
//! Setup read/synchronized //! Setup read/synchronized
void setupHandlingIsCompleted(bool available); void setupHandlingIsCompleted(bool available);
//! Startup completed //! Wait for setup data by calling the event loop and waiting until everything is ready
virtual void startupCompleted(); //! \remark requires parsing upfront
BlackMisc::CStatusMessageList waitForSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
//! Problem with network access manager //! Startup completed
virtual void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible); virtual void onStartUpCompleted();
//! Init class, allows to init from BlackGui::CGuiApplication as well (pseudo virtual) //! Init class, allows to init from BlackGui::CGuiApplication as well (pseudo virtual)
void init(bool withMetadata); void init(bool withMetadata);
@@ -516,7 +530,6 @@ namespace BlackCore
QCommandLineOption m_cmdTestCrashpad {"testcrashpad"}; //!< Test a crasphpad upload QCommandLineOption m_cmdTestCrashpad {"testcrashpad"}; //!< Test a crasphpad upload
bool m_parsed = false; //!< Parsing accomplished? bool m_parsed = false; //!< Parsing accomplished?
bool m_started = false; //!< started with success? bool m_started = false; //!< started with success?
bool m_startSetupReader = false; //!< start the setup reader
bool m_singleApplication = true; //!< only one instance of that application bool m_singleApplication = true; //!< only one instance of that application
bool m_alreadyRunning = false; //!< Application already running bool m_alreadyRunning = false; //!< Application already running

View File

@@ -9,11 +9,13 @@
#include "blackconfig/buildconfig.h" #include "blackconfig/buildconfig.h"
#include "blackcore/context/contextnetwork.h" #include "blackcore/context/contextnetwork.h"
#include "blackcore/setupreader.h"
#include "blackcore/data/globalsetup.h" #include "blackcore/data/globalsetup.h"
#include "blackcore/webdataservices.h" #include "blackcore/webdataservices.h"
#include "blackgui/components/applicationclosedialog.h" #include "blackgui/components/applicationclosedialog.h"
#include "blackgui/components/downloadandinstalldialog.h" #include "blackgui/components/downloadandinstalldialog.h"
#include "blackgui/components/aboutdialog.h" #include "blackgui/components/aboutdialog.h"
#include "blackgui/components/setuploadingdialog.h"
#include "blackgui/guiapplication.h" #include "blackgui/guiapplication.h"
#include "blackgui/guiutility.h" #include "blackgui/guiutility.h"
#include "blackgui/registermetadata.h" #include "blackgui/registermetadata.h"
@@ -82,6 +84,7 @@ namespace BlackGui
{ {
CGuiApplication::registerMetadata(); CGuiApplication::registerMetadata();
CApplication::init(false); // base class without metadata CApplication::init(false); // base class without metadata
if (this->hasSetupReader()) { this->getSetupReader()->setCheckCmdLineBootstrapUrl(false); } // no connect checks on setup reader (handled with interactive setup loading)
CGuiApplication::adjustPalette(); CGuiApplication::adjustPalette();
this->setWindowIcon(icon); this->setWindowIcon(icon);
this->settingsChanged(); this->settingsChanged();
@@ -207,9 +210,9 @@ namespace BlackGui
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
} }
void CGuiApplication::startupCompleted() void CGuiApplication::onStartUpCompleted()
{ {
CApplication::startupCompleted(); CApplication::onStartUpCompleted();
if (this->m_splashScreen) if (this->m_splashScreen)
{ {
this->m_splashScreen->close(); this->m_splashScreen->close();
@@ -597,6 +600,44 @@ namespace BlackGui
return m_styleSheetUtility.resetFont(); return m_styleSheetUtility.resetFont();
} }
bool CGuiApplication::interactivelySynchronizeSetup(int timeoutMs)
{
bool ok = false;
do
{
const CStatusMessageList msgs = this->synchronizeSetup(timeoutMs);
if (msgs.hasErrorMessages())
{
static const QString style = sGui->getStyleSheetUtility().styles(
{
CStyleSheetUtility::fileNameFonts(),
CStyleSheetUtility::fileNameStandardWidget()
});
CSetupLoadingDialog dialog(msgs, this->mainApplicationWindow());
dialog.setStyleSheet(style);
const int r = dialog.exec();
if (r == QDialog::Rejected)
{
ok = false;
break;
}
}
else
{
ok = true;
break;
}
}
while (true);
return ok;
}
bool CGuiApplication::parseAndSynchronizeSetup(int timeoutMs)
{
if (!this->parseAndStartupCheck()) return false;
return this->interactivelySynchronizeSetup(timeoutMs);
}
QDialog::DialogCode CGuiApplication::showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent) QDialog::DialogCode CGuiApplication::showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent)
{ {
const bool needsDialog = this->hasUnsavedSettings(); const bool needsDialog = this->hasUnsavedSettings();

View File

@@ -19,6 +19,7 @@
#include "blackgui/settings/guisettings.h" #include "blackgui/settings/guisettings.h"
#include "blackgui/settings/updatenotification.h" #include "blackgui/settings/updatenotification.h"
#include "blackgui/stylesheetutility.h" #include "blackgui/stylesheetutility.h"
#include "blackmisc/network/networkutils.h"
#include "blackmisc/icons.h" #include "blackmisc/icons.h"
#include "blackmisc/statusmessage.h" #include "blackmisc/statusmessage.h"
@@ -162,6 +163,14 @@ namespace BlackGui
//! Reset the font to default //! Reset the font to default
bool resetFont(); bool resetFont();
//! Wait for setup, in case it fails display a dialog how to continue
bool interactivelySynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
//! Combined function
//! \see parseAndStartupCheck
//! \see interactivelySynchronizeSetup
virtual bool parseAndSynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs()) override;
//! Show close dialog //! Show close dialog
QDialog::DialogCode showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent); QDialog::DialogCode showCloseDialog(QMainWindow *mainWindow, QCloseEvent *closeEvent);
@@ -194,7 +203,7 @@ namespace BlackGui
protected slots: protected slots:
//! Startup competed //! Startup competed
virtual void startupCompleted() override; virtual void onStartUpCompleted() override;
protected: protected:
//! \name print messages generated during parsing / cmd handling //! \name print messages generated during parsing / cmd handling
@@ -214,15 +223,15 @@ namespace BlackGui
private: private:
QPixmap m_windowIcon; QPixmap m_windowIcon;
BlackGui::Components::CDownloadAndInstallDialog *m_installDialog = nullptr; //!< software installation dialog
QCommandLineOption m_cmdWindowStateMinimized { "empty" }; //!< window state (minimized) QCommandLineOption m_cmdWindowStateMinimized { "empty" }; //!< window state (minimized)
QCommandLineOption m_cmdWindowMode { "empty" }; //!< window mode (flags: frameless ...) QCommandLineOption m_cmdWindowMode { "empty" }; //!< window mode (flags: frameless ...)
CStyleSheetUtility m_styleSheetUtility{{}, this}; //!< style sheet utility CStyleSheetUtility m_styleSheetUtility{{}, this}; //!< style sheet utility
bool m_uiSetupCompleted = false; //!< ui setup completed bool m_uiSetupCompleted = false; //!< ui setup completed
QScopedPointer<QSplashScreen> m_splashScreen; //!< splash screen QScopedPointer<QSplashScreen> m_splashScreen; //!< splash screen
BlackGui::Components::CApplicationCloseDialog *m_closeDialog = nullptr; //!< close dialog (no QScopedPointer because I need to set parent) Components::CDownloadAndInstallDialog *m_installDialog = nullptr; //!< software installation dialog
BlackMisc::CSettingReadOnly<BlackGui::Settings::TGeneralGui> m_guiSettings{ this, &CGuiApplication::settingsChanged }; Components::CApplicationCloseDialog *m_closeDialog = nullptr; //!< close dialog (no QScopedPointer because I need to set parent)
BlackMisc::CSettingReadOnly<BlackGui::Settings::TUpdateNotificationSettings> m_updateSetting { this }; //!< update notification settings BlackMisc::CSettingReadOnly<Settings::TGeneralGui> m_guiSettings{ this, &CGuiApplication::settingsChanged };
BlackMisc::CSettingReadOnly<Settings::TUpdateNotificationSettings> m_updateSetting { this }; //!< update notification settings
//! Qt help message to formatted HTML //! Qt help message to formatted HTML
static QString beautifyHelpMessage(const QString &helpText); static QString beautifyHelpMessage(const QString &helpText);

View File

@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
a.addVatlibOptions(); a.addVatlibOptions();
a.addParserOption({{"r", "start"}, QCoreApplication::translate("main", "Start the server.")}); a.addParserOption({{"r", "start"}, QCoreApplication::translate("main", "Start the server.")});
a.addParserOption({{"c", "coreaudio"}, QCoreApplication::translate("main", "Audio in core.")}); a.addParserOption({{"c", "coreaudio"}, QCoreApplication::translate("main", "Audio in core.")});
if (!a.parseAndStartupCheck()) { return EXIT_FAILURE; } if (!a.parseAndSynchronizeSetup()) { return EXIT_FAILURE; }
const QString dBusAdress(a.getCmdDBusAddressValue()); const QString dBusAdress(a.getCmdDBusAddressValue());
a.useContexts(a.isParserOptionSet("coreaudio") ? a.useContexts(a.isParserOptionSet("coreaudio") ?

View File

@@ -30,7 +30,7 @@ int main(int argc, char *argv[])
CGuiApplication a(CApplicationInfo::swiftMappingTool(), CApplicationInfo::MappingTool, CIcons::swiftDatabase48()); CGuiApplication a(CApplicationInfo::swiftMappingTool(), CApplicationInfo::MappingTool, CIcons::swiftDatabase48());
a.setSignalStartupAutomatically(false); // application will signal startup on its own a.setSignalStartupAutomatically(false); // application will signal startup on its own
a.splashScreen(CIcons::swiftDatabase256()); a.splashScreen(CIcons::swiftDatabase256());
if (!a.parseAndStartupCheck()) { return EXIT_FAILURE; } if (!a.parseAndSynchronizeSetup()) { return EXIT_FAILURE; }
a.useWebDataServices(BlackCore::CWebReaderFlags::AllSwiftDbReaders, CDatabaseReaderConfigList::forMappingTool()); a.useWebDataServices(BlackCore::CWebReaderFlags::AllSwiftDbReaders, CDatabaseReaderConfigList::forMappingTool());
if (!a.start()) if (!a.start())
{ {

View File

@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
CSwiftGuiStdApplication a; CSwiftGuiStdApplication a;
a.setSignalStartupAutomatically(false); // application will signal startup on its own a.setSignalStartupAutomatically(false); // application will signal startup on its own
a.splashScreen(CIcons::swift256()); a.splashScreen(CIcons::swift256());
if (!a.parseAndStartupCheck()) { return EXIT_FAILURE; } if (!a.parseAndSynchronizeSetup()) { return EXIT_FAILURE; }
if (!a.hasSetupReader() || !a.start()) if (!a.hasSetupReader() || !a.start())
{ {
a.gracefulShutdown(); a.gracefulShutdown();

View File

@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
CGuiApplication a(CApplicationInfo::swiftLauncher(), CApplicationInfo::Laucher, CIcons::swiftLauncher1024()); CGuiApplication a(CApplicationInfo::swiftLauncher(), CApplicationInfo::Laucher, CIcons::swiftLauncher1024());
a.addVatlibOptions(); // so it can be passed to started applications a.addVatlibOptions(); // so it can be passed to started applications
a.addParserOption({{"i", "installer"}, QCoreApplication::translate("main", "Installer setup.") }); a.addParserOption({{"i", "installer"}, QCoreApplication::translate("main", "Installer setup.") });
if (!a.parseAndStartupCheck()) { return EXIT_FAILURE; } if (!a.parseAndSynchronizeSetup()) { return EXIT_FAILURE; }
a.useWebDataServices(BlackCore::CWebReaderFlags::AllSwiftDbReaders, CDatabaseReaderConfigList::forLauncher()); a.useWebDataServices(BlackCore::CWebReaderFlags::AllSwiftDbReaders, CDatabaseReaderConfigList::forLauncher());
if (!a.start()) if (!a.start())
{ {