Move CInputManager from singleton to CApplication member

The main reason why CInputManager was singleton is the easy access across
the code. That had the negative side effect that time of destruction was
at a very late stage of the shutdown and could not be controlled by us.
My moving it to CApplication, the access is equally easy (using sApp) and
allows to be cleaned up properly during graceful shutdown.

ref T391
This commit is contained in:
Roland Winklmeier
2018-10-12 12:08:02 +02:00
committed by Klaus Basan
parent 705a56b1cb
commit f6ea2a9107
14 changed files with 86 additions and 72 deletions

View File

@@ -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();

View File

@@ -12,7 +12,7 @@
#ifndef BLACKCORE_ACTIONBIND_H
#define BLACKCORE_ACTIONBIND_H
#include "blackcore/inputmanager.h"
#include "blackcore/application.h"
#include "blackcoreexport.h"
#include <QPixmap>
@@ -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 <typename U>
@@ -32,15 +34,18 @@ namespace BlackCore
template <typename Receiver>
CActionBind(const QString &action, const QPixmap &icon, Receiver *receiver,
MembFunc<Receiver> slot = nullptr,
const std::function<void()> &deleteCallback = {}) :
m_deleteCallback(deleteCallback)
const std::function<void()> &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);

View File

@@ -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)

View File

@@ -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<CCoreFacade> m_coreFacade; //!< core facade if any
QScopedPointer<CSetupReader> m_setupReader; //!< setup reader
QScopedPointer<CWebDataServices> m_webDataServices; //!< web data services
QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger
QPointer<CCookieManager> m_cookieManager; //!< single cookie manager for our access manager
const QString m_applicationName; //!< application name
QReadWriteLock m_accessManagerLock; //!< lock to make access manager access threadsafe
CCoreFacadeConfig m_coreFacadeConfig; //!< Core facade config if any
CWebReaderFlags::WebReader m_webReadersUsed; //!< Readers to be used
Db::CDatabaseReaderConfigList m_dbReaderConfig; //!< Load or used caching?
CInputManager *m_inputManager = nullptr; //!< Input devices and hotkeys
QNetworkConfigurationManager *m_networkConfigManager = nullptr; //!< configuration
QNetworkAccessManager *m_accessManager = nullptr; //!< single network access manager
Db::CNetworkWatchdog *m_networkWatchDog = nullptr; //!< checking DB/internet access
BlackMisc::CApplicationInfo m_applicationInfo; //!< Application if specified
QScopedPointer<CCoreFacade> m_coreFacade; //!< core facade if any
QScopedPointer<CSetupReader> m_setupReader; //!< setup reader
QScopedPointer<CWebDataServices> m_webDataServices; //!< web data services
QScopedPointer<BlackMisc::CFileLogger> m_fileLogger; //!< file logger
QPointer<CCookieManager> m_cookieManager; //!< single cookie manager for our access manager
const QString m_applicationName; //!< application name
QReadWriteLock m_accessManagerLock; //!< lock to make access manager access threadsafe
CCoreFacadeConfig m_coreFacadeConfig; //!< Core facade config if any
CWebReaderFlags::WebReader m_webReadersUsed; //!< Readers to be used
Db::CDatabaseReaderConfigList m_dbReaderConfig; //!< Load or used caching?
bool m_noNwAccessPoint = false; //!< no network access point?
bool m_useContexts = false; //!< use contexts
bool m_useWebData = false; //!< use web data

View File

@@ -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

View File

@@ -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
{

View File

@@ -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))

View File

@@ -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