From 633ec9807d945cdda1e35e54ed30b5d0218edde3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 2 Feb 2015 15:56:03 -0800 Subject: [PATCH] New settings api --- libraries/shared/src/Settings.cpp | 136 +++++++++++++++++++++++----- libraries/shared/src/Settings.h | 145 +++++++++++------------------- 2 files changed, 166 insertions(+), 115 deletions(-) diff --git a/libraries/shared/src/Settings.cpp b/libraries/shared/src/Settings.cpp index 33cab0b735..309d5a1ae4 100644 --- a/libraries/shared/src/Settings.cpp +++ b/libraries/shared/src/Settings.cpp @@ -9,35 +9,125 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include +#include #include #include -#include +#include +#include "PathUtils.h" #include "Settings.h" -namespace SettingHandles { +namespace Setting { + class Manager : public QSettings { + public: + ~Manager(); + void registerHandle(Interface* handle); + void removeHandle(const QString& key); + + void loadSetting(Interface* handle); + void saveSetting(Interface* handle); + void saveAll(); + + private: + QHash _handles; + }; + Manager* privateInstance = nullptr; -static QThreadStorage storage; - -QSettings* getSettings() { - if (!storage.hasLocalData()) { - storage.setLocalData(new QSettings()); - QObject::connect(QThread::currentThread(), &QThread::destroyed, - storage.localData(), &QSettings::deleteLater); + // cleans up the settings private instance. Should only be run once at closing down. + void cleanupPrivateInstance() { + delete privateInstance; + privateInstance = nullptr; } - return storage.localData(); -} -QVariant SettingsBridge::getFromSettings(const QString& key, const QVariant& defaultValue) { - return getSettings()->value(key, defaultValue); -} - -void SettingsBridge::setInSettings(const QString& key, const QVariant& value) { - getSettings()->setValue(key, value); -} + // Sets up the settings private instance. Should only be run once at startup + void setupPrivateInstance() { + // read the ApplicationInfo.ini file for Name/Version/Domain information + QSettings::setDefaultFormat(QSettings::IniFormat); + QSettings applicationInfo(PathUtils::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); + // set the associated application properties + applicationInfo.beginGroup("INFO"); + QCoreApplication::setApplicationName(applicationInfo.value("name").toString()); + QCoreApplication::setOrganizationName(applicationInfo.value("organizationName").toString()); + QCoreApplication::setOrganizationDomain(applicationInfo.value("organizationDomain").toString()); + + // Let's set up the settings Private instance on it's own thread + QThread* thread = new QThread(); + Q_CHECK_PTR(thread); + privateInstance = new Manager(); + Q_CHECK_PTR(privateInstance); + thread->setObjectName("Settings Thread"); + QObject::connect(privateInstance, SIGNAL(destroyed()), thread, SLOT(quit())); + QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + privateInstance->moveToThread(thread); + thread->start(); + qDebug() << "Settings thread started."; + + // Register cleanupPrivateInstance to run inside QCoreApplication's destructor. + qAddPostRoutine(cleanupPrivateInstance); + } + // Register setupPrivateInstance to run after QCoreApplication's constructor. + Q_COREAPP_STARTUP_FUNCTION(setupPrivateInstance) -void SettingsBridge::removeFromSettings(const QString& key) { - getSettings()->remove(key); -} - -} + Interface::~Interface() { + if (privateInstance) { + privateInstance->removeHandle(_key); + } + } + + void Interface::init() { + if (privateInstance) { + // Register Handle + privateInstance->registerHandle(this); + _isInitialized = true; + + // Load value from disk + privateInstance->loadSetting(this); + } else { + qWarning() << "Setting::Interface::init(): Manager not yet created"; + } + } + + void Interface::maybeInit() { + if (!_isInitialized) { + init(); + } + } + + Manager::~Manager() { + saveAll(); + sync(); + } + + void Manager::registerHandle(Setting::Interface* handle) { + QString key = handle->getKey(); + if (_handles.contains(key)) { + qWarning() << "Setting::Manager::registerHandle(): Key registered more than once, overriding: " << key; + } + _handles.insert(key, handle); + } + + void Manager::removeHandle(const QString& key) { + _handles.remove(key); + } + + void Manager::loadSetting(Interface* handle) { + handle->setVariant(value(handle->getKey())); + } + + void Manager::saveSetting(Interface* handle) { + if (handle->isSet()) { + setValue(handle->getKey(), handle->getVariant()); + } else { + remove(handle->getKey()); + } + } + + void Manager::saveAll() { + for (auto handle : _handles) { + saveSetting(handle); + } + } + +} \ No newline at end of file diff --git a/libraries/shared/src/Settings.h b/libraries/shared/src/Settings.h index c1ebd73058..87fbc3d87b 100644 --- a/libraries/shared/src/Settings.h +++ b/libraries/shared/src/Settings.h @@ -21,101 +21,62 @@ class Settings : public QSettings { }; -namespace SettingHandles { - -template -class SettingHandle { -public: - SettingHandle(const QString& key); - SettingHandle(const QStringList& path); - SettingHandle(const QString& key, const T& defaultValue); - SettingHandle(const QStringList& path, const T& defaultValue); - - T get() const; // Returns setting value, returns its default value if not found - T get(const T& other) const; // Returns setting value, returns other if not found - T getDefault() const; - - void set(const T& value) const; - void reset() const; - - void remove() const; - -private: - const QString _key; - const QVariant _defaultValue; -}; - -class SettingsBridge { -private: - static QVariant getFromSettings(const QString& key, const QVariant& defaultValue); - static void setInSettings(const QString& key, const QVariant& value); - static void removeFromSettings(const QString& key); - - template - friend class SettingHandle; -}; - -template -SettingHandle::SettingHandle(const QString& key) : _key(key) { -} - -template -SettingHandle::SettingHandle(const QStringList& path) : _key(path.join("/")) { -} - -template -SettingHandle::SettingHandle(const QString& key, const T& defaultValue) : - _key(key), - _defaultValue(defaultValue) { -} - -template -SettingHandle::SettingHandle(const QStringList& path, const T& defaultValue) : - _key(path.join("/")), - _defaultValue(defaultValue) { +namespace Setting { + class Interface { + protected: + Interface(const QString& key) : _key(key) {} + virtual ~Interface(); + void init(); + void maybeInit(); -} - -template -T SettingHandle::get() const { - QVariant variant = SettingsBridge::getFromSettings(_key, _defaultValue); - if (variant.canConvert()) { - return variant.value(); - } - return _defaultValue.value(); -} - -template -T SettingHandle::get(const T& other) const { - QVariant variant = SettingsBridge::getFromSettings(_key, QVariant(other)); - if (variant.canConvert()) { - return variant.value(); - } - return other; -} - -template inline -T SettingHandle::getDefault() const { - return _defaultValue.value(); -} - -template inline -void SettingHandle::set(const T& value) const { - if (value != get()) { - SettingsBridge::setInSettings(_key, QVariant(value)); - } -} - -template inline -void SettingHandle::reset() const { - SettingsBridge::setInSettings(_key, _defaultValue); -} + QString getKey() const { return _key; } + bool isSet() const { return _isSet; } + + virtual void setVariant(const QVariant& variant) = 0; + virtual QVariant getVariant() = 0; + + bool _isInitialized = false; + bool _isSet = false; + const QString _key; + + friend class Manager; + }; -template inline -void SettingHandle::remove() const { - SettingsBridge::removeFromSettings(_key); -} + template + class Handle : public Interface { + public: + Handle(const QString& key) : Interface(key) {} + Handle(const QStringList& path) : Interface(path.join("/")) {} + + Handle(const QString& key, const T& defaultValue) : Interface(key), _defaultValue(defaultValue) {} + Handle(const QStringList& path, const T& defaultValue) : Handle(path.join("/"), defaultValue) {} + + // Returns setting value, returns its default value if not found + T get() { return get(_defaultValue); } + // Returns setting value, returns other if not found + T get(const T& other) { maybeInit(); return (_isSet) ? _value : other; } + T getDefault() const { return _defaultValue; } + + void set(const T& value) { maybeInit(); _value = value; _isSet = true; } + void reset() { set(_defaultValue); } + + void remove() { maybeInit(); _isSet = false; } + + protected: + virtual void setVariant(const QVariant& variant); + virtual QVariant getVariant() { return QVariant::fromValue(get()); } + + private: + T _value; + const T _defaultValue; + }; + template + void Handle::setVariant(const QVariant& variant) { + if (variant.canConvert()) { + set(variant.value()); + } + } } #endif // hifi_Settings_h \ No newline at end of file