diff --git a/res/controllers/Dummy Device Screen.hid.xml b/res/controllers/Dummy Device Screen.hid.xml
index 90526cc1a33..1d6526459a8 100644
--- a/res/controllers/Dummy Device Screen.hid.xml
+++ b/res/controllers/Dummy Device Screen.hid.xml
@@ -8,6 +8,62 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/controllers/legacycontrollersettings.cpp b/src/controllers/legacycontrollersettings.cpp
index f97d2b9d628..5240b71ed94 100644
--- a/src/controllers/legacycontrollersettings.cpp
+++ b/src/controllers/legacycontrollersettings.cpp
@@ -2,12 +2,19 @@
#include
+#include
#include
+#include
#include
#include
+#include
#include
#include
+#include
+#include
+#include
#include
+#include
#include "moc_legacycontrollersettings.cpp"
@@ -54,6 +61,8 @@ LegacyControllerSettingBuilder::LegacyControllerSettingBuilder() {
registerType();
registerType();
registerType();
+ registerType();
+ registerType();
}
AbstractLegacyControllerSetting::AbstractLegacyControllerSetting(const QDomElement& element) {
@@ -221,7 +230,8 @@ LegacyControllerEnumSetting::LegacyControllerEnumSetting(
!value.isNull();
value = value.nextSiblingElement("value")) {
QString val = value.text();
- m_options.append(std::tuple(val, value.attribute("label", val)));
+ QColor color = QColor(value.attribute("color"));
+ m_options.emplace_back(Item{val, value.attribute("label", val), color});
if (value.hasAttribute("default")) {
m_defaultValue = pos;
}
@@ -239,8 +249,8 @@ void LegacyControllerEnumSetting::parse(const QString& in, bool* ok) {
save();
size_t pos = 0;
- for (const auto& value : std::as_const(m_options)) {
- if (std::get<0>(value) == in) {
+ for (const auto& item : std::as_const(m_options)) {
+ if (item.value == in) {
if (ok != nullptr) {
*ok = true;
}
@@ -255,8 +265,15 @@ void LegacyControllerEnumSetting::parse(const QString& in, bool* ok) {
QWidget* LegacyControllerEnumSetting::buildInputWidget(QWidget* pParent) {
auto* pComboBox = new QComboBox(pParent);
- for (const auto& value : std::as_const(m_options)) {
- pComboBox->addItem(std::get<1>(value));
+ for (const auto& item : std::as_const(m_options)) {
+ if (item.color.isValid()) {
+ QPixmap icon(24, 24);
+ QPainter painter(&icon);
+ painter.fillRect(0, 0, 24, 24, item.color);
+ pComboBox->addItem(QIcon(icon), item.label);
+ } else {
+ pComboBox->addItem(item.label);
+ }
}
pComboBox->setCurrentIndex(static_cast(m_editedValue));
@@ -274,3 +291,140 @@ QWidget* LegacyControllerEnumSetting::buildInputWidget(QWidget* pParent) {
return pComboBox;
}
+
+LegacyControllerColorSetting::LegacyControllerColorSetting(
+ const QDomElement& element)
+ : AbstractLegacyControllerSetting(element),
+ m_defaultValue(QColor(element.attribute("default"))),
+ m_savedValue(m_defaultValue),
+ m_editedValue(m_defaultValue) {
+ reset();
+ save();
+}
+
+LegacyControllerColorSetting::~LegacyControllerColorSetting() = default;
+
+void LegacyControllerColorSetting::parse(const QString& in, bool* ok) {
+ if (ok != nullptr) {
+ *ok = false;
+ }
+ reset();
+ save();
+
+ m_savedValue = QColor(in);
+ if (ok != nullptr) {
+ *ok = m_editedValue.isValid();
+ }
+ if (!m_editedValue.isValid()) {
+ return;
+ }
+ m_editedValue = m_savedValue;
+}
+
+QWidget* LegacyControllerColorSetting::buildInputWidget(QWidget* pParent) {
+ auto* pPushButton = new QPushButton(tr("Change color"), pParent);
+
+ auto setColorIcon = [pPushButton](const QColor& color) {
+ QPixmap icon(24, 24);
+ QPainter painter(&icon);
+ painter.fillRect(0, 0, 24, 24, color);
+ pPushButton->setIcon(QIcon(icon));
+ };
+
+ connect(this,
+ &AbstractLegacyControllerSetting::valueReset,
+ pPushButton,
+ [this, pPushButton, setColorIcon]() {
+ if (m_editedValue.isValid()) {
+ setColorIcon(m_editedValue);
+ } else {
+ pPushButton->setIcon(QIcon());
+ }
+ });
+
+ connect(pPushButton, &QPushButton::clicked, this, [this, pPushButton, setColorIcon](bool) {
+ auto color = QColorDialog::getColor(m_editedValue, pPushButton, tr("Choose a new color"));
+ if (color.isValid()) {
+ m_editedValue = color;
+ setColorIcon(color);
+ emit changed();
+ }
+ });
+
+ if (m_savedValue.isValid()) {
+ setColorIcon(m_savedValue);
+ }
+
+ return pPushButton;
+}
+
+LegacyControllerFileSetting::LegacyControllerFileSetting(
+ const QDomElement& element)
+ : AbstractLegacyControllerSetting(element),
+ m_fileFilter(element.attribute("pattern")),
+ m_defaultValue(QFileInfo(element.attribute("default"))),
+ m_savedValue(m_defaultValue),
+ m_editedValue(m_defaultValue) {
+ reset();
+ save();
+}
+
+void LegacyControllerFileSetting::parse(const QString& in, bool* ok) {
+ if (ok != nullptr) {
+ *ok = false;
+ }
+ reset();
+ save();
+
+ m_editedValue = QFileInfo(in);
+ if (ok != nullptr) {
+ *ok = m_editedValue.exists();
+ }
+ if (!m_editedValue.exists()) {
+ return;
+ }
+ m_savedValue = m_editedValue;
+}
+
+QWidget* LegacyControllerFileSetting::buildInputWidget(QWidget* pParent) {
+ auto* pWidget = new QWidget(pParent);
+ pWidget->setLayout(new QHBoxLayout);
+ auto* pPushButton = new QPushButton(tr("Browse..."), pWidget);
+ auto* pLabel = new QLabel(pWidget);
+ auto setLabelText = [pLabel](QString&& text) {
+ pLabel->setText(QStringLiteral("%1").arg(text));
+ };
+ pWidget->layout()->addWidget(pLabel);
+ pWidget->layout()->addWidget(pPushButton);
+
+ connect(this, &AbstractLegacyControllerSetting::valueReset, pLabel, [this, setLabelText]() {
+ if (m_editedValue.exists()) {
+ setLabelText(m_editedValue.absoluteFilePath());
+ } else {
+ setLabelText(tr("No file selected"));
+ }
+ });
+
+ connect(pPushButton,
+ &QPushButton::clicked,
+ this,
+ [this, pLabel, pPushButton](bool) {
+ auto file = QFileInfo(QFileDialog::getOpenFileName(pPushButton,
+ tr("Select a file"),
+ QString(),
+ m_fileFilter));
+ if (file.exists()) {
+ m_editedValue = file;
+ pLabel->setText(QStringLiteral("%1").arg(file.absoluteFilePath()));
+ emit changed();
+ }
+ });
+
+ if (m_savedValue.exists()) {
+ setLabelText(m_savedValue.absoluteFilePath());
+ } else {
+ setLabelText(tr("No file selected"));
+ }
+
+ return pWidget;
+}
diff --git a/src/controllers/legacycontrollersettings.h b/src/controllers/legacycontrollersettings.h
index b7d2f378d9c..13bf730606b 100644
--- a/src/controllers/legacycontrollersettings.h
+++ b/src/controllers/legacycontrollersettings.h
@@ -1,5 +1,9 @@
#pragma once
+#include
+
+#include
+#include
#include
#include "controllers/legacycontrollersettingsfactory.h"
@@ -180,7 +184,7 @@ class LegacyControllerBooleanSetting
bool m_defaultValue;
bool m_editedValue;
- friend class LegacyControllerMappingSettingsTest_booleanSettingEditing_Test;
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, booleanSettingEditing);
};
template
@@ -297,8 +301,8 @@ class LegacyControllerNumberSetting
SettingType m_editedValue;
- friend class LegacyControllerMappingSettingsTest_integerSettingEditing_Test;
- friend class LegacyControllerMappingSettingsTest_doubleSettingEditing_Test;
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, integerSettingEditing);
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, doubleSettingEditing);
};
template
@@ -351,6 +355,12 @@ class LegacyControllerEnumSetting
: public LegacyControllerSettingFactory,
public AbstractLegacyControllerSetting {
public:
+ struct Item {
+ QString value;
+ QString label;
+ QColor color;
+ };
+
LegacyControllerEnumSetting(const QDomElement& element);
virtual ~LegacyControllerEnumSetting() = default;
@@ -359,12 +369,12 @@ class LegacyControllerEnumSetting
return QJSValue(stringify());
}
- const QList>& options() const {
+ const QList- & options() const {
return m_options;
}
QString stringify() const override {
- return std::get<0>(m_options.value(static_cast(m_savedValue)));
+ return m_options.value(static_cast(m_savedValue)).value;
}
void parse(const QString& in, bool* ok) override;
bool isDefault() const override {
@@ -400,7 +410,7 @@ class LegacyControllerEnumSetting
protected:
LegacyControllerEnumSetting(const QDomElement& element,
- const QList>& options,
+ const QList
- & options,
size_t currentValue,
size_t defaultValue)
: AbstractLegacyControllerSetting(element),
@@ -413,14 +423,158 @@ class LegacyControllerEnumSetting
private:
// We use a QList instead of QHash here because we want to keep the natural order
- QList> m_options;
+ QList
- m_options;
size_t m_savedValue;
size_t m_defaultValue;
size_t m_editedValue;
- friend class LegacyControllerMappingSettingsTest_enumSettingEditing_Test;
- friend class ControllerS4MK3SettingTest_ensureLibrarySettingValueAndEnumEquals;
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, enumSettingEditing);
+ FRIEND_TEST(ControllerS4MK3SettingTest, ensureLibrarySettingValueAndEnumEquals);
+};
+
+class LegacyControllerColorSetting
+ : public LegacyControllerSettingFactory,
+ public AbstractLegacyControllerSetting {
+ public:
+ LegacyControllerColorSetting(const QDomElement& element);
+
+ ~LegacyControllerColorSetting() override;
+
+ QJSValue value() const override {
+ return QJSValue(stringify());
+ }
+
+ QString stringify() const override {
+ return m_savedValue.name(QColor::HexRgb);
+ }
+ void parse(const QString& in, bool* ok) override;
+ bool isDefault() const override {
+ return m_savedValue == m_defaultValue;
+ }
+ bool isDirty() const override {
+ return m_savedValue != m_editedValue;
+ }
+
+ virtual void save() override {
+ m_savedValue = m_editedValue;
+ }
+
+ virtual void reset() override {
+ m_editedValue = m_defaultValue;
+ emit valueReset();
+ }
+
+ /// @brief Whether or not this setting definition and its current state are
+ /// valid. Validity scope includes a known default/current/dirty option.
+ /// @return true if valid
+ bool valid() const override {
+ return AbstractLegacyControllerSetting::valid() &&
+ m_defaultValue.isValid() &&
+ m_savedValue.isValid();
+ }
+
+ static AbstractLegacyControllerSetting* createFrom(const QDomElement& element) {
+ return new LegacyControllerColorSetting(element);
+ }
+ static inline bool match(const QDomElement& element) {
+ return element.hasAttribute("type") &&
+ QString::compare(element.attribute("type"),
+ "color",
+ Qt::CaseInsensitive) == 0;
+ }
+
+ protected:
+ LegacyControllerColorSetting(const QDomElement& element,
+ QColor currentValue,
+ QColor defaultValue)
+ : AbstractLegacyControllerSetting(element),
+ m_defaultValue(defaultValue),
+ m_savedValue(currentValue) {
+ }
+
+ virtual QWidget* buildInputWidget(QWidget* parent) override;
+
+ private:
+ QColor m_defaultValue;
+ QColor m_savedValue;
+
+ QColor m_editedValue;
+
+ FRIEND_TEST(ControllerS4MK3SettingTest, ensureLibrarySettingValueAndEnumEquals);
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, enumSettingEditing);
+};
+
+class LegacyControllerFileSetting
+ : public LegacyControllerSettingFactory,
+ public AbstractLegacyControllerSetting {
+ public:
+ LegacyControllerFileSetting(const QDomElement& element);
+
+ virtual ~LegacyControllerFileSetting() = default;
+
+ QJSValue value() const override {
+ return QJSValue(stringify());
+ }
+
+ QString stringify() const override {
+ return m_savedValue.absoluteFilePath();
+ }
+ void parse(const QString& in, bool* ok) override;
+ bool isDefault() const override {
+ return m_savedValue == m_defaultValue;
+ }
+ bool isDirty() const override {
+ return m_savedValue != m_editedValue;
+ }
+
+ virtual void save() override {
+ m_savedValue = m_editedValue;
+ }
+
+ virtual void reset() override {
+ m_editedValue = m_defaultValue;
+ emit valueReset();
+ }
+
+ /// @brief Whether or not this setting definition and its current state are
+ /// valid. Validity scope includes a known default/current/dirty option.
+ /// @return true if valid
+ bool valid() const override {
+ return AbstractLegacyControllerSetting::valid() &&
+ (m_defaultValue == m_savedValue || m_savedValue.exists());
+ }
+
+ static AbstractLegacyControllerSetting* createFrom(const QDomElement& element) {
+ return new LegacyControllerFileSetting(element);
+ }
+ static inline bool match(const QDomElement& element) {
+ return element.hasAttribute("type") &&
+ QString::compare(element.attribute("type"),
+ "file",
+ Qt::CaseInsensitive) == 0;
+ }
+
+ protected:
+ LegacyControllerFileSetting(const QDomElement& element,
+ const QFileInfo& currentValue,
+ const QFileInfo& defaultValue)
+ : AbstractLegacyControllerSetting(element),
+ m_defaultValue(defaultValue),
+ m_savedValue(currentValue) {
+ }
+
+ virtual QWidget* buildInputWidget(QWidget* parent) override;
+
+ private:
+ QString m_fileFilter;
+ QFileInfo m_defaultValue;
+ QFileInfo m_savedValue;
+
+ QFileInfo m_editedValue;
+
+ FRIEND_TEST(LegacyControllerMappingSettingsTest, enumSettingEditing);
+ FRIEND_TEST(ControllerS4MK3SettingTest, ensureLibrarySettingValueAndEnumEquals);
};
template<>
diff --git a/src/test/controllers/controller_columnid_regression_test.cpp b/src/test/controllers/controller_columnid_regression_test.cpp
index 7eac4448184..8b42a2c018a 100644
--- a/src/test/controllers/controller_columnid_regression_test.cpp
+++ b/src/test/controllers/controller_columnid_regression_test.cpp
@@ -76,7 +76,7 @@ TEST_F(ControllerLibraryColumnIDRegressionTest, ensureS4MK3) {
auto pEnum = std::dynamic_pointer_cast(setting);
EXPECT_TRUE(pEnum);
for (const auto& opt : pEnum->options()) {
- EXPECT_EQ(static_cast(COLUMN_MAPPING[std::get<0>(opt)]), std::get<1>(opt).toInt());
+ EXPECT_EQ(static_cast(COLUMN_MAPPING[opt.value]), opt.label.toInt());
}
count++;
}