瀏覽代碼

shared_widget: Forward-port Citra changes

Seemed like a good time to move these over.
Also remove usage of std::sto{l,ll,ul,f,d}
lat9nq 2 年之前
父節點
當前提交
3ae3706c84
共有 2 個文件被更改,包括 134 次插入31 次删除
  1. 126 31
      src/yuzu/configuration/shared_widget.cpp
  2. 8 0
      src/yuzu/configuration/shared_widget.h

+ 126 - 31
src/yuzu/configuration/shared_widget.cpp

@@ -151,7 +151,7 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
         return -1;
         return -1;
     };
     };
 
 
-    const u32 setting_value = std::stoi(setting.ToString());
+    const u32 setting_value = std::strtoul(setting.ToString().c_str(), nullptr, 0);
     combobox->setCurrentIndex(find_index(setting_value));
     combobox->setCurrentIndex(find_index(setting_value));
 
 
     serializer = [this, enumeration]() {
     serializer = [this, enumeration]() {
@@ -160,7 +160,7 @@ QWidget* Widget::CreateCombobox(std::function<std::string()>& serializer,
     };
     };
 
 
     restore_func = [this, find_index]() {
     restore_func = [this, find_index]() {
-        const u32 global_value = std::stoi(RelevantDefault(setting));
+        const u32 global_value = std::strtoul(RelevantDefault(setting).c_str(), nullptr, 0);
         combobox->setCurrentIndex(find_index(global_value));
         combobox->setCurrentIndex(find_index(global_value));
     };
     };
 
 
@@ -209,7 +209,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
         }
         }
     };
     };
 
 
-    const u32 setting_value = std::stoi(setting.ToString());
+    const u32 setting_value = std::strtoul(setting.ToString().c_str(), nullptr, 0);
     set_index(setting_value);
     set_index(setting_value);
 
 
     serializer = [get_selected]() {
     serializer = [get_selected]() {
@@ -218,7 +218,7 @@ QWidget* Widget::CreateRadioGroup(std::function<std::string()>& serializer,
     };
     };
 
 
     restore_func = [this, set_index]() {
     restore_func = [this, set_index]() {
-        const u32 global_value = std::stoi(RelevantDefault(setting));
+        const u32 global_value = std::strtoul(RelevantDefault(setting).c_str(), nullptr, 0);
         set_index(global_value);
         set_index(global_value);
     };
     };
 
 
@@ -255,6 +255,58 @@ QWidget* Widget::CreateLineEdit(std::function<std::string()>& serializer,
     return line_edit;
     return line_edit;
 }
 }
 
 
+static void CreateIntSlider(Settings::BasicSetting& setting, bool reversed, float multiplier,
+                            QLabel* feedback, const QString& use_format, QSlider* slider,
+                            std::function<std::string()>& serializer,
+                            std::function<void()>& restore_func) {
+    int max_val = std::strtol(setting.MaxVal().c_str(), nullptr, 0);
+
+    const auto update_feedback = [=](int value) {
+        int present = (reversed ? max_val - value : value) * multiplier + 0.5f;
+        feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
+    };
+
+    QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback);
+    update_feedback(std::strtol(setting.ToString().c_str(), nullptr, 0));
+
+    slider->setMinimum(std::strtol(setting.MinVal().c_str(), nullptr, 0));
+    slider->setMaximum(max_val);
+    slider->setValue(std::strtol(setting.ToString().c_str(), nullptr, 0));
+
+    serializer = [slider]() { return std::to_string(slider->value()); };
+    restore_func = [slider, &setting]() {
+        slider->setValue(std::strtol(RelevantDefault(setting).c_str(), nullptr, 0));
+    };
+}
+
+static void CreateFloatSlider(Settings::BasicSetting& setting, bool reversed, float multiplier,
+                              QLabel* feedback, const QString& use_format, QSlider* slider,
+                              std::function<std::string()>& serializer,
+                              std::function<void()>& restore_func) {
+    float max_val = std::strtof(setting.MaxVal().c_str(), nullptr);
+    float min_val = std::strtof(setting.MinVal().c_str(), nullptr);
+    float use_multiplier = multiplier == default_multiplier ? default_float_multiplier : multiplier;
+
+    const auto update_feedback = [=](float value) {
+        int present = (reversed ? max_val - value : value) + 0.5f;
+        feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
+    };
+
+    QObject::connect(slider, &QAbstractSlider::valueChanged, update_feedback);
+    update_feedback(std::strtof(setting.ToString().c_str(), nullptr));
+
+    slider->setMinimum(min_val * use_multiplier);
+    slider->setMaximum(max_val * use_multiplier);
+    slider->setValue(std::strtof(setting.ToString().c_str(), nullptr) * use_multiplier);
+
+    serializer = [slider, use_multiplier]() {
+        return std::to_string(slider->value() / use_multiplier);
+    };
+    restore_func = [slider, &setting, use_multiplier]() {
+        slider->setValue(std::strtof(RelevantDefault(setting).c_str(), nullptr) * use_multiplier);
+    };
+}
+
 QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& given_suffix,
 QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& given_suffix,
                               std::function<std::string()>& serializer,
                               std::function<std::string()>& serializer,
                               std::function<void()>& restore_func,
                               std::function<void()>& restore_func,
