From c7b91221ff997f8f237e7e303fdfd7ac5cfb7fb8 Mon Sep 17 00:00:00 2001 From: Rick Lan Date: Mon, 31 Mar 2025 11:09:36 +0800 Subject: [PATCH] spinbox - init --- selfdrive/assets/offroad/icon_plus.png | Bin 0 -> 2833 bytes selfdrive/ui/qt/widgets/controls.h | 133 +++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 selfdrive/assets/offroad/icon_plus.png diff --git a/selfdrive/assets/offroad/icon_plus.png b/selfdrive/assets/offroad/icon_plus.png new file mode 100644 index 0000000000000000000000000000000000000000..92b448b0bdcfcb2b1f1abede5f5b751b314353d1 GIT binary patch literal 2833 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 literal 0 HcmV?d00001 diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h index aebf934f2..936d27361 100644 --- a/selfdrive/ui/qt/widgets/controls.h +++ b/selfdrive/ui/qt/widgets/controls.h @@ -294,3 +294,136 @@ public: setLayout(l); } }; + +#include +class SpinBoxControl : public AbstractControl { + Q_OBJECT + +public: + SpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const int val = 0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) { + spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + spinbox.setAlignment(Qt::AlignCenter); + spinbox.setStyleSheet(R"( + QSpinBox { + width: 300px; + height: 80px; + padding: 0px; + border-radius:40px; + font-size: 36px; + } + QSpinBox::up-button { + subcontrol-origin: margin; + subcontrol-position: center right; + image: url(../assets/offroad/icon_plus.png); + right: 1px; + height: 80px; + width: 80px; + } + QSpinBox::down-button { + subcontrol-origin: margin; + subcontrol-position: center left; + image: url(../assets/offroad/icon_minus.png); + left: 1px; + height: 80px; + width: 80px; + } + )"); + + hlayout->addWidget(&spinbox); + QObject::connect(&spinbox, QOverload::of(&QSpinBox::valueChanged), this, &SpinBoxControl::valChanged); + } + +signals: + void valChanged(int val); + +protected: + QSpinBox spinbox; +}; + +class ParamSpinBoxControl : public SpinBoxControl { + Q_OBJECT + +public: + ParamSpinBoxControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const int minimum = 0, const int maximum = 100, const int step = 1, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : SpinBoxControl(title, desc, icon, 0, parent) { + spinbox.setRange(minimum, maximum); + spinbox.setSingleStep(step); + spinbox.setSuffix(suffix); + spinbox.setSpecialValueText(minText); + + std::string str_val = Params().get(param.toStdString().c_str()); + if (str_val != "") { + int val = std::stoi(str_val); + spinbox.setValue(val); + QObject::connect(this, &SpinBoxControl::valChanged, [=](int val) { + Params().put(param.toStdString(), std::to_string(val)); + }); + } + } +}; + +class DoubleSpinBoxControl : public AbstractControl { + Q_OBJECT + +public: + DoubleSpinBoxControl(const QString &title, const QString &desc = "", const QString &icon = "", const double val = 0.0, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) { + spinbox.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + spinbox.setAlignment(Qt::AlignCenter); + spinbox.setStyleSheet(R"( + QDoubleSpinBox { + width: 300px; + height: 80px; + padding: 0px; + border-radius:40px; + font-size: 36px; + } + QDoubleSpinBox::up-button { + subcontrol-origin: margin; + subcontrol-position: center right; + image: url(../assets/offroad/icon_plus.png); + right: 1px; + height: 80px; + width: 80px; + } + QDoubleSpinBox::down-button { + subcontrol-origin: margin; + subcontrol-position: center left; + image: url(../assets/offroad/icon_minus.png); + left: 1px; + height: 80px; + width: 80px; + } + )"); + + hlayout->addWidget(&spinbox); + QObject::connect(&spinbox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &DoubleSpinBoxControl::valChanged); + } + +signals: + void valChanged(double val); + +protected: + QDoubleSpinBox spinbox; +}; + +class ParamDoubleSpinBoxControl : public DoubleSpinBoxControl { + Q_OBJECT + +public: + ParamDoubleSpinBoxControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const double minimum = 0.0, const double maximum = 100.0, const double step = 1.0, const QString suffix = "", const QString minText = "", QWidget *parent = nullptr) : DoubleSpinBoxControl(title, desc, icon, 0.0, parent) { + spinbox.setRange(minimum, maximum); + spinbox.setSingleStep(step); + spinbox.setSuffix(suffix); + spinbox.setSpecialValueText(minText); + + std::string str_val = Params().get(param.toStdString().c_str()); + if (str_val != "") { + double val = std::stod(str_val); + spinbox.setValue(val); + + QObject::connect(this, &DoubleSpinBoxControl::valChanged, [=](double val) { + Params().put(param.toStdString(), std::to_string(val)); + }); + } + } + void setValue(float v) { spinbox.setValue(v); } +};