Merge branch 'settings_values_editor_2' into 'master'

Use settings values for editor (#6876)

See merge request OpenMW/openmw!3633
macos_ci_fix
Evil Eye 1 year ago
commit 78da1eb41f

@ -11,9 +11,8 @@
#include "state.hpp" #include "state.hpp"
CSMPrefs::BoolSetting::BoolSetting( CSMPrefs::BoolSetting::BoolSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, bool default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mDefault(default_)
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -27,7 +26,7 @@ CSMPrefs::BoolSetting& CSMPrefs::BoolSetting::setTooltip(const std::string& tool
CSMPrefs::SettingWidgets CSMPrefs::BoolSetting::makeWidgets(QWidget* parent) CSMPrefs::SettingWidgets CSMPrefs::BoolSetting::makeWidgets(QWidget* parent)
{ {
mWidget = new QCheckBox(getLabel(), parent); mWidget = new QCheckBox(getLabel(), parent);
mWidget->setCheckState(mDefault ? Qt::Checked : Qt::Unchecked); mWidget->setCheckState(getValue() ? Qt::Checked : Qt::Unchecked);
if (!mTooltip.empty()) if (!mTooltip.empty())
{ {
@ -44,17 +43,12 @@ void CSMPrefs::BoolSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ {
mWidget->setCheckState( mWidget->setCheckState(getValue() ? Qt::Checked : Qt::Unchecked);
Settings::Manager::getBool(getKey(), getParent()->getKey()) ? Qt::Checked : Qt::Unchecked);
} }
} }
void CSMPrefs::BoolSetting::valueChanged(int value) void CSMPrefs::BoolSetting::valueChanged(int value)
{ {
{ setValue(value != Qt::Unchecked);
QMutexLocker lock(getMutex());
Settings::Manager::setBool(getKey(), getParent()->getKey(), value);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -12,16 +12,16 @@ namespace CSMPrefs
{ {
class Category; class Category;
class BoolSetting : public Setting class BoolSetting final : public TypedSetting<bool>
{ {
Q_OBJECT Q_OBJECT
std::string mTooltip; std::string mTooltip;
bool mDefault;
QCheckBox* mWidget; QCheckBox* mWidget;
public: public:
BoolSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, bool default_); explicit BoolSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
BoolSetting& setTooltip(const std::string& tooltip); BoolSetting& setTooltip(const std::string& tooltip);

@ -5,6 +5,7 @@
#include "setting.hpp" #include "setting.hpp"
#include "state.hpp" #include "state.hpp"
#include "subcategory.hpp"
CSMPrefs::Category::Category(State* parent, const std::string& key) CSMPrefs::Category::Category(State* parent, const std::string& key)
: mParent(parent) : mParent(parent)
@ -23,6 +24,14 @@ CSMPrefs::State* CSMPrefs::Category::getState() const
} }
void CSMPrefs::Category::addSetting(Setting* setting) void CSMPrefs::Category::addSetting(Setting* setting)
{
if (!mIndex.emplace(setting->getKey(), setting).second)
throw std::logic_error("Category " + mKey + " already has setting: " + setting->getKey());
mSettings.push_back(setting);
}
void CSMPrefs::Category::addSubcategory(Subcategory* setting)
{ {
mSettings.push_back(setting); mSettings.push_back(setting);
} }
@ -39,11 +48,12 @@ CSMPrefs::Category::Iterator CSMPrefs::Category::end()
CSMPrefs::Setting& CSMPrefs::Category::operator[](const std::string& key) CSMPrefs::Setting& CSMPrefs::Category::operator[](const std::string& key)
{ {
for (Iterator iter = mSettings.begin(); iter != mSettings.end(); ++iter) const auto it = mIndex.find(key);
if ((*iter)->getKey() == key)
return **iter; if (it != mIndex.end())
return *it->second;
throw std::logic_error("Invalid user setting: " + key); throw std::logic_error("Invalid user setting in " + mKey + " category: " + key);
} }
void CSMPrefs::Category::update() void CSMPrefs::Category::update()

@ -3,12 +3,14 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
namespace CSMPrefs namespace CSMPrefs
{ {
class State; class State;
class Setting; class Setting;
class Subcategory;
class Category class Category
{ {
@ -20,6 +22,7 @@ namespace CSMPrefs
State* mParent; State* mParent;
std::string mKey; std::string mKey;
Container mSettings; Container mSettings;
std::unordered_map<std::string, Setting*> mIndex;
public: public:
Category(State* parent, const std::string& key); Category(State* parent, const std::string& key);
@ -30,6 +33,8 @@ namespace CSMPrefs
void addSetting(Setting* setting); void addSetting(Setting* setting);
void addSubcategory(Subcategory* setting);
Iterator begin(); Iterator begin();
Iterator end(); Iterator end();

@ -14,9 +14,8 @@
#include "state.hpp" #include "state.hpp"
CSMPrefs::ColourSetting::ColourSetting( CSMPrefs::ColourSetting::ColourSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, QColor default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mDefault(std::move(default_))
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -31,7 +30,7 @@ CSMPrefs::SettingWidgets CSMPrefs::ColourSetting::makeWidgets(QWidget* parent)
{ {
QLabel* label = new QLabel(getLabel(), parent); QLabel* label = new QLabel(getLabel(), parent);
mWidget = new CSVWidget::ColorEditor(mDefault, parent); mWidget = new CSVWidget::ColorEditor(toColor(), parent);
if (!mTooltip.empty()) if (!mTooltip.empty())
{ {
@ -48,18 +47,12 @@ CSMPrefs::SettingWidgets CSMPrefs::ColourSetting::makeWidgets(QWidget* parent)
void CSMPrefs::ColourSetting::updateWidget() void CSMPrefs::ColourSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ mWidget->setColor(toColor());
mWidget->setColor(QString::fromStdString(Settings::Manager::getString(getKey(), getParent()->getKey())));
}
} }
void CSMPrefs::ColourSetting::valueChanged() void CSMPrefs::ColourSetting::valueChanged()
{ {
CSVWidget::ColorEditor& widget = dynamic_cast<CSVWidget::ColorEditor&>(*sender()); CSVWidget::ColorEditor& widget = dynamic_cast<CSVWidget::ColorEditor&>(*sender());
{ setValue(widget.color().name().toStdString());
QMutexLocker lock(getMutex());
Settings::Manager::setString(getKey(), getParent()->getKey(), widget.color().name().toUtf8().data());
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -20,16 +20,17 @@ namespace CSVWidget
namespace CSMPrefs namespace CSMPrefs
{ {
class Category; class Category;
class ColourSetting : public Setting
class ColourSetting final : public TypedSetting<std::string>
{ {
Q_OBJECT Q_OBJECT
std::string mTooltip; std::string mTooltip;
QColor mDefault;
CSVWidget::ColorEditor* mWidget; CSVWidget::ColorEditor* mWidget;
public: public:
ColourSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, QColor default_); explicit ColourSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
ColourSetting& setTooltip(const std::string& tooltip); ColourSetting& setTooltip(const std::string& tooltip);

@ -15,12 +15,11 @@
#include "state.hpp" #include "state.hpp"
CSMPrefs::DoubleSetting::DoubleSetting( CSMPrefs::DoubleSetting::DoubleSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, double default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mPrecision(2) , mPrecision(2)
, mMin(0) , mMin(0)
, mMax(std::numeric_limits<double>::max()) , mMax(std::numeric_limits<double>::max())
, mDefault(default_)
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -63,7 +62,7 @@ CSMPrefs::SettingWidgets CSMPrefs::DoubleSetting::makeWidgets(QWidget* parent)
mWidget = new QDoubleSpinBox(parent); mWidget = new QDoubleSpinBox(parent);
mWidget->setDecimals(mPrecision); mWidget->setDecimals(mPrecision);
mWidget->setRange(mMin, mMax); mWidget->setRange(mMin, mMax);
mWidget->setValue(mDefault); mWidget->setValue(getValue());
if (!mTooltip.empty()) if (!mTooltip.empty())
{ {
@ -80,17 +79,11 @@ CSMPrefs::SettingWidgets CSMPrefs::DoubleSetting::makeWidgets(QWidget* parent)
void CSMPrefs::DoubleSetting::updateWidget() void CSMPrefs::DoubleSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ mWidget->setValue(getValue());
mWidget->setValue(Settings::Manager::getFloat(getKey(), getParent()->getKey()));
}
} }
void CSMPrefs::DoubleSetting::valueChanged(double value) void CSMPrefs::DoubleSetting::valueChanged(double value)
{ {
{ setValue(value);
QMutexLocker lock(getMutex());
Settings::Manager::setFloat(getKey(), getParent()->getKey(), value);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -9,7 +9,7 @@ namespace CSMPrefs
{ {
class Category; class Category;
class DoubleSetting : public Setting class DoubleSetting final : public TypedSetting<double>
{ {
Q_OBJECT Q_OBJECT
@ -17,11 +17,11 @@ namespace CSMPrefs
double mMin; double mMin;
double mMax; double mMax;
std::string mTooltip; std::string mTooltip;
double mDefault;
QDoubleSpinBox* mWidget; QDoubleSpinBox* mWidget;
public: public:
DoubleSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, double default_); explicit DoubleSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
DoubleSetting& setPrecision(int precision); DoubleSetting& setPrecision(int precision);

@ -45,9 +45,8 @@ CSMPrefs::EnumValues& CSMPrefs::EnumValues::add(const std::string& value, const
} }
CSMPrefs::EnumSetting::EnumSetting( CSMPrefs::EnumSetting::EnumSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, const EnumValue& default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mDefault(default_)
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -83,16 +82,18 @@ CSMPrefs::SettingWidgets CSMPrefs::EnumSetting::makeWidgets(QWidget* parent)
mWidget = new QComboBox(parent); mWidget = new QComboBox(parent);
size_t index = 0; size_t index = 0;
const std::string value = getValue();
for (size_t i = 0; i < mValues.mValues.size(); ++i) for (size_t i = 0; i < mValues.mValues.size(); ++i)
{ {
if (mDefault.mValue == mValues.mValues[i].mValue) if (value == mValues.mValues[i].mValue)
index = i; index = i;
mWidget->addItem(QString::fromUtf8(mValues.mValues[i].mValue.c_str())); mWidget->addItem(QString::fromUtf8(mValues.mValues[i].mValue.c_str()));
if (!mValues.mValues[i].mTooltip.empty()) if (!mValues.mValues[i].mTooltip.empty())
mWidget->setItemData(i, QString::fromUtf8(mValues.mValues[i].mTooltip.c_str()), Qt::ToolTipRole); mWidget->setItemData(
static_cast<int>(i), QString::fromUtf8(mValues.mValues[i].mTooltip.c_str()), Qt::ToolTipRole);
} }
mWidget->setCurrentIndex(static_cast<int>(index)); mWidget->setCurrentIndex(static_cast<int>(index));
@ -111,20 +112,11 @@ CSMPrefs::SettingWidgets CSMPrefs::EnumSetting::makeWidgets(QWidget* parent)
void CSMPrefs::EnumSetting::updateWidget() void CSMPrefs::EnumSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ mWidget->setCurrentIndex(mWidget->findText(QString::fromStdString(getValue())));
int index
= mWidget->findText(QString::fromStdString(Settings::Manager::getString(getKey(), getParent()->getKey())));
mWidget->setCurrentIndex(index);
}
} }
void CSMPrefs::EnumSetting::valueChanged(int value) void CSMPrefs::EnumSetting::valueChanged(int value)
{ {
{ setValue(mValues.mValues.at(value).mValue);
QMutexLocker lock(getMutex());
Settings::Manager::setString(getKey(), getParent()->getKey(), mValues.mValues.at(value).mValue);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -34,18 +34,17 @@ namespace CSMPrefs
EnumValues& add(const std::string& value, const std::string& tooltip); EnumValues& add(const std::string& value, const std::string& tooltip);
}; };
class EnumSetting : public Setting class EnumSetting final : public TypedSetting<std::string>
{ {
Q_OBJECT Q_OBJECT
std::string mTooltip; std::string mTooltip;
EnumValue mDefault;
EnumValues mValues; EnumValues mValues;
QComboBox* mWidget; QComboBox* mWidget;
public: public:
EnumSetting( explicit EnumSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, const EnumValue& default_); Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
EnumSetting& setTooltip(const std::string& tooltip); EnumSetting& setTooltip(const std::string& tooltip);

@ -15,11 +15,10 @@
#include "state.hpp" #include "state.hpp"
CSMPrefs::IntSetting::IntSetting( CSMPrefs::IntSetting::IntSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, int default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mMin(0) , mMin(0)
, mMax(std::numeric_limits<int>::max()) , mMax(std::numeric_limits<int>::max())
, mDefault(default_)
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -55,7 +54,7 @@ CSMPrefs::SettingWidgets CSMPrefs::IntSetting::makeWidgets(QWidget* parent)
mWidget = new QSpinBox(parent); mWidget = new QSpinBox(parent);
mWidget->setRange(mMin, mMax); mWidget->setRange(mMin, mMax);
mWidget->setValue(mDefault); mWidget->setValue(getValue());
if (!mTooltip.empty()) if (!mTooltip.empty())
{ {
@ -72,17 +71,11 @@ CSMPrefs::SettingWidgets CSMPrefs::IntSetting::makeWidgets(QWidget* parent)
void CSMPrefs::IntSetting::updateWidget() void CSMPrefs::IntSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ mWidget->setValue(getValue());
mWidget->setValue(Settings::Manager::getInt(getKey(), getParent()->getKey()));
}
} }
void CSMPrefs::IntSetting::valueChanged(int value) void CSMPrefs::IntSetting::valueChanged(int value)
{ {
{ setValue(value);
QMutexLocker lock(getMutex());
Settings::Manager::setInt(getKey(), getParent()->getKey(), value);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -12,18 +12,18 @@ namespace CSMPrefs
{ {
class Category; class Category;
class IntSetting : public Setting class IntSetting final : public TypedSetting<int>
{ {
Q_OBJECT Q_OBJECT
int mMin; int mMin;
int mMax; int mMax;
std::string mTooltip; std::string mTooltip;
int mDefault;
QSpinBox* mWidget; QSpinBox* mWidget;
public: public:
IntSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, int default_); explicit IntSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
// defaults to [0, std::numeric_limits<int>::max()] // defaults to [0, std::numeric_limits<int>::max()]
IntSetting& setRange(int min, int max); IntSetting& setRange(int min, int max);

@ -19,8 +19,9 @@ class QWidget;
namespace CSMPrefs namespace CSMPrefs
{ {
ModifierSetting::ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) ModifierSetting::ModifierSetting(
: Setting(parent, mutex, key, label) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: TypedSetting(parent, mutex, key, label, index)
, mButton(nullptr) , mButton(nullptr)
, mEditorActive(false) , mEditorActive(false)
{ {
@ -53,7 +54,7 @@ namespace CSMPrefs
{ {
if (mButton) if (mButton)
{ {
const std::string& shortcut = Settings::Manager::getString(getKey(), getParent()->getKey()); const std::string& shortcut = getValue();
int modifier; int modifier;
State::get().getShortcutManager().convertFromString(shortcut, modifier); State::get().getShortcutManager().convertFromString(shortcut, modifier);
@ -131,15 +132,7 @@ namespace CSMPrefs
void ModifierSetting::storeValue(int modifier) void ModifierSetting::storeValue(int modifier)
{ {
State::get().getShortcutManager().setModifier(getKey(), modifier); State::get().getShortcutManager().setModifier(getKey(), modifier);
setValue(State::get().getShortcutManager().convertToString(modifier));
// Convert to string and assign
std::string value = State::get().getShortcutManager().convertToString(modifier);
{
QMutexLocker lock(getMutex());
Settings::Manager::setString(getKey(), getParent()->getKey(), value);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -15,12 +15,14 @@ class QPushButton;
namespace CSMPrefs namespace CSMPrefs
{ {
class Category; class Category;
class ModifierSetting : public Setting
class ModifierSetting final : public TypedSetting<std::string>
{ {
Q_OBJECT Q_OBJECT
public: public:
ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); explicit ModifierSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
SettingWidgets makeWidgets(QWidget* parent) override; SettingWidgets makeWidgets(QWidget* parent) override;

@ -5,6 +5,7 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/settings/settingvalue.hpp>
#include "category.hpp" #include "category.hpp"
#include "state.hpp" #include "state.hpp"
@ -14,12 +15,14 @@ QMutex* CSMPrefs::Setting::getMutex()
return mMutex; return mMutex;
} }
CSMPrefs::Setting::Setting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) CSMPrefs::Setting::Setting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: QObject(parent->getState()) : QObject(parent->getState())
, mParent(parent) , mParent(parent)
, mMutex(mutex) , mMutex(mutex)
, mKey(key) , mKey(key)
, mLabel(label) , mLabel(label)
, mIndex(index)
{ {
} }
@ -33,30 +36,6 @@ const std::string& CSMPrefs::Setting::getKey() const
return mKey; return mKey;
} }
int CSMPrefs::Setting::toInt() const
{
QMutexLocker lock(mMutex);
return Settings::Manager::getInt(mKey, mParent->getKey());
}
double CSMPrefs::Setting::toDouble() const
{
QMutexLocker lock(mMutex);
return Settings::Manager::getFloat(mKey, mParent->getKey());
}
std::string CSMPrefs::Setting::toString() const
{
QMutexLocker lock(mMutex);
return Settings::Manager::getString(mKey, mParent->getKey());
}
bool CSMPrefs::Setting::isTrue() const
{
QMutexLocker lock(mMutex);
return Settings::Manager::getBool(mKey, mParent->getKey());
}
QColor CSMPrefs::Setting::toColor() const QColor CSMPrefs::Setting::toColor() const
{ {
// toString() handles lock // toString() handles lock

@ -4,8 +4,13 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <QMutexLocker>
#include <QObject> #include <QObject>
#include <components/settings/settingvalue.hpp>
#include "category.hpp"
class QWidget; class QWidget;
class QColor; class QColor;
class QMutex; class QMutex;
@ -14,8 +19,6 @@ class QLabel;
namespace CSMPrefs namespace CSMPrefs
{ {
class Category;
struct SettingWidgets struct SettingWidgets
{ {
QLabel* mLabel; QLabel* mLabel;
@ -31,12 +34,35 @@ namespace CSMPrefs
QMutex* mMutex; QMutex* mMutex;
std::string mKey; std::string mKey;
QString mLabel; QString mLabel;
Settings::Index& mIndex;
protected: protected:
QMutex* getMutex(); QMutex* getMutex();
template <class T>
void resetValueImpl()
{
QMutexLocker lock(mMutex);
return mIndex.get<T>(mParent->getKey(), mKey).reset();
}
template <class T>
T getValueImpl() const
{
QMutexLocker lock(mMutex);
return mIndex.get<T>(mParent->getKey(), mKey).get();
}
template <class T>
void setValueImpl(const T& value)
{
QMutexLocker lock(mMutex);
return mIndex.get<T>(mParent->getKey(), mKey).set(value);
}
public: public:
Setting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); explicit Setting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
~Setting() override = default; ~Setting() override = default;
@ -47,23 +73,42 @@ namespace CSMPrefs
/// \note If make_widgets() has not been called yet then nothing happens. /// \note If make_widgets() has not been called yet then nothing happens.
virtual void updateWidget() = 0; virtual void updateWidget() = 0;
virtual void reset() = 0;
const Category* getParent() const; const Category* getParent() const;
const std::string& getKey() const; const std::string& getKey() const;
const QString& getLabel() const { return mLabel; } const QString& getLabel() const { return mLabel; }
int toInt() const; int toInt() const { return getValueImpl<int>(); }
double toDouble() const; double toDouble() const { return getValueImpl<double>(); }
std::string toString() const; std::string toString() const { return getValueImpl<std::string>(); }
bool isTrue() const; bool isTrue() const { return getValueImpl<bool>(); }
QColor toColor() const; QColor toColor() const;
}; };
template <class T>
class TypedSetting : public Setting
{
public:
using Setting::Setting;
void reset() final
{
resetValueImpl<T>();
updateWidget();
}
T getValue() const { return getValueImpl<T>(); }
void setValue(const T& value) { return setValueImpl(value); }
};
// note: fullKeys have the format categoryKey/settingKey // note: fullKeys have the format categoryKey/settingKey
bool operator==(const Setting& setting, const std::string& fullKey); bool operator==(const Setting& setting, const std::string& fullKey);
bool operator==(const std::string& fullKey, const Setting& setting); bool operator==(const std::string& fullKey, const Setting& setting);

@ -18,8 +18,9 @@
namespace CSMPrefs namespace CSMPrefs
{ {
ShortcutSetting::ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) ShortcutSetting::ShortcutSetting(
: Setting(parent, mutex, key, label) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: TypedSetting(parent, mutex, key, label, index)
, mButton(nullptr) , mButton(nullptr)
, mEditorActive(false) , mEditorActive(false)
, mEditorPos(0) , mEditorPos(0)
@ -57,7 +58,7 @@ namespace CSMPrefs
{ {
if (mButton) if (mButton)
{ {
const std::string& shortcut = Settings::Manager::getString(getKey(), getParent()->getKey()); const std::string shortcut = getValue();
QKeySequence sequence; QKeySequence sequence;
State::get().getShortcutManager().convertFromString(shortcut, sequence); State::get().getShortcutManager().convertFromString(shortcut, sequence);
@ -170,15 +171,7 @@ namespace CSMPrefs
void ShortcutSetting::storeValue(const QKeySequence& sequence) void ShortcutSetting::storeValue(const QKeySequence& sequence)
{ {
State::get().getShortcutManager().setSequence(getKey(), sequence); State::get().getShortcutManager().setSequence(getKey(), sequence);
setValue(State::get().getShortcutManager().convertToString(sequence));
// Convert to string and assign
std::string value = State::get().getShortcutManager().convertToString(sequence);
{
QMutexLocker lock(getMutex());
Settings::Manager::setString(getKey(), getParent()->getKey(), value);
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -17,12 +17,14 @@ class QWidget;
namespace CSMPrefs namespace CSMPrefs
{ {
class Category; class Category;
class ShortcutSetting : public Setting
class ShortcutSetting final : public TypedSetting<std::string>
{ {
Q_OBJECT Q_OBJECT
public: public:
ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); explicit ShortcutSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
SettingWidgets makeWidgets(QWidget* parent) override; SettingWidgets makeWidgets(QWidget* parent) override;

@ -463,11 +463,7 @@ CSMPrefs::IntSetting& CSMPrefs::State::declareInt(const std::string& key, const
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
setDefault(key, std::to_string(default_)); CSMPrefs::IntSetting* setting = new CSMPrefs::IntSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
default_ = Settings::Manager::getInt(key, mCurrentCategory->second.getKey());
CSMPrefs::IntSetting* setting = new CSMPrefs::IntSetting(&mCurrentCategory->second, &mMutex, key, label, default_);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -479,14 +475,8 @@ CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble(const std::string& key,
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
std::ostringstream stream;
stream << default_;
setDefault(key, stream.str());
default_ = Settings::Manager::getFloat(key, mCurrentCategory->second.getKey());
CSMPrefs::DoubleSetting* setting CSMPrefs::DoubleSetting* setting
= new CSMPrefs::DoubleSetting(&mCurrentCategory->second, &mMutex, key, label, default_); = new CSMPrefs::DoubleSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -498,12 +488,7 @@ CSMPrefs::BoolSetting& CSMPrefs::State::declareBool(const std::string& key, cons
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
setDefault(key, default_ ? "true" : "false"); CSMPrefs::BoolSetting* setting = new CSMPrefs::BoolSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
default_ = Settings::Manager::getBool(key, mCurrentCategory->second.getKey());
CSMPrefs::BoolSetting* setting
= new CSMPrefs::BoolSetting(&mCurrentCategory->second, &mMutex, key, label, default_);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -515,12 +500,7 @@ CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum(const std::string& key, cons
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
setDefault(key, default_.mValue); CSMPrefs::EnumSetting* setting = new CSMPrefs::EnumSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
default_.mValue = Settings::Manager::getString(key, mCurrentCategory->second.getKey());
CSMPrefs::EnumSetting* setting
= new CSMPrefs::EnumSetting(&mCurrentCategory->second, &mMutex, key, label, default_);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -532,13 +512,8 @@ CSMPrefs::ColourSetting& CSMPrefs::State::declareColour(const std::string& key,
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
setDefault(key, default_.name().toUtf8().data());
default_.setNamedColor(
QString::fromUtf8(Settings::Manager::getString(key, mCurrentCategory->second.getKey()).c_str()));
CSMPrefs::ColourSetting* setting CSMPrefs::ColourSetting* setting
= new CSMPrefs::ColourSetting(&mCurrentCategory->second, &mMutex, key, label, default_); = new CSMPrefs::ColourSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -551,34 +526,27 @@ CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut(
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
std::string seqStr = getShortcutManager().convertToString(default_);
setDefault(key, seqStr);
// Setup with actual data // Setup with actual data
QKeySequence sequence; QKeySequence sequence;
getShortcutManager().convertFromString( getShortcutManager().convertFromString(mIndex->get<std::string>(mCurrentCategory->second.getKey(), key), sequence);
Settings::Manager::getString(key, mCurrentCategory->second.getKey()), sequence);
getShortcutManager().setSequence(key, sequence); getShortcutManager().setSequence(key, sequence);
CSMPrefs::ShortcutSetting* setting = new CSMPrefs::ShortcutSetting(&mCurrentCategory->second, &mMutex, key, label); CSMPrefs::ShortcutSetting* setting
= new CSMPrefs::ShortcutSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
return *setting; return *setting;
} }
CSMPrefs::StringSetting& CSMPrefs::State::declareString( CSMPrefs::StringSetting& CSMPrefs::State::declareString(
const std::string& key, const QString& label, std::string default_) const std::string& key, const QString& label, const std::string& default_)
{ {
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
setDefault(key, default_);
default_ = Settings::Manager::getString(key, mCurrentCategory->second.getKey());
CSMPrefs::StringSetting* setting CSMPrefs::StringSetting* setting
= new CSMPrefs::StringSetting(&mCurrentCategory->second, &mMutex, key, label, default_); = new CSMPrefs::StringSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
@ -590,17 +558,14 @@ CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier(const std::string& k
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
std::string modStr = getShortcutManager().convertToString(default_);
setDefault(key, modStr);
// Setup with actual data // Setup with actual data
int modifier; int modifier;
getShortcutManager().convertFromString( getShortcutManager().convertFromString(mIndex->get<std::string>(mCurrentCategory->second.getKey(), key), modifier);
Settings::Manager::getString(key, mCurrentCategory->second.getKey()), modifier);
getShortcutManager().setModifier(key, modifier); getShortcutManager().setModifier(key, modifier);
CSMPrefs::ModifierSetting* setting = new CSMPrefs::ModifierSetting(&mCurrentCategory->second, &mMutex, key, label); CSMPrefs::ModifierSetting* setting
= new CSMPrefs::ModifierSetting(&mCurrentCategory->second, &mMutex, key, label, *mIndex);
mCurrentCategory->second.addSetting(setting); mCurrentCategory->second.addSetting(setting);
return *setting; return *setting;
@ -611,17 +576,8 @@ void CSMPrefs::State::declareSubcategory(const QString& label)
if (mCurrentCategory == mCategories.end()) if (mCurrentCategory == mCategories.end())
throw std::logic_error("no category for setting"); throw std::logic_error("no category for setting");
mCurrentCategory->second.addSetting(new CSMPrefs::Subcategory(&mCurrentCategory->second, &mMutex, label)); mCurrentCategory->second.addSubcategory(
} new CSMPrefs::Subcategory(&mCurrentCategory->second, &mMutex, label, *mIndex));
void CSMPrefs::State::setDefault(const std::string& key, const std::string& default_)
{
Settings::CategorySetting fullKey(mCurrentCategory->second.getKey(), key);
Settings::CategorySettingValueMap::iterator iter = Settings::Manager::mDefaultSettings.find(fullKey);
if (iter == Settings::Manager::mDefaultSettings.end())
Settings::Manager::mDefaultSettings.insert(std::make_pair(fullKey, default_));
} }
CSMPrefs::State::State(const Files::ConfigurationManager& configurationManager) CSMPrefs::State::State(const Files::ConfigurationManager& configurationManager)
@ -630,17 +586,14 @@ CSMPrefs::State::State(const Files::ConfigurationManager& configurationManager)
, mConfigurationManager(configurationManager) , mConfigurationManager(configurationManager)
, mCurrentCategory(mCategories.end()) , mCurrentCategory(mCategories.end())
, mIndex(std::make_unique<Settings::Index>()) , mIndex(std::make_unique<Settings::Index>())
, mValues(std::make_unique<Values>(*mIndex))
{ {
if (sThis) if (sThis)
throw std::logic_error("An instance of CSMPRefs::State already exists"); throw std::logic_error("An instance of CSMPRefs::State already exists");
sThis = this; sThis = this;
Values values(*mIndex);
declare(); declare();
mValues = std::make_unique<Values>(std::move(values));
} }
CSMPrefs::State::~State() CSMPrefs::State::~State()
@ -693,27 +646,13 @@ CSMPrefs::State& CSMPrefs::State::get()
void CSMPrefs::State::resetCategory(const std::string& category) void CSMPrefs::State::resetCategory(const std::string& category)
{ {
for (Settings::CategorySettingValueMap::iterator i = Settings::Manager::mUserSettings.begin();
i != Settings::Manager::mUserSettings.end(); ++i)
{
// if the category matches
if (i->first.first == category)
{
// mark the setting as changed
Settings::Manager::mChangedSettings.insert(std::make_pair(i->first.first, i->first.second));
// reset the value to the default
i->second = Settings::Manager::mDefaultSettings[i->first];
}
}
Collection::iterator container = mCategories.find(category); Collection::iterator container = mCategories.find(category);
if (container != mCategories.end()) if (container != mCategories.end())
{ {
Category settings = container->second; for (Setting* setting : container->second)
for (Category::Iterator i = settings.begin(); i != settings.end(); ++i)
{ {
(*i)->updateWidget(); setting->reset();
update(**i); update(*setting);
} }
} }
} }

@ -74,14 +74,12 @@ namespace CSMPrefs
ShortcutSetting& declareShortcut(const std::string& key, const QString& label, const QKeySequence& default_); ShortcutSetting& declareShortcut(const std::string& key, const QString& label, const QKeySequence& default_);
StringSetting& declareString(const std::string& key, const QString& label, std::string default_); StringSetting& declareString(const std::string& key, const QString& label, const std::string& default_);
ModifierSetting& declareModifier(const std::string& key, const QString& label, int modifier_); ModifierSetting& declareModifier(const std::string& key, const QString& label, int modifier_);
void declareSubcategory(const QString& label); void declareSubcategory(const QString& label);
void setDefault(const std::string& key, const std::string& default_);
public: public:
State(const Files::ConfigurationManager& configurationManager); State(const Files::ConfigurationManager& configurationManager);

@ -12,9 +12,8 @@
#include "state.hpp" #include "state.hpp"
CSMPrefs::StringSetting::StringSetting( CSMPrefs::StringSetting::StringSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, std::string_view default_) Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index)
: Setting(parent, mutex, key, label) : TypedSetting(parent, mutex, key, label, index)
, mDefault(default_)
, mWidget(nullptr) , mWidget(nullptr)
{ {
} }
@ -27,7 +26,7 @@ CSMPrefs::StringSetting& CSMPrefs::StringSetting::setTooltip(const std::string&
CSMPrefs::SettingWidgets CSMPrefs::StringSetting::makeWidgets(QWidget* parent) CSMPrefs::SettingWidgets CSMPrefs::StringSetting::makeWidgets(QWidget* parent)
{ {
mWidget = new QLineEdit(QString::fromUtf8(mDefault.c_str()), parent); mWidget = new QLineEdit(QString::fromStdString(getValue()), parent);
if (!mTooltip.empty()) if (!mTooltip.empty())
{ {
@ -43,17 +42,11 @@ CSMPrefs::SettingWidgets CSMPrefs::StringSetting::makeWidgets(QWidget* parent)
void CSMPrefs::StringSetting::updateWidget() void CSMPrefs::StringSetting::updateWidget()
{ {
if (mWidget) if (mWidget)
{ mWidget->setText(QString::fromStdString(getValue()));
mWidget->setText(QString::fromStdString(Settings::Manager::getString(getKey(), getParent()->getKey())));
}
} }
void CSMPrefs::StringSetting::textChanged(const QString& text) void CSMPrefs::StringSetting::textChanged(const QString& text)
{ {
{ setValue(text.toStdString());
QMutexLocker lock(getMutex());
Settings::Manager::setString(getKey(), getParent()->getKey(), text.toStdString());
}
getParent()->getState()->update(*this); getParent()->getState()->update(*this);
} }

@ -14,17 +14,17 @@ class QWidget;
namespace CSMPrefs namespace CSMPrefs
{ {
class Category; class Category;
class StringSetting : public Setting
class StringSetting final : public TypedSetting<std::string>
{ {
Q_OBJECT Q_OBJECT
std::string mTooltip; std::string mTooltip;
std::string mDefault;
QLineEdit* mWidget; QLineEdit* mWidget;
public: public:
StringSetting( explicit StringSetting(
Category* parent, QMutex* mutex, const std::string& key, const QString& label, std::string_view default_); Category* parent, QMutex* mutex, const std::string& key, const QString& label, Settings::Index& index);
StringSetting& setTooltip(const std::string& tooltip); StringSetting& setTooltip(const std::string& tooltip);

@ -6,8 +6,8 @@ namespace CSMPrefs
{ {
class Category; class Category;
Subcategory::Subcategory(Category* parent, QMutex* mutex, const QString& label) Subcategory::Subcategory(Category* parent, QMutex* mutex, const QString& label, Settings::Index& index)
: Setting(parent, mutex, "", label) : Setting(parent, mutex, "", label, index)
{ {
} }

@ -15,11 +15,13 @@ namespace CSMPrefs
Q_OBJECT Q_OBJECT
public: public:
explicit Subcategory(Category* parent, QMutex* mutex, const QString& label); explicit Subcategory(Category* parent, QMutex* mutex, const QString& label, Settings::Index& index);
SettingWidgets makeWidgets(QWidget* parent) override; SettingWidgets makeWidgets(QWidget* parent) override;
void updateWidget() override {} void updateWidget() override {}
void reset() override {}
}; };
} }

@ -7,6 +7,7 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include <apps/opencs/model/prefs/state.hpp>
#include <apps/opencs/model/world/columns.hpp> #include <apps/opencs/model/world/columns.hpp>
#include <apps/opencs/model/world/idcollection.hpp> #include <apps/opencs/model/world/idcollection.hpp>
#include <apps/opencs/model/world/record.hpp> #include <apps/opencs/model/world/record.hpp>
@ -132,11 +133,11 @@ namespace CSMWorld
bool beast = mRaceData ? mRaceData->isBeast() : false; bool beast = mRaceData ? mRaceData->isBeast() : false;
if (beast) if (beast)
return Settings::Manager::getString("baseanimkna", "Models"); return CSMPrefs::get()["Models"]["baseanimkna"].toString();
else if (mFemale) else if (mFemale)
return Settings::Manager::getString("baseanimfemale", "Models"); return CSMPrefs::get()["Models"]["baseanimfemale"].toString();
else else
return Settings::Manager::getString("baseanim", "Models"); return CSMPrefs::get()["Models"]["baseanim"].toString();
} }
ESM::RefId ActorAdapter::ActorData::getPart(ESM::PartReferenceType index) const ESM::RefId ActorAdapter::ActorData::getPart(ESM::PartReferenceType index) const

@ -59,6 +59,33 @@ namespace Settings
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1);
} }
TEST_F(SettingsValuesTest, constructorWithDefaultShouldDoLookup)
{
Manager::mUserSettings[std::make_pair("category", "value")] = "13";
Index index;
SettingValue<int> value{ index, "category", "value", 42 };
EXPECT_EQ(value.get(), 13);
value.reset();
EXPECT_EQ(value.get(), 42);
}
TEST_F(SettingsValuesTest, constructorWithDefaultShouldSanitize)
{
Manager::mUserSettings[std::make_pair("category", "value")] = "2";
Index index;
SettingValue<int> value{ index, "category", "value", -1, Settings::makeClampSanitizerInt(0, 1) };
EXPECT_EQ(value.get(), 1);
value.reset();
EXPECT_EQ(value.get(), 0);
}
TEST_F(SettingsValuesTest, constructorWithDefaultShouldFallbackToDefault)
{
Index index;
const SettingValue<int> value{ index, "category", "value", 42 };
EXPECT_EQ(value.get(), 42);
}
TEST_F(SettingsValuesTest, moveConstructorShouldSetDefaults) TEST_F(SettingsValuesTest, moveConstructorShouldSetDefaults)
{ {
Index index; Index index;
@ -79,6 +106,13 @@ namespace Settings
EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1); EXPECT_EQ(values.mCamera.mFieldOfView.get(), 1);
} }
TEST_F(SettingsValuesTest, moveConstructorShouldThrowOnMissingSetting)
{
Index index;
SettingValue<int> defaultValue{ index, "category", "value", 42 };
EXPECT_THROW([&] { SettingValue<int> value(std::move(defaultValue)); }(), std::runtime_error);
}
TEST_F(SettingsValuesTest, findShouldThrowExceptionOnTypeMismatch) TEST_F(SettingsValuesTest, findShouldThrowExceptionOnTypeMismatch)
{ {
Index index; Index index;

@ -77,6 +77,15 @@ namespace Settings
static osg::Vec2f getVector2(std::string_view setting, std::string_view category); static osg::Vec2f getVector2(std::string_view setting, std::string_view category);
static osg::Vec3f getVector3(std::string_view setting, std::string_view category); static osg::Vec3f getVector3(std::string_view setting, std::string_view category);
template <class T>
static T getOrDefault(std::string_view setting, std::string_view category, const T& defaultValue)
{
const auto key = std::make_pair(category, setting);
if (!mUserSettings.contains(key) && !mDefaultSettings.contains(key))
return defaultValue;
return get<T>(setting, category);
}
template <class T> template <class T>
static T get(std::string_view setting, std::string_view category) static T get(std::string_view setting, std::string_view category)
{ {

@ -339,8 +339,8 @@ namespace Settings
std::unique_ptr<const Sanitizer<T>>&& sanitizer = nullptr) std::unique_ptr<const Sanitizer<T>>&& sanitizer = nullptr)
: BaseSettingValue(getSettingValueType<T>(), category, name, index) : BaseSettingValue(getSettingValueType<T>(), category, name, index)
, mSanitizer(std::move(sanitizer)) , mSanitizer(std::move(sanitizer))
, mDefaultValue(defaultValue) , mDefaultValue(sanitize(defaultValue))
, mValue(defaultValue) , mValue(sanitize(Settings::Manager::getOrDefault<T>(mName, mCategory, mDefaultValue)))
{ {
} }

Loading…
Cancel
Save