diff --git a/src/blackcore/contextapplicationimpl.cpp b/src/blackcore/contextapplicationimpl.cpp index 8269627a0..69a32f8b8 100644 --- a/src/blackcore/contextapplicationimpl.cpp +++ b/src/blackcore/contextapplicationimpl.cpp @@ -22,7 +22,9 @@ namespace BlackCore { CContextApplication::CContextApplication(CRuntimeConfig::ContextMode mode, CRuntime *runtime) : IContextApplication(mode, runtime) - {} + { + connect(CSettingsCache::instance(), &CSettingsCache::valuesSaveRequested, CSettingsCache::instance(), &CSettingsCache::saveToStoreByPacket); + } CContextApplication *CContextApplication::registerWithDBus(BlackMisc::CDBusServer *server) { diff --git a/src/blackmisc/datacache.h b/src/blackmisc/datacache.h index 65cef9203..049975298 100644 --- a/src/blackmisc/datacache.h +++ b/src/blackmisc/datacache.h @@ -148,6 +148,9 @@ namespace BlackMisc //! Deleted copy assignment operator. CDataTrait &operator =(const CDataTrait &) = delete; + + //! Data cache doesn't support setAndSave (because set() already causes save anyway). + CStatusMessage setAndSave(const T &value) = delete; }; } diff --git a/src/blackmisc/settingscache.cpp b/src/blackmisc/settingscache.cpp index db64116c9..c22809f16 100644 --- a/src/blackmisc/settingscache.cpp +++ b/src/blackmisc/settingscache.cpp @@ -8,6 +8,7 @@ */ #include "settingscache.h" +#include "logmessage.h" #include namespace BlackMisc @@ -33,6 +34,15 @@ namespace BlackMisc return saveToFiles(persistentStore(), keyPrefix); } + void CSettingsCache::saveToStoreByPacket(const CValueCachePacket &values) + { + CStatusMessage status = saveToFiles(persistentStore(), values.toVariantMap()); + if (! status.isEmpty()) + { + CLogMessage(this).preformatted(status); + } + } + BlackMisc::CStatusMessage CSettingsCache::loadFromStore() { return loadFromFiles(persistentStore()); diff --git a/src/blackmisc/settingscache.h b/src/blackmisc/settingscache.h index db6f04a5a..71dd24018 100644 --- a/src/blackmisc/settingscache.h +++ b/src/blackmisc/settingscache.h @@ -34,6 +34,10 @@ namespace BlackMisc //! Save core settings to disk. BlackMisc::CStatusMessage saveToStore(const QString &keyPrefix = {}); + //! Save individual settings to disk. + //! Core application context connects this slot to the valuesSaveRequested signal. + void saveToStoreByPacket(const CValueCachePacket &values); + //! Load core settings from disk. BlackMisc::CStatusMessage loadFromStore(); diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index a8bd21509..b7ac01498 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -168,7 +168,7 @@ namespace BlackMisc { QMutexLocker lock(&m_mutex); if (values.empty()) { return; } - CValueCachePacket ratifiedChanges; + CValueCachePacket ratifiedChanges(values.isSaved()); auto out = m_elements.lowerBound(values.cbegin().key()); auto end = m_elements.upperBound((values.cend() - 1).key()); for (auto in = values.cbegin(); in != values.cend(); ++in) @@ -191,6 +191,7 @@ namespace BlackMisc } if (! ratifiedChanges.empty()) { + if (ratifiedChanges.isSaved()) { emit valuesSaveRequested(ratifiedChanges); } emit valuesChanged(ratifiedChanges, nullptr); } } @@ -395,7 +396,7 @@ namespace BlackMisc return element.m_value.read(); } - CStatusMessage CValuePage::setValue(Element &element, const CVariant &value) + CStatusMessage CValuePage::setValue(Element &element, const CVariant &value, bool save) { Q_ASSERT(QThread::currentThread() == thread()); @@ -412,10 +413,10 @@ namespace BlackMisc { Q_ASSERT(isSafeToIncrement(element.m_pendingChanges)); element.m_pendingChanges++; - element.m_saved = false; + element.m_saved = save; element.m_value.uniqueWrite() = value; - emit valuesWantToCache({ { { element.m_key, value } }, QDateTime::currentMSecsSinceEpoch() }); + emit valuesWantToCache({ { { element.m_key, value } }, QDateTime::currentMSecsSinceEpoch(), save }); } } else diff --git a/src/blackmisc/valuecache.h b/src/blackmisc/valuecache.h index 5675e08d6..72fda9a86 100644 --- a/src/blackmisc/valuecache.h +++ b/src/blackmisc/valuecache.h @@ -180,6 +180,10 @@ namespace BlackMisc //! of CValueCache instances in all processes including this one. The slot will do its own round-trip detection. void valuesChangedByLocal(const BlackMisc::CValueCachePacket &values); + //! Emitted when this cache has ratified a change which included a request to save (i.e. via CCaches::setAndSave). + //! If the derived class does not handle such requests, the signal can be ignored. + void valuesSaveRequested(const BlackMisc::CValueCachePacket &values); + private: struct Element; // remove forward declaration when elementsStartingWith uses C++14 auto deduced return type @@ -274,6 +278,9 @@ namespace BlackMisc //! Write a new value. Must be called from the thread in which the owner lives. CStatusMessage set(const T &value) { return m_page.setValue(m_element, CVariant::from(value)); } + //! Write and save in the same step. Must be called from the thread in which the owner lives. + CStatusMessage setAndSave(const T &value) { return m_page.setValue(m_element, CVariant::from(value), true); } + //! Get the key string of this value. const QString &getKey() const { return m_page.getKey(m_element); } diff --git a/src/blackmisc/valuecacheprivate.h b/src/blackmisc/valuecacheprivate.h index 89e0cc5e6..255b4efec 100644 --- a/src/blackmisc/valuecacheprivate.h +++ b/src/blackmisc/valuecacheprivate.h @@ -62,7 +62,7 @@ namespace BlackMisc const CVariant &getValue(const Element &element) const; //! Write the value corresponding to the element's key and begin synchronizing it to any other pages. - CStatusMessage setValue(Element &element, const CVariant &value); + CStatusMessage setValue(Element &element, const CVariant &value, bool save = false); //! Get the key string corresponding to the element. const QString &getKey(const Element &element) const;