9 #include <QCoreApplication>
13 #include <QHttpMultiPart>
14 #include <QNetworkReply>
15 #include <QNetworkRequest>
17 #include <QRegularExpression>
19 #include <QStandardPaths>
20 #include <QStringBuilder>
21 #include <QStringList>
23 #include <QTemporaryDir>
26 #include <QWriteLocker>
58 using namespace swift::config;
60 using namespace swift::misc::db;
61 using namespace swift::misc::network;
62 using namespace swift::misc::aviation;
63 using namespace swift::misc::simulation;
64 using namespace swift::misc::weather;
66 using namespace swift::core::context;
67 using namespace swift::core::vatsim;
74 static const QString &swiftDataRoot()
91 Q_ASSERT_X(!
sApp, Q_FUNC_INFO,
"already initialized");
126 this->tagApplicationDataDirectory();
161 CLogMessage(cat).
debug(u
"Worker named '%1' still exists after application destroyed")
162 << worker->objectName();
188 if (!apps.
contains(myself)) {
return true; }
201 Q_ASSERT_X(
instance(), Q_FUNC_INFO,
"missing application");
250 static const QString s(m_applicationName % u
" " % CBuildConfig::getVersionString());
271 if (!m_gitHubPackagesReader) {
return CUpdateInfo(); }
272 return m_gitHubPackagesReader->getUpdateInfo();
278 if (!m_gitHubPackagesReader) {
return; }
279 m_gitHubPackagesReader->readUpdateInfo();
284 if (CBuildConfig::isLocalDeveloperDebugBuild()) {
return CDistribution::localDeveloperBuild(); }
293 Q_ASSERT_X(
m_parsed, Q_FUNC_INFO,
"Call this function after parsing");
311 this->simulateCrash();
315 Q_ASSERT_X(m_setupReader && m_setupReader->isSetupAvailable(), Q_FUNC_INFO,
"Setup not available");
322 msgs.
push_back(this->initLocalSettings());
341 if (
m_shutdown || !m_setupReader) {
return false; }
342 return m_setupReader->isSetupAvailable();
347 return (this->
getGlobalSetup().isSwiftVersionMinimumMappingVersion());
353 return !m_webDataServices.isNull();
361 Q_ASSERT_X(m_webDataServices, Q_FUNC_INFO,
362 "Missing web data services, use hasWebDataServices to test if existing");
363 return m_webDataServices.data();
370 static const QString s(CBuildConfig::getVersionStringPlatform() % u
" [dev,DEVDBG]");
375 static const QString s(CBuildConfig::getVersionStringPlatform() % u
" [dev]");
378 if (CBuildConfig::isLocalDeveloperDebugBuild())
380 static const QString s(CBuildConfig::getVersionStringPlatform() % u
" [DEVDBG]");
383 return CBuildConfig::getVersionStringPlatform();
398 bool CApplication::initIsRunningInDeveloperEnvironment()
const
405 if (CBuildConfig::isLocalDeveloperDebugBuild()) {
return true; }
416 m_localSettingsLoaded =
true;
459 QString str = CBuildConfig::getVersionString() % u
" " %
460 (CBuildConfig::isReleaseBuild() ? u
"Release build" : u
"Debug build") % separator %
461 u
"Local dev.dbg.: " % boolToYesNo(CBuildConfig::isLocalDeveloperDebugBuild()) % separator %
462 u
"dev.env.: " % boolToYesNo(this->
isDeveloperFlagSet()) % separator % u
"distribution: " %
464 boolToYesNo(CBuildConfig::isRunningOnWindowsNtPlatform()) % separator % u
"Linux: " %
465 boolToYesNo(CBuildConfig::isRunningOnLinuxPlatform()) %
" Unix: " %
466 boolToYesNo(CBuildConfig::isRunningOnUnixPlatform()) % separator % u
"MacOS: " %
467 boolToYesNo(CBuildConfig::isRunningOnMacOSPlatform()) % separator %
"Build Abi: " %
469 CBuildConfig::compiledWithInfo();
471 if (this->
supportsContexts()) { str += (separator % u
"Supporting contexts"); }
480 return this->
getFromNetwork(url, callback, progress, maxRedirects);
499 return this->
getFromNetwork(request, callback, progress, maxRedirects);
513 return this->httpRequestImpl(request, logId, callback, progress, maxRedirects,
524 return this->httpRequestImpl(request, logId, callback, progress, maxRedirects,
534 return this->httpRequestImpl(request, logId, callback,
NoRedirects,
547 return httpRequestImpl(request, logId, callback,
NoRedirects,
550 if (!myself) {
return nr; }
551 if (!multiPart) {
return nr; }
552 nr = qam.
post(request, multiPart);
566 return httpRequestImpl(
576 if (url.
isEmpty()) {
return nullptr; }
577 if (saveAsFileName.
isEmpty()) {
return nullptr; }
579 if (!fi.
dir().
exists()) {
return nullptr; }
588 << url.
getFullUrl() << nwReply->errorString();
596 u
"Saving file '%1' downloaded from '%2' failed")
601 if (!sApp || sApp->isShuttingDown()) { return; }
606 ProgressSlot progressSlot(
this, [=](
int, qint64, qint64,
const QUrl &) {
610 QNetworkReply *reply = this->getFromNetwork(url, callbackSlot, progressSlot, maxRedirects);
614 void CApplication::deleteAllCookies() { m_cookieManager->deleteAllCookies(); }
616 void CApplication::exit(
int retcode)
618 if (
sApp) { instance()->gracefulShutdown(); }
631 for (
const QString &arg : args)
646 const int index = indexOfCommandLineOption(option, args);
647 if (index < 0) {
return; }
654 void CApplication::processEventsFor(
int milliseconds)
666 Q_ASSERT_X(m_parsed, Q_FUNC_INFO,
"Call this function after parsing");
668 m_coreFacadeConfig = coreConfig;
674 if (!m_webDataServices)
677 CWebReaderFlags::AllReaders, CDatabaseReaderConfigList::forPilotClient());
680 return this->startCoreFacade();
685 Q_ASSERT_X(m_parsed, Q_FUNC_INFO,
"Call this function after parsing");
691 return this->startCoreFacade();
697 Q_ASSERT_X(m_webDataServices.isNull(), Q_FUNC_INFO,
"Services already started");
701 return this->startWebDataServices(webReader, dbReaderConfig);
704 bool CApplication::isLocalContext()
const
706 return this->getIContextApplication() && this->getIContextApplication()->isUsingImplementingObject();
709 bool CApplication::isDBusContext()
const
711 return this->getIContextApplication() && !this->getIContextApplication()->isUsingImplementingObject() &&
712 !this->getIContextApplication()->isEmptyObject();
717 Q_ASSERT_X(m_parsed, Q_FUNC_INFO,
"Call this function after parsing");
719 if (!m_setupReader || !m_setupReader->isSetupAvailable())
724 Q_ASSERT_X(m_coreFacade.isNull(), Q_FUNC_INFO,
"Cannot alter facade");
725 Q_ASSERT_X(m_setupReader, Q_FUNC_INFO,
"No facade without setup possible");
726 Q_ASSERT_X(m_webDataServices, Q_FUNC_INFO,
"Need running web data services");
729 m_coreFacade.reset(
new CCoreFacade(m_coreFacadeConfig));
730 emit this->coreFacadeStarted();
737 Q_ASSERT_X(m_parsed, Q_FUNC_INFO,
"Call this function after parsing");
739 if (!m_setupReader || !m_setupReader->isSetupAvailable())
744 Q_ASSERT_X(m_setupReader, Q_FUNC_INFO,
"No web data services without setup possible");
746 if (!m_webDataServices)
749 m_webDataServices.reset(
new CWebDataServices(webReader, dbReaderConfig,
this));
750 Q_ASSERT_X(m_webDataServices, Q_FUNC_INFO,
"Missing web services");
752 emit this->webDataServicesStarted(
true);
759 void CApplication::initLogging()
761 CLogHandler::instance()->install();
765 connect(CLogHandler::instance(), &CLogHandler::localMessageLogged, m_fileLogger.data(),
766 &CFileLogger::writeStatusMessageToFile);
767 connect(CLogHandler::instance(), &CLogHandler::remoteMessageLogged, m_fileLogger.data(),
768 &CFileLogger::writeStatusMessageToFile);
769 m_fileLogger->changeLogPattern(
CLogPattern().withSeverityAtOrAbove(CStatusMessage::SeverityDebug));
772 void CApplication::initParser()
775 m_parser.setApplicationDescription(m_applicationName);
776 m_cmdHelp = m_parser.addHelpOption();
777 m_cmdVersion = m_parser.addVersionOption();
778 m_allOptions.append(m_cmdHelp);
779 m_allOptions.append(m_cmdVersion);
784 this->addParserOption(m_cmdDevelopment);
789 this->addParserOption(m_cmdSkipSingleApp);
794 this->addParserOption(m_cmdClearCache);
799 this->addParserOption(m_cmdTestCrashpad);
802 bool CApplication::isSet(
const QCommandLineOption &option)
const {
return (m_parser.isSet(option)); }
804 void CApplication::registerMetadata()
812 const QStringList files(CDataCache::instance()->enumerateStore());
813 CDataCache::instance()->clearAllValues();
817 void CApplication::gracefulShutdown()
819 if (m_shutdown) {
return; }
820 if (m_shutdownInProgress) {
return; }
821 m_shutdownInProgress =
true;
826 emit this->aboutToShutdown();
832 CLogMessage(
this).
info(u
"Graceful shutdown of CApplication, released devices");
833 m_inputManager->releaseDevices();
837 if (m_parsed && m_saveSettingsOnShutdown)
839 const CStatusMessage m = this->supportsContexts() ? this->getIContextApplication()->saveSettings() :
840 CSettingsCache::instance()->saveToStore();
847 if (this->supportsContexts(
true))
849 CLogMessage(
this).
info(u
"Graceful shutdown of CApplication, shutdown of contexts");
852 m_coreFacade->gracefulShutdown();
853 m_coreFacade.reset();
856 if (m_webDataServices)
858 CLogMessage(
this).
info(u
"Graceful shutdown of CApplication, shutdown of web services");
860 m_webDataServices->gracefulShutdown();
861 m_webDataServices.reset();
864 if (m_gitHubPackagesReader) { m_gitHubPackagesReader.reset(); }
866 if (m_setupReader) { m_setupReader.reset(); }
868 CLogMessage(
this).
info(u
"Graceful shutdown of CApplication, shutdown of logger");
869 m_fileLogger->close();
882 void CApplication::onStartUpCompleted()
887 void CApplication::initNetwork()
892 m_cookieManager->setParent(m_accessManager);
893 m_accessManager->setCookieJar(m_cookieManager);
896 Q_ASSERT_X(m_accessManager, Q_FUNC_INFO,
"Need QAM");
909 static const QStringList l({
"swift.application",
"swift." % executable() });
919 m_allOptions.
append(option);
920 return m_parser.addOption(option);
925 m_allOptions.append(options);
926 return m_parser.addOptions(options);
929 void CApplication::addDBusAddressOption()
932 {
"dbus",
"dbusaddress" },
935 this->addParserOption(m_cmdDBusAddress);
938 void CApplication::addNetworkOptions() { this->addParserOptions(IContextNetwork::getCmdLineOptions()); }
940 void CApplication::addAudioOptions() { this->addParserOptions(CContextAudioBase::getCmdLineOptions()); }
942 QString CApplication::getCmdDBusAddressValue()
const
944 if (!this->isParserOptionSet(m_cmdDBusAddress)) {
return {}; }
945 const QString v(this->getParserValue(m_cmdDBusAddress));
946 const QString dBusAddress(CDBusServer::normalizeAddress(v));
950 bool CApplication::isParserOptionSet(
const QString &option)
const {
return m_parser.isSet(option); }
952 bool CApplication::skipSingleApplicationCheck()
const {
return this->isParserOptionSet(m_cmdSkipSingleApp); }
954 bool CApplication::isParserOptionSet(
const QCommandLineOption &option)
const {
return m_parser.isSet(option); }
960 return m_parser.value(option).
trimmed();
963 bool CApplication::parseCommandLineArgsAndLoadSetup()
965 if (!this->startupCheck())
return false;
966 if (!this->parseCommandLineArguments())
return false;
967 if (!this->loadSetupAndHandleErrors())
return false;
971 bool CApplication::parseCommandLineArguments()
973 if (m_parsed) {
return m_parsed; }
977 if (!m_parser.parse(args))
979 this->cmdLineErrorMessage(
"Parser error:", m_parser.errorText());
983 if (m_alreadyRunning && !this->skipSingleApplicationCheck())
985 this->cmdLineErrorMessage(
"Program must only run once",
986 "You cannot run two or more instances side-by-side.");
991 if (m_parser.isSet(m_cmdHelp))
994 this->cmdLineHelpMessage();
997 if (m_parser.isSet(m_cmdVersion))
1000 this->cmdLineVersionMessage();
1005 m_devFlag = this->initIsRunningInDeveloperEnvironment();
1008 if (!this->parsingHookIn()) {
return false; }
1015 bool CApplication::startupCheck()
const
1017 const QStringList verifyErrors = CSwiftDirectories::verifyRuntimeDirectoriesAndFiles();
1018 if (!verifyErrors.
isEmpty() && !m_applicationInfo.isUnitTest())
1020 cmdLineErrorMessage(
"Missing runtime directories/files:", verifyErrors.
join(
", "));
1026 bool CApplication::loadSetupAndHandleErrors()
1030 if (msgs.
isFailure()) { displaySetupLoadFailure(msgs); }
1040 void CApplication::cmdLineErrorMessage(
const QString &text,
const QString &informativeText)
const
1042 fputs(qPrintable(text + informativeText), stderr);
1047 if (msgs.
isEmpty()) {
return; }
1049 CApplication::cmdLineErrorMessage(msgs.
toQString(
true),
"");
1054 if (!this->hasSimulator()) {
return nullptr; }
1055 return this->getCoreFacade()->getCContextSimulator()->simulator();
1058 bool CApplication::hasSimulator()
const
1060 if (!this->getCoreFacade()) {
return false; }
1061 if (!this->getCoreFacade()->getIContextSimulator()->isUsingImplementingObject()) {
return false; }
1062 return (this->getCoreFacade()->getCContextSimulator());
1065 void CApplication::cmdLineHelpMessage()
1067 m_parser.showHelp();
1071 void CApplication::cmdLineVersionMessage()
1073 m_parser.showVersion();
1079 QStringList joinedArguments = CApplication::arguments();
1096 toBeRemoved.
append(
"--installer");
1105 const int n = indexOfCommandLineOption(option, toBeRemoved);
1106 if (n >= 0) { argumentsWithoutOption(option, joinedArguments); }
1110 joinedArguments.
append(newArgumentsChecked);
1111 return joinedArguments;
1120 bool CApplication::supportsContexts(
bool ignoreShutdownTest)
const
1122 if (!ignoreShutdownTest && m_shutdown) {
return false; }
1123 if (m_coreFacade.isNull()) {
return false; }
1124 if (!m_coreFacade->getIContextApplication()) {
return false; }
1125 return (!m_coreFacade->getIContextApplication()->isEmptyObject());
1130 if (!supportsContexts()) {
return nullptr; }
1136 if (!supportsContexts()) {
return nullptr; }
1142 if (!supportsContexts()) {
return nullptr; }
1143 return m_coreFacade->getCContextAudioBase();
1148 if (!supportsContexts()) {
return nullptr; }
1154 if (!supportsContexts()) {
return nullptr; }
1160 if (!supportsContexts()) {
return nullptr; }
1166 if (!supportsContexts()) {
return nullptr; }
1172 if (!supportsContexts()) {
return nullptr; }
1178 if (!supportsContexts()) {
return nullptr; }
1179 return m_coreFacade->getCContextAudioBase();
1184 if (!supportsContexts()) {
return nullptr; }
1190 if (!supportsContexts()) {
return nullptr; }
1196 if (!supportsContexts()) {
return nullptr; }
1200 void CApplication::onCoreFacadeStarted()
1209 bool CApplication::hasSetupReader()
const {
return !m_setupReader.isNull(); }
1211 CSetupReader *CApplication::getSetupReader()
const {
return m_setupReader.data(); }
1216 if (!m_setupReader) {
return CStatusMessage(
this).
error(u
"No reader for setup/version"); }
1217 Q_ASSERT_X(m_parsed, Q_FUNC_INFO,
"Not yet parsed");
1222 CUrl CApplication::getVatsimMetarUrl()
const
1224 if (m_shutdown) {
return {}; }
1225 if (m_webDataServices)
1227 const CUrl url(m_webDataServices->getVatsimMetarUrl());
1228 if (!url.
isEmpty()) {
return url; }
1230 if (m_setupReader) {
return m_setupReader->getSetup().getVatsimMetarsUrl(); }
1234 CUrl CApplication::getVatsimDataFileUrl()
const
1236 if (m_shutdown) {
return {}; }
1237 if (m_webDataServices)
1239 const CUrl url(m_webDataServices->getVatsimDataFileUrl());
1240 if (!url.
isEmpty()) {
return url; }
1242 if (m_setupReader) {
return m_setupReader->getSetup().getVatsimDataFileUrl(); }
1246 CUrl CApplication::getVatsimServerFileUrl()
const
1248 if (m_shutdown || !m_setupReader) {
return {}; }
1250 return m_setupReader->getSetup().getVatsimServerFileUrl();
1253 CUrl CApplication::getVatsimFsdHttpUrl()
const
1255 if (m_shutdown || !m_setupReader) {
return {}; }
1257 return m_setupReader->getSetup().getVatsimFsdHttpUrl();
1260 void CApplication::onCrashDumpUploadEnabledChanged()
1262 const bool enabled = CBuildConfig::isReleaseBuild() && m_crashDumpUploadEnabled.getThreadLocal();
1263 this->enableCrashDumpUpload(enabled);
1266 void CApplication::simulateCrash() { CCrashHandler::instance()->simulateCrash(); }
1268 void CApplication::simulateAssert() { CCrashHandler::instance()->simulateAssert(); }
1270 void CApplication::enableCrashDumpUpload(
bool enable) { CCrashHandler::instance()->setUploadsEnabled(enable); }
1272 bool CApplication::isSupportingCrashpad()
const
1274 #ifdef SWIFT_USE_CRASHPAD
1281 void CApplication::httpRequestImplInQAMThread(
const QNetworkRequest &request,
int logId,
1282 const CallbackSlot &callback,
const ProgressSlot &progress,
1283 int maxRedirects, NetworkRequestOrPostFunction getPostOrDeleteRequest)
1286 if (this->isShuttingDown()) {
return; }
1290 Q_ASSERT_X(CThreadUtils::isInThisThread(
sApp->m_accessManager), Q_FUNC_INFO,
1291 "Wrong thread, must be QAM thread");
1292 this->httpRequestImpl(request, logId, callback, progress, maxRedirects, getPostOrDeleteRequest);
1298 NetworkRequestOrPostFunction requestOrPostMethod)
1300 ProgressSlot progress;
1301 return this->httpRequestImpl(request, logId, callback, progress, maxRedirects, requestOrPostMethod);
1305 const CallbackSlot &callback,
const ProgressSlot &progress,
1306 int maxRedirects, NetworkRequestOrPostFunction getPostOrDeleteRequest)
1308 if (this->isShuttingDown()) {
return nullptr; }
1311 Q_ASSERT_X(m_accessManager->thread() == qApp->thread(), Q_FUNC_INFO,
1312 "Network manager supposed to be in main thread");
1313 if (!CThreadUtils::isInThisThread(m_accessManager))
1315 this->httpRequestImplInQAMThread(request, logId, callback, progress, maxRedirects, getPostOrDeleteRequest);
1319 Q_ASSERT_X(CThreadUtils::isInThisThread(m_accessManager), Q_FUNC_INFO,
"Network manager thread mismatch");
1321 CNetworkUtils::getSwiftNetworkRequest(request, this->getApplicationNameAndVersion());
1323 QNetworkReply *reply = getPostOrDeleteRequest(*m_accessManager, copiedRequest);
1327 QString urlStr = url.toString();
1332 [=](qint64 current, qint64 max) { progress(logId, current, max, url); });
1337 Q_ASSERT_X(callback.object(), Q_FUNC_INFO,
"Need callback object (to determine thread)");
1346 const bool isRedirect = CNetworkUtils::isHttpStatusRedirect(reply);
1347 if (isRedirect && maxRedirects > 0)
1349 const QUrl redirectUrl = CNetworkUtils::getHttpRedirectUrl(reply);
1350 if (!redirectUrl.isEmpty())
1352 QNetworkRequest redirectRequest(redirectUrl);
1353 const int redirectsLeft = maxRedirects - 1;
1354 CLogMessage(sApp).info(u
"Redirecting '%1' to '%2'") << urlStr << redirectUrl.toString();
1355 this->httpRequestImplInQAMThread(redirectRequest, logId, callback, progress, redirectsLeft,
1356 getPostOrDeleteRequest);
1368 void CApplication::tagApplicationDataDirectory()
1372 if (!dir.exists() || !dir.isReadable()) {
return; }
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
QStringList argumentsJoined(const QStringList &newArguments={}, const QStringList &removeArguments={}) const
Current parameters replaced by new arguments without the cmd line argument.
const QString & versionStringDetailed() const
String with beta, dev. and version.
~CApplication()
Destructor.
QNetworkReply * getFromNetwork(const swift::misc::network::CUrl &url, const CallbackSlot &callback, int maxRedirects=DefaultMaxRedirects)
Request to get network reply.
QNetworkReply * downloadFromNetwork(const swift::misc::network::CUrl &url, const QString &saveAsFileName, const swift::misc::CSlot< void(const swift::misc::CStatusMessage &)> &callback, int maxRedirects=DefaultMaxRedirects)
Download file from network and store it as passed.
std::atomic_bool m_shutdown
Is being shutdown?
void restartApplication(const QStringList &newArguments={}, const QStringList &removeArguments={})
Stop and restart application.
bool m_parsed
Parsing accomplished?
data::CGlobalSetup getGlobalSetup() const
Global setup.
static constexpr int NoLogRequestId
network request without logging
bool isDeveloperFlagSet() const
Running with dev.flag?
swift::misc::db::CDistribution getOwnDistribution() const
Own distribution.
bool m_alreadyRunning
Application already running.
const char * swiftVersionChar()
swift info string
std::atomic_bool m_incognito
Incognito mode?
QCommandLineOption m_cmdClearCache
Clear cache.
const context::IContextApplication * getIContextApplication() const
Direct access to contexts if a CCoreFacade has been initialized.
virtual void onStartUpCompleted()
Startup completed.
static bool unregisterAsRunning()
Unregister from running.
bool isIncognito() const
Is incognito mode?
static void processEventsFor(int milliseconds)
Process all events for some time.
bool hasUnsavedSettings() const
Unsaved settings.
QNetworkReply * postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, const CallbackSlot &callback)
Post to network.
virtual void onCoreFacadeStarted()
Called when facade/contexts have been started.
const QString & swiftVersionString() const
swift info string
void coreFacadeStarted()
Facade started.
void setIncognito(bool incognito)
Set incognito mode.
static QString getTemporaryDirectory()
Directory for temporary files.
bool hasWebDataServices() const
Web data services available?
virtual void cmdLineErrorMessage(const QString &text, const QString &informativeText) const
Display error message.
void init(bool withMetadata)
Init class, allows to init from swift::gui::CGuiApplication as well (pseudo virtual)
void updateInfoAvailable(bool success)
Update info available (cache, web load)
swift::misc::CStatusMessage saveSettingsByKey(const QStringList &keys)
Save all settings.
CApplication(swift::misc::CApplicationInfo::Application application, bool init=true)
Constructor.
static void exit(int retcode=EXIT_SUCCESS)
Exit application, perform graceful shutdown and exit.
QString getInfoString(const QString &separator) const
Comprehensive info.
bool isShuttingDown() const
Is application shutting down?
QNetworkReply * deleteResourceFromNetwork(const QNetworkRequest &request, int logId, const CallbackSlot &callback, int maxRedirects=DefaultMaxRedirects)
Request to delete a network resource from network, supporting swift::misc::network::CUrlLog.
static constexpr int NoRedirects
network request not allowing redirects
QCommandLineOption m_cmdDevelopment
Development flag.
bool isSet(const QCommandLineOption &option) const
Flag set or explicitly set to true.
std::atomic_bool m_shutdownInProgress
shutdown in progress?
static swift::misc::CApplicationInfoList getRunningApplications()
Information about all running apps (including this one only if exec() has already been called)
QStringList getUnsavedSettingsKeys() const
All unsaved settings.
const QString & getApplicationNameVersionDetailed() const
Version, name beta and dev info.
void toggleIncognito()
Toggle incognito mode.
virtual swift::misc::CStatusMessageList startHookIn()
Can be used to start special services.
static bool isApplicationRunning(swift::misc::CApplicationInfo::Application application)
Is application running?
bool m_started
Started with success?
swift::misc::db::CUpdateInfo getUpdateInfo() const
Update info.
bool isSetupAvailable() const
Setup already synchronized.
static QStringList clearCaches()
Clear the caches.
virtual bool start()
Start services, if not yet parsed call CApplication::parse.
bool supportsContexts(bool ignoreShutdownTest=false) const
Supports contexts.
void reloadUpdateInfo()
Reload update info.
CWebDataServices * getWebDataServices() const
Get the web data services.
const swift::misc::CApplicationInfo & getApplicationInfo() const
swift application running
int exec()
Finishes initialization and executes the event loop.
const QString & getApplicationNameAndVersion() const
Application name and version.
virtual void gracefulShutdown()
Graceful shutdown.
void saveSettingsOnShutdown(bool saveSettings)
Save settings on shutdown.
QCommandLineOption m_cmdTestCrashpad
Test a crasphpad upload.
static void registerMetadata()
Register metadata.
bool isAlreadyRunning() const
True if this swift application is already running (including different versions)
virtual bool hasMinimumMappingVersion() const
Minimum mapping version check.
void startUpCompleted(bool success)
Startup has been completed Will be triggered shortly before starting the event loop.
QNetworkReply * headerFromNetwork(const swift::misc::network::CUrl &url, const CallbackSlot &callback, int maxRedirects=NoRedirects)
Request to get network repy using HTTP's HEADER method.
static CApplication * instance()
Similar to.
static bool registerAsRunning()
Register as running.
Threadsafe version of QNetworkCookieJar.
Configuration object for the contexts.
ContextMode getMode() const
Mode.
@ Remote
context runs in a different process.
The class providing facades (the contexts) for all DBus relevant operations.
Read available updates from GitHub Packages REST API.
void updateInfoAvailable(bool available)
Updates have been received from GitHub Packages.
Read the central URLs / locations of our data, setup and versions.
data::CGlobalSetup getSetup() const
Current setup (reader URLs, DB location, crash server)
Encapsulates reading data from web sources.
Audio context base class.
Application context interface.
virtual misc::CStatusMessage saveSettingsByKey(const QStringList &keys)=0
Save core settings to disk.
virtual QStringList getUnsavedSettingsKeys() const =0
Get keys of all unsaved settings currently in core settings cache.
const IContextSimulator * getIContextSimulator() const
Context for simulator.
IContextNetwork * getIContextNetwork()
Context for network.
const IContextApplication * getIContextApplication() const
Context for application.
IContextAudio * getIContextAudio()
Context for network.
IContextOwnAircraft * getIContextOwnAircraft()
Context for own aircraft.
Global settings for readers, debug flags, etc.
Value object encapsulating a list of reader configs.
Description of a swift application.
Application getApplication() const
Get application.
static const QString & fileName()
File name of the application info file.
Application
Enumeration of application roles.
const CProcessInfo & getProcessInfo() const
Get process info.
void setApplicationDataDirectory(const QString &appDataDir)
Set application data dir.
List of swift application descriptions.
bool containsApplication(CApplicationInfo::Application application) const
List containing entry for CApplicationInfo::Application ?
QString toJsonString(QJsonDocument::JsonFormat format=QJsonDocument::Indented) const
Convenience function JSON as string.
CStatusMessage convertFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call convertFromJson, catch any CJsonException that is thrown and return it as CStatusMessage.
Class to write log messages to file.
static QString readLockedFileToString(const QString &fileNameAndPath)
Read file into string, with a lock so two applications can't access at the same time.
static bool writeStringToFile(const QString &content, const QString &fileNameAndPath)
Write string to text file.
static bool writeByteArrayToFile(const QByteArray &data, const QString &fileNameAndPath)
Write byte array to file.
static bool writeStringToLockedFile(const QString &content, const QString &fileNameAndPath)
Write string to file, with a lock so two applications can't access at the same time.
static QString appendFilePaths(const QString &path1, const QString &path2)
Append file paths.
Base class with a member CIdentifier to be inherited by a class which has an identity in the environm...
A sequence of log categories.
Class for emitting a log message.
static void preformatted(const CStatusMessage &statusMessage)
Sends a verbatim, preformatted message to the log.
Value class for matching log messages based on their categories.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
bool containsBy(Predicate p) const
Return true if there is an element for which a given predicate returns true.
bool contains(const T &object) const
Return true if there is an element equal to given object. Uses the most efficient implementation avai...
int removeIf(Predicate p)
Remove elements for which a given predicate returns true.
void push_back(const T &value)
Appends an element at the end of the sequence.
int remove(const T &object)
Remove all elements equal to the given object, if it is contained.
bool isEmpty() const
Synonym for empty.
CStatusMessage loadFromStore()
Load settings from disk.
void enableLocalSave()
Connects signal CValueCache::valuesSaveRequested to a private slot that saves the values....
static CSettingsCache * instance()
Return the singleton instance.
CStatusMessage saveToStore(const QString &keyPrefix={})
Save settings to disk.
Callable wrapper for a member function with function signature F.
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityInfo
Status severities.
bool isFailure() const
Operation considered unsuccessful.
Status messages, e.g. from Core -> GUI.
bool isFailure() const
Any message is marked as failure.
bool hasErrorMessages() const
Error messages.
bool isSuccess() const
All messages are marked as success.
static const QString & normalizedApplicationDataDirectory()
swift application data directory for one specific installation (a version)
QStringList getAllUnsavedKeys(const QString &keyPrefix={}) const
Return keys of all values which have been changed but not saved.
Base class for CWorker and CContinuousWorker.
static const QSet< CWorkerBase * > & allWorkers()
All workers currently existing.
Distributions for channel.
Update info, i.e. artifacts and distributions.
CDistribution anticipateOwnDistribution() const
Own distribution.
QString toQString(bool i18n=false) const
Cast as QString.
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
bool isEmpty() const
Empty.
QNetworkRequest toNetworkRequest() const
To request.
QString getFullUrl(bool withQuery=true) const
Qualified name.
A transport mechanism using signals and slots distributed by DBus.
Core data traits (aka cached values) and classes.
Classes interacting with the swift database (aka "datastore").
Backend services of the swift project, like dealing with the network or the simulators.
void registerMetadata()
Register all relevant metadata in swift::core.
Free functions in swift::misc.
SWIFT_MISC_EXPORT void setMockCacheRootDirectory(const QString &path)
Overwrite the default root directory for cache and settings, for testing purposes.
void registerMetadata()
Register all relevant metadata in Misc.
QString applicationName()
Get application name.
const char * constData() const const
QStringList names() const const
QString valueName() const const
QString applicationFilePath()
void setApplicationName(const QString &application)
void setApplicationVersion(const QString &version)
void exit(int returnCode)
QCoreApplication * instance()
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
qint64 currentMSecsSinceEpoch()
bool exists() const const
int exec(QEventLoop::ProcessEventsFlags flags)
void append(QList< T > &&value)
QList< T >::const_reference at(qsizetype i) const const
bool isEmpty() const const
void removeAt(qsizetype i)
qsizetype size() const const
bool startsWith(QList< T >::parameter_type value) const const
QNetworkReply * deleteResource(const QNetworkRequest &request)
QNetworkReply * get(const QNetworkRequest &request)
QNetworkReply * head(const QNetworkRequest &request)
QNetworkReply * post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
QNetworkReply::NetworkError error() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
bool moveToThread(QThread *targetThread)
void setObjectName(QAnyStringView name)
void setParent(QObject *parent)
bool setProperty(const char *name, QVariant &&value)
QThread * thread() const const
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
QString writableLocation(QStandardPaths::StandardLocation type)
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) &&
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString trimmed() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QStringList filter(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
qsizetype removeDuplicates()
QString buildCpuArchitecture()
bool isValid() const const
QString path() const const
QFuture< QtFuture::ArgsType< Signal >> connect(Sender *sender, Signal signal)
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.