diff --git a/src/blackcore/actionbind.cpp b/src/blackcore/actionbind.cpp index 69cfa67f1..b4fb50f3f 100644 --- a/src/blackcore/actionbind.cpp +++ b/src/blackcore/actionbind.cpp @@ -11,7 +11,8 @@ namespace BlackCore { - CActionBind::CActionBind(const QString &action, const QPixmap &icon) + CActionBind::CActionBind(const QString &action, const QPixmap &icon, QObject *parent) + : QObject(parent) { CActionBind::registerAction(action, icon); } @@ -19,13 +20,24 @@ namespace BlackCore QString CActionBind::registerAction(const QString &action, const QPixmap &icon) { const QString a = CActionBind::normalizeAction(action); - CInputManager *inputManger = CInputManager::instance(); - Q_ASSERT_X(inputManger, Q_FUNC_INFO, "Missing input manager"); - inputManger->registerAction(a, icon); + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + sApp->getInputManager()->registerAction(a, icon); return a; } CActionBind::~CActionBind() + { + } + + void CActionBind::unbind() + { + if (m_index < 0) { return; } + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + sApp->getInputManager()->unbind(m_index); + m_index = -1; + } + + void CActionBind::shutdown() { unbind(); if (m_deleteCallback) @@ -34,14 +46,6 @@ namespace BlackCore } } - void CActionBind::unbind() - { - if (m_index < 0) { return; } - auto inputManger = CInputManager::instance(); - inputManger->unbind(m_index); - m_index = -1; - } - QString CActionBind::normalizeAction(const QString &action) { QString n = action.trimmed(); diff --git a/src/blackcore/actionbind.h b/src/blackcore/actionbind.h index a622f261f..b1d0b0573 100644 --- a/src/blackcore/actionbind.h +++ b/src/blackcore/actionbind.h @@ -12,7 +12,7 @@ #ifndef BLACKCORE_ACTIONBIND_H #define BLACKCORE_ACTIONBIND_H -#include "blackcore/inputmanager.h" +#include "blackcore/application.h" #include "blackcoreexport.h" #include @@ -21,8 +21,10 @@ namespace BlackCore /*! * CActionBind binds a member function to an action */ - class BLACKCORE_EXPORT CActionBind + class BLACKCORE_EXPORT CActionBind : public QObject { + Q_OBJECT + public: //! Signature of receiving member function template @@ -32,15 +34,18 @@ namespace BlackCore template CActionBind(const QString &action, const QPixmap &icon, Receiver *receiver, MembFunc slot = nullptr, - const std::function &deleteCallback = {}) : - m_deleteCallback(deleteCallback) + const std::function &deleteCallback = {}, + QObject *parent = nullptr) : + QObject(parent), m_deleteCallback(deleteCallback) { const QString a = CActionBind::registerAction(action, icon); - m_index = CInputManager::instance()->bind(a, receiver, slot); + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + m_index = sApp->getInputManager()->bind(a, receiver, slot); + QObject::connect(sApp, &CApplication::aboutToShutdown, this, &CActionBind::shutdown); } //! Signature just to set an icon for an action - CActionBind(const QString &action, const QPixmap &icon); + CActionBind(const QString &action, const QPixmap &icon, QObject *parent = nullptr); //! Not copyable //! @{ @@ -49,7 +54,7 @@ namespace BlackCore //! @} //! Destructor - ~CActionBind(); + virtual ~CActionBind(); //! Unbind from BlackCore::CInputManager void unbind(); @@ -61,6 +66,8 @@ namespace BlackCore int getIndex() const { return m_index; } private: + void shutdown(); + //! Normalize the action string static QString normalizeAction(const QString &action); diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 13d8dd97f..c66e7441b 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -163,7 +163,6 @@ namespace BlackCore this->initNetwork(); - // global setup m_setupReader.reset(new CSetupReader(this)); connect(m_setupReader.data(), &CSetupReader::setupHandlingCompleted, this, &CApplication::onSetupHandlingCompleted, Qt::QueuedConnection); @@ -179,7 +178,8 @@ namespace BlackCore if (!this->getApplicationInfo().isUnitTest()) { - CInputManager::instance()->createDevices(); + m_inputManager = new CInputManager(this); + m_inputManager->createDevices(); } } } @@ -985,7 +985,7 @@ namespace BlackCore // Release all input devices to not cause any accidental hotkey triggers anymore. // This is also necessary to properly free platform specific instances at a defined point in time. - CInputManager::instance()->releaseDevices(); + if (m_inputManager) { m_inputManager->releaseDevices(); } // mark as shutdown if (m_networkWatchDog) { m_networkWatchDog->gracefulShutdown(); } @@ -1002,8 +1002,6 @@ namespace BlackCore // from here on we really rip apart the application object // and it should no longer be used - sApp = nullptr; - disconnect(this); if (this->supportsContexts()) { @@ -1031,6 +1029,11 @@ namespace BlackCore } m_fileLogger->close(); + + qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete); + + sApp = nullptr; + disconnect(this); } void CApplication::onSetupHandlingCompleted(bool available) diff --git a/src/blackcore/application.h b/src/blackcore/application.h index e3658051a..9570a6a61 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -17,6 +17,7 @@ #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" @@ -299,6 +300,12 @@ namespace BlackCore virtual QString cmdLineArgumentsAsString(bool withExecutable = true); //! @} + // ----------------------- Input ---------------------------------------- + + //! The input manager, if available + CInputManager *getInputManager() const { return m_inputManager; } + + // ----------------------- simulator ---------------------------------------- //! The simulator plugin, if available @@ -633,20 +640,21 @@ namespace BlackCore //! Write meta information into the application directory so other swift versions can display them void tagApplicationDataDirectory(); - 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 m_coreFacade; //!< core facade if any - QScopedPointer m_setupReader; //!< setup reader - QScopedPointer m_webDataServices; //!< web data services - QScopedPointer m_fileLogger; //!< file logger - QPointer 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? + 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 m_coreFacade; //!< core facade if any + QScopedPointer m_setupReader; //!< setup reader + QScopedPointer m_webDataServices; //!< web data services + QScopedPointer m_fileLogger; //!< file logger + QPointer 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 diff --git a/src/blackcore/context/contextapplication.cpp b/src/blackcore/context/contextapplication.cpp index ac03731ed..ec77da2e1 100644 --- a/src/blackcore/context/contextapplication.cpp +++ b/src/blackcore/context/contextapplication.cpp @@ -7,6 +7,7 @@ * contained in the LICENSE file. */ +#include "blackcore/application.h" #include "blackcore/context/contextapplication.h" #include "blackcore/context/contextapplicationempty.h" #include "blackcore/context/contextapplicationimpl.h" @@ -91,7 +92,8 @@ namespace BlackCore CSettingsCache::instance()->changeValuesFromRemote(settings, origin); }); - bool s = connect(CInputManager::instance(), &CInputManager::hotkeyActionRegistered, [ = ](const QStringList & actions) + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + bool s = connect(sApp->getInputManager(), &CInputManager::hotkeyActionRegistered, [ = ](const QStringList & actions) { if (!myself) { return; } this->registerHotkeyActions(actions, {}); @@ -102,12 +104,12 @@ namespace BlackCore s = connect(this, &IContextApplication::hotkeyActionsRegistered, [ = ](const QStringList & actions, const CIdentifier & origin) { if (origin.hasApplicationProcessId()) { return; } - CInputManager::instance()->registerRemoteActions(actions); + sApp->getInputManager()->registerRemoteActions(actions); }); Q_ASSERT_X(s, Q_FUNC_INFO, "Connect hotkey actions failed"); Q_UNUSED(s); - s = connect(CInputManager::instance(), &CInputManager::remoteActionFromLocal, this, [ = ](const QString & action, bool argument) + s = connect(sApp->getInputManager(), &CInputManager::remoteActionFromLocal, this, [ = ](const QString & action, bool argument) { if (!myself) { return; } this->callHotkeyAction(action, argument, {}); @@ -121,14 +123,14 @@ namespace BlackCore { if (!myself) { return; } if (origin.isFromLocalMachine()) { return; } - CInputManager::instance()->callFunctionsBy(action, argument); + sApp->getInputManager()->callFunctionsBy(action, argument); CLogMessage(this, CLogCategory::contextSlot()).debug() << "Calling function" << action << "from origin" << origin.getMachineName(); }); Q_ASSERT_X(s, Q_FUNC_INFO, "Connect remote hotkey action failed"); Q_UNUSED(s); // Enable event forwarding from GUI process to core - CInputManager::instance()->setForwarding(true); + sApp->getInputManager()->setForwarding(true); } CIdentifierList IContextApplication::subscribersOf(const CStatusMessage &message) const diff --git a/src/blackcore/context/contextapplicationimpl.cpp b/src/blackcore/context/contextapplicationimpl.cpp index 975b99214..7044f7c13 100644 --- a/src/blackcore/context/contextapplicationimpl.cpp +++ b/src/blackcore/context/contextapplicationimpl.cpp @@ -7,6 +7,7 @@ * contained in the LICENSE file. */ +#include "blackcore/application.h" #include "blackcore/context/contextapplicationimpl.h" #include "blackcore/inputmanager.h" #include "blackmisc/dbusserver.h" @@ -161,7 +162,7 @@ namespace BlackCore { m_registeredApplications.push_back(identifier); emit this->registrationChanged(); - emit this->hotkeyActionsRegistered(CInputManager::instance()->allAvailableActions(), {}); + emit this->hotkeyActionsRegistered(sApp->getInputManager()->allAvailableActions(), {}); } else { diff --git a/src/blackcore/inputmanager.cpp b/src/blackcore/inputmanager.cpp index 141b829cf..871dfbb9e 100644 --- a/src/blackcore/inputmanager.cpp +++ b/src/blackcore/inputmanager.cpp @@ -30,12 +30,6 @@ namespace BlackCore reloadHotkeySettings(); } - CInputManager *CInputManager::instance() - { - static CInputManager instance; - return &instance; - } - void CInputManager::registerAction(const QString &action, const QPixmap &icon) { if (!m_availableActions.contains(action)) diff --git a/src/blackcore/inputmanager.h b/src/blackcore/inputmanager.h index f2e06e877..f2c550b95 100644 --- a/src/blackcore/inputmanager.h +++ b/src/blackcore/inputmanager.h @@ -38,6 +38,9 @@ namespace BlackCore Q_OBJECT public: + //! Constructor + CInputManager(QObject *parent = nullptr); + //! Register new action void registerAction(const QString &action, const QPixmap &icon = BlackMisc::CIcons::empty16()); @@ -93,9 +96,6 @@ namespace BlackCore //! Releases all devices void releaseDevices(); - //! Creates a native keyboard handler object - static CInputManager *instance(); - signals: //! Event hotkeyfunction occured void remoteActionFromLocal(const QString &action, bool argument); @@ -109,12 +109,6 @@ namespace BlackCore //! New hotkey action is registered void hotkeyActionRegistered(const QStringList &actions); - protected: - //! Constructor - CInputManager(QObject *parent = nullptr); - - - private: //! Handle to a bound action struct BindInfo diff --git a/src/blackgui/components/hotkeydialog.cpp b/src/blackgui/components/hotkeydialog.cpp index 226029d1d..29aa39a1b 100644 --- a/src/blackgui/components/hotkeydialog.cpp +++ b/src/blackgui/components/hotkeydialog.cpp @@ -70,7 +70,6 @@ namespace BlackGui m_actionModel(this) { setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - m_inputManager = BlackCore::CInputManager::instance(); ui->setupUi(this); ui->qf_Advanced->hide(); @@ -105,8 +104,8 @@ namespace BlackGui connect(ui->pb_SelectedHotkey, &QPushButton::clicked, this, &CHotkeyDialog::selectHotkey); connect(ui->pb_Accept, &QPushButton::clicked, this, &CHotkeyDialog::accept); connect(ui->pb_Cancel, &QPushButton::clicked, this, &CHotkeyDialog::reject); - connect(m_inputManager, &BlackCore::CInputManager::combinationSelectionChanged, this, &CHotkeyDialog::combinationSelectionChanged); - connect(m_inputManager, &BlackCore::CInputManager::combinationSelectionFinished, this, &CHotkeyDialog::combinationSelectionFinished); + connect(sApp->getInputManager(), &BlackCore::CInputManager::combinationSelectionChanged, this, &CHotkeyDialog::combinationSelectionChanged); + connect(sApp->getInputManager(), &BlackCore::CInputManager::combinationSelectionFinished, this, &CHotkeyDialog::combinationSelectionFinished); connect(ui->tv_Actions->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CHotkeyDialog::changeSelectedAction); connect(ui->cb_Identifier, static_cast(&QComboBox::currentIndexChanged), this, &CHotkeyDialog::changeApplicableMachine); @@ -155,7 +154,7 @@ namespace BlackGui void CHotkeyDialog::selectHotkey() { ui->pb_SelectedHotkey->setText("Press any key/button..."); - m_inputManager->startCapture(); + sApp->getInputManager()->startCapture(); } void CHotkeyDialog::combinationSelectionChanged(const CHotkeyCombination &combination) diff --git a/src/blackgui/components/hotkeydialog.h b/src/blackgui/components/hotkeydialog.h index c5d1fe0f9..573e993de 100644 --- a/src/blackgui/components/hotkeydialog.h +++ b/src/blackgui/components/hotkeydialog.h @@ -107,7 +107,6 @@ namespace BlackGui QScopedPointer ui; BlackMisc::Input::CActionHotkey m_actionHotkey; BlackGui::Models::CActionModel m_actionModel; - BlackCore::CInputManager *m_inputManager = nullptr; }; } // ns } // ns diff --git a/src/blackgui/components/settingshotkeycomponent.cpp b/src/blackgui/components/settingshotkeycomponent.cpp index 5c3fff720..3a009d2cd 100644 --- a/src/blackgui/components/settingshotkeycomponent.cpp +++ b/src/blackgui/components/settingshotkeycomponent.cpp @@ -67,7 +67,8 @@ namespace BlackGui void CSettingsHotkeyComponent::registerDummyPttEntry() { - CInputManager::instance()->registerAction(IContextAudio::pttHotkeyAction(), IContextAudio::pttHotkeyIcon()); + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + sApp->getInputManager()->registerAction(IContextAudio::pttHotkeyAction(), IContextAudio::pttHotkeyIcon()); } void CSettingsHotkeyComponent::addEntry() diff --git a/src/blackgui/guiactionbind.cpp b/src/blackgui/guiactionbind.cpp index 8d3ca535d..8f3ee760a 100644 --- a/src/blackgui/guiactionbind.cpp +++ b/src/blackgui/guiactionbind.cpp @@ -19,16 +19,17 @@ namespace BlackGui CGuiActionBindHandler::CGuiActionBindHandler(QAction *action) : QObject(action), m_action(action) { this->connectDestroy(action); + connect(sApp, &CApplication::aboutToShutdown, this, &CGuiActionBindHandler::unbind); } CGuiActionBindHandler::CGuiActionBindHandler(QAbstractButton *button) : QObject(button), m_button(button) { this->connectDestroy(button); + connect(sApp, &CApplication::aboutToShutdown, this, &CGuiActionBindHandler::unbind); } CGuiActionBindHandler::~CGuiActionBindHandler() { - this->unbind(); } CActionBindings CGuiActionBindHandler::bindMenu(QMenu *menu, const QString &path) @@ -87,10 +88,10 @@ namespace BlackGui void CGuiActionBindHandler::unbind() { - Q_ASSERT_X(CInputManager::instance(), Q_FUNC_INFO, "Missing input manager"); if (this->hasTarget()) { - CInputManager::instance()->unbind(m_index); + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + sApp->getInputManager()->unbind(m_index); } this->reset(); } diff --git a/src/blackgui/models/actionmodel.cpp b/src/blackgui/models/actionmodel.cpp index 2daaf37fa..2e2edf44f 100644 --- a/src/blackgui/models/actionmodel.cpp +++ b/src/blackgui/models/actionmodel.cpp @@ -7,7 +7,7 @@ * contained in the LICENSE file. */ -#include "blackcore/inputmanager.h" +#include "blackcore/application.h" #include "blackgui/models/actionitem.h" #include "blackgui/models/actionmodel.h" #include "blackmisc/icons.h" @@ -57,7 +57,7 @@ namespace BlackGui Qt::ItemFlags CActionModel::flags(const QModelIndex &index) const { - if (!index.isValid()) { return 0; } + if (!index.isValid()) { return Qt::NoItemFlags; } const CActionItem *item = static_cast(index.internalPointer()); const Qt::ItemFlags flags = QAbstractItemModel::flags(index); const bool selectable = item && !item->hasChildren(); // only leafs are selectable @@ -103,7 +103,8 @@ namespace BlackGui { m_rootItem.reset(new CActionItem(QString(), QString())); - const QMap availableActionsAndIcons = CInputManager::instance()->allAvailableActionsAndIcons(); + Q_ASSERT_X(sApp && sApp->getInputManager(), Q_FUNC_INFO, "Missing input manager"); + const QMap availableActionsAndIcons = sApp->getInputManager()->allAvailableActionsAndIcons(); QStringList keys = availableActionsAndIcons.keys(); keys.sort(); for (const QString &actionPath : as_const(keys)) diff --git a/src/blackgui/models/actionmodel.h b/src/blackgui/models/actionmodel.h index 58cb49c7b..386fe131d 100644 --- a/src/blackgui/models/actionmodel.h +++ b/src/blackgui/models/actionmodel.h @@ -29,7 +29,7 @@ namespace BlackGui /*! * Action tree model, used with hotkey actions - * \remark data from CInputManager::instance() + * \remark data from CInputManager */ class BLACKGUI_EXPORT CActionModel : public QAbstractItemModel {