@@ -278,27 +330,20 @@ QWidget* Widget::CreateSlider(bool reversed, float multiplier, const QString& gi
 
 
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setContentsMargins(0, 0, 0, 0);
 
 
-    int max_val = std::stoi(setting.MaxVal());
-
     QString suffix =
     QString suffix =
         given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
         given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
 
 
     const QString use_format = QStringLiteral("%1").append(suffix);
     const QString use_format = QStringLiteral("%1").append(suffix);
 
 
-    QObject::connect(slider, &QAbstractSlider::valueChanged, [=](int value) {
-        int present = (reversed ? max_val - value : value) * multiplier + 0.5f;
-        feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
-    });
-
-    slider->setMinimum(std::stoi(setting.MinVal()));
-    slider->setMaximum(max_val);
-    slider->setValue(std::stoi(setting.ToString()));
+    if (setting.IsIntegral()) {
+        CreateIntSlider(setting, reversed, multiplier, feedback, use_format, slider, serializer,
+                        restore_func);
+    } else {
+        CreateFloatSlider(setting, reversed, multiplier, feedback, use_format, slider, serializer,
+                          restore_func);
+    }
 
 
     slider->setInvertedAppearance(reversed);
     slider->setInvertedAppearance(reversed);
-    slider->setInvertedControls(reversed);
-
-    serializer = [this]() { return std::to_string(slider->value()); };
-    restore_func = [this]() { slider->setValue(std::stoi(RelevantDefault(setting))); };
 
 
     if (!Settings::IsConfiguringGlobal()) {
     if (!Settings::IsConfiguringGlobal()) {
         QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); });
         QObject::connect(slider, &QAbstractSlider::actionTriggered, [touch]() { touch(); });
