diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 6d8e74d57..9f312f3a3 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -149,15 +150,20 @@ namespace BlackCore } } + bool CApplication::registerAsRunning() + { + CApplicationInfoList apps = getRunningApplications(); + const CApplicationInfo myself = instance()->getApplicationInfo(); + if (!apps.contains(myself)) { apps.insert(myself); } + const bool ok = CFileUtils::writeStringToLockedFile(apps.toJsonString(), CFileUtils::appendFilePaths(swiftDataRoot(), "apps.json")); + if (!ok) { CLogMessage(static_cast(nullptr)).error("Failed to write to application list file"); } + return ok; + } + int CApplication::exec() { Q_ASSERT_X(instance(), Q_FUNC_INFO, "missing application"); - - CApplicationInfoList apps = getRunningApplications(); - apps.push_back(instance()->getApplicationInfo()); - bool ok = CFileUtils::writeStringToLockedFile(apps.toJsonString(), swiftDataRoot() + "apps.json"); - if (!ok) { CLogMessage(static_cast(nullptr)).error("Failed to write to application list file"); } - + CApplication::registerAsRunning(); return QCoreApplication::exec(); } @@ -182,6 +188,12 @@ namespace BlackCore return apps; } + bool CApplication::isApplicationRunning(CApplicationInfo::Application application) + { + const CApplicationInfoList running = CApplication::getRunningApplications(); + return running.containsApplication(application); + } + bool CApplication::isAlreadyRunning() const { return getRunningApplications().containsBy([this](const CApplicationInfo & info) { return info.application() == getSwiftApplication(); }); @@ -214,6 +226,34 @@ namespace BlackCore return CApplicationInfo::Unknown; } + QString CApplication::getExecutableForApplication(CApplicationInfo::Application application) const + { + QString search; + switch (application) + { + case CApplicationInfo::PilotClientCore: search = "core"; break; + case CApplicationInfo::Laucher: search = "launcher"; break; + case CApplicationInfo::MappingTool: search = "data"; break; + case CApplicationInfo::PilotClientGui: search = "gui"; break; + default: + break; + } + if (search.isEmpty()) return ""; + for (const QString &executable : CFileUtils::getSwiftExecutables()) + { + if (!executable.contains("swift", Qt::CaseInsensitive)) { continue; } + if (executable.contains(search, Qt::CaseInsensitive)) { return executable; } + } + return ""; + } + + bool CApplication::startLauncher() + { + static const QString launcher = CApplication::getExecutableForApplication(CApplicationInfo::Application::Laucher); + if (launcher.isEmpty() || CApplication::isApplicationRunning(CApplicationInfo::Laucher)) { return false; } + return QProcess::startDetached(launcher); + } + bool CApplication::isUnitTest() const { return this->m_unitTest; diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 9d6602751..c6c5fdd86 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -113,6 +113,9 @@ namespace BlackCore //! 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; @@ -125,6 +128,12 @@ namespace BlackCore //! swift application running BlackMisc::CApplicationInfo::Application getSwiftApplication() const; + //! Executable names for the given applications + QString getExecutableForApplication(BlackMisc::CApplicationInfo::Application application) const; + + //! Start the launcher + bool startLauncher(); + //! Unit test? bool isUnitTest() const; @@ -199,6 +208,10 @@ namespace BlackCore //! Directory for temporary files QString getTemporaryDirectory() const; + //! Register as running + //! \note Normally done automatically when CApplication::exec is called + static bool registerAsRunning(); + //! Run event loop static int exec(); @@ -474,11 +487,11 @@ namespace BlackCore BlackMisc::CStatusMessageList initCrashHandler(); void crashDumpUploadEnabledChanged(); - #ifdef BLACK_USE_CRASHPAD +#ifdef BLACK_USE_CRASHPAD std::unique_ptr m_crashpadClient; std::unique_ptr m_crashReportDatabase; BlackMisc::CSettingReadOnly m_crashDumpUploadEnabled { this, &CApplication::crashDumpUploadEnabledChanged }; - #endif +#endif }; } // namespace diff --git a/src/swiftlauncher/main.cpp b/src/swiftlauncher/main.cpp index e36cd51f1..34c04f15e 100644 --- a/src/swiftlauncher/main.cpp +++ b/src/swiftlauncher/main.cpp @@ -30,7 +30,8 @@ int main(int argc, char *argv[]) { //! [SwiftApplicationDemo] CGuiApplication::highDpiScreenSupport(); - QApplication qa(argc, argv); + QApplication qa(argc, argv); // needed + Q_UNUSED(qa); CGuiApplication a("swift launcher", CApplicationInfo::Laucher, CIcons::swiftLauncher1024()); a.addParserOption({{"i", "installer"}, QCoreApplication::translate("main", "Installer setup."), "installer"}); if (!a.parse()) { return EXIT_FAILURE; } @@ -44,6 +45,7 @@ int main(int argc, char *argv[]) // Dialog to decide external or internal core CSwiftLauncher launcher; + CGuiApplication::registerAsRunning(); // needed because own exec is called if (launcher.exec() == QDialog::Rejected) { return EXIT_SUCCESS; } launcher.close();