refs #694 Support human readable names for settings and data cache traits.

This commit is contained in:
Mathew Sutcliffe
2016-07-28 22:26:47 +01:00
parent 61f3655b2c
commit 87b2396edb
5 changed files with 47 additions and 8 deletions

View File

@@ -296,7 +296,7 @@ namespace BlackMisc
//! Must be a void, non-const member function of the owner.
template <typename T>
CData(T *owner, NotifySlot<T> 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; }

View File

@@ -79,7 +79,7 @@ namespace BlackMisc
//! Must be a void, non-const member function of the owner.
template <typename T>
CSetting(T *owner, NotifySlot<T> 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; }

View File

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

View File

@@ -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<Element>; // QMap doesn't support move-only types
QMap<QString, ElementPtr> m_elements;
QMap<QString, QString> m_humanReadable;
Element &getElement(const QString &key);
Element &getElement(const QString &key, QMap<QString, ElementPtr>::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 <typename U>
CCached(CValueCache *cache, const QString &key, U *owner, NotifySlot<U> slot = nullptr) :
CCached(cache, key, nullptr, T{}, owner, slot)
CCached(CValueCache *cache, const QString &key, const QString &name, U *owner, NotifySlot<U> 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 <typename U, typename F>
CCached(CValueCache *cache, const QString &key, F validator, const T &defaultValue, U *owner, NotifySlot<U> slot = nullptr) :
CCached(CValueCache *cache, const QString &key, const QString &name, F validator, const T &defaultValue, U *owner, NotifySlot<U> slot = nullptr) :
m_page(Private::CValuePage::getPageFor(owner, cache)),
m_element(m_page.createElement(key, qMetaTypeId<T>(), 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<const T *>(getVariant().data()) : &empty); }

View File

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