mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-10 22:15:34 +08:00
The main reason why CInputManager was singleton is the easy access across the code. That had the negative side effect that time of destruction was at a very late stage of the shutdown and could not be controlled by us. My moving it to CApplication, the access is equally easy (using sApp) and allows to be cleaned up properly during graceful shutdown. ref T391
690 lines
29 KiB
C++
690 lines
29 KiB
C++
/* Copyright (C) 2016
|
|
* swift project Community / Contributors
|
|
*
|
|
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
|
|
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
|
|
* including this file, may be copied, modified, propagated, or distributed except according to the terms
|
|
* contained in the LICENSE file.
|
|
*/
|
|
|
|
//! \file
|
|
|
|
#ifndef BLACKCORE_APPLICATION_H
|
|
#define BLACKCORE_APPLICATION_H
|
|
|
|
#include "blackcore/blackcoreexport.h"
|
|
#include "blackcore/corefacadeconfig.h"
|
|
#include "blackcore/db/databasereaderconfig.h"
|
|
#include "blackcore/data/globalsetup.h"
|
|
#include "blackcore/application/applicationsettings.h"
|
|
#include "blackcore/inputmanager.h"
|
|
#include "blackcore/webreaderflags.h"
|
|
#include "blackmisc/db/updateinfo.h"
|
|
#include "blackmisc/network/urllist.h"
|
|
#include "blackmisc/network/networkutils.h"
|
|
#include "blackmisc/identifiable.h"
|
|
#include "blackmisc/slot.h"
|
|
#include "blackmisc/applicationinfolist.h"
|
|
#include "blackmisc/statusmessagelist.h"
|
|
#include "blackmisc/crashinfo.h"
|
|
|
|
#include <QByteArray>
|
|
#include <QCommandLineOption>
|
|
#include <QCommandLineParser>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkConfigurationManager>
|
|
#include <QReadWriteLock>
|
|
#include <QStringList>
|
|
#include <QString>
|
|
#include <QList>
|
|
#include <QObject>
|
|
#include <QScopedPointer>
|
|
#include <QByteArray>
|
|
#include <atomic>
|
|
#include <functional>
|
|
|
|
#if defined(Q_CC_MSVC) || defined(Q_OS_MACOS) // Crashpad only supported on MSVC and MacOS/X
|
|
#define BLACK_USE_CRASHPAD
|
|
#endif
|
|
|
|
class QHttpMultiPart;
|
|
class QNetworkReply;
|
|
class QNetworkRequest;
|
|
|
|
namespace BlackMisc
|
|
{
|
|
class CFileLogger;
|
|
class CLogCategoryList;
|
|
}
|
|
|
|
namespace crashpad
|
|
{
|
|
class CrashpadClient;
|
|
class CrashReportDatabase;
|
|
}
|
|
|
|
namespace BlackCore
|
|
{
|
|
class CCoreFacade;
|
|
class CCookieManager;
|
|
class CSetupReader;
|
|
class CWebDataServices;
|
|
class ISimulator;
|
|
namespace Context
|
|
{
|
|
class IContextApplication;
|
|
class IContextAudio;
|
|
class IContextNetwork;
|
|
class IContextOwnAircraft;
|
|
class IContextSimulator;
|
|
}
|
|
namespace Db { class CNetworkWatchdog; }
|
|
|
|
/*!
|
|
* Our runtime. Normally one instance is to be initialized at the beginning of main, and thereafter
|
|
* it can be used everywhere via QApplication::instance
|
|
*
|
|
* - A swift standard cmd line parser is part of the application.
|
|
* Hence cmd arguments can be optained any time / everywhere when required.
|
|
* Also some standard swift cmd arguments do not need to be re-implemented for each swift application.
|
|
* - The core facade (aka core runtime) is now part of the application. It can be started via cmd line arguments.
|
|
* - Settings are loaded
|
|
* - Setup is loaded (load the so called bootstrap file) to find servers and other resources
|
|
* - Update information (new swift versions etc.) are loaded
|
|
* - If applicable VATSIM status data (where are the VATSIM files?) are loaded
|
|
* - An end of lifetime can be specified, aka time bombing
|
|
*
|
|
* \sa BlackGui::CGuiApplication for the GUI version of application
|
|
*/
|
|
class BLACKCORE_EXPORT CApplication :
|
|
public QObject,
|
|
public BlackMisc::CIdentifiable
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
//! Similar to \sa QCoreApplication::instance() returns the single instance
|
|
static CApplication *instance();
|
|
|
|
//! Own log categories
|
|
static const BlackMisc::CLogCategoryList &getLogCategories();
|
|
|
|
//! Constructor
|
|
CApplication(BlackMisc::CApplicationInfo::Application application, bool init = true);
|
|
|
|
//! Constructor
|
|
CApplication(const QString &applicationName = executable(), BlackMisc::CApplicationInfo::Application application = BlackMisc::CApplicationInfo::Unknown, bool init = true);
|
|
|
|
//! Destructor
|
|
virtual ~CApplication();
|
|
|
|
//! Information about all running apps (including this one only if exec() has already been called)
|
|
static BlackMisc::CApplicationInfoList getRunningApplications();
|
|
|
|
//! Is application running?
|
|
static bool isApplicationRunning(BlackMisc::CApplicationInfo::Application application);
|
|
|
|
//! True if this swift application is already running (including different versions)
|
|
bool isAlreadyRunning() const;
|
|
|
|
//! Graceful shutdown
|
|
virtual void gracefulShutdown();
|
|
|
|
//! Is application shutting down?
|
|
//! \threadsafe
|
|
bool isShuttingDown() const;
|
|
|
|
//! swift application running
|
|
const BlackMisc::CApplicationInfo &getApplicationInfo() const { return m_applicationInfo; }
|
|
|
|
//! Application name and version
|
|
const QString &getApplicationName() const { return m_applicationName; }
|
|
|
|
//! Application name and version
|
|
const QString &getApplicationNameAndVersion() const;
|
|
|
|
//! Version, name beta and dev info
|
|
const QString &getApplicationNameVersionDetailed() const;
|
|
|
|
//! Force single application (only one instance)
|
|
void setSingleApplication(bool singleApplication);
|
|
|
|
//! Executable names for the given applications
|
|
QString getExecutableForApplication(BlackMisc::CApplicationInfo::Application application) const;
|
|
|
|
//! Start the launcher
|
|
bool startLauncher();
|
|
|
|
//! Start the launcher and quit
|
|
bool startLauncherAndQuit();
|
|
|
|
//! Global setup
|
|
//! \threadsafe
|
|
Data::CGlobalSetup getGlobalSetup() const;
|
|
|
|
//! Update info
|
|
//! \threadsafe
|
|
BlackMisc::Db::CUpdateInfo getUpdateInfo() const;
|
|
|
|
//! Own distribution
|
|
//! \threadsafe
|
|
BlackMisc::Db::CDistribution getOwnDistribution() const;
|
|
|
|
//! Currently running in application thread?
|
|
bool isApplicationThread() const;
|
|
|
|
//! String with beta, dev. and version
|
|
const QString &versionStringDetailed() const;
|
|
|
|
//! swift info string
|
|
const QString &swiftVersionString() const;
|
|
|
|
//! swift info string
|
|
const char *swiftVersionChar();
|
|
|
|
//! Running with dev.flag?
|
|
bool isDeveloperFlagSet() const { return m_devFlag; }
|
|
|
|
//! Signal startup automatically or individually
|
|
void setSignalStartupAutomatically(bool enabled) { m_signalStartup = enabled; }
|
|
|
|
//! Comprehensive info
|
|
QString getInfoString(const QString &separator) const;
|
|
|
|
//! Stop and restart application
|
|
void restartApplication(const QStringList &newArguments = {}, const QStringList &removeArguments = {});
|
|
|
|
//! Directory for temporary files
|
|
static QString getTemporaryDirectory();
|
|
|
|
//! Register as running
|
|
//! \note Normally done automatically when CApplication::exec is called
|
|
static bool registerAsRunning();
|
|
|
|
//! Unregister from running
|
|
//! \note Normally done automatically, needed for restart
|
|
static bool unregisterAsRunning();
|
|
|
|
//! Run event loop
|
|
static int exec();
|
|
|
|
//! Exit application, perform graceful shutdown and exit
|
|
static void exit(int retcode = EXIT_SUCCESS);
|
|
|
|
//! Process all events for some time
|
|
//! \remark unlike QCoreApplication::processEvents this will spend at least the given time in the function, using QThread::msleep
|
|
//! \remark using processEventsFor can lead to undesired behaviour: A function may be called again before it is finished, even with only one thread
|
|
//! \sa BlackMisc::CEventLoop
|
|
static void processEventsFor(int milliseconds);
|
|
|
|
//! Clear the caches
|
|
//! \return all cache files
|
|
static QStringList clearCaches();
|
|
|
|
// ----------------------- settings -------------------------------
|
|
|
|
//! Unsaved settings
|
|
bool hasUnsavedSettings() const;
|
|
|
|
//! Save settings on shutdown
|
|
void saveSettingsOnShutdown(bool saveSettings);
|
|
|
|
//! All unsaved settings
|
|
QStringList getUnsavedSettingsKeys() const;
|
|
|
|
//! Save all settings
|
|
BlackMisc::CStatusMessage saveSettingsByKey(const QStringList &keys);
|
|
|
|
// ----------------------- cmd line args / parsing ----------------------------------------
|
|
|
|
//! Current parameters replaced by new arguments without the cmd line argument
|
|
virtual QStringList argumentsJoined(const QStringList &newArguments = {}, const QStringList &removeArguments = {}) const;
|
|
|
|
//! Similar to QCoreApplication::arguments
|
|
static QStringList arguments();
|
|
|
|
//! \name cmd line args and parsing of command line options
|
|
//! @{
|
|
|
|
//! \copydoc QCommandLineParser::addOption
|
|
bool addParserOption(const QCommandLineOption &option);
|
|
|
|
//! \copydoc QCommandLineParser::addOptions
|
|
bool addParserOptions(const QList<QCommandLineOption> &options);
|
|
|
|
//! CMD line argument for DBus address
|
|
void addDBusAddressOption();
|
|
|
|
//! DBus address from CMD line, otherwise ""
|
|
QString getCmdDBusAddressValue() const;
|
|
|
|
//! Add the VATLIB options
|
|
void addVatlibOptions();
|
|
|
|
//! Private resource dir for developer's own resource files
|
|
QString getCmdSwiftPrivateSharedDir() const;
|
|
|
|
//! Delegates to QCommandLineParser::isSet
|
|
bool isParserOptionSet(const QString &option) const;
|
|
|
|
//! Called by installer?
|
|
bool isInstallerOptionSet() const;
|
|
|
|
//! Delegates to QCommandLineParser::isSet
|
|
bool isParserOptionSet(const QCommandLineOption &option) const;
|
|
|
|
//! Delegates to QCommandLineParser::value
|
|
QString getParserValue(const QString &option) const;
|
|
|
|
//! Delegates to QCommandLineParser::value
|
|
QString getParserValue(const QCommandLineOption &option) const;
|
|
|
|
//! Parses and handles the standard options such as help, version, parse error
|
|
//! \note in some cases (error, version, help) application is terminated during this step
|
|
//! \sa parsingHookIn
|
|
//! \return true means to continue, false to stop
|
|
bool parseAndStartupCheck();
|
|
|
|
//! Combined function
|
|
//! \see parseAndStartupCheck
|
|
//! \see synchronizeSetup
|
|
virtual bool parseAndSynchronizeSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
|
|
|
|
//! Display error message
|
|
virtual bool cmdLineErrorMessage(const QString &cmdLineErrorMessage, bool retry = false) const;
|
|
|
|
//! Display error message
|
|
virtual bool cmdLineErrorMessage(const BlackMisc::CStatusMessageList &msgs, bool retry = false) const;
|
|
|
|
//! cmd line arguments as string
|
|
virtual QString cmdLineArgumentsAsString(bool withExecutable = true);
|
|
//! @}
|
|
|
|
// ----------------------- Input ----------------------------------------
|
|
|
|
//! The input manager, if available
|
|
CInputManager *getInputManager() const { return m_inputManager; }
|
|
|
|
|
|
// ----------------------- simulator ----------------------------------------
|
|
|
|
//! The simulator plugin, if available
|
|
ISimulator *getISimulator() const;
|
|
|
|
// ----------------------- contexts ----------------------------------------
|
|
|
|
//! \name Context / core facade related
|
|
//! @{
|
|
|
|
//! Supports contexts
|
|
//! \remark checks the real availability of the contexts, so it can happen that we want to use contexts, and they are not yet initialized (false here)
|
|
//! \sa m_useContexts we use or we will use contexts
|
|
bool supportsContexts() const;
|
|
|
|
//! The core facade config
|
|
const CCoreFacadeConfig &getCoreFacadeConfig() const { return m_coreFacadeConfig; }
|
|
|
|
//! Init the contexts part and start core facade
|
|
//! \sa coreFacadeStarted
|
|
//! \remark requires setup loaded
|
|
BlackMisc::CStatusMessageList useContexts(const CCoreFacadeConfig &coreConfig);
|
|
|
|
//! Init web data services and start them
|
|
//! \sa webDataServicesStarted
|
|
//! \remark requires setup loaded
|
|
BlackMisc::CStatusMessageList useWebDataServices(const CWebReaderFlags::WebReader webReader, const Db::CDatabaseReaderConfigList &dbReaderConfig);
|
|
|
|
//! Get the facade
|
|
CCoreFacade *getCoreFacade() { return m_coreFacade.data(); }
|
|
|
|
//! Get the facade
|
|
const CCoreFacade *getCoreFacade() const { return m_coreFacade.data(); }
|
|
//! @}
|
|
|
|
//! \name Direct access to contexts if a CCoreFacade has been initialized
|
|
//! @{
|
|
const Context::IContextNetwork *getIContextNetwork() const;
|
|
const Context::IContextAudio *getIContextAudio() const;
|
|
const Context::IContextApplication *getIContextApplication() const;
|
|
const Context::IContextOwnAircraft *getIContextOwnAircraft() const;
|
|
const Context::IContextSimulator *getIContextSimulator() const;
|
|
Context::IContextNetwork *getIContextNetwork();
|
|
Context::IContextAudio *getIContextAudio();
|
|
Context::IContextApplication *getIContextApplication();
|
|
Context::IContextOwnAircraft *getIContextOwnAircraft();
|
|
Context::IContextSimulator *getIContextSimulator();
|
|
//! @}
|
|
|
|
// ----------------------- setup data ---------------------------------
|
|
|
|
//! Last setup URL (successfully read)
|
|
//! \threadsafe
|
|
QString getLastSuccesfulSetupUrl() const;
|
|
|
|
//! Last distribution URL (successfully read)
|
|
//! \threadsafe
|
|
QString getLastSuccesfulDistributionUrl() const;
|
|
|
|
//! Reload setup and version
|
|
BlackMisc::CStatusMessageList requestReloadOfSetupAndVersion();
|
|
|
|
//! 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
|
|
CSetupReader *getSetupReader() const;
|
|
|
|
//! Setup already synchronized
|
|
bool isSetupAvailable() const;
|
|
|
|
//! Consolidated version of METAR URLs, either from CGlobalSetup or CVatsimSetup
|
|
//! \threadsafe
|
|
BlackMisc::Network::CUrlList getVatsimMetarUrls() const;
|
|
|
|
//! Consolidated version of data file URLs, either from CGlobalSetup or CVatsimSetup
|
|
//! \threadsafe
|
|
BlackMisc::Network::CUrlList getVatsimDataFileUrls() const;
|
|
|
|
//! Start services, if not yet parsed call CApplication::parse
|
|
virtual bool start();
|
|
|
|
// ------------------------- network -----------------------------------------------
|
|
|
|
static constexpr int NoRedirects = -1; //!< network request not allowing redirects
|
|
static constexpr int NoLogRequestId = -1; //!< network request without logging
|
|
static constexpr int DefaultMaxRedirects = 2; //!< network request, default for max.redirects
|
|
|
|
//! The network reply callback when request is completed
|
|
using CallbackSlot = BlackMisc::CSlot<void(QNetworkReply *)>;
|
|
|
|
//! Delete all cookies from cookie manager
|
|
void deleteAllCookies();
|
|
|
|
//! Get the watchdog
|
|
//! \private mostly for UNIT tests etc, normally not meant to be used directly
|
|
Db::CNetworkWatchdog *getNetworkWatchdog() const;
|
|
|
|
//! Allows to mark the DB as "up" or "down"
|
|
//! \see BlackCore::Db::CNetworkWatchdog::setDbAccessibility
|
|
void setSwiftDbAccessibility(bool accessible);
|
|
|
|
//! \copydoc BlackCore::Db::CNetworkWatchdog::triggerCheck
|
|
int triggerNetworkWatchdogChecks();
|
|
|
|
//! Is network accessible
|
|
bool isNetworkAccessible() const;
|
|
|
|
//! \copydoc BlackCore::Db::CNetworkWatchdog::isInternetAccessible
|
|
bool isInternetAccessible() const;
|
|
|
|
//! \copydoc BlackCore::Db::CNetworkWatchdog::isSwiftDbAccessible
|
|
bool isSwiftDbAccessible() const;
|
|
|
|
//! \copydoc BlackCore::Db::CNetworkWatchdog::hasWorkingSharedUrl
|
|
bool hasWorkingSharedUrl() const;
|
|
|
|
//! \copydoc BlackCore::Db::CNetworkWatchdog::getWorkingSharedUrl
|
|
BlackMisc::Network::CUrl getWorkingSharedUrl() const;
|
|
|
|
//! Access to access manager
|
|
//! \remark supposed to be used only in special cases
|
|
const QNetworkAccessManager *getNetworkAccessManager() const { return m_accessManager; }
|
|
|
|
//! Access to configuration manager
|
|
//! \remark supposed to be used only in special cases
|
|
const QNetworkConfigurationManager *getNetworkConfigurationManager() const { return m_networkConfigManager; }
|
|
|
|
//! Web data services available?
|
|
//! \threadsafe
|
|
bool hasWebDataServices() const;
|
|
|
|
//! Get the web data services
|
|
//! \remark use hasWebDataServices to test if services are available
|
|
CWebDataServices *getWebDataServices() const;
|
|
|
|
//! Request to get network reply
|
|
//! \threadsafe
|
|
QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url,
|
|
const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects);
|
|
|
|
//! Request to get network reply, supporting BlackMisc::Network::CUrlLog
|
|
//! \threadsafe
|
|
QNetworkReply *getFromNetwork(const BlackMisc::Network::CUrl &url, int logId,
|
|
const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects);
|
|
|
|
//! Request to get network reply
|
|
//! \threadsafe
|
|
QNetworkReply *getFromNetwork(const QNetworkRequest &request,
|
|
const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects);
|
|
|
|
//! Request to get network reply, supporting BlackMisc::Network::CUrlLog
|
|
//! \threadsafe
|
|
QNetworkReply *getFromNetwork(const QNetworkRequest &request, int logId,
|
|
const CallbackSlot &callback, int maxRedirects = DefaultMaxRedirects);
|
|
|
|
//! Post to network
|
|
//! \threadsafe
|
|
QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, const CallbackSlot &callback);
|
|
|
|
//! Post to network
|
|
//! \note This method takes ownership over \c multiPart.
|
|
//! \threadsafe
|
|
QNetworkReply *postToNetwork(const QNetworkRequest &request, int logId, QHttpMultiPart *multiPart, const CallbackSlot &callback);
|
|
|
|
//! Request to get network repy using HTTP's HEADER method
|
|
//! \threadsafe
|
|
QNetworkReply *headerFromNetwork(const BlackMisc::Network::CUrl &url, const CallbackSlot &callback, int maxRedirects = NoRedirects);
|
|
|
|
//! Request to get network repy using HTTP's HEADER method
|
|
//! \threadsafe
|
|
QNetworkReply *headerFromNetwork(const QNetworkRequest &request, const CallbackSlot &callback, int maxRedirects = NoRedirects);
|
|
|
|
//! Download file from network and store it as passed
|
|
//! \threadsafe
|
|
QNetworkReply *downloadFromNetwork(const BlackMisc::Network::CUrl &url, const QString &saveAsFileName,
|
|
const BlackMisc::CSlot<void(const BlackMisc::CStatusMessage &)> &callback, int maxRedirects = DefaultMaxRedirects);
|
|
|
|
signals:
|
|
//! Setup available (cache, web load, ..) or failed to load setup
|
|
void setupHandlingCompleted(bool success);
|
|
|
|
//! Update info available (cache, web load)
|
|
void updateInfoAvailable(bool success);
|
|
|
|
//! Startup has been completed
|
|
//! \remark needs to be triggered by application when it think it is done
|
|
//! \fixme http://doc.qt.io/qt-5/signalsandslots.html#signals recommends signals be only emitted by their own class
|
|
void startUpCompleted(bool success);
|
|
|
|
//! Facade started
|
|
void coreFacadeStarted();
|
|
|
|
//! Web data services started
|
|
void webDataServicesStarted(bool success);
|
|
|
|
//! Internet accessibility changed
|
|
void changedInternetAccessibility(bool accessible);
|
|
|
|
//! DB accessibility changed
|
|
void changedSwiftDbAccessibility(bool accessible, const BlackMisc::Network::CUrl &testedUrl);
|
|
|
|
//! About to shutdown
|
|
void aboutToShutdown();
|
|
|
|
protected:
|
|
//! Setup read/synchronized
|
|
void onSetupHandlingCompleted(bool available);
|
|
|
|
//! Wait for setup data by calling the event loop and waiting until everything is ready
|
|
//! \remark requires parsing upfront
|
|
BlackMisc::CStatusMessageList waitForSetup(int timeoutMs = BlackMisc::Network::CNetworkUtils::getLongTimeoutMs());
|
|
|
|
//! Startup completed
|
|
virtual void onStartUpCompleted();
|
|
|
|
//! Init class, allows to init from BlackGui::CGuiApplication as well (pseudo virtual)
|
|
void init(bool withMetadata);
|
|
|
|
//! Display help message
|
|
virtual void cmdLineHelpMessage();
|
|
|
|
//! Display version message
|
|
virtual void cmdLineVersionMessage() const;
|
|
|
|
//! Is the command line option represented in the given arguments?
|
|
static int indexOfCommandLineOption(const QCommandLineOption &option, const QStringList &args = CApplication::arguments());
|
|
|
|
//! Arguments without that given option
|
|
static void argumentsWithoutOption(const QCommandLineOption &option, QStringList &args);
|
|
|
|
//! Can be used to parse specialized arguments
|
|
virtual bool parsingHookIn() { return true; }
|
|
|
|
//! Called when facade/contexts have been started
|
|
virtual void onCoreFacadeStarted();
|
|
|
|
//! Can be used to start special services
|
|
virtual BlackMisc::CStatusMessageList startHookIn() { return BlackMisc::CStatusMessageList(); }
|
|
|
|
//! Flag set or explicitly set to true
|
|
bool isSet(const QCommandLineOption &option) const;
|
|
|
|
//! Severe issue during startup, most likely it does not make sense to continue
|
|
//! \note call this here if the parsing stage is over and reaction to a runtime issue is needed
|
|
[[ noreturn ]] void severeStartupProblem(const BlackMisc::CStatusMessage &message);
|
|
|
|
//! Start the core facade
|
|
//! \note does nothing when setup is not yet loaded
|
|
BlackMisc::CStatusMessageList startCoreFacadeAndWebDataServices();
|
|
|
|
//! Start the web data services
|
|
//! \note does nothing when setup is not yet loaded
|
|
BlackMisc::CStatusMessageList startWebDataServices();
|
|
|
|
//! executable name
|
|
static const QString &executable();
|
|
|
|
//! Register metadata
|
|
static void registerMetadata();
|
|
|
|
// cmd parsing
|
|
QList<QCommandLineOption> m_allOptions; //!< all registered options
|
|
QCommandLineParser m_parser; //!< cmd parser
|
|
QCommandLineOption m_cmdHelp {"help"}; //!< help option
|
|
QCommandLineOption m_cmdVersion {"version"}; //!< version option
|
|
QCommandLineOption m_cmdDBusAddress {"emptyDBus"}; //!< DBus address
|
|
QCommandLineOption m_cmdDevelopment {"dev"}; //!< Development flag
|
|
QCommandLineOption m_cmdSharedDir {"shared"}; //!< Shared directory
|
|
QCommandLineOption m_cmdClearCache {"clearcache"}; //!< Clear cache
|
|
QCommandLineOption m_cmdTestCrashpad {"testcrashpad"}; //!< Test a crasphpad upload
|
|
bool m_parsed = false; //!< Parsing accomplished?
|
|
bool m_started = false; //!< started with success?
|
|
bool m_singleApplication = true; //!< only one instance of that application
|
|
bool m_alreadyRunning = false; //!< Application already running
|
|
std::atomic_bool m_shutdown { false }; //!< is being shutdown?
|
|
std::atomic_bool m_shutdownInProgress { false }; //!< shutdown in progress?
|
|
|
|
private:
|
|
//! Problem with network access manager
|
|
void onChangedNetworkAccessibility(QNetworkAccessManager::NetworkAccessibility accessible);
|
|
|
|
//! Changed internet accessibility
|
|
void onChangedInternetAccessibility(bool accessible);
|
|
|
|
//! Changed swift DB accessibility
|
|
void onChangedSwiftDbAccessibility(bool accessible, const BlackMisc::Network::CUrl &url);
|
|
|
|
//! Network configurations update completed
|
|
void onNetworkConfigurationsUpdateCompleted();
|
|
|
|
//! Init network
|
|
void initNetwork();
|
|
|
|
//! init logging system
|
|
void initLogging();
|
|
|
|
//! Init parser
|
|
void initParser();
|
|
|
|
//! Dev.environment, return value will be used for m_devEnv
|
|
bool initIsRunningInDeveloperEnvironment() const;
|
|
|
|
//! Init the local settings
|
|
BlackMisc::CStatusMessage initLocalSettings();
|
|
|
|
//! Async. start when setup is loaded
|
|
BlackMisc::CStatusMessageList asyncWebAndContextStart();
|
|
|
|
using NetworkRequestOrPostFunction = std::function<QNetworkReply *(QNetworkAccessManager &, const QNetworkRequest &)>;
|
|
|
|
//! Implementation for getFromNetwork(), postToNetwork() and headerFromNetwork()
|
|
//! \return QNetworkReply reply will only be returned, if the QNetworkAccessManager is in the same thread
|
|
QNetworkReply *httpRequestImpl(const QNetworkRequest &request,
|
|
int logId, const CallbackSlot &callback,
|
|
int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod);
|
|
|
|
//! Call httpRequestImpl in correct thread
|
|
void httpRequestImplInQAMThread(const QNetworkRequest &request,
|
|
int logId, const CallbackSlot &callback,
|
|
int maxRedirects, NetworkRequestOrPostFunction requestOrPostMethod);
|
|
|
|
//! Triggers a check of the network accessibility
|
|
//! \remark this is a check that will double check that the watchdog will receive the correct QNetworkAccessManager::NetworkAccessibility
|
|
void triggerNetworkAccessibilityCheck(int deferredMs);
|
|
|
|
//! Write meta information into the application directory so other swift versions can display them
|
|
void tagApplicationDataDirectory();
|
|
|
|
CInputManager *m_inputManager = nullptr; //!< Input devices and hotkeys
|
|
QNetworkConfigurationManager *m_networkConfigManager = nullptr; //!< configuration
|
|
QNetworkAccessManager *m_accessManager = nullptr; //!< single network access manager
|
|
Db::CNetworkWatchdog *m_networkWatchDog = nullptr; //!< checking DB/internet access
|
|
BlackMisc::CApplicationInfo m_applicationInfo; //!< Application if specified
|
|
QScopedPointer<CCoreFacade> m_coreFacade; //!< core facade if any
|
|
QScopedPointer<CSetupReader> m_setupReader; //!< setup reader
|
|
QScopedPointer<CWebDataServices> m_webDataServices; //!< web data services
|
|
QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger
|
|
QPointer<CCookieManager> m_cookieManager; //!< single cookie manager for our access manager
|
|
const QString m_applicationName; //!< application name
|
|
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
|
|
Db::CDatabaseReaderConfigList m_dbReaderConfig; //!< Load or used caching?
|
|
bool m_noNwAccessPoint = false; //!< no network access point?
|
|
bool m_useContexts = false; //!< use contexts
|
|
bool m_useWebData = false; //!< use web data
|
|
bool m_signalStartup = true; //!< signal startup automatically
|
|
bool m_devFlag = false; //!< dev. environment
|
|
bool m_saveSettingsOnShutdown = true; //!< saving all settings on shutdown
|
|
bool m_localSettingsLoaded = false; //!< local settings loaded?
|
|
|
|
// -------------- crashpad -----------------
|
|
//! Init the crash handler
|
|
BlackMisc::CStatusMessageList initCrashHandler();
|
|
|
|
//! Upload settings changed
|
|
void onCrashDumpUploadEnabledChanged();
|
|
|
|
//! Extra annotation for crash to easier identify annotation
|
|
void setCrashInfo(const BlackMisc::CCrashInfo &info);
|
|
|
|
#ifdef BLACK_USE_CRASHPAD
|
|
std::unique_ptr<crashpad::CrashpadClient> m_crashpadClient;
|
|
std::unique_ptr<crashpad::CrashReportDatabase> m_crashReportDatabase;
|
|
BlackMisc::CSettingReadOnly<Application::TCrashDumpSettings> m_crashDumpSettings { this, &CApplication::onCrashDumpUploadEnabledChanged };
|
|
#endif
|
|
BlackMisc::CCrashInfo m_crashInfo; //!< info representing details
|
|
|
|
};
|
|
} // namespace
|
|
|
|
//! Single instance of application object
|
|
extern BLACKCORE_EXPORT BlackCore::CApplication *sApp;
|
|
|
|
#endif // guard
|