diff --git a/src/blackcore/blackcore.pro b/src/blackcore/blackcore.pro index 805374881..a355fab06 100644 --- a/src/blackcore/blackcore.pro +++ b/src/blackcore/blackcore.pro @@ -24,6 +24,7 @@ precompile_header:!isEmpty(PRECOMPILED_HEADER) { DEFINES += LOG_IN_FILE BUILD_BLACKCORE_LIB HEADERS += *.h + $$PWD/settings/*.h SOURCES += *.cpp LIBS *= -lvatlib2 diff --git a/src/blackcore/context_application.cpp b/src/blackcore/context_application.cpp index 8c6b69a08..b4b778d38 100644 --- a/src/blackcore/context_application.cpp +++ b/src/blackcore/context_application.cpp @@ -12,6 +12,7 @@ #include "blackcore/context_application_proxy.h" #include "blackcore/context_settings.h" #include "blackcore/input_manager.h" +#include "blackcore/settingscache.h" #include "blackmisc/statusmessage.h" #include "blackmisc/loghandler.h" #include @@ -46,9 +47,26 @@ namespace BlackCore this->logMessage(message, {}); }); + connect(CSettingsCache::instance(), &CSettingsCache::valuesChangedByLocal, [this](const CVariantMap &settings) + { + this->changeSettings(settings, {}); + }); + connect(this, &IContextApplication::settingsChanged, [](const CVariantMap &settings, const CIdentifier &origin) + { + // Intentionally don't check for round trip here + CSettingsCache::instance()->changeValuesFromRemote(settings, origin); + }); + changeSettings(IContextSettings::SettingsHotKeys); } + void IContextApplication::changeSettings(const CVariantMap &settings, const CIdentifier &origin) + { + Q_UNUSED(settings); + Q_UNUSED(origin); + qFatal("Not implemented"); // avoid losing a change during context interface construction + } + void IContextApplication::changeSettings(uint typeValue) { auto type = static_cast(typeValue); diff --git a/src/blackcore/context_application.h b/src/blackcore/context_application.h index a49e7de3b..c349c7acd 100644 --- a/src/blackcore/context_application.h +++ b/src/blackcore/context_application.h @@ -18,6 +18,7 @@ #include "blackmisc/audio/voiceroomlist.h" #include "blackmisc/eveventhotkeyfunction.h" #include "blackmisc/identifierlist.h" +#include "blackmisc/variantmap.h" #include #include @@ -78,6 +79,10 @@ namespace BlackCore //! \note Used with CLogMessage, do not use directly void messageLogged(const BlackMisc::CStatusMessage &message, const BlackMisc::CIdentifier &origin); + //! One or more settings were changed + //! \note Used for cache relay, do not use directly + void settingsChanged(const BlackMisc::CVariantMap &settings, const BlackMisc::CIdentifier &origin); + //! Work around for audio context, #382 void fakedSetComVoiceRoom(const BlackMisc::Audio::CVoiceRoomList &requestedRooms); @@ -87,6 +92,11 @@ namespace BlackCore //! \note this is the function which relays CLogMessage via DBus virtual void logMessage(const BlackMisc::CStatusMessage &message, const BlackMisc::CIdentifier &origin) { Q_UNUSED(message); Q_UNUSED(origin); } + //! Ratify some settings changed by another process + //! \note Not pure because it can be called from the base class constructor. + //! \note This is the function which relays cache changes via DBus. + virtual void changeSettings(const BlackMisc::CVariantMap &settings, const BlackMisc::CIdentifier &origin); + //! Register application, can also be used for ping virtual BlackMisc::CIdentifier registerApplication(const BlackMisc::CIdentifier &application) = 0; diff --git a/src/blackcore/context_application_impl.cpp b/src/blackcore/context_application_impl.cpp index 454f61b61..77f23c547 100644 --- a/src/blackcore/context_application_impl.cpp +++ b/src/blackcore/context_application_impl.cpp @@ -10,6 +10,7 @@ #include "context_application_impl.h" #include "context_runtime.h" #include "input_manager.h" +#include "settingscache.h" #include "blackmisc/settingutilities.h" #include "blackmisc/logmessage.h" #include "blackmisc/loghandler.h" @@ -40,6 +41,12 @@ namespace BlackCore emit this->messageLogged(message, origin); } + void CContextApplication::changeSettings(const CVariantMap &settings, const CIdentifier &origin) + { + // Intentionally don't check for round trip here + emit this->settingsChanged(settings, origin); + } + bool CContextApplication::writeToFile(const QString &fileName, const QString &content) { if (m_debugEnabled) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << fileName << content.left(25); } diff --git a/src/blackcore/context_application_impl.h b/src/blackcore/context_application_impl.h index 57e236085..0d49dbf51 100644 --- a/src/blackcore/context_application_impl.h +++ b/src/blackcore/context_application_impl.h @@ -32,6 +32,9 @@ namespace BlackCore //! \copydoc IContextApplication::logMessage virtual void logMessage(const BlackMisc::CStatusMessage &message, const BlackMisc::CIdentifier &origin) override; + //! \copydoc IContextApplication::changeSettings + virtual void changeSettings(const BlackMisc::CVariantMap &settings, const BlackMisc::CIdentifier &origin) override; + //! \copydoc IContextApplication::writeToFile virtual bool writeToFile(const QString &fileName, const QString &content) override; @@ -56,6 +59,10 @@ namespace BlackCore //! \copydoc IContextApplication::processHotkeyFuncEvent virtual void processHotkeyFuncEvent(const BlackMisc::Event::CEventHotkeyFunction &event) override; + public: + //! \todo Remove with old settings + using IContextApplication::changeSettings; + protected: //! Constructor CContextApplication(CRuntimeConfig::ContextMode mode, CRuntime *runtime); diff --git a/src/blackcore/context_application_proxy.cpp b/src/blackcore/context_application_proxy.cpp index 902e46bad..e8113e888 100644 --- a/src/blackcore/context_application_proxy.cpp +++ b/src/blackcore/context_application_proxy.cpp @@ -9,6 +9,7 @@ #include "blackcore/context_application_proxy.h" #include "blackcore/input_manager.h" +#include "blackcore/settingscache.h" #include "blackmisc/blackmiscfreefunctions.h" #include "blackmisc/loghandler.h" #include "blackmisc/identifierlist.h" @@ -61,6 +62,11 @@ namespace BlackCore this->m_dBusInterface->callDBus(QLatin1Literal("logMessage"), message, origin); } + void CContextApplicationProxy::changeSettings(const CVariantMap &settings, const CIdentifier &origin) + { + this->m_dBusInterface->callDBus(QLatin1Literal("changeSettings"), settings, origin); + } + BlackMisc::CIdentifier CContextApplicationProxy::registerApplication(const CIdentifier &application) { return this->m_dBusInterface->callDBusRet(QLatin1Literal("registerApplication"), application); diff --git a/src/blackcore/context_application_proxy.h b/src/blackcore/context_application_proxy.h index e0d9dfacd..a326214de 100644 --- a/src/blackcore/context_application_proxy.h +++ b/src/blackcore/context_application_proxy.h @@ -28,6 +28,9 @@ namespace BlackCore //! \copydoc IContextApplication::logMessage virtual void logMessage(const BlackMisc::CStatusMessage &message, const BlackMisc::CIdentifier &origin) override; + //! \copydoc IContextApplication::changeSettings + virtual void changeSettings(const BlackMisc::CVariantMap &settings, const BlackMisc::CIdentifier &origin) override; + //! \copydoc IContextApplication::registerApplication virtual BlackMisc::CIdentifier registerApplication(const BlackMisc::CIdentifier &application) override; @@ -52,6 +55,10 @@ namespace BlackCore //! \copydoc IContextApplication::processHotkeyFuncEvent virtual void processHotkeyFuncEvent(const BlackMisc::Event::CEventHotkeyFunction &event) override; + public: + //! \todo Remove with old settings + using IContextApplication::changeSettings; + protected: //! Constructor CContextApplicationProxy(CRuntimeConfig::ContextMode mode, CRuntime *runtime) : IContextApplication(mode, runtime), m_dBusInterface(nullptr) {} diff --git a/src/blackcore/context_runtime.cpp b/src/blackcore/context_runtime.cpp index effc401c0..05bd3b444 100644 --- a/src/blackcore/context_runtime.cpp +++ b/src/blackcore/context_runtime.cpp @@ -148,8 +148,9 @@ namespace BlackCore if (this->m_contextSettings && this->m_contextApplication) { + // \todo Remove with old settings c = connect(this->m_contextSettings, &IContextSettings::changedSettings, - this->getIContextApplication(), &IContextApplication::changeSettings); + this->getIContextApplication(), static_cast(&IContextApplication::changeSettings)); Q_ASSERT(c); } times.insert("Post setup, connects first", time.restart()); diff --git a/src/blackcore/settingscache.cpp b/src/blackcore/settingscache.cpp new file mode 100644 index 000000000..83ea1870c --- /dev/null +++ b/src/blackcore/settingscache.cpp @@ -0,0 +1,25 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "settingscache.h" + +namespace BlackCore +{ + + CSettingsCache::CSettingsCache() : + CValueCache(CValueCache::Distributed) + {} + + CSettingsCache *CSettingsCache::instance() + { + static CSettingsCache cache; + return &cache; + } + +} diff --git a/src/blackcore/settingscache.h b/src/blackcore/settingscache.h new file mode 100644 index 000000000..fb7c83ef7 --- /dev/null +++ b/src/blackcore/settingscache.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2015 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKCORE_SETTINGSCACHE_H +#define BLACKCORE_SETTINGSCACHE_H + +#include "blackcore/blackcoreexport.h" +#include "blackmisc/valuecache.h" + +namespace BlackCore +{ + + /*! + * Singleton derived class of CValueCache, for core settings. + */ + class BLACKCORE_EXPORT CSettingsCache : public BlackMisc::CValueCache + { + public: + //! Return the singleton instance. + static CSettingsCache *instance(); + + private: + CSettingsCache(); + }; + + /*! + * Class template for accessing a specific value in the CSettingsCache. + * \tparam Trait A subclass of BlackCore::CSettingTrait that identifies the value's key and other metadata. + */ + template + class CSetting : public BlackMisc::CCached + { + public: + //! \copydoc BlackMisc::CCached::NotifySlot + template + using NotifySlot = typename BlackMisc::CCached::template NotifySlot; + + //! Constructor. + //! \param owner Will be the parent of the internal QObject used to access the value. + //! \param slot Slot to call when the value is modified by another object. + //! Must be a void, non-const member function of the owner. + template + CSetting(T *owner, NotifySlot slot = nullptr) : + CSetting::CCached(CSettingsCache::instance(), Trait::key(), Trait::isValid, Trait::defaultValue(), owner, slot) + {} + + //! Reset the setting to its default value. + void setDefault() { this->set(Trait::defaultValue()); } + }; + + /*! + * Base class for traits to be used as template argument to BlackCore::CSetting. + */ + template + struct CSettingTrait + { + //! Data type of the value. + using type = T; + + //! Key string of the value. Reimplemented in derived class. + static const char *key() { qFatal("Not implemented"); return ""; } + + //! Validator function. Return true if the argument is valid, false otherwise. Default + //! implementation just returns true. Reimplemented in derived class to support validation of the value. + static bool isValid(const T &) { return true; } + + //! Return the value to use in case the supplied value does not satisfy the validator. + //! Default implementation returns a default-constructed value. + static const T &defaultValue() { static const T def {}; return def; } + + //! Deleted default constructor. + CSettingTrait() = delete; + + //! Deleted copy constructor. + CSettingTrait(const CSettingTrait &) = delete; + + //! Deleted copy assignment operator. + CSettingTrait &operator =(const CSettingTrait &) = delete; + }; + +} + +#endif