diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 20bd62d145..b040980529 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -116,7 +116,7 @@ opencs_units (view/prefs opencs_units (model/prefs state setting intsetting doublesetting boolsetting enumsetting coloursetting shortcut - shortcuteventhandler shortcutmanager shortcutsetting modifiersetting stringsetting + shortcuteventhandler shortcutmanager shortcutsetting modifiersetting stringsetting subcategory ) opencs_units (model/prefs diff --git a/apps/opencs/model/prefs/boolsetting.cpp b/apps/opencs/model/prefs/boolsetting.cpp index c668bc0af4..c1eb626969 100644 --- a/apps/opencs/model/prefs/boolsetting.cpp +++ b/apps/opencs/model/prefs/boolsetting.cpp @@ -11,7 +11,7 @@ #include "state.hpp" CSMPrefs::BoolSetting::BoolSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, bool default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, bool default_) : Setting(parent, mutex, key, label) , mDefault(default_) , mWidget(nullptr) @@ -24,9 +24,9 @@ CSMPrefs::BoolSetting& CSMPrefs::BoolSetting::setTooltip(const std::string& tool return *this; } -std::pair CSMPrefs::BoolSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::BoolSetting::makeWidgets(QWidget* parent) { - mWidget = new QCheckBox(QString::fromUtf8(getLabel().c_str()), parent); + mWidget = new QCheckBox(getLabel(), parent); mWidget->setCheckState(mDefault ? Qt::Checked : Qt::Unchecked); if (!mTooltip.empty()) @@ -37,7 +37,7 @@ std::pair CSMPrefs::BoolSetting::makeWidgets(QWidget* parent connect(mWidget, &QCheckBox::stateChanged, this, &BoolSetting::valueChanged); - return std::make_pair(static_cast(nullptr), mWidget); + return SettingWidgets{ .mLabel = nullptr, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::BoolSetting::updateWidget() diff --git a/apps/opencs/model/prefs/boolsetting.hpp b/apps/opencs/model/prefs/boolsetting.hpp index e75ea1a346..9d53f98e9e 100644 --- a/apps/opencs/model/prefs/boolsetting.hpp +++ b/apps/opencs/model/prefs/boolsetting.hpp @@ -21,12 +21,12 @@ namespace CSMPrefs QCheckBox* mWidget; public: - BoolSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label, bool default_); + BoolSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, bool default_); BoolSetting& setTooltip(const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/coloursetting.cpp b/apps/opencs/model/prefs/coloursetting.cpp index 86f3a5d772..e2ece04722 100644 --- a/apps/opencs/model/prefs/coloursetting.cpp +++ b/apps/opencs/model/prefs/coloursetting.cpp @@ -14,7 +14,7 @@ #include "state.hpp" CSMPrefs::ColourSetting::ColourSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, QColor default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, QColor default_) : Setting(parent, mutex, key, label) , mDefault(std::move(default_)) , mWidget(nullptr) @@ -27,9 +27,9 @@ CSMPrefs::ColourSetting& CSMPrefs::ColourSetting::setTooltip(const std::string& return *this; } -std::pair CSMPrefs::ColourSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::ColourSetting::makeWidgets(QWidget* parent) { - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); mWidget = new CSVWidget::ColorEditor(mDefault, parent); @@ -42,7 +42,7 @@ std::pair CSMPrefs::ColourSetting::makeWidgets(QWidget* pare connect(mWidget, &CSVWidget::ColorEditor::pickingFinished, this, &ColourSetting::valueChanged); - return std::make_pair(label, mWidget); + return SettingWidgets{ .mLabel = label, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::ColourSetting::updateWidget() diff --git a/apps/opencs/model/prefs/coloursetting.hpp b/apps/opencs/model/prefs/coloursetting.hpp index 0c22d9cc5d..5a1a7a2df2 100644 --- a/apps/opencs/model/prefs/coloursetting.hpp +++ b/apps/opencs/model/prefs/coloursetting.hpp @@ -29,13 +29,12 @@ namespace CSMPrefs CSVWidget::ColorEditor* mWidget; public: - ColourSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, QColor default_); + ColourSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, QColor default_); ColourSetting& setTooltip(const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/doublesetting.cpp b/apps/opencs/model/prefs/doublesetting.cpp index 7e3aadb0c3..153298ce57 100644 --- a/apps/opencs/model/prefs/doublesetting.cpp +++ b/apps/opencs/model/prefs/doublesetting.cpp @@ -15,7 +15,7 @@ #include "state.hpp" CSMPrefs::DoubleSetting::DoubleSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, double default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, double default_) : Setting(parent, mutex, key, label) , mPrecision(2) , mMin(0) @@ -56,9 +56,9 @@ CSMPrefs::DoubleSetting& CSMPrefs::DoubleSetting::setTooltip(const std::string& return *this; } -std::pair CSMPrefs::DoubleSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::DoubleSetting::makeWidgets(QWidget* parent) { - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); mWidget = new QDoubleSpinBox(parent); mWidget->setDecimals(mPrecision); @@ -74,7 +74,7 @@ std::pair CSMPrefs::DoubleSetting::makeWidgets(QWidget* pare connect(mWidget, qOverload(&QDoubleSpinBox::valueChanged), this, &DoubleSetting::valueChanged); - return std::make_pair(label, mWidget); + return SettingWidgets{ .mLabel = label, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::DoubleSetting::updateWidget() diff --git a/apps/opencs/model/prefs/doublesetting.hpp b/apps/opencs/model/prefs/doublesetting.hpp index c951d2a88c..33342d2f5b 100644 --- a/apps/opencs/model/prefs/doublesetting.hpp +++ b/apps/opencs/model/prefs/doublesetting.hpp @@ -21,8 +21,7 @@ namespace CSMPrefs QDoubleSpinBox* mWidget; public: - DoubleSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, double default_); + DoubleSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, double default_); DoubleSetting& setPrecision(int precision); @@ -36,7 +35,7 @@ namespace CSMPrefs DoubleSetting& setTooltip(const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/enumsetting.cpp b/apps/opencs/model/prefs/enumsetting.cpp index a3ac9bce2b..d55e4005a4 100644 --- a/apps/opencs/model/prefs/enumsetting.cpp +++ b/apps/opencs/model/prefs/enumsetting.cpp @@ -45,7 +45,7 @@ CSMPrefs::EnumValues& CSMPrefs::EnumValues::add(const std::string& value, const } CSMPrefs::EnumSetting::EnumSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, const EnumValue& default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, const EnumValue& default_) : Setting(parent, mutex, key, label) , mDefault(default_) , mWidget(nullptr) @@ -76,9 +76,9 @@ CSMPrefs::EnumSetting& CSMPrefs::EnumSetting::addValue(const std::string& value, return *this; } -std::pair CSMPrefs::EnumSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::EnumSetting::makeWidgets(QWidget* parent) { - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); mWidget = new QComboBox(parent); @@ -105,7 +105,7 @@ std::pair CSMPrefs::EnumSetting::makeWidgets(QWidget* parent connect(mWidget, qOverload(&QComboBox::currentIndexChanged), this, &EnumSetting::valueChanged); - return std::make_pair(label, mWidget); + return SettingWidgets{ .mLabel = label, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::EnumSetting::updateWidget() diff --git a/apps/opencs/model/prefs/enumsetting.hpp b/apps/opencs/model/prefs/enumsetting.hpp index 57bd2115ce..f430988aa6 100644 --- a/apps/opencs/model/prefs/enumsetting.hpp +++ b/apps/opencs/model/prefs/enumsetting.hpp @@ -44,8 +44,8 @@ namespace CSMPrefs QComboBox* mWidget; public: - EnumSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label, - const EnumValue& default_); + EnumSetting( + Category* parent, QMutex* mutex, const std::string& key, const QString& label, const EnumValue& default_); EnumSetting& setTooltip(const std::string& tooltip); @@ -56,7 +56,7 @@ namespace CSMPrefs EnumSetting& addValue(const std::string& value, const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/intsetting.cpp b/apps/opencs/model/prefs/intsetting.cpp index 90cc77c788..7d0b40a45a 100644 --- a/apps/opencs/model/prefs/intsetting.cpp +++ b/apps/opencs/model/prefs/intsetting.cpp @@ -15,7 +15,7 @@ #include "state.hpp" CSMPrefs::IntSetting::IntSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, int default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, int default_) : Setting(parent, mutex, key, label) , mMin(0) , mMax(std::numeric_limits::max()) @@ -49,9 +49,9 @@ CSMPrefs::IntSetting& CSMPrefs::IntSetting::setTooltip(const std::string& toolti return *this; } -std::pair CSMPrefs::IntSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::IntSetting::makeWidgets(QWidget* parent) { - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); mWidget = new QSpinBox(parent); mWidget->setRange(mMin, mMax); @@ -66,7 +66,7 @@ std::pair CSMPrefs::IntSetting::makeWidgets(QWidget* parent) connect(mWidget, qOverload(&QSpinBox::valueChanged), this, &IntSetting::valueChanged); - return std::make_pair(label, mWidget); + return SettingWidgets{ .mLabel = label, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::IntSetting::updateWidget() diff --git a/apps/opencs/model/prefs/intsetting.hpp b/apps/opencs/model/prefs/intsetting.hpp index 8a655178a4..8fb3bdb1f6 100644 --- a/apps/opencs/model/prefs/intsetting.hpp +++ b/apps/opencs/model/prefs/intsetting.hpp @@ -23,7 +23,7 @@ namespace CSMPrefs QSpinBox* mWidget; public: - IntSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label, int default_); + IntSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label, int default_); // defaults to [0, std::numeric_limits::max()] IntSetting& setRange(int min, int max); @@ -35,7 +35,7 @@ namespace CSMPrefs IntSetting& setTooltip(const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/modifiersetting.cpp b/apps/opencs/model/prefs/modifiersetting.cpp index 8752a4d51e..173092dc2b 100644 --- a/apps/opencs/model/prefs/modifiersetting.cpp +++ b/apps/opencs/model/prefs/modifiersetting.cpp @@ -19,21 +19,21 @@ class QWidget; namespace CSMPrefs { - ModifierSetting::ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label) + ModifierSetting::ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) : Setting(parent, mutex, key, label) , mButton(nullptr) , mEditorActive(false) { } - std::pair ModifierSetting::makeWidgets(QWidget* parent) + SettingWidgets ModifierSetting::makeWidgets(QWidget* parent) { int modifier = 0; State::get().getShortcutManager().getModifier(getKey(), modifier); QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(modifier).c_str()); - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); QPushButton* widget = new QPushButton(text, parent); widget->setCheckable(true); @@ -46,7 +46,7 @@ namespace CSMPrefs connect(widget, &QPushButton::toggled, this, &ModifierSetting::buttonToggled); - return std::make_pair(label, widget); + return SettingWidgets{ .mLabel = label, .mInput = widget, .mLayout = nullptr }; } void ModifierSetting::updateWidget() diff --git a/apps/opencs/model/prefs/modifiersetting.hpp b/apps/opencs/model/prefs/modifiersetting.hpp index ae984243ac..9e308875fd 100644 --- a/apps/opencs/model/prefs/modifiersetting.hpp +++ b/apps/opencs/model/prefs/modifiersetting.hpp @@ -20,9 +20,9 @@ namespace CSMPrefs Q_OBJECT public: - ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label); + ModifierSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/setting.cpp b/apps/opencs/model/prefs/setting.cpp index efe360d1e8..666b4ba1b1 100644 --- a/apps/opencs/model/prefs/setting.cpp +++ b/apps/opencs/model/prefs/setting.cpp @@ -14,7 +14,7 @@ QMutex* CSMPrefs::Setting::getMutex() return mMutex; } -CSMPrefs::Setting::Setting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label) +CSMPrefs::Setting::Setting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) : QObject(parent->getState()) , mParent(parent) , mMutex(mutex) @@ -23,13 +23,6 @@ CSMPrefs::Setting::Setting(Category* parent, QMutex* mutex, const std::string& k { } -std::pair CSMPrefs::Setting::makeWidgets(QWidget* parent) -{ - return std::pair(0, 0); -} - -void CSMPrefs::Setting::updateWidget() {} - const CSMPrefs::Category* CSMPrefs::Setting::getParent() const { return mParent; @@ -40,11 +33,6 @@ const std::string& CSMPrefs::Setting::getKey() const return mKey; } -const std::string& CSMPrefs::Setting::getLabel() const -{ - return mLabel; -} - int CSMPrefs::Setting::toInt() const { QMutexLocker lock(mMutex); diff --git a/apps/opencs/model/prefs/setting.hpp b/apps/opencs/model/prefs/setting.hpp index f63271b3f2..882add20ca 100644 --- a/apps/opencs/model/prefs/setting.hpp +++ b/apps/opencs/model/prefs/setting.hpp @@ -9,11 +9,20 @@ class QWidget; class QColor; class QMutex; +class QGridLayout; +class QLabel; namespace CSMPrefs { class Category; + struct SettingWidgets + { + QLabel* mLabel; + QWidget* mInput; + QGridLayout* mLayout; + }; + class Setting : public QObject { Q_OBJECT @@ -21,32 +30,28 @@ namespace CSMPrefs Category* mParent; QMutex* mMutex; std::string mKey; - std::string mLabel; + QString mLabel; protected: QMutex* getMutex(); public: - Setting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label); + Setting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); ~Setting() override = default; - /// Return label, input widget. - /// - /// \note first can be a 0-pointer, which means that the label is part of the input - /// widget. - virtual std::pair makeWidgets(QWidget* parent); + virtual SettingWidgets makeWidgets(QWidget* parent) = 0; /// Updates the widget returned by makeWidgets() to the current setting. /// /// \note If make_widgets() has not been called yet then nothing happens. - virtual void updateWidget(); + virtual void updateWidget() = 0; const Category* getParent() const; const std::string& getKey() const; - const std::string& getLabel() const; + const QString& getLabel() const { return mLabel; } int toInt() const; diff --git a/apps/opencs/model/prefs/shortcutsetting.cpp b/apps/opencs/model/prefs/shortcutsetting.cpp index d8c71d7008..aae290b3f4 100644 --- a/apps/opencs/model/prefs/shortcutsetting.cpp +++ b/apps/opencs/model/prefs/shortcutsetting.cpp @@ -18,7 +18,7 @@ namespace CSMPrefs { - ShortcutSetting::ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label) + ShortcutSetting::ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label) : Setting(parent, mutex, key, label) , mButton(nullptr) , mEditorActive(false) @@ -30,14 +30,14 @@ namespace CSMPrefs } } - std::pair ShortcutSetting::makeWidgets(QWidget* parent) + SettingWidgets ShortcutSetting::makeWidgets(QWidget* parent) { QKeySequence sequence; State::get().getShortcutManager().getSequence(getKey(), sequence); QString text = QString::fromUtf8(State::get().getShortcutManager().convertToString(sequence).c_str()); - QLabel* label = new QLabel(QString::fromUtf8(getLabel().c_str()), parent); + QLabel* label = new QLabel(getLabel(), parent); QPushButton* widget = new QPushButton(text, parent); widget->setCheckable(true); @@ -50,7 +50,7 @@ namespace CSMPrefs connect(widget, &QPushButton::toggled, this, &ShortcutSetting::buttonToggled); - return std::make_pair(label, widget); + return SettingWidgets{ .mLabel = label, .mInput = widget, .mLayout = nullptr }; } void ShortcutSetting::updateWidget() diff --git a/apps/opencs/model/prefs/shortcutsetting.hpp b/apps/opencs/model/prefs/shortcutsetting.hpp index bef140dada..74cad995d4 100644 --- a/apps/opencs/model/prefs/shortcutsetting.hpp +++ b/apps/opencs/model/prefs/shortcutsetting.hpp @@ -22,9 +22,9 @@ namespace CSMPrefs Q_OBJECT public: - ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label); + ShortcutSetting(Category* parent, QMutex* mutex, const std::string& key, const QString& label); - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index 97f29bc8be..d74044f6d5 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,7 @@ #include "modifiersetting.hpp" #include "shortcutsetting.hpp" #include "stringsetting.hpp" +#include "values.hpp" CSMPrefs::State* CSMPrefs::State::sThis = nullptr; @@ -40,7 +42,6 @@ void CSMPrefs::State::declare() .setTooltip( "If a newly open top level window is showing status bars or not. " " Note that this does not affect existing windows."); - declareSeparator(); declareBool("reuse", "Reuse Subviews", true) .setTooltip( "When a new subview is requested and a matching subview already " @@ -58,7 +59,6 @@ void CSMPrefs::State::declare() declareInt("minimum-width", "Minimum subview width", 325) .setTooltip("Minimum width of subviews.") .setRange(50, 10000); - declareSeparator(); EnumValue scrollbarOnly("Scrollbar Only", "Simple addition of scrollbars, the view window " "does not grow automatically."); @@ -98,7 +98,6 @@ void CSMPrefs::State::declare() declareEnum("double-s", "Shift Double Click", editRecord).addValues(doubleClickValues); declareEnum("double-c", "Control Double Click", view).addValues(doubleClickValues); declareEnum("double-sc", "Shift Control Double Click", editRecordAndClose).addValues(doubleClickValues); - declareSeparator(); EnumValue jumpAndSelect("Jump and Select", "Scroll new record into view and make it the selection"); declareEnum("jump-to-added", "Action on adding or cloning a record", jumpAndSelect) .addValue(jumpAndSelect) @@ -161,7 +160,6 @@ void CSMPrefs::State::declare() declareInt("error-height", "Initial height of the error panel", 100).setRange(100, 10000); declareBool("highlight-occurrences", "Highlight other occurrences of selected names", true); declareColour("colour-highlight", "Colour of highlighted occurrences", QColor("lightcyan")); - declareSeparator(); declareColour("colour-int", "Highlight Colour: Integer Literals", QColor("darkmagenta")); declareColour("colour-float", "Highlight Colour: Float Literals", QColor("magenta")); declareColour("colour-name", "Highlight Colour: Names", QColor("grey")); @@ -180,14 +178,12 @@ void CSMPrefs::State::declare() declareDouble("navi-wheel-factor", "Camera Zoom Sensitivity", 8).setRange(-100.0, 100.0); declareDouble("s-navi-sensitivity", "Secondary Camera Movement Sensitivity", 50.0).setRange(-1000.0, 1000.0); - declareSeparator(); declareDouble("p-navi-free-sensitivity", "Free Camera Sensitivity", 1 / 650.).setPrecision(5).setRange(0.0, 1.0); declareBool("p-navi-free-invert", "Invert Free Camera Mouse Input", false); declareDouble("navi-free-lin-speed", "Free Camera Linear Speed", 1000.0).setRange(1.0, 10000.0); declareDouble("navi-free-rot-speed", "Free Camera Rotational Speed", 3.14 / 2).setRange(0.001, 6.28); declareDouble("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0); - declareSeparator(); declareDouble("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1 / 650.).setPrecision(5).setRange(0.0, 1.0); declareBool("p-navi-orbit-invert", "Invert Orbit Camera Mouse Input", false); @@ -195,7 +191,6 @@ void CSMPrefs::State::declare() declareDouble("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4) .setRange(0.001, 1000.0); declareBool("navi-orbit-const-roll", "Keep camera roll constant for orbital camera", true); - declareSeparator(); declareBool("context-select", "Context Sensitive Selection", false); declareDouble("drag-factor", "Mouse sensitivity during drag operations", 1.0).setRange(0.001, 100.0); @@ -463,7 +458,7 @@ void CSMPrefs::State::declareCategory(const std::string& key) } } -CSMPrefs::IntSetting& CSMPrefs::State::declareInt(const std::string& key, const std::string& label, int default_) +CSMPrefs::IntSetting& CSMPrefs::State::declareInt(const std::string& key, const QString& label, int default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -479,8 +474,7 @@ CSMPrefs::IntSetting& CSMPrefs::State::declareInt(const std::string& key, const return *setting; } -CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble( - const std::string& key, const std::string& label, double default_) +CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble(const std::string& key, const QString& label, double default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -499,7 +493,7 @@ CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble( return *setting; } -CSMPrefs::BoolSetting& CSMPrefs::State::declareBool(const std::string& key, const std::string& label, bool default_) +CSMPrefs::BoolSetting& CSMPrefs::State::declareBool(const std::string& key, const QString& label, bool default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -516,8 +510,7 @@ CSMPrefs::BoolSetting& CSMPrefs::State::declareBool(const std::string& key, cons return *setting; } -CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum( - const std::string& key, const std::string& label, EnumValue default_) +CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum(const std::string& key, const QString& label, EnumValue default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -534,8 +527,7 @@ CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum( return *setting; } -CSMPrefs::ColourSetting& CSMPrefs::State::declareColour( - const std::string& key, const std::string& label, QColor default_) +CSMPrefs::ColourSetting& CSMPrefs::State::declareColour(const std::string& key, const QString& label, QColor default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -554,7 +546,7 @@ CSMPrefs::ColourSetting& CSMPrefs::State::declareColour( } CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut( - const std::string& key, const std::string& label, const QKeySequence& default_) + const std::string& key, const QString& label, const QKeySequence& default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -576,7 +568,7 @@ CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut( } CSMPrefs::StringSetting& CSMPrefs::State::declareString( - const std::string& key, const std::string& label, std::string default_) + const std::string& key, const QString& label, std::string default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -593,8 +585,7 @@ CSMPrefs::StringSetting& CSMPrefs::State::declareString( return *setting; } -CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier( - const std::string& key, const std::string& label, int default_) +CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier(const std::string& key, const QString& label, int default_) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); @@ -615,24 +606,12 @@ CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier( return *setting; } -void CSMPrefs::State::declareSeparator() +void CSMPrefs::State::declareSubcategory(const QString& label) { if (mCurrentCategory == mCategories.end()) throw std::logic_error("no category for setting"); - CSMPrefs::Setting* setting = new CSMPrefs::Setting(&mCurrentCategory->second, &mMutex, "", ""); - - mCurrentCategory->second.addSetting(setting); -} - -void CSMPrefs::State::declareSubcategory(const std::string& label) -{ - if (mCurrentCategory == mCategories.end()) - throw std::logic_error("no category for setting"); - - CSMPrefs::Setting* setting = new CSMPrefs::Setting(&mCurrentCategory->second, &mMutex, "", label); - - mCurrentCategory->second.addSetting(setting); + mCurrentCategory->second.addSetting(new CSMPrefs::Subcategory(&mCurrentCategory->second, &mMutex, label)); } void CSMPrefs::State::setDefault(const std::string& key, const std::string& default_) @@ -650,13 +629,18 @@ CSMPrefs::State::State(const Files::ConfigurationManager& configurationManager) , mDefaultConfigFile("defaults-cs.bin") , mConfigurationManager(configurationManager) , mCurrentCategory(mCategories.end()) + , mIndex(std::make_unique()) { if (sThis) throw std::logic_error("An instance of CSMPRefs::State already exists"); sThis = this; + Values values(*mIndex); + declare(); + + mValues = std::make_unique(std::move(values)); } CSMPrefs::State::~State() diff --git a/apps/opencs/model/prefs/state.hpp b/apps/opencs/model/prefs/state.hpp index 354f4552e3..e398f06e4a 100644 --- a/apps/opencs/model/prefs/state.hpp +++ b/apps/opencs/model/prefs/state.hpp @@ -17,6 +17,11 @@ class QColor; +namespace Settings +{ + class Index; +} + namespace CSMPrefs { class IntSetting; @@ -27,6 +32,7 @@ namespace CSMPrefs class ModifierSetting; class Setting; class StringSetting; + struct Values; /// \brief User settings state /// @@ -50,43 +56,41 @@ namespace CSMPrefs Collection mCategories; Iterator mCurrentCategory; QMutex mMutex; + std::unique_ptr mIndex; + std::unique_ptr mValues; - // not implemented - State(const State&); - State& operator=(const State&); - - private: void declare(); void declareCategory(const std::string& key); - IntSetting& declareInt(const std::string& key, const std::string& label, int default_); - DoubleSetting& declareDouble(const std::string& key, const std::string& label, double default_); + IntSetting& declareInt(const std::string& key, const QString& label, int default_); + DoubleSetting& declareDouble(const std::string& key, const QString& label, double default_); - BoolSetting& declareBool(const std::string& key, const std::string& label, bool default_); + BoolSetting& declareBool(const std::string& key, const QString& label, bool default_); - EnumSetting& declareEnum(const std::string& key, const std::string& label, EnumValue default_); + EnumSetting& declareEnum(const std::string& key, const QString& label, EnumValue default_); - ColourSetting& declareColour(const std::string& key, const std::string& label, QColor default_); + ColourSetting& declareColour(const std::string& key, const QString& label, QColor default_); - ShortcutSetting& declareShortcut( - const std::string& key, const std::string& label, const QKeySequence& default_); + ShortcutSetting& declareShortcut(const std::string& key, const QString& label, const QKeySequence& default_); - StringSetting& declareString(const std::string& key, const std::string& label, std::string default_); + StringSetting& declareString(const std::string& key, const QString& label, std::string default_); - ModifierSetting& declareModifier(const std::string& key, const std::string& label, int modifier_); + ModifierSetting& declareModifier(const std::string& key, const QString& label, int modifier_); - void declareSeparator(); - - void declareSubcategory(const std::string& label); + void declareSubcategory(const QString& label); void setDefault(const std::string& key, const std::string& default_); public: State(const Files::ConfigurationManager& configurationManager); + State(const State&) = delete; + ~State(); + State& operator=(const State&) = delete; + void save(); Iterator begin(); diff --git a/apps/opencs/model/prefs/stringsetting.cpp b/apps/opencs/model/prefs/stringsetting.cpp index 2a8fdd587a..0cba2d047d 100644 --- a/apps/opencs/model/prefs/stringsetting.cpp +++ b/apps/opencs/model/prefs/stringsetting.cpp @@ -12,7 +12,7 @@ #include "state.hpp" CSMPrefs::StringSetting::StringSetting( - Category* parent, QMutex* mutex, const std::string& key, const std::string& label, std::string_view default_) + Category* parent, QMutex* mutex, const std::string& key, const QString& label, std::string_view default_) : Setting(parent, mutex, key, label) , mDefault(default_) , mWidget(nullptr) @@ -25,7 +25,7 @@ CSMPrefs::StringSetting& CSMPrefs::StringSetting::setTooltip(const std::string& return *this; } -std::pair CSMPrefs::StringSetting::makeWidgets(QWidget* parent) +CSMPrefs::SettingWidgets CSMPrefs::StringSetting::makeWidgets(QWidget* parent) { mWidget = new QLineEdit(QString::fromUtf8(mDefault.c_str()), parent); @@ -37,7 +37,7 @@ std::pair CSMPrefs::StringSetting::makeWidgets(QWidget* pare connect(mWidget, &QLineEdit::textChanged, this, &StringSetting::textChanged); - return std::make_pair(static_cast(nullptr), mWidget); + return SettingWidgets{ .mLabel = nullptr, .mInput = mWidget, .mLayout = nullptr }; } void CSMPrefs::StringSetting::updateWidget() diff --git a/apps/opencs/model/prefs/stringsetting.hpp b/apps/opencs/model/prefs/stringsetting.hpp index 4b5499ef86..5c03a6ea12 100644 --- a/apps/opencs/model/prefs/stringsetting.hpp +++ b/apps/opencs/model/prefs/stringsetting.hpp @@ -23,13 +23,13 @@ namespace CSMPrefs QLineEdit* mWidget; public: - StringSetting(Category* parent, QMutex* mutex, const std::string& key, const std::string& label, - std::string_view default_); + StringSetting( + Category* parent, QMutex* mutex, const std::string& key, const QString& label, std::string_view default_); StringSetting& setTooltip(const std::string& tooltip); /// Return label, input widget. - std::pair makeWidgets(QWidget* parent) override; + SettingWidgets makeWidgets(QWidget* parent) override; void updateWidget() override; diff --git a/apps/opencs/model/prefs/subcategory.cpp b/apps/opencs/model/prefs/subcategory.cpp new file mode 100644 index 0000000000..cca558407c --- /dev/null +++ b/apps/opencs/model/prefs/subcategory.cpp @@ -0,0 +1,21 @@ +#include "subcategory.hpp" + +#include + +namespace CSMPrefs +{ + class Category; + + Subcategory::Subcategory(Category* parent, QMutex* mutex, const QString& label) + : Setting(parent, mutex, "", label) + { + } + + SettingWidgets Subcategory::makeWidgets(QWidget* /*parent*/) + { + QGridLayout* const layout = new QGridLayout(); + layout->setSizeConstraint(QLayout::SetMinAndMaxSize); + + return SettingWidgets{ .mLabel = nullptr, .mInput = nullptr, .mLayout = layout }; + } +} diff --git a/apps/opencs/model/prefs/subcategory.hpp b/apps/opencs/model/prefs/subcategory.hpp new file mode 100644 index 0000000000..4f62c1743c --- /dev/null +++ b/apps/opencs/model/prefs/subcategory.hpp @@ -0,0 +1,26 @@ +#ifndef OPENMW_APPS_OPENCS_MODEL_PREFS_SUBCATEGORY_H +#define OPENMW_APPS_OPENCS_MODEL_PREFS_SUBCATEGORY_H + +#include "setting.hpp" + +#include +#include + +namespace CSMPrefs +{ + class Category; + + class Subcategory final : public Setting + { + Q_OBJECT + + public: + explicit Subcategory(Category* parent, QMutex* mutex, const QString& label); + + SettingWidgets makeWidgets(QWidget* parent) override; + + void updateWidget() override {} + }; +} + +#endif diff --git a/apps/opencs/model/prefs/values.hpp b/apps/opencs/model/prefs/values.hpp new file mode 100644 index 0000000000..247c025e80 --- /dev/null +++ b/apps/opencs/model/prefs/values.hpp @@ -0,0 +1,532 @@ +#ifndef OPENMW_APPS_OPENCS_MODEL_PREFS_VALUES_H +#define OPENMW_APPS_OPENCS_MODEL_PREFS_VALUES_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace CSMPrefs +{ + struct EnumValueView + { + std::string_view mValue; + std::string_view mTooltip; + }; + + class EnumSanitizer final : public Settings::Sanitizer + { + public: + explicit EnumSanitizer(std::span values) + : mValues(values) + { + } + + std::string apply(const std::string& value) const override + { + const auto hasValue = [&](const EnumValueView& v) { return v.mValue == value; }; + if (std::find_if(mValues.begin(), mValues.end(), hasValue) == mValues.end()) + { + std::ostringstream message; + message << "Invalid enum value: " << value; + throw std::runtime_error(message.str()); + } + return value; + } + + private: + std::span mValues; + }; + + inline std::unique_ptr> makeEnumSanitizerString( + std::span values) + { + return std::make_unique(values); + } + + struct WindowsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Windows"; + + static constexpr std::array sMainwindowScrollbarValues{ + EnumValueView{ + "Scrollbar Only", "Simple addition of scrollbars, the view window does not grow automatically." }, + EnumValueView{ "Grow Only", "The view window grows as subviews are added. No scrollbars." }, + EnumValueView{ + "Grow then Scroll", "The view window grows. The scrollbar appears once it cannot grow any further." }, + }; + + Settings::SettingValue mDefaultWidth{ mIndex, sName, "default-width", 800 }; + Settings::SettingValue mDefaultHeight{ mIndex, sName, "default-height", 600 }; + Settings::SettingValue mShowStatusbar{ mIndex, sName, "show-statusbar", true }; + Settings::SettingValue mReuse{ mIndex, sName, "reuse", true }; + Settings::SettingValue mMaxSubviews{ mIndex, sName, "max-subviews", 256 }; + Settings::SettingValue mHideSubview{ mIndex, sName, "hide-subview", false }; + Settings::SettingValue mMinimumWidth{ mIndex, sName, "minimum-width", 325 }; + Settings::SettingValue mMainwindowScrollbar{ mIndex, sName, "mainwindow-scrollbar", + std::string(sMainwindowScrollbarValues[0].mValue), makeEnumSanitizerString(sMainwindowScrollbarValues) }; + Settings::SettingValue mGrowLimit{ mIndex, sName, "grow-limit", false }; + }; + + struct RecordsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Records"; + + static constexpr std::array sRecordValues{ + EnumValueView{ "Icon and Text", "" }, + EnumValueView{ "Icon Only", "" }, + EnumValueView{ "Text Only", "" }, + }; + + Settings::SettingValue mStatusFormat{ mIndex, sName, "status-format", + std::string(sRecordValues[0].mValue), makeEnumSanitizerString(sRecordValues) }; + Settings::SettingValue mTypeFormat{ mIndex, sName, "type-format", + std::string(sRecordValues[0].mValue), makeEnumSanitizerString(sRecordValues) }; + }; + + struct IdTablesCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "ID Tables"; + + static constexpr std::array sDoubleClickValues{ + EnumValueView{ "Edit in Place", "Edit the clicked cell" }, + EnumValueView{ "Edit Record", "Open a dialogue subview for the clicked record" }, + EnumValueView{ "View", "Open a scene subview for the clicked record (not available everywhere)" }, + EnumValueView{ "Revert", "" }, + EnumValueView{ "Delete", "" }, + EnumValueView{ "Edit Record and Close", "" }, + EnumValueView{ + "View and Close", "Open a scene subview for the clicked record and close the table subview" }, + }; + + static constexpr std::array sJumpAndSelectValues{ + EnumValueView{ "Jump and Select", "Scroll new record into view and make it the selection" }, + EnumValueView{ "Jump Only", "Scroll new record into view" }, + EnumValueView{ "No Jump", "No special action" }, + }; + + Settings::SettingValue mDouble{ mIndex, sName, "double", std::string(sDoubleClickValues[0].mValue), + makeEnumSanitizerString(sDoubleClickValues) }; + Settings::SettingValue mDoubleS{ mIndex, sName, "double-s", + std::string(sDoubleClickValues[1].mValue), makeEnumSanitizerString(sDoubleClickValues) }; + Settings::SettingValue mDoubleC{ mIndex, sName, "double-c", + std::string(sDoubleClickValues[2].mValue), makeEnumSanitizerString(sDoubleClickValues) }; + Settings::SettingValue mDoubleSc{ mIndex, sName, "double-sc", + std::string(sDoubleClickValues[5].mValue), makeEnumSanitizerString(sDoubleClickValues) }; + Settings::SettingValue mJumpToAdded{ mIndex, sName, "jump-to-added", + std::string(sJumpAndSelectValues[0].mValue), makeEnumSanitizerString(sJumpAndSelectValues) }; + Settings::SettingValue mExtendedConfig{ mIndex, sName, "extended-config", false }; + Settings::SettingValue mSubviewNewWindow{ mIndex, sName, "subview-new-window", false }; + }; + + struct IdDialoguesCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "ID Dialogues"; + + Settings::SettingValue mToolbar{ mIndex, sName, "toolbar", true }; + }; + + struct ReportsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Reports"; + + static constexpr std::array sReportValues{ + EnumValueView{ "None", "" }, + EnumValueView{ "Edit", "Open a table or dialogue suitable for addressing the listed report" }, + EnumValueView{ "Remove", "Remove the report from the report table" }, + EnumValueView{ "Edit And Remove", + "Open a table or dialogue suitable for addressing the listed report, then remove the report from the " + "report table" }, + }; + + Settings::SettingValue mDouble{ mIndex, sName, "double", std::string(sReportValues[1].mValue), + makeEnumSanitizerString(sReportValues) }; + Settings::SettingValue mDoubleS{ mIndex, sName, "double-s", std::string(sReportValues[2].mValue), + makeEnumSanitizerString(sReportValues) }; + Settings::SettingValue mDoubleC{ mIndex, sName, "double-c", std::string(sReportValues[3].mValue), + makeEnumSanitizerString(sReportValues) }; + Settings::SettingValue mDoubleSc{ mIndex, sName, "double-sc", std::string(sReportValues[0].mValue), + makeEnumSanitizerString(sReportValues) }; + Settings::SettingValue mIgnoreBaseRecords{ mIndex, sName, "ignore-base-records", false }; + }; + + struct SearchAndReplaceCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Search & Replace"; + + Settings::SettingValue mCharBefore{ mIndex, sName, "char-before", 10 }; + Settings::SettingValue mCharAfter{ mIndex, sName, "char-after", 10 }; + Settings::SettingValue mAutoDelete{ mIndex, sName, "auto-delete", true }; + }; + + struct ScriptsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Scripts"; + + static constexpr std::array sWarningValues{ + EnumValueView{ "Ignore", "Do not report warning" }, + EnumValueView{ "Normal", "Report warnings as warning" }, + EnumValueView{ "Strict", "Promote warning to an error" }, + }; + + Settings::SettingValue mShowLinenum{ mIndex, sName, "show-linenum", true }; + Settings::SettingValue mWrapLines{ mIndex, sName, "wrap-lines", false }; + Settings::SettingValue mMonoFont{ mIndex, sName, "mono-font", true }; + Settings::SettingValue mTabWidth{ mIndex, sName, "tab-width", 4 }; + Settings::SettingValue mWarnings{ mIndex, sName, "warnings", std::string(sWarningValues[1].mValue), + makeEnumSanitizerString(sWarningValues) }; + Settings::SettingValue mToolbar{ mIndex, sName, "toolbar", true }; + Settings::SettingValue mCompileDelay{ mIndex, sName, "compile-delay", 100 }; + Settings::SettingValue mErrorHeight{ mIndex, sName, "error-height", 100 }; + Settings::SettingValue mHighlightOccurrences{ mIndex, sName, "highlight-occurrences", true }; + Settings::SettingValue mColourHighlight{ mIndex, sName, "colour-highlight", "lightcyan" }; + Settings::SettingValue mColourInt{ mIndex, sName, "colour-int", "darkmagenta" }; + Settings::SettingValue mColourFloat{ mIndex, sName, "colour-float", "magenta" }; + Settings::SettingValue mColourName{ mIndex, sName, "colour-name", "grey" }; + Settings::SettingValue mColourKeyword{ mIndex, sName, "colour-keyword", "red" }; + Settings::SettingValue mColourSpecial{ mIndex, sName, "colour-special", "darkorange" }; + Settings::SettingValue mColourComment{ mIndex, sName, "colour-comment", "green" }; + Settings::SettingValue mColourId{ mIndex, sName, "colour-id", "blue" }; + }; + + struct GeneralInputCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "General Input"; + + Settings::SettingValue mCycle{ mIndex, sName, "cycle", false }; + }; + + struct SceneInputCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "3D Scene Input"; + + Settings::SettingValue mNaviWheelFactor{ mIndex, sName, "navi-wheel-factor", 8 }; + Settings::SettingValue mSNaviSensitivity{ mIndex, sName, "s-navi-sensitivity", 50 }; + Settings::SettingValue mPNaviFreeSensitivity{ mIndex, sName, "p-navi-free-sensitivity", 1 / 650.0 }; + Settings::SettingValue mPNaviFreeInvert{ mIndex, sName, "p-navi-free-invert", false }; + Settings::SettingValue mNaviFreeLinSpeed{ mIndex, sName, "navi-free-lin-speed", 1000 }; + Settings::SettingValue mNaviFreeRotSpeed{ mIndex, sName, "navi-free-rot-speed", 3.14 / 2 }; + Settings::SettingValue mNaviFreeSpeedMult{ mIndex, sName, "navi-free-speed-mult", 8 }; + Settings::SettingValue mPNaviOrbitSensitivity{ mIndex, sName, "p-navi-orbit-sensitivity", 1 / 650.0 }; + Settings::SettingValue mPNaviOrbitInvert{ mIndex, sName, "p-navi-orbit-invert", false }; + Settings::SettingValue mNaviOrbitRotSpeed{ mIndex, sName, "navi-orbit-rot-speed", 3.14 / 4 }; + Settings::SettingValue mNaviOrbitSpeedMult{ mIndex, sName, "navi-orbit-speed-mult", 4 }; + Settings::SettingValue mNaviOrbitConstRoll{ mIndex, sName, "navi-orbit-const-roll", true }; + Settings::SettingValue mContextSelect{ mIndex, sName, "context-select", false }; + Settings::SettingValue mDragFactor{ mIndex, sName, "drag-factor", 1 }; + Settings::SettingValue mDragWheelFactor{ mIndex, sName, "drag-wheel-factor", 1 }; + Settings::SettingValue mDragShiftFactor{ mIndex, sName, "drag-shift-factor", 4 }; + Settings::SettingValue mRotateFactor{ mIndex, sName, "rotate-factor", 0.007 }; + }; + + struct RenderingCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Rendering"; + + Settings::SettingValue mFramerateLimit{ mIndex, sName, "framerate-limit", 60 }; + Settings::SettingValue mCameraFov{ mIndex, sName, "camera-fov", 90 }; + Settings::SettingValue mCameraOrtho{ mIndex, sName, "camera-ortho", false }; + Settings::SettingValue mCameraOrthoSize{ mIndex, sName, "camera-ortho-size", 100 }; + Settings::SettingValue mObjectMarkerAlpha{ mIndex, sName, "object-marker-alpha", 0.5 }; + Settings::SettingValue mSceneUseGradient{ mIndex, sName, "scene-use-gradient", true }; + Settings::SettingValue mSceneDayBackgroundColour{ mIndex, sName, "scene-day-background-colour", + "#6e7880" }; + Settings::SettingValue mSceneDayGradientColour{ mIndex, sName, "scene-day-gradient-colour", + "#2f3333" }; + Settings::SettingValue mSceneBrightBackgroundColour{ mIndex, sName, + "scene-bright-background-colour", "#4f575c" }; + Settings::SettingValue mSceneBrightGradientColour{ mIndex, sName, "scene-bright-gradient-colour", + "#2f3333" }; + Settings::SettingValue mSceneNightBackgroundColour{ mIndex, sName, "scene-night-background-colour", + "#404d4f" }; + Settings::SettingValue mSceneNightGradientColour{ mIndex, sName, "scene-night-gradient-colour", + "#2f3333" }; + Settings::SettingValue mSceneDayNightSwitchNodes{ mIndex, sName, "scene-day-night-switch-nodes", true }; + }; + + struct TooltipsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Tooltips"; + + Settings::SettingValue mScene{ mIndex, sName, "scene", true }; + Settings::SettingValue mSceneHideBasic{ mIndex, sName, "scene-hide-basic", false }; + Settings::SettingValue mSceneDelay{ mIndex, sName, "scene-delay", 500 }; + }; + + struct SceneEditingCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "3D Scene Editing"; + + static constexpr std::array sInsertOutsideCellValues{ + EnumValueView{ "Create cell and insert", "" }, + EnumValueView{ "Discard", "" }, + EnumValueView{ "Insert anyway", "" }, + }; + + static constexpr std::array sInsertOutsideVisibleCellValues{ + EnumValueView{ "Show cell and insert", "" }, + EnumValueView{ "Discard", "" }, + EnumValueView{ "Insert anyway", "" }, + }; + + static constexpr std::array sLandEditOutsideCellValues{ + EnumValueView{ "Create cell and land, then edit", "" }, + EnumValueView{ "Discard", "" }, + }; + + static constexpr std::array sLandEditOutsideVisibleCellValues{ + EnumValueView{ "Show cell and edit", "" }, + EnumValueView{ "Discard", "" }, + }; + + static constexpr std::array sPrimarySelectAction{ + EnumValueView{ "Select only", "" }, + EnumValueView{ "Add to selection", "" }, + EnumValueView{ "Remove from selection", "" }, + EnumValueView{ "Invert selection", "" }, + }; + + static constexpr std::array sSecondarySelectAction{ + EnumValueView{ "Select only", "" }, + EnumValueView{ "Add to selection", "" }, + EnumValueView{ "Remove from selection", "" }, + EnumValueView{ "Invert selection", "" }, + }; + + Settings::SettingValue mGridsnapMovement{ mIndex, sName, "gridsnap-movement", 16 }; + Settings::SettingValue mGridsnapRotation{ mIndex, sName, "gridsnap-rotation", 15 }; + Settings::SettingValue mGridsnapScale{ mIndex, sName, "gridsnap-scale", 0.25 }; + Settings::SettingValue mDistance{ mIndex, sName, "distance", 50 }; + Settings::SettingValue mOutsideDrop{ mIndex, sName, "outside-drop", + std::string(sInsertOutsideCellValues[0].mValue), makeEnumSanitizerString(sInsertOutsideCellValues) }; + Settings::SettingValue mOutsideVisibleDrop{ mIndex, sName, "outside-visible-drop", + std::string(sInsertOutsideVisibleCellValues[0].mValue), + makeEnumSanitizerString(sInsertOutsideVisibleCellValues) }; + Settings::SettingValue mOutsideLandedit{ mIndex, sName, "outside-landedit", + std::string(sLandEditOutsideCellValues[0].mValue), makeEnumSanitizerString(sLandEditOutsideCellValues) }; + Settings::SettingValue mOutsideVisibleLandedit{ mIndex, sName, "outside-visible-landedit", + std::string(sLandEditOutsideVisibleCellValues[0].mValue), + makeEnumSanitizerString(sLandEditOutsideVisibleCellValues) }; + Settings::SettingValue mTexturebrushMaximumsize{ mIndex, sName, "texturebrush-maximumsize", 50 }; + Settings::SettingValue mShapebrushMaximumsize{ mIndex, sName, "shapebrush-maximumsize", 100 }; + Settings::SettingValue mLandeditPostSmoothpainting{ mIndex, sName, "landedit-post-smoothpainting", + false }; + Settings::SettingValue mLandeditPostSmoothstrength{ mIndex, sName, "landedit-post-smoothstrength", + 0.25 }; + Settings::SettingValue mOpenListView{ mIndex, sName, "open-list-view", false }; + Settings::SettingValue mPrimarySelectAction{ mIndex, sName, "primary-select-action", + std::string(sPrimarySelectAction[0].mValue), makeEnumSanitizerString(sPrimarySelectAction) }; + Settings::SettingValue mSecondarySelectAction{ mIndex, sName, "secondary-select-action", + std::string(sPrimarySelectAction[1].mValue), makeEnumSanitizerString(sPrimarySelectAction) }; + }; + + struct KeyBindingsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Key Bindings"; + + Settings::SettingValue mDocumentFileNewgame{ mIndex, sName, "document-file-newgame", "Ctrl+N" }; + Settings::SettingValue mDocumentFileNewaddon{ mIndex, sName, "document-file-newaddon", "" }; + Settings::SettingValue mDocumentFileOpen{ mIndex, sName, "document-file-open", "Ctrl+O" }; + Settings::SettingValue mDocumentFileSave{ mIndex, sName, "document-file-save", "Ctrl+S" }; + Settings::SettingValue mDocumentHelpHelp{ mIndex, sName, "document-help-help", "F1" }; + Settings::SettingValue mDocumentHelpTutorial{ mIndex, sName, "document-help-tutorial", "" }; + Settings::SettingValue mDocumentFileVerify{ mIndex, sName, "document-file-verify", "" }; + Settings::SettingValue mDocumentFileMerge{ mIndex, sName, "document-file-merge", "" }; + Settings::SettingValue mDocumentFileErrorlog{ mIndex, sName, "document-file-errorlog", "" }; + Settings::SettingValue mDocumentFileMetadata{ mIndex, sName, "document-file-metadata", "" }; + Settings::SettingValue mDocumentFileClose{ mIndex, sName, "document-file-close", "Ctrl+W" }; + Settings::SettingValue mDocumentFileExit{ mIndex, sName, "document-file-exit", "Ctrl+Q" }; + Settings::SettingValue mDocumentEditUndo{ mIndex, sName, "document-edit-undo", "Ctrl+Z" }; + Settings::SettingValue mDocumentEditRedo{ mIndex, sName, "document-edit-redo", "Ctrl+Shift+Z" }; + Settings::SettingValue mDocumentEditPreferences{ mIndex, sName, "document-edit-preferences", "" }; + Settings::SettingValue mDocumentEditSearch{ mIndex, sName, "document-edit-search", "Ctrl+F" }; + Settings::SettingValue mDocumentViewNewview{ mIndex, sName, "document-view-newview", "" }; + Settings::SettingValue mDocumentViewStatusbar{ mIndex, sName, "document-view-statusbar", "" }; + Settings::SettingValue mDocumentViewFilters{ mIndex, sName, "document-view-filters", "" }; + Settings::SettingValue mDocumentWorldRegions{ mIndex, sName, "document-world-regions", "" }; + Settings::SettingValue mDocumentWorldCells{ mIndex, sName, "document-world-cells", "" }; + Settings::SettingValue mDocumentWorldReferencables{ mIndex, sName, "document-world-referencables", + "" }; + Settings::SettingValue mDocumentWorldReferences{ mIndex, sName, "document-world-references", "" }; + Settings::SettingValue mDocumentWorldLands{ mIndex, sName, "document-world-lands", "" }; + Settings::SettingValue mDocumentWorldLandtextures{ mIndex, sName, "document-world-landtextures", + "" }; + Settings::SettingValue mDocumentWorldPathgrid{ mIndex, sName, "document-world-pathgrid", "" }; + Settings::SettingValue mDocumentWorldRegionmap{ mIndex, sName, "document-world-regionmap", "" }; + Settings::SettingValue mDocumentMechanicsGlobals{ mIndex, sName, "document-mechanics-globals", + "" }; + Settings::SettingValue mDocumentMechanicsGamesettings{ mIndex, sName, + "document-mechanics-gamesettings", "" }; + Settings::SettingValue mDocumentMechanicsScripts{ mIndex, sName, "document-mechanics-scripts", + "" }; + Settings::SettingValue mDocumentMechanicsSpells{ mIndex, sName, "document-mechanics-spells", "" }; + Settings::SettingValue mDocumentMechanicsEnchantments{ mIndex, sName, + "document-mechanics-enchantments", "" }; + Settings::SettingValue mDocumentMechanicsMagiceffects{ mIndex, sName, + "document-mechanics-magiceffects", "" }; + Settings::SettingValue mDocumentMechanicsStartscripts{ mIndex, sName, + "document-mechanics-startscripts", "" }; + Settings::SettingValue mDocumentCharacterSkills{ mIndex, sName, "document-character-skills", "" }; + Settings::SettingValue mDocumentCharacterClasses{ mIndex, sName, "document-character-classes", + "" }; + Settings::SettingValue mDocumentCharacterFactions{ mIndex, sName, "document-character-factions", + "" }; + Settings::SettingValue mDocumentCharacterRaces{ mIndex, sName, "document-character-races", "" }; + Settings::SettingValue mDocumentCharacterBirthsigns{ mIndex, sName, + "document-character-birthsigns", "" }; + Settings::SettingValue mDocumentCharacterTopics{ mIndex, sName, "document-character-topics", "" }; + Settings::SettingValue mDocumentCharacterJournals{ mIndex, sName, "document-character-journals", + "" }; + Settings::SettingValue mDocumentCharacterTopicinfos{ mIndex, sName, + "document-character-topicinfos", "" }; + Settings::SettingValue mDocumentCharacterJournalinfos{ mIndex, sName, + "document-character-journalinfos", "" }; + Settings::SettingValue mDocumentCharacterBodyparts{ mIndex, sName, "document-character-bodyparts", + "" }; + Settings::SettingValue mDocumentAssetsReload{ mIndex, sName, "document-assets-reload", "F5" }; + Settings::SettingValue mDocumentAssetsSounds{ mIndex, sName, "document-assets-sounds", "" }; + Settings::SettingValue mDocumentAssetsSoundgens{ mIndex, sName, "document-assets-soundgens", "" }; + Settings::SettingValue mDocumentAssetsMeshes{ mIndex, sName, "document-assets-meshes", "" }; + Settings::SettingValue mDocumentAssetsIcons{ mIndex, sName, "document-assets-icons", "" }; + Settings::SettingValue mDocumentAssetsMusic{ mIndex, sName, "document-assets-music", "" }; + Settings::SettingValue mDocumentAssetsSoundres{ mIndex, sName, "document-assets-soundres", "" }; + Settings::SettingValue mDocumentAssetsTextures{ mIndex, sName, "document-assets-textures", "" }; + Settings::SettingValue mDocumentAssetsVideos{ mIndex, sName, "document-assets-videos", "" }; + Settings::SettingValue mDocumentDebugRun{ mIndex, sName, "document-debug-run", "" }; + Settings::SettingValue mDocumentDebugShutdown{ mIndex, sName, "document-debug-shutdown", "" }; + Settings::SettingValue mDocumentDebugProfiles{ mIndex, sName, "document-debug-profiles", "" }; + Settings::SettingValue mDocumentDebugRunlog{ mIndex, sName, "document-debug-runlog", "" }; + Settings::SettingValue mTableEdit{ mIndex, sName, "table-edit", "" }; + Settings::SettingValue mTableAdd{ mIndex, sName, "table-add", "Shift+A" }; + Settings::SettingValue mTableClone{ mIndex, sName, "table-clone", "Shift+D" }; + Settings::SettingValue mTouchRecord{ mIndex, sName, "touch-record", "" }; + Settings::SettingValue mTableRevert{ mIndex, sName, "table-revert", "" }; + Settings::SettingValue mTableRemove{ mIndex, sName, "table-remove", "Delete" }; + Settings::SettingValue mTableMoveup{ mIndex, sName, "table-moveup", "" }; + Settings::SettingValue mTableMovedown{ mIndex, sName, "table-movedown", "" }; + Settings::SettingValue mTableView{ mIndex, sName, "table-view", "Shift+C" }; + Settings::SettingValue mTablePreview{ mIndex, sName, "table-preview", "Shift+V" }; + Settings::SettingValue mTableExtendeddelete{ mIndex, sName, "table-extendeddelete", "" }; + Settings::SettingValue mTableExtendedrevert{ mIndex, sName, "table-extendedrevert", "" }; + Settings::SettingValue mReporttableShow{ mIndex, sName, "reporttable-show", "" }; + Settings::SettingValue mReporttableRemove{ mIndex, sName, "reporttable-remove", "Delete" }; + Settings::SettingValue mReporttableReplace{ mIndex, sName, "reporttable-replace", "" }; + Settings::SettingValue mReporttableRefresh{ mIndex, sName, "reporttable-refresh", "" }; + Settings::SettingValue mSceneNaviPrimary{ mIndex, sName, "scene-navi-primary", "LMB" }; + Settings::SettingValue mSceneNaviSecondary{ mIndex, sName, "scene-navi-secondary", "Ctrl+LMB" }; + Settings::SettingValue mSceneOpenPrimary{ mIndex, sName, "scene-open-primary", "Shift+LMB" }; + Settings::SettingValue mSceneEditPrimary{ mIndex, sName, "scene-edit-primary", "RMB" }; + Settings::SettingValue mSceneEditSecondary{ mIndex, sName, "scene-edit-secondary", "Ctrl+RMB" }; + Settings::SettingValue mSceneSelectPrimary{ mIndex, sName, "scene-select-primary", "MMB" }; + Settings::SettingValue mSceneSelectSecondary{ mIndex, sName, "scene-select-secondary", + "Ctrl+MMB" }; + Settings::SettingValue mSceneSelectTertiary{ mIndex, sName, "scene-select-tertiary", "Shift+MMB" }; + Settings::SettingValue mSceneSpeedModifier{ mIndex, sName, "scene-speed-modifier", "Shift" }; + Settings::SettingValue mSceneDelete{ mIndex, sName, "scene-delete", "Delete" }; + Settings::SettingValue mSceneInstanceDropTerrain{ mIndex, sName, "scene-instance-drop-terrain", + "G" }; + Settings::SettingValue mSceneInstanceDropCollision{ mIndex, sName, "scene-instance-drop-collision", + "H" }; + Settings::SettingValue mSceneInstanceDropTerrainSeparately{ mIndex, sName, + "scene-instance-drop-terrain-separately", "" }; + Settings::SettingValue mSceneInstanceDropCollisionSeparately{ mIndex, sName, + "scene-instance-drop-collision-separately", "" }; + Settings::SettingValue mSceneLoadCamCell{ mIndex, sName, "scene-load-cam-cell", "Keypad+5" }; + Settings::SettingValue mSceneLoadCamEastcell{ mIndex, sName, "scene-load-cam-eastcell", + "Keypad+6" }; + Settings::SettingValue mSceneLoadCamNorthcell{ mIndex, sName, "scene-load-cam-northcell", + "Keypad+8" }; + Settings::SettingValue mSceneLoadCamWestcell{ mIndex, sName, "scene-load-cam-westcell", + "Keypad+4" }; + Settings::SettingValue mSceneLoadCamSouthcell{ mIndex, sName, "scene-load-cam-southcell", + "Keypad+2" }; + Settings::SettingValue mSceneEditAbort{ mIndex, sName, "scene-edit-abort", "Escape" }; + Settings::SettingValue mSceneFocusToolbar{ mIndex, sName, "scene-focus-toolbar", "T" }; + Settings::SettingValue mSceneRenderStats{ mIndex, sName, "scene-render-stats", "F3" }; + Settings::SettingValue mFreeForward{ mIndex, sName, "free-forward", "W" }; + Settings::SettingValue mFreeBackward{ mIndex, sName, "free-backward", "S" }; + Settings::SettingValue mFreeLeft{ mIndex, sName, "free-left", "A" }; + Settings::SettingValue mFreeRight{ mIndex, sName, "free-right", "D" }; + Settings::SettingValue mFreeRollLeft{ mIndex, sName, "free-roll-left", "Q" }; + Settings::SettingValue mFreeRollRight{ mIndex, sName, "free-roll-right", "E" }; + Settings::SettingValue mFreeSpeedMode{ mIndex, sName, "free-speed-mode", "F" }; + Settings::SettingValue mOrbitUp{ mIndex, sName, "orbit-up", "W" }; + Settings::SettingValue mOrbitDown{ mIndex, sName, "orbit-down", "S" }; + Settings::SettingValue mOrbitLeft{ mIndex, sName, "orbit-left", "A" }; + Settings::SettingValue mOrbitRight{ mIndex, sName, "orbit-right", "D" }; + Settings::SettingValue mOrbitRollLeft{ mIndex, sName, "orbit-roll-left", "Q" }; + Settings::SettingValue mOrbitRollRight{ mIndex, sName, "orbit-roll-right", "E" }; + Settings::SettingValue mOrbitSpeedMode{ mIndex, sName, "orbit-speed-mode", "F" }; + Settings::SettingValue mOrbitCenterSelection{ mIndex, sName, "orbit-center-selection", "C" }; + Settings::SettingValue mScriptEditorComment{ mIndex, sName, "script-editor-comment", "" }; + Settings::SettingValue mScriptEditorUncomment{ mIndex, sName, "script-editor-uncomment", "" }; + }; + + struct ModelsCategory : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + static constexpr std::string_view sName = "Models"; + + Settings::SettingValue mBaseanim{ mIndex, sName, "baseanim", "meshes/base_anim.nif" }; + Settings::SettingValue mBaseanimkna{ mIndex, sName, "baseanimkna", "meshes/base_animkna.nif" }; + Settings::SettingValue mBaseanimfemale{ mIndex, sName, "baseanimfemale", + "meshes/base_anim_female.nif" }; + Settings::SettingValue mWolfskin{ mIndex, sName, "wolfskin", "meshes/wolf/skin.nif" }; + }; + + struct Values : Settings::WithIndex + { + using Settings::WithIndex::WithIndex; + + WindowsCategory mWindows{ mIndex }; + RecordsCategory mRecords{ mIndex }; + IdTablesCategory mIdTables{ mIndex }; + IdDialoguesCategory mIdDialogues{ mIndex }; + ReportsCategory mReports{ mIndex }; + SearchAndReplaceCategory mSearchAndReplace{ mIndex }; + ScriptsCategory mScripts{ mIndex }; + GeneralInputCategory mGeneralInput{ mIndex }; + SceneInputCategory mSceneInput{ mIndex }; + RenderingCategory mRendering{ mIndex }; + TooltipsCategory mTooltips{ mIndex }; + SceneEditingCategory mSceneEditing{ mIndex }; + KeyBindingsCategory mKeyBindings{ mIndex }; + ModelsCategory mModels{ mIndex }; + }; +} + +#endif diff --git a/apps/opencs/view/prefs/keybindingpage.cpp b/apps/opencs/view/prefs/keybindingpage.cpp index d3cc1ff889..b88627aca1 100644 --- a/apps/opencs/view/prefs/keybindingpage.cpp +++ b/apps/opencs/view/prefs/keybindingpage.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -61,46 +62,35 @@ namespace CSVPrefs void KeyBindingPage::addSetting(CSMPrefs::Setting* setting) { - std::pair widgets = setting->makeWidgets(this); + const CSMPrefs::SettingWidgets widgets = setting->makeWidgets(this); - if (widgets.first) + if (widgets.mLabel != nullptr && widgets.mInput != nullptr) { // Label, Option widgets assert(mPageLayout); int next = mPageLayout->rowCount(); - mPageLayout->addWidget(widgets.first, next, 0); - mPageLayout->addWidget(widgets.second, next, 1); + mPageLayout->addWidget(widgets.mLabel, next, 0); + mPageLayout->addWidget(widgets.mInput, next, 1); } - else if (widgets.second) + else if (widgets.mInput != nullptr) { // Wide single widget assert(mPageLayout); int next = mPageLayout->rowCount(); - mPageLayout->addWidget(widgets.second, next, 0, 1, 2); + mPageLayout->addWidget(widgets.mInput, next, 0, 1, 2); } - else + else if (widgets.mLayout != nullptr) { - if (setting->getLabel().empty()) - { - // Insert empty space - assert(mPageLayout); + // Create new page + QWidget* pageWidget = new QWidget(); + mPageLayout = widgets.mLayout; + mPageLayout->setParent(pageWidget); - int next = mPageLayout->rowCount(); - mPageLayout->addWidget(new QWidget(), next, 0); - } - else - { - // Create new page - QWidget* pageWidget = new QWidget(); - mPageLayout = new QGridLayout(pageWidget); - mPageLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); + mStackedLayout->addWidget(pageWidget); - mStackedLayout->addWidget(pageWidget); - - mPageSelector->addItem(QString::fromUtf8(setting->getLabel().c_str())); - } + mPageSelector->addItem(setting->getLabel()); } } diff --git a/apps/opencs/view/prefs/page.cpp b/apps/opencs/view/prefs/page.cpp index 4f04a39f00..cc74122782 100644 --- a/apps/opencs/view/prefs/page.cpp +++ b/apps/opencs/view/prefs/page.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "../../model/prefs/category.hpp" #include "../../model/prefs/setting.hpp" @@ -24,21 +25,17 @@ CSVPrefs::Page::Page(CSMPrefs::Category& category, QWidget* parent) void CSVPrefs::Page::addSetting(CSMPrefs::Setting* setting) { - std::pair widgets = setting->makeWidgets(this); + const CSMPrefs::SettingWidgets widgets = setting->makeWidgets(this); int next = mGrid->rowCount(); - if (widgets.first) + if (widgets.mLabel != nullptr && widgets.mInput != nullptr) { - mGrid->addWidget(widgets.first, next, 0); - mGrid->addWidget(widgets.second, next, 1); + mGrid->addWidget(widgets.mLabel, next, 0); + mGrid->addWidget(widgets.mInput, next, 1); } - else if (widgets.second) + else if (widgets.mInput != nullptr) { - mGrid->addWidget(widgets.second, next, 0, 1, 2); - } - else - { - mGrid->addWidget(new QWidget(this), next, 0); + mGrid->addWidget(widgets.mInput, next, 0, 1, 2); } } diff --git a/components/settings/settingvalue.hpp b/components/settings/settingvalue.hpp index 2f239a4ebd..392e5b646f 100644 --- a/components/settings/settingvalue.hpp +++ b/components/settings/settingvalue.hpp @@ -335,6 +335,15 @@ namespace Settings { } + explicit SettingValue(Index& index, std::string_view category, std::string_view name, T&& defaultValue, + std::unique_ptr>&& sanitizer = nullptr) + : BaseSettingValue(getSettingValueType(), category, name, index) + , mSanitizer(std::move(sanitizer)) + , mDefaultValue(defaultValue) + , mValue(defaultValue) + { + } + SettingValue(SettingValue&& other) : BaseSettingValue(std::move(other)) , mSanitizer(std::move(other.mSanitizer))