mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
348 lines
10 KiB
C++
348 lines
10 KiB
C++
//
|
|
// SettingHandle.h
|
|
//
|
|
//
|
|
// Created by Clement on 1/18/15.
|
|
// Copyright 2015 High Fidelity, Inc.
|
|
// Copyright 2022 Overte e.V.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#ifndef hifi_SettingHandle_h
|
|
#define hifi_SettingHandle_h
|
|
|
|
#include <type_traits>
|
|
|
|
#include <QtCore/QStack>
|
|
#include <QtCore/QString>
|
|
#include <QtCore/QVariant>
|
|
#include <QtCore/QReadWriteLock>
|
|
#include <QtCore/QSharedPointer>
|
|
#include <QtCore/QDebug>
|
|
#include <QLoggingCategory>
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/quaternion.hpp>
|
|
|
|
#include "SettingInterface.h"
|
|
|
|
|
|
Q_DECLARE_LOGGING_CATEGORY(settings_handle)
|
|
|
|
/**
|
|
* @brief Name of the fully private settings group
|
|
*
|
|
* Settings in this group will be protected from reading and writing from script engines.
|
|
*
|
|
*/
|
|
|
|
extern const QString SETTINGS_FULL_PRIVATE_GROUP_NAME;
|
|
|
|
/**
|
|
* @brief QSettings analog
|
|
*
|
|
* This class emulates the interface of QSettings, and forwards all reads and writes to the global Setting::Manager.
|
|
*
|
|
* It should be used in the same manner as QSettings -- created only wherever it happens to be needed.
|
|
* It's not thread safe, and each thread should have their own.
|
|
*
|
|
* Unlike QSettings, destruction doesn't cause the config to be saved, instead Config::Manager is in
|
|
* charge of taking care of that.
|
|
*
|
|
* @note childGroups and childKeys are unimplemented because nothing in the code needs them so far.
|
|
*/
|
|
class Settings {
|
|
public:
|
|
|
|
class Group {
|
|
public:
|
|
|
|
Group(const QString &groupName = QString()) {
|
|
_name = groupName;
|
|
}
|
|
|
|
QString name() const { return _name; }
|
|
|
|
bool isArray() const { return _arraySize != -1; }
|
|
|
|
void setIndex(int i) {
|
|
if ( _arraySize < i+1) {
|
|
_arraySize = i+1;
|
|
}
|
|
|
|
_arrayIndex = i;
|
|
}
|
|
|
|
int index() const { return _arrayIndex; }
|
|
int size() const { return _arraySize; }
|
|
void setSize(int sz) { _arraySize = sz; }
|
|
|
|
private:
|
|
|
|
QString _name;
|
|
int _arrayIndex{0};
|
|
int _arraySize{-1};
|
|
};
|
|
|
|
static const QString firstRun;
|
|
Settings();
|
|
|
|
QString fileName() const;
|
|
|
|
void remove(const QString& key);
|
|
|
|
// These are not currently being used
|
|
// QStringList childGroups() const;
|
|
// QStringList childKeys() const;
|
|
|
|
QStringList allKeys() const;
|
|
bool contains(const QString& key) const;
|
|
int beginReadArray(const QString & prefix);
|
|
void beginWriteArray(const QString& prefix, int size = -1);
|
|
void endArray();
|
|
void setArrayIndex(int i);
|
|
|
|
void beginGroup(const QString& prefix);
|
|
void endGroup();
|
|
|
|
void setValue(const QString& name, const QVariant& value);
|
|
QVariant value(const QString& name, const QVariant& defaultValue = QVariant()) const;
|
|
|
|
void getFloatValueIfValid(const QString& name, float& floatValue);
|
|
void getBoolValue(const QString& name, bool& boolValue);
|
|
|
|
void setVec3Value(const QString& name, const glm::vec3& vecValue);
|
|
void getVec3ValueIfValid(const QString& name, glm::vec3& vecValue);
|
|
|
|
void setQuatValue(const QString& name, const glm::quat& quatValue);
|
|
void getQuatValueIfValid(const QString& name, glm::quat& quatValue);
|
|
|
|
void clear();
|
|
|
|
private:
|
|
QString getGroupPrefix() const;
|
|
QString getPath(const QString &value) const;
|
|
|
|
QSharedPointer<Setting::Manager> _manager;
|
|
QStack<Group> _groups;
|
|
QString _groupPrefix;
|
|
};
|
|
|
|
namespace Setting {
|
|
|
|
/**
|
|
* @brief Handle to a setting of type T.
|
|
*
|
|
* This creates an object that manipulates a setting in the settings system. Changes will be written
|
|
* to the configuration file at some point controlled by Setting::Manager.
|
|
*
|
|
* @tparam T Type of the setting.
|
|
*/
|
|
template <typename T>
|
|
class Handle : public Interface {
|
|
public:
|
|
|
|
/**
|
|
* @brief Construct handle to a setting
|
|
*
|
|
* @param key The key corresponding to the setting in the settings file. Eg, 'shadowsEnabled'
|
|
*/
|
|
Handle(const QString& key) : Interface(key) {}
|
|
|
|
/**
|
|
* @brief Construct a handle to a setting
|
|
*
|
|
* @param path Path to the key corresponding to the setting in the settings file. Eg, QStringList() << group << key
|
|
*/
|
|
Handle(const QStringList& path) : Interface(path.join("/")) {}
|
|
|
|
/**
|
|
* @brief Construct handle to a setting with a default value
|
|
*
|
|
* @param key The key corresponding to the setting in the settings file. Eg, 'shadowsEnabled'
|
|
* @param defaultValue Default value for this setting
|
|
*/
|
|
Handle(const QString& key, const T& defaultValue) : Interface(key), _defaultValue(defaultValue) {}
|
|
|
|
/**
|
|
* @brief Construct a handle to a setting with a default value
|
|
*
|
|
* @param path Path to the key corresponding to the setting in the settings file. Eg, QStringList() << group << key
|
|
* @param defaultValue Default value for this setting
|
|
*/
|
|
Handle(const QStringList& path, const T& defaultValue) : Handle(path.join("/"), defaultValue) {}
|
|
|
|
/**
|
|
* @brief Construct a handle to a deprecated setting
|
|
*
|
|
* If used, a warning will written to the log.
|
|
*
|
|
* @param key The key corresponding to the setting in the settings file. Eg, 'shadowsEnabled'
|
|
* @return Handle The handle object
|
|
*/
|
|
static Handle Deprecated(const QString& key) {
|
|
Handle handle = Handle(key);
|
|
handle.deprecate();
|
|
return handle;
|
|
}
|
|
|
|
/**
|
|
* @brief Construct a handle to a deprecated setting
|
|
*
|
|
* If used, a warning will written to the log.
|
|
*
|
|
* @param path Path to the key corresponding to the setting in the settings file. Eg, QStringList() << group << key
|
|
* @return Handle The handle object
|
|
*/
|
|
static Handle Deprecated(const QStringList& path) {
|
|
return Deprecated(path.join("/"));
|
|
}
|
|
|
|
/**
|
|
* @brief Construct a handle to a deprecated setting with a default value
|
|
*
|
|
* If used, a warning will written to the log.
|
|
*
|
|
* @param key The key corresponding to the setting in the settings file. Eg, 'shadowsEnabled'
|
|
* @param defaultValue Default value for this setting
|
|
* @return Handle The handle object
|
|
*/
|
|
static Handle Deprecated(const QString& key, const T& defaultValue) {
|
|
Handle handle = Handle(key, defaultValue);
|
|
handle.deprecate();
|
|
return handle;
|
|
}
|
|
|
|
/**
|
|
* @brief Construct a handle to a deprecated setting with a default value
|
|
*
|
|
* If used, a warning will written to the log.
|
|
*
|
|
* @param path Path to the key corresponding to the setting in the settings file. Eg, QStringList() << group << key
|
|
* @param defaultValue Default value for this setting
|
|
* @return Handle The handle object
|
|
*/
|
|
static Handle Deprecated(const QStringList& path, const T& defaultValue) {
|
|
return Deprecated(path.join("/"), defaultValue);
|
|
}
|
|
|
|
virtual ~Handle() {
|
|
deinit();
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the value of the setting, or the default value if not found
|
|
*
|
|
* @return T Value of the associated setting
|
|
*/
|
|
T get() const {
|
|
return get(_defaultValue);
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the value of the setting, or 'other' if not found.
|
|
*
|
|
* @param other Value to return if the setting is not set
|
|
* @return T Value of the associated setting
|
|
*/
|
|
T get(const T& other) const {
|
|
maybeInit();
|
|
return (_isSet) ? _value : other;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns whether the setting is set to a value
|
|
*
|
|
* @return true The setting has a value
|
|
* @return false The setting has no value
|
|
*/
|
|
bool isSet() const {
|
|
maybeInit();
|
|
return _isSet;
|
|
}
|
|
|
|
/**
|
|
* @brief Returns the default value for this setting
|
|
*
|
|
* @return const T& Default value for this setting
|
|
*/
|
|
const T& getDefault() const {
|
|
return _defaultValue;
|
|
}
|
|
|
|
/**
|
|
* @brief Sets the value to the default
|
|
*
|
|
*/
|
|
void reset() {
|
|
set(_defaultValue);
|
|
}
|
|
|
|
/**
|
|
* @brief Set the setting to the specified value.
|
|
*
|
|
* The value will be stored in the configuration file.
|
|
*
|
|
* @param value Value to set the setting to.
|
|
*/
|
|
void set(const T& value) {
|
|
maybeInit();
|
|
|
|
// qCDebug(settings_handle) << "Setting" << this->getKey() << "to" << value;
|
|
|
|
if ((!_isSet && (value != _defaultValue)) || _value != value) {
|
|
_value = value;
|
|
_isSet = true;
|
|
save();
|
|
}
|
|
if (_isDeprecated) {
|
|
deprecate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Remove the value from the setting
|
|
*
|
|
* This returns the setting to an unset state. If read, it will be read as the default value.
|
|
*
|
|
*/
|
|
void remove() {
|
|
maybeInit();
|
|
if (_isSet) {
|
|
_isSet = false;
|
|
save();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
virtual void setVariant(const QVariant& variant) override;
|
|
virtual QVariant getVariant() override { return QVariant::fromValue(get()); }
|
|
|
|
private:
|
|
void deprecate() {
|
|
if (_isSet) {
|
|
if (get() != getDefault()) {
|
|
qCInfo(settings_handle).nospace() << "[DEPRECATION NOTICE] " << _key << "(" << get() << ") has been deprecated, and has no effect";
|
|
} else {
|
|
remove();
|
|
}
|
|
}
|
|
_isDeprecated = true;
|
|
}
|
|
|
|
T _value;
|
|
const T _defaultValue;
|
|
bool _isDeprecated{ false };
|
|
};
|
|
|
|
template <typename T>
|
|
void Handle<T>::setVariant(const QVariant& variant) {
|
|
if (variant.canConvert<T>() || std::is_same<T, QVariant>::value) {
|
|
set(variant.value<T>());
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // hifi_SettingHandle_h
|