diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index db8dd2529..c504f3e08 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -83,6 +83,8 @@ namespace BlackCore sApp = this; this->m_setupReader.reset(new CSetupReader(this)); connect(this->m_setupReader.data(), &CSetupReader::setupSynchronized, this, &CApplication::ps_setupSyncronized); + connect(this->m_setupReader.data(), &CSetupReader::updateInfoSynchronized, this, &CApplication::updateInfoSynchronized); + this->m_parser.addOptions(this->m_setupReader->getCmdLineOptions()); // notify when app goes down @@ -107,13 +109,20 @@ namespace BlackCore return s; } - Data::CGlobalSetup CApplication::getGlobalSetup() const + CGlobalSetup CApplication::getGlobalSetup() const { const CSetupReader *r = this->m_setupReader.data(); if (!r) { return CGlobalSetup(); } return r->getSetup(); } + CUpdateInfo CApplication::getUpdateInfo() const + { + const CSetupReader *r = this->m_setupReader.data(); + if (!r) { return CUpdateInfo(); } + return r->getUpdateInfo(); + } + bool CApplication::start(bool waitForStart) { if (!this->m_parsed) @@ -523,7 +532,7 @@ namespace BlackCore { if (success) { - emit setupSyncronized(); + emit setupSyncronized(success); this->m_started = this->asyncWebAndContextStart(); } this->m_startUpCompleted = true; @@ -695,7 +704,8 @@ namespace BlackCore bool CApplication::supportsContexts() const { - if (m_coreFacade.isNull()) { return false; } + if (this->m_shutdown) { return false; } + if (this->m_coreFacade.isNull()) { return false; } if (!this->m_coreFacade->getIContextApplication()) { return false; } return (!this->m_coreFacade->getIContextApplication()->isEmptyObject()); } diff --git a/src/blackcore/application.h b/src/blackcore/application.h index 865e3fc8a..e261e2cab 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -15,6 +15,7 @@ #include "corefacadeconfig.h" #include "cookiemanager.h" #include "webdataservices.h" +#include "blackcore/data/updateinfo.h" #include "blackmisc/network/url.h" #include "blackmisc/network/entityflags.h" #include "blackmisc/logcategorylist.h" @@ -79,6 +80,10 @@ namespace BlackCore //! \threadsafe BlackCore::Data::CGlobalSetup getGlobalSetup() const; + //! Update info + //! \threadsafe + BlackCore::Data::CUpdateInfo getUpdateInfo() const; + //! Delete all cookies from cookier manager void deleteAllCookies(); @@ -240,7 +245,10 @@ namespace BlackCore signals: //! Setup syncronized - void setupSyncronized(); + void setupSyncronized(bool success); + + //! Update info syncronized + void updateInfoSynchronized(bool success); //! Startup has been completed void startUpCompleted(bool success); diff --git a/src/blackgui/guiapplication.cpp b/src/blackgui/guiapplication.cpp index acb7974fe..413e46333 100644 --- a/src/blackgui/guiapplication.cpp +++ b/src/blackgui/guiapplication.cpp @@ -10,10 +10,16 @@ #include "guiapplication.h" #include "guiutility.h" #include "stylesheetutility.h" +#include "blackmisc/logmessage.h" #include "blackmisc/project.h" #include "blackmisc/verify.h" +#include "blackmisc/metadatautils.h" +#include "blackmisc/settingscache.h" #include #include +#include +#include +#include using namespace BlackMisc; @@ -26,6 +32,12 @@ namespace BlackGui return qobject_cast(CApplication::instance()); } + const BlackMisc::CLogCategoryList &CGuiApplication::getLogCategories() + { + static const CLogCategoryList l(CApplication::getLogCategories().join( { CLogCategory::guiComponent() })); + return l; + } + CGuiApplication::CGuiApplication(const QString &applicationName, const QPixmap &icon) : CApplication(applicationName) { setWindowIcon(icon); @@ -139,11 +151,189 @@ namespace BlackGui return m->displayInOverlayWindow(message); } + bool CGuiApplication::displayTextInConsole(const QString &text) + { + IMainWindowAccess *m = mainWindowAccess(); + BLACK_VERIFY_X(m, Q_FUNC_INFO, "No access interface"); + if (!m) { return false; } + return m->displayTextInConsole(text); + } + bool CGuiApplication::reloadStyleSheets() const { return CStyleSheetUtility::instance().read(); } + void CGuiApplication::addMenuForSettingsAndCache(QMenu &menu) + { + QMenu *sm = menu.addMenu(CIcons::appSettings16(), "Settings"); + sm->setIcon(CIcons::appSettings16()); + QAction *a = sm->addAction(CIcons::disk16(), "Settings directory"); + bool c = connect(a, &QAction::triggered, this, [a, this]() + { + const QString path(QDir::toNativeSeparators(CSettingsCache::persistentStore())); + if (QDir(path).exists()) + { + QDesktopServices::openUrl(QUrl("file:///" + path)); + } + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = sm->addAction("Reset settings"); + c = connect(a, &QAction::triggered, this, [this]() + { + CSettingsCache::instance()->clearAllValues(); + this->displayTextInConsole("Cleared all settings!"); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = sm->addAction("List settings files"); + c = connect(a, &QAction::triggered, this, [this]() + { + const QStringList files(CSettingsCache::instance()->enumerateStore()); + this->displayTextInConsole(files.join("\n")); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + sm = menu.addMenu("Cache"); + sm->setIcon(CIcons::appSettings16()); + a = sm->addAction(CIcons::disk16(), "Cache directory"); + c = connect(a, &QAction::triggered, this, [this]() + { + const QString path(QDir::toNativeSeparators(CDataCache::persistentStore())); + if (QDir(path).exists()) + { + QDesktopServices::openUrl(QUrl("file:///" + path)); + } + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = sm->addAction("Reset cache"); + c = connect(a, &QAction::triggered, this, [this]() + { + CDataCache::instance()->clearAllValues(); + this->displayTextInConsole("Cleared cache!"); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = sm->addAction("List cache files"); + c = connect(a, &QAction::triggered, this, [this]() + { + const QStringList files(CDataCache::instance()->enumerateStore()); + this->displayTextInConsole(files.join("\n")); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + } + + void CGuiApplication::addMenuForStyleSheets(QMenu &menu) + { + QMenu *sm = menu.addMenu("Style sheet"); + QAction *a = sm->addAction(CIcons::refresh16(), "Reload"); + bool c = connect(a, &QAction::triggered, this, [a, this]() + { + this->reloadStyleSheets(); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + } + + void CGuiApplication::addMenuFile(QMenu &menu) + { + addMenuForSettingsAndCache(menu); + addMenuForStyleSheets(menu); + + menu.addSeparator(); + QAction *a = menu.addAction("E&xit"); + a->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q)); + bool c = connect(a, &QAction::triggered, this, [a, this]() + { + // a close event might already trigger a shutdown + this->mainApplicationWindow()->close(); + this->gracefulShutdown(); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + } + + void CGuiApplication::addMenuInternals(QMenu &menu) + { + QMenu *sm = menu.addMenu("Templates"); + QAction *a = sm->addAction("JSON bootstrap"); + bool c = connect(a, &QAction::triggered, this, [a, this]() + { + this->displayTextInConsole(this->getGlobalSetup().toJsonString()); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = sm->addAction("JSON update info"); + c = connect(a, &QAction::triggered, this, [a, this]() + { + this->displayTextInConsole(this->getUpdateInfo().toJsonString()); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction("Metadata (slow)"); + c = connect(a, &QAction::triggered, this, [a, this]() + { + this->displayTextInConsole(getAllUserMetatypesTypes()); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction("Setup"); + c = connect(a, &QAction::triggered, this, [a, this]() + { + this->displayTextInConsole(this->getGlobalSetup().convertToQString("\n", true)); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction("Compile info"); + c = connect(a, &QAction::triggered, this, [a, this]() + { + this->displayTextInConsole(this->getInfoString("\n")); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + } + + void CGuiApplication::addMenuWindow(QMenu &menu) + { + QWidget *w = mainApplicationWindow(); + if (!w) { return; } + QAction *a = menu.addAction(w->style()->standardIcon(QStyle::SP_TitleBarMaxButton), "Fullscreen"); + bool c = connect(a, &QAction::triggered, this, [a, w]() + { + w->showFullScreen(); + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction(w->style()->standardIcon(QStyle::SP_TitleBarMinButton), "Minimize"); + c = connect(a, &QAction::triggered, this, [a, w]() + { + w->showMinimized(); + + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction(w->style()->standardIcon(QStyle::SP_TitleBarNormalButton), "Normal"); + c = connect(a, &QAction::triggered, this, [a, w]() + { + w->showNormal(); + + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + + a = menu.addAction("Toggle stay on top"); + c = connect(a, &QAction::triggered, this, [a, w]() + { + if (CGuiUtility::toggleStayOnTop(w)) + { + CLogMessage(w).info("Window on top"); + } + else + { + CLogMessage(w).info("Window not always on top"); + } + }); + Q_ASSERT_X(c, Q_FUNC_INFO, "Connect failed"); + } + void CGuiApplication::cmdLineHelpMessage() { if (CProject::isRunningOnWindowsNtPlatform()) diff --git a/src/blackgui/guiapplication.h b/src/blackgui/guiapplication.h index 0dd55d58d..ce5a10233 100644 --- a/src/blackgui/guiapplication.h +++ b/src/blackgui/guiapplication.h @@ -16,6 +16,7 @@ #include "blackgui/mainwindowaccess.h" #include "blackgui/enableforframelesswindow.h" #include "blackgui/blackguiexport.h" +#include namespace BlackGui { @@ -25,6 +26,18 @@ namespace BlackGui * \details Analog to QCoreApplication and QApplication this class provides more details for swift * GUI applications. It is normally used via the global sGui pointer. As an example of how to extend this * class see CSwiftGuiStdApplication. + * + * - style sheet handling + * - standard menus + * + * Simple example + * \snippet swiftlauncher/main.cpp CSwiftGuiStdApplication + * + * Derived class example, hence very short (logic in CSwiftGuiStdApplication) + * \snippet swiftguistandard/main.cpp CSwiftGuiStdApplication + * + * Longer example + * \snippet swiftcore/main.cpp CSwiftGuiStdApplication */ class BLACKGUI_EXPORT CGuiApplication : public BlackCore::CApplication, @@ -36,6 +49,9 @@ namespace BlackGui //! Similar to \sa QCoreApplication::instance() returns the single instance static CGuiApplication *instance(); + //! Own log categories + static const BlackMisc::CLogCategoryList &getLogCategories(); + //! Constructor CGuiApplication(const QString &applicationName = executable(), const QPixmap &icon = BlackMisc::CIcons::swift48()); @@ -57,6 +73,9 @@ namespace BlackGui //! Allow the GUI to refresh by processing events void processEventsToRefreshGui() const; + //! Reload style sheets + bool reloadStyleSheets() const; + //! Init the main application window based on information in this application void initMainApplicationWindow(QWidget *mainWindow) const; @@ -69,10 +88,23 @@ namespace BlackGui //! @{ virtual bool displayInStatusBar(const BlackMisc::CStatusMessage &message) override; virtual bool displayInOverlayWindow(const BlackMisc::CStatusMessage &message) override; - //! }@ + virtual bool displayTextInConsole(const QString &text) override; + //! @} - //! Reload style sheets - bool reloadStyleSheets() const; + //! Add menu items for settings and cache + void addMenuForSettingsAndCache(QMenu &menu); + + //! Add menu for style sheets + void addMenuForStyleSheets(QMenu &menu); + + //! File menu + void addMenuFile(QMenu &menu); + + //! Internals menu + void addMenuInternals(QMenu &menu); + + //! Window operations + void addMenuWindow(QMenu &menu); //! Set icon //! \note Pixmap requires a valid QApplication, so it cannot be passed as constructor parameter diff --git a/src/blackgui/guiutility.cpp b/src/blackgui/guiutility.cpp index 808ec1316..5b2aefb16 100644 --- a/src/blackgui/guiutility.cpp +++ b/src/blackgui/guiutility.cpp @@ -32,7 +32,7 @@ namespace BlackGui { CEnableForFramelessWindow *CGuiUtility::mainFramelessEnabledApplicationWindow() { - QWidgetList tlw = topLevelApplicationWidgetsWithName(); + const QWidgetList tlw = topLevelApplicationWidgetsWithName(); for (QWidget *w : tlw) { // best choice is to check on frameless window @@ -51,13 +51,12 @@ namespace BlackGui } // second choice, try via QMainWindow - QWidgetList tlw = topLevelApplicationWidgetsWithName(); + const QWidgetList tlw = topLevelApplicationWidgetsWithName(); for (QWidget *w : tlw) { QMainWindow *qmw = qobject_cast(w); if (!qmw) { continue; } if (!qmw->parentWidget()) { return qmw; } - } return nullptr; } @@ -241,4 +240,30 @@ namespace BlackGui // then finally delete layout; } + + bool CGuiUtility::staysOnTop(QWidget *widget) + { + if (!widget) { return false; } + const Qt::WindowFlags flags = widget->windowFlags(); + return Qt::WindowStaysOnTopHint & flags; + } + + bool CGuiUtility::toggleStayOnTop(QWidget *widget) + { + if (!widget) { return false; } + Qt::WindowFlags flags = widget->windowFlags(); + if (Qt::WindowStaysOnTopHint & flags) + { + flags ^= Qt::WindowStaysOnTopHint; + flags |= Qt::WindowStaysOnBottomHint; + } + else + { + flags ^= Qt::WindowStaysOnBottomHint; + flags |= Qt::WindowStaysOnTopHint; + } + widget->setWindowFlags(flags); + widget->show(); + return Qt::WindowStaysOnTopHint & flags; + } } // ns diff --git a/src/blackgui/guiutility.h b/src/blackgui/guiutility.h index 9403a7997..0424d0a68 100644 --- a/src/blackgui/guiutility.h +++ b/src/blackgui/guiutility.h @@ -25,7 +25,6 @@ namespace BlackGui //! GUI utilities class BLACKGUI_EXPORT CGuiUtility { - public: //! Main (frameless enabled) application window static CEnableForFramelessWindow *mainFramelessEnabledApplicationWindow(); @@ -72,6 +71,12 @@ namespace BlackGui //! Pseudo readonly state for checkbox static void checkBoxReadOnly(QCheckBox *checkBox, bool readOnly); + //! Toogle window flags / stay on top + static bool toggleStayOnTop(QWidget *widget); + + //! Window on top? + static bool staysOnTop(QWidget *widget); + private: //! Constructor, use static methods only CGuiUtility() {} diff --git a/src/swiftdata/swiftdata.cpp b/src/swiftdata/swiftdata.cpp index 5947f813d..018103793 100644 --- a/src/swiftdata/swiftdata.cpp +++ b/src/swiftdata/swiftdata.cpp @@ -54,25 +54,6 @@ void CSwiftData::initStyleSheet() CSwiftData::~CSwiftData() { } -bool CSwiftData::displayInStatusBar(const CStatusMessage &message) -{ - this->m_statusBar.displayStatusMessage(message); - return true; -} - -bool CSwiftData::displayInOverlayWindow(const CStatusMessage &message) -{ - this->ui->comp_MainInfoArea->getMappingComponent()->showOverlayMessage(message); - return true; -} - -void CSwiftData::closeEvent(QCloseEvent *event) -{ - Q_UNUSED(event); - this->performGracefulShutdown(); - sGui->exit(); -} - void CSwiftData::ps_appendLogMessage(const CStatusMessage &message) { CLogComponent *logComponent = ui->comp_MainInfoArea->getLogComponent(); @@ -91,8 +72,13 @@ void CSwiftData::ps_onStyleSheetsChanged() void CSwiftData::init() { sGui->initMainApplicationWindow(this); - this->initStyleSheet(); this->initLogDisplay(); + + this->m_mwaLogComponent = this->ui->comp_MainInfoArea->getLogComponent(); + this->m_mwaStatusBar = &this->m_statusBar; + this->m_mwaOverlayFrame = this->ui->comp_MainInfoArea->getMappingComponent(); + + this->initStyleSheet(); connect(sGui, &CGuiApplication::styleSheetsChanged, this, &CSwiftData::ps_onStyleSheetsChanged); this->initMenu(); } @@ -112,32 +98,17 @@ void CSwiftData::initLogDisplay() void CSwiftData::initMenu() { // menu + this->initDynamicMenus(); this->ui->menu_WindowMinimize->setIcon(this->style()->standardIcon(QStyle::SP_TitleBarMinButton)); - connect(this->ui->menu_FileExit, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_FileReloadStyleSheets, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_FileResetSettings, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - - connect(this->ui->menu_SettingsDirectory, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_SettingsFiles, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_SettingsReset, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_CacheDirectory, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_CacheFiles, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_CacheReset, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); connect(this->ui->menu_WindowFont, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_WindowMinimize, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_WindowToggleOnTop, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_MappingMaxData, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); connect(this->ui->menu_MappingMaxMapping, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_InternalsCompileInfo, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_InternalsEnvVars, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_InternalsMetatypes, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_InternalsSetup, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_JsonBootstrapTemplate, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); - connect(this->ui->menu_JsonDownloadTemplate, &QAction::triggered, this, &CSwiftData::ps_onMenuClicked); + sGui->addMenuFile(*this->ui->menu_File); + sGui->addMenuInternals(*this->ui->menu_Internals); + sGui->addMenuWindow(*this->ui->menu_Window); } void CSwiftData::performGracefulShutdown() diff --git a/src/swiftdata/swiftdata.h b/src/swiftdata/swiftdata.h index f209cbf5a..e5fddb453 100644 --- a/src/swiftdata/swiftdata.h +++ b/src/swiftdata/swiftdata.h @@ -43,16 +43,6 @@ public: //! Destructor ~CSwiftData(); - //! \name direct access to main application window - //! @{ - virtual bool displayInStatusBar(const BlackMisc::CStatusMessage &message) override; - virtual bool displayInOverlayWindow(const BlackMisc::CStatusMessage &message) override; - //! }@ - -protected: - //! \copydoc QMainWindow::closeEvent - virtual void closeEvent(QCloseEvent *event) override; - private slots: //! Append log message void ps_appendLogMessage(const BlackMisc::CStatusMessage &message); @@ -76,7 +66,7 @@ private: QScopedPointer ui; BlackGui::CManagedStatusBar m_statusBar; - BlackMisc::CData m_updateInfo { this }; //!< download / version data + BlackMisc::CData m_updateInfo { this }; //!< download / version data }; #endif // guard diff --git a/src/swiftdata/swiftdata.ui b/src/swiftdata/swiftdata.ui index e8d0b8456..fb0436008 100644 --- a/src/swiftdata/swiftdata.ui +++ b/src/swiftdata/swiftdata.ui @@ -79,34 +79,13 @@ File - - - Settings - - - - - - - - Cache - - - - - - - - - Window - @@ -120,27 +99,10 @@ - + - Test + Internals - - - Internals - - - - Templates - - - - - - - - - - @@ -153,7 +115,7 @@ - + diff --git a/src/swiftdata/swiftdatamenus.cpp b/src/swiftdata/swiftdatamenus.cpp index 25a6c9f73..34395b75d 100644 --- a/src/swiftdata/swiftdatamenus.cpp +++ b/src/swiftdata/swiftdatamenus.cpp @@ -35,64 +35,11 @@ using namespace BlackMisc; void CSwiftData::ps_onMenuClicked() { QObject *sender = QObject::sender(); - if (sender == this->ui->menu_FileReloadStyleSheets) - { - sGui->reloadStyleSheets(); - } - else if (sender == this->ui->menu_WindowFont) + if (sender == this->ui->menu_WindowFont) { // this->ps_setMainPageToInfoArea(); // this->ui->comp_MainInfoArea->selectSettingsTab(BlackGui::Components::CSettingsComponent::SettingTabGui); } - else if (sender == this->ui->menu_WindowMinimize) - { - this->showMinimized(); - } - else if (sender == this->ui->menu_FileExit) - { - CLogMessage(this).info("Closing"); - this->close(); // graceful shutdown in close event - } - else if (sender == this->ui->menu_SettingsDirectory) - { - QString path(QDir::toNativeSeparators(CSettingsCache::persistentStore())); - if (QDir(path).exists()) - { - QDesktopServices::openUrl(QUrl("file:///" + path)); - } - } - else if (sender == this->ui->menu_SettingsReset) - { - CSettingsCache::instance()->clearAllValues(); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole("Cleared all settings!"); - this->displayConsole(); - } - else if (sender == this->ui->menu_SettingsFiles) - { - QStringList cachedFiles(CSettingsCache::instance()->enumerateStore()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(cachedFiles.join("\n")); - this->displayConsole(); - } - else if (sender == this->ui->menu_CacheDirectory) - { - QString path(QDir::toNativeSeparators(CDataCache::persistentStore())); - if (QDir(path).exists()) - { - QDesktopServices::openUrl(QUrl("file:///" + path)); - } - } - else if (sender == this->ui->menu_CacheFiles) - { - QStringList cachedFiles(CDataCache::instance()->enumerateStore()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(cachedFiles.join("\n")); - this->displayConsole(); - } - else if (sender == this->ui->menu_CacheReset) - { - CDataCache::instance()->clearAllValues(); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole("Cleared all cached values!"); - this->displayConsole(); - } else if (sender == this->ui->menu_MappingMaxData) { CDbMappingComponent *mappingComponent = this->ui->comp_MainInfoArea->getMappingComponent(); @@ -103,36 +50,6 @@ void CSwiftData::ps_onMenuClicked() CDbMappingComponent *mappingComponent = this->ui->comp_MainInfoArea->getMappingComponent(); mappingComponent->resizeForMapping(); } - else if (sender == this->ui->menu_JsonBootstrapTemplate) - { - QString json(sApp->getGlobalSetup().toJsonString()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(json); - this->displayConsole(); - } - else if (sender == this->ui->menu_JsonDownloadTemplate) - { - QString json(m_updateInfo.get().toJsonString()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(json); - this->displayConsole(); - } - else if (sender == this->ui->menu_InternalsMetatypes) - { - QString metadata(getAllUserMetatypesTypes()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(metadata); - this->displayConsole(); - } - else if (sender == this->ui->menu_InternalsSetup) - { - QString setup(sApp->getGlobalSetup().convertToQString("\n", true)); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(setup); - this->displayConsole(); - } - else if (sender == this->ui->menu_InternalsCompileInfo) - { - QString project(sGui->convertToQString("\n")); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(project); - this->displayConsole(); - } } void CSwiftData::initDynamicMenus() diff --git a/src/swiftguistandard/swiftguistd.cpp b/src/swiftguistandard/swiftguistd.cpp index 1904152ed..5a1702d7e 100644 --- a/src/swiftguistandard/swiftguistd.cpp +++ b/src/swiftguistandard/swiftguistd.cpp @@ -9,16 +9,18 @@ #include "swiftguistd.h" #include "ui_swiftguistd.h" -#include "blackmisc/icon.h" #include "blackgui/stylesheetutility.h" #include "blackgui/models/atcstationlistmodel.h" #include "blackgui/components/logcomponent.h" #include "blackgui/components/settingscomponent.h" #include "blackgui/guiapplication.h" +#include "blackgui/guiutility.h" #include "blackcore/contextnetwork.h" #include "blackcore/contextapplication.h" #include "blackcore/contextownaircraft.h" #include "blackcore/network.h" +#include "blackmisc/threadutils.h" +#include "blackmisc/icon.h" #include "blackmisc/dbusserver.h" #include "blackmisc/logmessage.h" #include "blackmisc/audio/notificationsounds.h" @@ -54,18 +56,6 @@ SwiftGuiStd::SwiftGuiStd(BlackGui::CEnableForFramelessWindow::WindowMode windowM SwiftGuiStd::~SwiftGuiStd() { } -bool SwiftGuiStd::displayInStatusBar(const CStatusMessage &message) -{ - this->ps_displayStatusMessageInGui(message); - return true; -} - -bool SwiftGuiStd::displayInOverlayWindow(const CStatusMessage &message) -{ - this->ui->fr_CentralFrameInside->showOverlayMessage(message); - return true; -} - void SwiftGuiStd::mouseMoveEvent(QMouseEvent *event) { if (!handleMouseMoveEvent(event)) { QMainWindow::mouseMoveEvent(event); } @@ -81,13 +71,15 @@ void SwiftGuiStd::performGracefulShutdown() if (!this->m_init) { return; } this->m_init = false; + Q_ASSERT_X(CThreadUtils::isCurrentThreadApplicationThread(), Q_FUNC_INFO, "Should shutdown in main thread"); + // shut down all timers this->stopAllTimers(true); // if we have a context, we shut some things down if (this->m_contextNetworkAvailable) { - if (sGui->getIContextNetwork() && sGui->getIContextNetwork()->isConnected()) + if (sGui && sGui->getIContextNetwork() && sGui->getIContextNetwork()->isConnected()) { if (this->m_contextAudioAvailable) { @@ -103,11 +95,9 @@ void SwiftGuiStd::performGracefulShutdown() this->ui->comp_MainInfoArea->dockAllWidgets(); // allow some other parts to react + if (!sGui) { return; } // overall shutdown sGui->processEventsToRefreshGui(); - // tell GUI components to shut down - emit requestGracefulShutdown(); - // tell context GUI is going down if (sGui->getIContextApplication()) { @@ -267,13 +257,16 @@ void SwiftGuiStd::setContextAvailability() { bool corePreviouslyAvailable = this->m_coreAvailable; - if (sGui->getIContextApplication()->isUsingImplementingObject()) + if (sGui && sGui->getIContextApplication()->isUsingImplementingObject()) { this->m_coreAvailable = true; } else { - this->m_coreAvailable = isMyIdentifier(sGui->getIContextApplication()->registerApplication(getCurrentTimestampIdentifier())); + // ping to check if core is still alive + this->m_coreAvailable = + sGui && + this->isMyIdentifier(sGui->getIContextApplication()->registerApplication(getCurrentTimestampIdentifier())); } this->m_contextNetworkAvailable = this->m_coreAvailable || sGui->getIContextNetwork()->isUsingImplementingObject(); this->m_contextAudioAvailable = this->m_coreAvailable || sGui->getIContextAudio()->isUsingImplementingObject(); @@ -283,7 +276,7 @@ void SwiftGuiStd::setContextAvailability() { if (this->m_coreAvailable) { - // core has just become available + // core has just become available (startup) sGui->getIContextApplication()->synchronizeLogSubscriptions(); sGui->getIContextApplication()->synchronizeLocalSettings(); } @@ -321,21 +314,7 @@ void SwiftGuiStd::ps_onChangedWindowOpacity(int opacity) void SwiftGuiStd::ps_toogleWindowStayOnTop() { - Qt::WindowFlags flags = this->windowFlags(); - if (Qt::WindowStaysOnTopHint & flags) - { - flags ^= Qt::WindowStaysOnTopHint; - flags |= Qt::WindowStaysOnBottomHint; - CLogMessage(this).info("Window on bottom"); - } - else - { - flags ^= Qt::WindowStaysOnBottomHint; - flags |= Qt::WindowStaysOnTopHint; - CLogMessage(this).info("Window on top"); - } - this->setWindowFlags(flags); - this->show(); + CGuiUtility::toggleStayOnTop(this); } void SwiftGuiStd::ps_toggleWindowVisibility() diff --git a/src/swiftguistandard/swiftguistd.h b/src/swiftguistandard/swiftguistd.h index 153ab708d..812c824d8 100644 --- a/src/swiftguistandard/swiftguistd.h +++ b/src/swiftguistandard/swiftguistd.h @@ -70,17 +70,7 @@ public: //! Log message category static QString getMessageCategory() { return "swift.gui.stdgui"; } - //! \name direct access to main application window - //! @{ - virtual bool displayInStatusBar(const BlackMisc::CStatusMessage &message) override; - virtual bool displayInOverlayWindow(const BlackMisc::CStatusMessage &message) override; - //! }@ - signals: - //! GUI is shutting down, request graceful shutdown - void requestGracefulShutdown(); - - //! Main info area changed //! \remarks using widget pointer allows the component itself to identify if it is current void currentMainInfoAreaChanged(const QWidget *currentWidget); @@ -150,10 +140,7 @@ private: void initGuiSignals(); //! Init dynamic menus - void initDynamicMenus(); - - //! Menu icons where required - void initMenuIcons(); + void initMenus(); //! Graceful shutdown void performGracefulShutdown(); diff --git a/src/swiftguistandard/swiftguistd.ui b/src/swiftguistandard/swiftguistd.ui index b4320d1e1..f390817f5 100644 --- a/src/swiftguistandard/swiftguistd.ui +++ b/src/swiftguistandard/swiftguistd.ui @@ -259,25 +259,14 @@ - - - Reload - - - - + Internals - - - - + - - + - @@ -288,27 +277,7 @@ File - - - Settings - - - - - - - - Cache - - - - - - - - - @@ -320,9 +289,8 @@ Window - - + @@ -498,9 +466,9 @@ Compile info - + - Internal page + Internals page @@ -546,6 +514,12 @@ + + BlackGui::COverlayMessagesFrame + QFrame +
blackgui/overlaymessagesframe.h
+ 1 +
BlackGui::Components::CMainInfoAreaComponent QWidget @@ -582,12 +556,6 @@
blackgui/components/internalscomponent.h
1
- - BlackGui::COverlayMessagesFrame - QFrame -
blackgui/overlaymessagesframe.h
- 1 -
diff --git a/src/swiftguistandard/swiftguistdinit.cpp b/src/swiftguistandard/swiftguistdinit.cpp index b0e30cad3..21bf93227 100644 --- a/src/swiftguistandard/swiftguistdinit.cpp +++ b/src/swiftguistandard/swiftguistdinit.cpp @@ -35,8 +35,14 @@ void SwiftGuiStd::init() // POST(!) GUI init if (this->m_init) { return; } + this->setVisible(false); // hide all, so no flashing windows during init + this->m_mwaStatusBar = &this->m_statusBar; + this->m_mwaOverlayFrame = this->ui->fr_CentralFrameInside; + this->m_mwaLogComponent = this->ui->comp_MainInfoArea->getLogComponent(); + sGui->initMainApplicationWindow(this); + this->initStyleSheet(); // with frameless window, we shift menu and statusbar into central widget // http://stackoverflow.com/questions/18316710/frameless-and-transparent-window-qt5 @@ -102,8 +108,7 @@ void SwiftGuiStd::init() // start screen and complete menu this->ps_setMainPageToInfoArea(); - this->initDynamicMenus(); - this->initMenuIcons(); + this->initMenus(); // info this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(sGui->swiftVersionString()); @@ -148,34 +153,17 @@ void SwiftGuiStd::initGuiSignals() connect(this->ui->comp_MainInfoArea, &CMainInfoAreaComponent::changedInfoAreaStatus, ui->comp_MainKeypadArea, &CMainKeypadAreaComponent::onMainInfoAreaChanged); // menu - connect(this->ui->menu_ReloadSettings, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_TestLocationsEDDF, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_TestLocationsEDDM, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_TestLocationsEDNX, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_TestLocationsEDRY, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_TestLocationsLOWW, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_FileExit, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_FileReloadStyleSheets, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - - connect(this->ui->menu_SettingsDirectory, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_SettingsFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_SettingsReset, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_CacheDirectory, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_CacheFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_CacheReset, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_WindowFont, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_WindowMinimize, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_WindowToggleOnTop, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); connect(this->ui->menu_WindowToggleNavigator, &QAction::triggered, this->m_navigator.data(), &CNavigatorDialog::toggleNavigator); - - connect(this->ui->menu_InternalsCompileInfo, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_InternalsEnvVars, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_InternalsMetatypes, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_InternalsSetup, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_InternalsDeleteCachedFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); - connect(this->ui->menu_InternalsDisplayCachedFiles, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); + connect(this->ui->menu_InternalsPage, &QAction::triggered, this, &SwiftGuiStd::ps_onMenuClicked); // command line / text messages connect(this->ui->comp_MainInfoArea->getTextMessageComponent(), &CTextMessageComponent::displayInInfoWindow, this->ui->fr_CentralFrameInside, &COverlayMessagesFrame::showOverlayVariant); diff --git a/src/swiftguistandard/swiftguistdmenus.cpp b/src/swiftguistandard/swiftguistdmenus.cpp index abb32c6cd..313e01c55 100644 --- a/src/swiftguistandard/swiftguistdmenus.cpp +++ b/src/swiftguistandard/swiftguistdmenus.cpp @@ -56,100 +56,23 @@ void SwiftGuiStd::ps_onMenuClicked() { this->setTestPosition("N 48° 7′ 6.3588", "E 16° 33′ 39.924", CAltitude(100, CAltitude::MeanSeaLevel, CLengthUnit::m())); } - else if (sender == this->ui->menu_FileReloadStyleSheets) - { - sGui->reloadStyleSheets(); - } else if (sender == this->ui->menu_WindowFont) { this->ps_setMainPageToInfoArea(); this->ui->comp_MainInfoArea->selectSettingsTab(BlackGui::Components::CSettingsComponent::SettingTabGui); } - else if (sender == this->ui->menu_WindowMinimize) - { - this->ps_showMinimized(); - } - else if (sender == this->ui->menu_WindowToggleOnTop) - { - this->ps_toogleWindowStayOnTop(); - } - else if (sender == this->ui->menu_FileExit) - { - CLogMessage(this).info("Closing"); - this->close(); - } - else if (sender == this->ui->menu_SettingsDirectory) - { - QString path(QDir::toNativeSeparators(CSettingsCache::persistentStore())); - if (QDir(path).exists()) - { - QDesktopServices::openUrl(QUrl("file:///" + path)); - } - } - else if (sender == this->ui->menu_SettingsReset) - { - CSettingsCache::instance()->clearAllValues(); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole("Cleared all settings!"); - this->displayConsole(); - } - else if (sender == this->ui->menu_SettingsFiles) - { - QStringList cachedFiles(CSettingsCache::instance()->enumerateStore()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(cachedFiles.join("\n")); - this->displayConsole(); - } - else if (sender == this->ui->menu_CacheDirectory) - { - QString path(QDir::toNativeSeparators(CDataCache::persistentStore())); - if (QDir(path).exists()) - { - QDesktopServices::openUrl(QUrl("file:///" + path)); - } - } - else if (sender == this->ui->menu_CacheFiles) - { - QStringList cachedFiles(CDataCache::instance()->enumerateStore()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(cachedFiles.join("\n")); - this->displayConsole(); - } - else if (sender == this->ui->menu_CacheReset) - { - CDataCache::instance()->clearAllValues(); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole("Cleared all cached values!"); - this->displayConsole(); - } - else if (sender == this->ui->menu_Internals) + else if (sender == this->ui->menu_InternalsPage) { this->ui->sw_MainMiddle->setCurrentIndex(MainPageInternals); } - else if (sender == this->ui->menu_InternalsMetatypes) - { - QString metadata(getAllUserMetatypesTypes()); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(metadata); - this->displayConsole(); - } - else if (sender == this->ui->menu_InternalsSetup) - { - QString setup(sApp->getGlobalSetup().convertToQString("\n", true)); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(setup); - this->displayConsole(); - } - else if (sender == this->ui->menu_InternalsCompileInfo) - { - QString project(sGui->convertToQString("\n")); - this->ui->comp_MainInfoArea->getLogComponent()->appendPlainTextToConsole(project); - this->displayConsole(); - } } -void SwiftGuiStd::initDynamicMenus() +void SwiftGuiStd::initMenus() { Q_ASSERT(this->ui->menu_InfoAreas); Q_ASSERT(this->ui->comp_MainInfoArea); + sGui->addMenuFile(*this->ui->menu_File); + sGui->addMenuInternals(*this->ui->menu_Internals); + sGui->addMenuWindow(*this->ui->menu_Window); this->ui->menu_InfoAreas->addActions(this->ui->comp_MainInfoArea->getInfoAreaSelectActions(this->ui->menu_InfoAreas)); } - -void SwiftGuiStd::initMenuIcons() -{ - this->ui->menu_WindowMinimize->setIcon(this->style()->standardIcon(QStyle::SP_TitleBarMinButton)); -} diff --git a/src/swiftlauncher/main.cpp b/src/swiftlauncher/main.cpp index 251607f87..8f2814d25 100644 --- a/src/swiftlauncher/main.cpp +++ b/src/swiftlauncher/main.cpp @@ -27,10 +27,12 @@ using namespace BlackCore; int main(int argc, char *argv[]) { + //! [CSwiftGuiStdApplication] QApplication qa(argc, argv); CGuiApplication a("swift launcher", CIcons::swift24()); a.addParserOption({{"i", "installer"}, QCoreApplication::translate("main", "Installer setup."), "installer"}); a.parse(); + //! [CSwiftGuiStdApplication] // Dialog to decide external or internal core CSwiftLauncher launcher; diff --git a/src/swiftlauncher/swiftlauncher.cpp b/src/swiftlauncher/swiftlauncher.cpp index 2b65019f2..cf5ac69aa 100644 --- a/src/swiftlauncher/swiftlauncher.cpp +++ b/src/swiftlauncher/swiftlauncher.cpp @@ -45,7 +45,9 @@ CSwiftLauncher::CSwiftLauncher(QWidget *parent) : connect(ui->tb_SwiftGui, &QPushButton::pressed, this, &CSwiftLauncher::ps_startButtonPressed); connect(ui->tb_Database, &QPushButton::pressed, this, &CSwiftLauncher::ps_startButtonPressed); connect(ui->tb_BackToMain, &QToolButton::pressed, this, &CSwiftLauncher::ps_showMainPage); - // connect(&CSetupReader::instance(), &CSetupReader::updateInfoSynchronized, this, &CSwiftLauncher::ps_loadedSetup); + + // use version signal as trigger for completion + connect(sGui, &CApplication::updateInfoSynchronized, this, &CSwiftLauncher::ps_loadedUpdateInfo); new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this, SLOT(ps_showLogPage())); this->ui->le_DBusServerPort->setValidator(new QIntValidator(0, 65535, this)); @@ -285,12 +287,12 @@ void CSwiftLauncher::ps_loadSetup() if (!this->ui->le_LatestVersion->text().isEmpty()) { this->ui->le_LatestVersion->setText(""); - CStatusMessage m(sApp->requestReloadOfSetupAndVersion()); + const CStatusMessage m(sApp->requestReloadOfSetupAndVersion()); this->ps_appendLogMessage(m); } } -void CSwiftLauncher::ps_loadedSetup(bool success) +void CSwiftLauncher::ps_loadedUpdateInfo(bool success) { if (!success) { @@ -298,8 +300,8 @@ void CSwiftLauncher::ps_loadedSetup(bool success) return; } - CUpdateInfo updateInfo(this->m_updateInfo.get()); - QString latestVersion(updateInfo.getLatestVersion()) ; // need to get this from somewhere + const CUpdateInfo updateInfo(this->m_updateInfo.get()); + const QString latestVersion(updateInfo.getLatestVersion()) ; // need to get this from somewhere CFailoverUrlList downloadUrls(updateInfo.getDownloadUrls()); bool newVersionAvailable = CProject::isNewerVersion(latestVersion) && !downloadUrls.isEmpty(); this->ui->wi_NewVersionAvailable->setVisible(newVersionAvailable); @@ -308,8 +310,8 @@ void CSwiftLauncher::ps_loadedSetup(bool success) if (!downloadUrls.isEmpty()) { - CUrl downloadUrl(downloadUrls.obtainNextUrl()); - QString urlStr(downloadUrl.toQString()); + const CUrl downloadUrl(downloadUrls.obtainNextUrl()); + const QString urlStr(downloadUrl.toQString()); QString hl("%2 %3"); this->ui->lbl_NewVersionUrl->setText(hl.arg(urlStr).arg(urlStr).arg(latestVersion)); } @@ -317,9 +319,9 @@ void CSwiftLauncher::ps_loadedSetup(bool success) this->loadLatestNews(); } -void CSwiftLauncher::ps_changedCache() +void CSwiftLauncher::ps_changedUpdateInfoCache() { - this->ps_loadedSetup(true); + this->ps_loadedUpdateInfo(true); } void CSwiftLauncher::ps_startButtonPressed() diff --git a/src/swiftlauncher/swiftlauncher.h b/src/swiftlauncher/swiftlauncher.h index 81a082d41..71c547546 100644 --- a/src/swiftlauncher/swiftlauncher.h +++ b/src/swiftlauncher/swiftlauncher.h @@ -66,7 +66,7 @@ private slots: private: QScopedPointer ui; - BlackMisc::CData m_updateInfo { this, &CSwiftLauncher::ps_changedCache }; //!< version cache + BlackMisc::CData m_updateInfo { this, &CSwiftLauncher::ps_changedUpdateInfoCache }; //!< version cache BlackMisc::CSetting m_dbusServerAddress { this }; //!< DBus address QString m_executable; QStringList m_executableArgs; @@ -124,10 +124,10 @@ private slots: void ps_loadSetup(); //! Loaded latest version - void ps_loadedSetup(bool success); + void ps_loadedUpdateInfo(bool success); //! Cache values have been changed - void ps_changedCache(); + void ps_changedUpdateInfoCache(); //! Start button pressed void ps_startButtonPressed();