@@ -311,11 +356,9 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
                                std::function<std::string()>& serializer,
                                std::function<std::string()>& serializer,
                                std::function<void()>& restore_func,
                                std::function<void()>& restore_func,
                                const std::function<void()>& touch) {
                                const std::function<void()>& touch) {
-    const int min_val =
-        setting.Ranged() ? std::stoi(setting.MinVal()) : std::numeric_limits<int>::min();
-    const int max_val =
-        setting.Ranged() ? std::stoi(setting.MaxVal()) : std::numeric_limits<int>::max();
-    const int default_val = std::stoi(setting.ToString());
+    const auto min_val = std::strtol(setting.MinVal().c_str(), nullptr, 0);
+    const auto max_val = std::strtol(setting.MaxVal().c_str(), nullptr, 0);
+    const auto default_val = std::strtol(setting.ToString().c_str(), nullptr, 0);
 
 
     QString suffix =
     QString suffix =
         given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
         given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
@@ -329,13 +372,13 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
     serializer = [this]() { return std::to_string(spinbox->value()); };
     serializer = [this]() { return std::to_string(spinbox->value()); };
 
 
     restore_func = [this]() {
     restore_func = [this]() {
-        auto value{std::stol(RelevantDefault(setting))};
+        auto value{std::strtol(RelevantDefault(setting).c_str(), nullptr, 0)};
         spinbox->setValue(value);
         spinbox->setValue(value);
     };
     };
 
 
     if (!Settings::IsConfiguringGlobal()) {
     if (!Settings::IsConfiguringGlobal()) {
         QObject::connect(spinbox, QOverload<int>::of(&QSpinBox::valueChanged), [this, touch]() {
         QObject::connect(spinbox, QOverload<int>::of(&QSpinBox::valueChanged), [this, touch]() {
-            if (spinbox->value() != std::stoi(setting.ToStringGlobal())) {
+            if (spinbox->value() != std::strtol(setting.ToStringGlobal().c_str(), nullptr, 0)) {
                 touch();
                 touch();
             }
             }
         });
         });
@@ -344,6 +387,43 @@ QWidget* Widget::CreateSpinBox(const QString& given_suffix,
     return spinbox;
     return spinbox;
 }
 }
 
 
+QWidget* Widget::CreateDoubleSpinBox(const QString& given_suffix,
+                                     std::function<std::string()>& serializer,
+                                     std::function<void()>& restore_func,
+                                     const std::function<void()>& touch) {
+    const auto min_val = std::strtod(setting.MinVal().c_str(), nullptr);
+    const auto max_val = std::strtod(setting.MaxVal().c_str(), nullptr);
+    const auto default_val = std::strtod(setting.ToString().c_str(), nullptr);
+
+    QString suffix =
+        given_suffix == QStringLiteral("") ? DefaultSuffix(this, setting) : given_suffix;
+
+    double_spinbox = new QDoubleSpinBox(this);
+    double_spinbox->setRange(min_val, max_val);
+    double_spinbox->setValue(default_val);
+    double_spinbox->setSuffix(suffix);
+    double_spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+    serializer = [this]() { return fmt::format("{:f}", double_spinbox->value()); };
+
+    restore_func = [this]() {
+        auto value{std::strtod(RelevantDefault(setting).c_str(), nullptr)};
+        double_spinbox->setValue(value);
+    };
+
+    if (!Settings::IsConfiguringGlobal()) {
+        QObject::connect(double_spinbox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
+                         [this, touch]() {
+                             if (double_spinbox->value() !=
+                                 std::strtod(setting.ToStringGlobal().c_str(), nullptr)) {
+                                 touch();
+                             }
+                         });
+    }
+
+    return double_spinbox;
+}
+
 QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
 QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
                                std::function<void()>& restore_func,
                                std::function<void()>& restore_func,
                                const std::function<void()>& touch) {
                                const std::function<void()>& touch) {
@@ -353,7 +433,8 @@ QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
     }
     }
 
 
     auto to_hex = [=](const std::string& input) {
     auto to_hex = [=](const std::string& input) {
-        return QString::fromStdString(fmt::format("{:08x}", std::stoul(input)));
+        return QString::fromStdString(
+            fmt::format("{:08x}", std::strtoul(input.c_str(), nullptr, 0)));
     };
     };
 
 
     QRegularExpressionValidator* regex = new QRegularExpressionValidator(
     QRegularExpressionValidator* regex = new QRegularExpressionValidator(
@@ -366,7 +447,7 @@ QWidget* Widget::CreateHexEdit(std::function<std::string()>& serializer,
     line_edit->setValidator(regex);
     line_edit->setValidator(regex);
 
 
     auto hex_to_dec = [this]() -> std::string {
     auto hex_to_dec = [this]() -> std::string {
-        return std::to_string(std::stoul(line_edit->text().toStdString(), nullptr, 16));
+        return std::to_string(std::strtoul(line_edit->text().toStdString().c_str(), nullptr, 16));
     };
     };
 
 
     serializer = [hex_to_dec]() { return hex_to_dec(); };
     serializer = [hex_to_dec]() { return hex_to_dec(); };
@@ -386,7 +467,8 @@ QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict,
                                     std::function<void()>& restore_func,
                                     std::function<void()>& restore_func,
                                     const std::function<void()>& touch) {
                                     const std::function<void()>& touch) {
     const long long current_time = QDateTime::currentSecsSinceEpoch();
     const long long current_time = QDateTime::currentSecsSinceEpoch();
-    const s64 the_time = disabled ? current_time : std::stoll(setting.ToString());
+    const s64 the_time =
+        disabled ? current_time : std::strtoll(setting.ToString().c_str(), nullptr, 0);
     const auto default_val = QDateTime::fromSecsSinceEpoch(the_time);
     const auto default_val = QDateTime::fromSecsSinceEpoch(the_time);
 
 
     date_time_edit = new QDateTimeEdit(this);
     date_time_edit = new QDateTimeEdit(this);
@@ -399,7 +481,7 @@ QWidget* Widget::CreateDateTimeEdit(bool disabled, bool restrict,
     auto get_clear_val = [this, restrict, current_time]() {
     auto get_clear_val = [this, restrict, current_time]() {
         return QDateTime::fromSecsSinceEpoch([this, restrict, current_time]() {
         return QDateTime::fromSecsSinceEpoch([this, restrict, current_time]() {
             if (restrict && checkbox->checkState() == Qt::Checked) {
             if (restrict && checkbox->checkState() == Qt::Checked) {
-                return std::stoll(RelevantDefault(setting));
+                return std::strtoll(RelevantDefault(setting).c_str(), nullptr, 0);
             }
             }
             return current_time;
             return current_time;
         }());
         }());
@@ -506,8 +588,7 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
         } else {
         } else {
             data_component = CreateCombobox(serializer, restore_func, touch);
             data_component = CreateCombobox(serializer, restore_func, touch);
         }
         }
-    } else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) ||
-               type == typeid(s64) || type == typeid(u8)) {
+    } else if (setting.IsIntegral()) {
         switch (request) {
         switch (request) {
         case RequestType::Slider:
         case RequestType::Slider:
         case RequestType::ReverseSlider:
         case RequestType::ReverseSlider:
@@ -534,6 +615,20 @@ void Widget::SetupComponent(const QString& label, std::function<void()>& load_fu
         default:
         default:
             UNIMPLEMENTED();
             UNIMPLEMENTED();
         }
         }
+    } else if (setting.IsFloatingPoint()) {
+        switch (request) {
+        case RequestType::Default:
+        case RequestType::SpinBox:
+            data_component = CreateDoubleSpinBox(suffix, serializer, restore_func, touch);
+            break;
+        case RequestType::Slider:
+        case RequestType::ReverseSlider:
+            data_component = CreateSlider(request == RequestType::ReverseSlider, multiplier, suffix,
+                                          serializer, restore_func, touch);
+            break;
+        default:
+            UNIMPLEMENTED();
+        }
     } else if (type == typeid(std::string)) {
     } else if (type == typeid(std::string)) {
         switch (request) {
         switch (request) {
         case RequestType::Default:
         case RequestType::Default:

+ 8 - 0
src/yuzu/configuration/shared_widget.h

@@ -22,6 +22,7 @@ class QObject;
 class QPushButton;
 class QPushButton;
 class QSlider;
 class QSlider;
 class QSpinBox;
 class QSpinBox;
+class QDoubleSpinBox;
 class QRadioButton;
 class QRadioButton;
 
 
 namespace Settings {
 namespace Settings {
@@ -43,6 +44,9 @@ enum class RequestType {
     MaxEnum,
     MaxEnum,
 };
 };
 
 
+constexpr const float default_multiplier{1.f};
+constexpr const float default_float_multiplier{100.f};
+
 class Widget : public QWidget {
 class Widget : public QWidget {
     Q_OBJECT
     Q_OBJECT
 
 
@@ -89,6 +93,7 @@ public:
     QPushButton* restore_button{}; ///< Restore button for custom configurations
     QPushButton* restore_button{}; ///< Restore button for custom configurations
     QLineEdit* line_edit{};        ///< QLineEdit, used for LineEdit and HexEdit
     QLineEdit* line_edit{};        ///< QLineEdit, used for LineEdit and HexEdit
     QSpinBox* spinbox{};
     QSpinBox* spinbox{};
+    QDoubleSpinBox* double_spinbox{};
     QCheckBox* checkbox{};
     QCheckBox* checkbox{};
     QSlider* slider{};
     QSlider* slider{};
     QComboBox* combobox{};
     QComboBox* combobox{};
@@ -126,6 +131,9 @@ private:
                                 const std::function<void()>& touch);
                                 const std::function<void()>& touch);
     QWidget* CreateSpinBox(const QString& suffix, std::function<std::string()>& serializer,
     QWidget* CreateSpinBox(const QString& suffix, std::function<std::string()>& serializer,
                            std::function<void()>& restore_func, const std::function<void()>& touch);
                            std::function<void()>& restore_func, const std::function<void()>& touch);
+    QWidget* CreateDoubleSpinBox(const QString& suffix, std::function<std::string()>& serializer,
+                                 std::function<void()>& restore_func,
+                                 const std::function<void()>& touch);
 
 
     QWidget* parent;
     QWidget* parent;
     const TranslationMap& translations;
     const TranslationMap& translations;