From 87b2396edbf105af3e1006a828a0bab308ec3b15 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 28 Jul 2016 22:26:47 +0100 Subject: [PATCH] refs #694 Support human readable names for settings and data cache traits. --- src/blackmisc/datacache.h | 5 ++++- src/blackmisc/settingscache.h | 5 ++++- src/blackmisc/valuecache.cpp | 19 +++++++++++++++++++ src/blackmisc/valuecache.h | 22 ++++++++++++++++++---- tests/blackmisc/testvaluecache.cpp | 4 ++-- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/blackmisc/datacache.h b/src/blackmisc/datacache.h index ffd3506ad..a08b2fb66 100644 --- a/src/blackmisc/datacache.h +++ b/src/blackmisc/datacache.h @@ -296,7 +296,7 @@ namespace BlackMisc //! Must be a void, non-const member function of the owner. template CData(T *owner, NotifySlot slot = nullptr) : - CData::CCached(CDataCache::instance(), Trait::key(), Trait::isValid, Trait::defaultValue(), owner, slot) + CData::CCached(CDataCache::instance(), Trait::key(), Trait::humanReadable(), Trait::isValid, Trait::defaultValue(), owner, slot) { if (Trait::timeToLive() >= 0) { CDataCache::instance()->setTimeToLive(Trait::key(), Trait::timeToLive()); } if (Trait::isPinned()) { CDataCache::instance()->pinValue(Trait::key()); } @@ -393,6 +393,9 @@ namespace BlackMisc //! Key string of the value. Reimplemented in derived class. static const char *key() { qFatal("Not implemented"); return ""; } + //! Optional human readable name. + static const QString &humanReadable() { static const QString name; return name; } + //! 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; } diff --git a/src/blackmisc/settingscache.h b/src/blackmisc/settingscache.h index 972f9dec5..fd2ff4e38 100644 --- a/src/blackmisc/settingscache.h +++ b/src/blackmisc/settingscache.h @@ -79,7 +79,7 @@ namespace BlackMisc //! 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) + CSetting::CCached(CSettingsCache::instance(), Trait::key(), Trait::humanReadable(), Trait::isValid, Trait::defaultValue(), owner, slot) {} //! Reset the setting to its default value. @@ -123,6 +123,9 @@ namespace BlackMisc //! Key string of the value. Reimplemented in derived class. static const char *key() { qFatal("Not implemented"); return ""; } + //! Optional human readable name. + static const QString &humanReadable() { static const QString name; return name; } + //! 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; } diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index b1e5532af..3e6126875 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -473,6 +473,25 @@ namespace BlackMisc changeValues({ values, 0 }); } + QString CValueCache::getHumanReadableName(const QString &key) const + { + QMutexLocker lock(&m_mutex); + return m_humanReadable.value(key, key); + } + + QString CValueCache::getHumanReadableWithKey(const QString &key) const + { + QMutexLocker lock(&m_mutex); + QString hr = m_humanReadable.value(key); + return hr.isEmpty() ? key : QString("%1 (%2)").arg(hr, key); + } + + void CValueCache::setHumanReadableName(const QString &key, const QString &name) + { + QMutexLocker lock(&m_mutex); + if (! m_humanReadable.contains(key)) { m_humanReadable.insert(key, name); } + } + CValueCache::BatchGuard CValueCache::batchChanges(QObject *owner) { Q_ASSERT(QThread::currentThread() == owner->thread()); diff --git a/src/blackmisc/valuecache.h b/src/blackmisc/valuecache.h index 9df45ab49..fd143b3f6 100644 --- a/src/blackmisc/valuecache.h +++ b/src/blackmisc/valuecache.h @@ -220,6 +220,15 @@ namespace BlackMisc //! \threadsafe void clearAllValues(const QString &keyPrefix = {}); + //! Return the human readable name of the given key, or the raw key string if there is none. + QString getHumanReadableName(const QString &key) const; + + //! Return the human readable name of the given key, with the raw key string appended. + QString getHumanReadableWithKey(const QString &key) const; + + //! \private + void setHumanReadableName(const QString &key, const QString &name); + //! Begins a batch of changes to be made through CCached instances owned by owner. //! \details All changes made through those CCached instances will be deferred until the returned RAII object is //! destroyed. If the destruction happens during stack unwinding due to an exception being thrown, the changes are @@ -297,6 +306,7 @@ namespace BlackMisc using ElementPtr = QSharedPointer; // QMap doesn't support move-only types QMap m_elements; + QMap m_humanReadable; Element &getElement(const QString &key); Element &getElement(const QString &key, QMap::const_iterator pos); @@ -329,25 +339,29 @@ namespace BlackMisc //! Constructor. //! \param cache The CValueCache object which manages the value. //! \param key The key string which identifies the value. + //! \param name Human readable name corresponding to the key. //! \param owner Will be the parent of the internal QObject used for signal/slot connections. //! \param slot A member function of owner which will be called when the value is changed by another source. template - CCached(CValueCache *cache, const QString &key, U *owner, NotifySlot slot = nullptr) : - CCached(cache, key, nullptr, T{}, owner, slot) + CCached(CValueCache *cache, const QString &key, const QString &name, U *owner, NotifySlot slot = nullptr) : + CCached(cache, key, name, nullptr, T{}, owner, slot) {} //! Constructor. //! \param cache The CValueCache object which manages the value. //! \param key The key string which identifies the value. + //! \param name Human readable name corresponding to the key. //! \param validator A functor which tests the validity of a value and returns true if it is valid. //! \param defaultValue A value which will be used as default if the value is invalid. //! \param owner Will be the parent of the internal QObject used for signal/slot connections. //! \param slot A member function of owner which will be called when the value is changed by another source. template - CCached(CValueCache *cache, const QString &key, F validator, const T &defaultValue, U *owner, NotifySlot slot = nullptr) : + CCached(CValueCache *cache, const QString &key, const QString &name, F validator, const T &defaultValue, U *owner, NotifySlot slot = nullptr) : m_page(Private::CValuePage::getPageFor(owner, cache)), m_element(m_page.createElement(key, qMetaTypeId(), wrap(validator), CVariant::from(defaultValue), slot_cast(slot))) - {} + { + cache->setHumanReadableName(key, name); + } //! Read the current value. const T &getThreadLocal() const { static const T empty {}; return *(isValid() ? static_cast(getVariant().data()) : &empty); } diff --git a/tests/blackmisc/testvaluecache.cpp b/tests/blackmisc/testvaluecache.cpp index 1d9864194..1c1c45f56 100644 --- a/tests/blackmisc/testvaluecache.cpp +++ b/tests/blackmisc/testvaluecache.cpp @@ -270,8 +270,8 @@ namespace BlackMiscTest } CValueCacheUser::CValueCacheUser(CValueCache *cache) : - m_value1(cache, "value1", validator, 0, this, &CValueCacheUser::ps_valueChanged), - m_value2(cache, "value2", validator, 0, this, &CValueCacheUser::ps_valueChanged) + m_value1(cache, "value1", "", validator, 0, this, &CValueCacheUser::ps_valueChanged), + m_value2(cache, "value2", "", validator, 0, this, &CValueCacheUser::ps_valueChanged) {} void CValueCacheUser::ps_valueChanged()