AbstractControlSP, ButtonParamControlSP, OptionalControlSP

This commit is contained in:
Jason Wen
2024-07-13 23:32:36 -04:00
parent d0ec155a9d
commit 2e7942ef16
24 changed files with 432 additions and 358 deletions
-45
View File
@@ -62,51 +62,6 @@ void AbstractControl::hideEvent(QHideEvent *e) {
}
}
SPAbstractControl::SPAbstractControl(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(0);
hlayout = new QHBoxLayout;
hlayout->setMargin(0);
hlayout->setSpacing(0);
// title
if (!title.isEmpty()) {
title_label = new QPushButton(title);
title_label->setFixedHeight(120);
title_label->setStyleSheet("font-size: 50px; font-weight: 450; text-align: left; border: none;");
main_layout->addWidget(title_label, 1);
connect(title_label, &QPushButton::clicked, [=]() {
if (!description->isVisible()) {
emit showDescriptionEvent();
}
if (!description->text().isEmpty()) {
description->setVisible(!description->isVisible());
}
});
} else {
main_layout->addSpacing(20);
}
main_layout->addLayout(hlayout);
main_layout->addSpacing(2);
// description
description = new QLabel(desc);
description->setContentsMargins(0, 20, 40, 20);
description->setStyleSheet("font-size: 40px; color: grey");
description->setWordWrap(true);
description->setVisible(false);
main_layout->addWidget(description);
main_layout->addStretch();
}
void SPAbstractControl::hideEvent(QHideEvent *e) {
}
// controls
ButtonControl::ButtonControl(const QString &title, const QString &text, const QString &desc, QWidget *parent) : AbstractControl(title, desc, "", parent) {
+10 -244
View File
@@ -208,71 +208,29 @@ private:
bool store_confirm = false;
};
class SPAbstractControl : public QFrame {
Q_OBJECT
public:
void setDescription(const QString &desc) {
if (description) description->setText(desc);
}
void setTitle(const QString &title) {
title_label->setText(title);
}
const QString getDescription() {
return description->text();
}
public slots:
void showDescription() {
description->setVisible(true);
}
void hideDescription() {
description->setVisible(false);
}
signals:
void showDescriptionEvent();
protected:
SPAbstractControl(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr);
void hideEvent(QHideEvent *e) override;
QHBoxLayout *hlayout;
QPushButton *title_label;
private:
QLabel *description = nullptr;
};
class ButtonParamControl : public SPAbstractControl {
class ButtonParamControl : public AbstractControl {
Q_OBJECT
public:
ButtonParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon,
const std::vector<QString> &button_texts, const int minimum_button_width = 300) : SPAbstractControl(title, desc, icon), button_texts(button_texts) {
const std::vector<QString> &button_texts, const int minimum_button_width = 225) : AbstractControl(title, desc, icon) {
const QString style = R"(
QPushButton {
border-radius: 20px;
font-size: 50px;
font-weight: 450;
height:150px;
border-radius: 50px;
font-size: 40px;
font-weight: 500;
height:100px;
padding: 0 25 0 25;
color: #FFFFFF;
color: #E4E4E4;
background-color: #393939;
}
QPushButton:pressed {
background-color: #4a4a4a;
}
QPushButton:checked:enabled {
background-color: #696868;
background-color: #33Ab4C;
}
QPushButton:disabled {
color: #33FFFFFF;
}
QPushButton:checked:disabled {
background-color: #121212;
color: #33FFFFFF;
color: #33E4E4E4;
}
)";
key = param.toStdString();
@@ -286,16 +244,12 @@ public:
button->setChecked(i == value);
button->setStyleSheet(style);
button->setMinimumWidth(minimum_button_width);
if (i == 0) hlayout->addSpacing(2);
hlayout->addWidget(button);
button_group->addButton(button, i);
}
hlayout->setAlignment(Qt::AlignLeft);
QObject::connect(button_group, QOverload<int>::of(&QButtonGroup::buttonClicked), [=](int id) {
params.put(key, std::to_string(id));
emit buttonToggled(id);
});
}
@@ -303,9 +257,6 @@ public:
for (auto btn : button_group->buttons()) {
btn->setEnabled(enable);
}
button_group_enabled = enable;
update();
}
void setCheckedButton(int id) {
@@ -314,14 +265,6 @@ public:
void refresh() {
int value = atoi(params.get(key).c_str());
if (value >= button_texts.size()) {
value = button_texts.size() - 1;
}
if (value < 0) {
value = 0;
}
button_group->button(value)->setChecked(true);
}
@@ -329,53 +272,10 @@ public:
refresh();
}
void setButton(QString param) {
key = param.toStdString();
int value = atoi(params.get(key).c_str());
for (int i = 0; i < button_group->buttons().size(); i++) {
button_group->buttons()[i]->setChecked(i == value);
}
}
void setDisabledSelectedButton(std::string val) {
int value = atoi(val.c_str());
for (int i = 0; i < button_group->buttons().size(); i++) {
button_group->buttons()[i]->setEnabled(i != value);
}
}
protected:
void paintEvent(QPaintEvent *event) override {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
// Calculate the total width and height for the background rectangle
int w = 0;
int h = 150;
for (int i = 0; i < hlayout->count(); ++i) {
QPushButton *button = qobject_cast<QPushButton *>(hlayout->itemAt(i)->widget());
if (button) {
w += button->width();
}
}
// Draw the rectangle
QRect rect(0 + 2, h - 24, w, h);
p.setPen(QPen(QColor(button_group_enabled ? "#696868" : "#121212"), 3));
p.drawRoundedRect(rect, 20, 20);
}
signals:
void buttonToggled(int btn_id);
private:
std::string key;
Params params;
QButtonGroup *button_group;
std::vector<QString> button_texts;
bool button_group_enabled = true;
};
class ListWidget : public QWidget {
@@ -439,140 +339,6 @@ public:
}
};
class SPOptionControl : public SPAbstractControl {
Q_OBJECT
private:
struct MinMaxValue {
int min_value;
int max_value;
};
public:
SPOptionControl(const QString &param, const QString &title, const QString &desc, const QString &icon,
const MinMaxValue &range, const int per_value_change = 1) : _title(title), SPAbstractControl(title, desc, icon) {
const QString style = R"(
QPushButton {
border-radius: 20px;
font-size: 60px;
font-weight: 500;
width: 150px;
height: 150px;
padding: -3 25 3 25;
color: #FFFFFF;
font-weight: bold;
}
QPushButton:pressed {
color: #5C5C5C;
}
QPushButton:disabled {
color: #5C5C5C;
}
)";
label.setStyleSheet(label_enabled_style);
label.setFixedWidth(300);
label.setAlignment(Qt::AlignCenter);
const std::vector<QString> button_texts{"", ""};
key = param.toStdString();
value = atoi(params.get(key).c_str());
button_group = new QButtonGroup(this);
button_group->setExclusive(true);
for (int i = 0; i < button_texts.size(); i++) {
QPushButton *button = new QPushButton(button_texts[i], this);
button->setStyleSheet(style + ((i == 0) ? "QPushButton { text-align: left; }" :
"QPushButton { text-align: right; }"));
hlayout->addWidget(button, 0, ((i == 0) ? Qt::AlignLeft : Qt::AlignRight) | Qt::AlignVCenter);
if (i == 0) {
hlayout->addWidget(&label, 0, Qt::AlignCenter);
}
button_group->addButton(button, i);
QObject::connect(button, &QPushButton::clicked, [=]() {
int change_value = (i == 0) ? -per_value_change : per_value_change;
key = param.toStdString();
value = atoi(params.get(key).c_str());
value += change_value;
value = std::clamp(value, range.min_value, range.max_value);
params.put(key, QString::number(value).toStdString());
button_group->button(0)->setEnabled(!(value <= range.min_value));
button_group->button(1)->setEnabled(!(value >= range.max_value));
updateLabels();
if (request_update) {
emit updateOtherToggles();
}
});
}
hlayout->setAlignment(Qt::AlignLeft);
}
void setUpdateOtherToggles(bool _update) {
request_update = _update;
}
inline void setLabel(const QString &text) { label.setText(text); }
void setEnabled(bool enabled) {
for (auto btn : button_group->buttons()) {
btn->setEnabled(enabled);
}
label.setEnabled(enabled);
label.setStyleSheet(enabled ? label_enabled_style : label_disabled_style);
button_enabled = enabled;
update();
}
protected:
void paintEvent(QPaintEvent *event) override {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
// Calculate the total width and height for the background rectangle
int w = 0;
int h = 150;
for (int i = 0; i < hlayout->count(); ++i) {
QWidget *widget = qobject_cast<QWidget *>(hlayout->itemAt(i)->widget());
if (widget) {
w += widget->width();
}
}
// Draw the rectangle
QRect rect(0, !_title.isEmpty() ? (h - 24) : 20, w, h);
p.setBrush(QColor(button_enabled ? "#b24a4a4a" : "#121212")); // Background color
p.setPen(QPen(Qt::NoPen));
p.drawRoundedRect(rect, 20, 20);
}
signals:
void updateLabels();
void updateOtherToggles();
private:
std::string key;
int value;
QButtonGroup *button_group;
QLabel label;
Params params;
std::map<QString, QString> option_label = {};
bool request_update = false;
QString _title = "";
const QString label_enabled_style = "font-size: 50px; font-weight: 450; color: #FFFFFF;";
const QString label_disabled_style = "font-size: 50px; font-weight: 450; color: #5C5C5C;";
bool button_enabled = true;
};
class SubPanelButton : public QPushButton {
Q_OBJECT
@@ -14,13 +14,13 @@ CustomOffsetsSettings::CustomOffsetsSettings(QWidget* parent) : QWidget(parent)
// Controls: Camera Offset (cm)
camera_offset = new CameraOffset();
connect(camera_offset, &SPOptionControl::updateLabels, camera_offset, &CameraOffset::refresh);
connect(camera_offset, &OptionControlSP::updateLabels, camera_offset, &CameraOffset::refresh);
camera_offset->showDescription();
list->addItem(camera_offset);
// Controls: Path Offset (cm)
path_offset = new PathOffset();
connect(path_offset, &SPOptionControl::updateLabels, path_offset, &PathOffset::refresh);
connect(path_offset, &OptionControlSP::updateLabels, path_offset, &PathOffset::refresh);
path_offset->showDescription();
list->addItem(path_offset);
@@ -28,7 +28,7 @@ CustomOffsetsSettings::CustomOffsetsSettings(QWidget* parent) : QWidget(parent)
}
// Camera Offset Value
CameraOffset::CameraOffset() : SPOptionControl (
CameraOffset::CameraOffset() : OptionControlSP (
"CameraOffset",
tr("Camera Offset - Laneful Only"),
tr("Hack to trick vehicle to be left or right biased in its lane. Decreasing the value will make the car keep more left, increasing will make it keep more right. Changes take effect immediately. Default: +4 cm"),
@@ -48,7 +48,7 @@ void CameraOffset::refresh() {
}
// Path Offset Value
PathOffset::PathOffset() : SPOptionControl (
PathOffset::PathOffset() : OptionControlSP (
"PathOffset",
tr("Path Offset"),
tr("Hack to trick the model path to be left or right biased of the lane. Decreasing the value will shift the model more left, increasing will shift the model more right. Changes take effect immediately."),
@@ -3,7 +3,7 @@
#include "selfdrive/ui/sunnypilot/qt/widgets/sp_priv_controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
class CameraOffset : public SPOptionControl {
class CameraOffset : public OptionControlSP {
Q_OBJECT
public:
@@ -15,7 +15,7 @@ private:
Params params;
};
class PathOffset : public SPOptionControl {
class PathOffset : public OptionControlSP {
Q_OBJECT
public:
@@ -18,24 +18,24 @@ DisplayPanel::DisplayPanel(QWidget *parent) : ListWidget(parent, false) {
// General: Max Time Offroad (Shutdown timer)
auto max_time_offroad = new MaxTimeOffroad();
connect(max_time_offroad, &SPOptionControl::updateLabels, max_time_offroad, &MaxTimeOffroad::refresh);
connect(max_time_offroad, &OptionControlSP::updateLabels, max_time_offroad, &MaxTimeOffroad::refresh);
addItem(max_time_offroad);
// General: Onroad Screen Off (Auto Onroad Screen Timer)
onroad_screen_off = new OnroadScreenOff();
onroad_screen_off->setUpdateOtherToggles(true);
connect(onroad_screen_off, &SPOptionControl::updateLabels, onroad_screen_off, &OnroadScreenOff::refresh);
connect(onroad_screen_off, &SPOptionControl::updateOtherToggles, this, &DisplayPanel::updateToggles);
connect(onroad_screen_off, &OptionControlSP::updateLabels, onroad_screen_off, &OnroadScreenOff::refresh);
connect(onroad_screen_off, &OptionControlSP::updateOtherToggles, this, &DisplayPanel::updateToggles);
addItem(onroad_screen_off);
// General: Onroad Screen Off Brightness
onroad_screen_off_brightness = new OnroadScreenOffBrightness();
connect(onroad_screen_off_brightness, &SPOptionControl::updateLabels, onroad_screen_off_brightness, &OnroadScreenOffBrightness::refresh);
connect(onroad_screen_off_brightness, &OptionControlSP::updateLabels, onroad_screen_off_brightness, &OnroadScreenOffBrightness::refresh);
addItem(onroad_screen_off_brightness);
// General: Brightness Control (Global)
auto brightness_control = new BrightnessControl();
connect(brightness_control, &SPOptionControl::updateLabels, brightness_control, &BrightnessControl::refresh);
connect(brightness_control, &OptionControlSP::updateLabels, brightness_control, &BrightnessControl::refresh);
for (auto &[param, title, desc, icon] : toggle_defs) {
auto toggle = new ParamControlSP(param, title, desc, icon, this);
@@ -65,7 +65,7 @@ void DisplayPanel::updateToggles() {
}
// Max Time Offroad (Shutdown timer)
MaxTimeOffroad::MaxTimeOffroad() : SPOptionControl (
MaxTimeOffroad::MaxTimeOffroad() : OptionControlSP (
"MaxTimeOffroad",
tr("Max Time Offroad"),
tr("Device is automatically turned off after a set time when the engine is turned off (off-road) after driving (on-road)."),
@@ -110,7 +110,7 @@ void MaxTimeOffroad::refresh() {
}
// Onroad Screen Off (Auto Onroad Screen Timer)
OnroadScreenOff::OnroadScreenOff() : SPOptionControl (
OnroadScreenOff::OnroadScreenOff() : OptionControlSP (
"OnroadScreenOff",
tr("Driving Screen Off Timer"),
tr("Turn off the device screen or reduce brightness to protect the screen after driving starts. It automatically brightens or turns on when a touch or event occurs."),
@@ -136,7 +136,7 @@ void OnroadScreenOff::refresh() {
}
// Onroad Screen Off Brightness
OnroadScreenOffBrightness::OnroadScreenOffBrightness() : SPOptionControl (
OnroadScreenOffBrightness::OnroadScreenOffBrightness() : OptionControlSP (
"OnroadScreenOffBrightness",
tr("Driving Screen Off Brightness (%)"),
tr("When using the Driving Screen Off feature, the brightness is reduced according to the automatic brightness ratio."),
@@ -157,7 +157,7 @@ void OnroadScreenOffBrightness::refresh() {
}
// Brightness Control (Global)
BrightnessControl::BrightnessControl() : SPOptionControl (
BrightnessControl::BrightnessControl() : OptionControlSP (
"BrightnessControl",
tr("Brightness"),
tr("Manually adjusts the global brightness of the screen."),
@@ -2,7 +2,7 @@
#include "selfdrive/ui/sunnypilot/qt/widgets/sp_priv_controls.h"
class OnroadScreenOff : public SPOptionControl {
class OnroadScreenOff : public OptionControlSP {
Q_OBJECT
public:
@@ -14,7 +14,7 @@ private:
Params params;
};
class OnroadScreenOffBrightness : public SPOptionControl {
class OnroadScreenOffBrightness : public OptionControlSP {
Q_OBJECT
public:
@@ -26,7 +26,7 @@ private:
Params params;
};
class MaxTimeOffroad : public SPOptionControl {
class MaxTimeOffroad : public OptionControlSP {
Q_OBJECT
public:
@@ -38,7 +38,7 @@ private:
Params params;
};
class BrightnessControl : public SPOptionControl {
class BrightnessControl : public OptionControlSP {
Q_OBJECT
public:
@@ -37,14 +37,14 @@ LaneChangeSettings::LaneChangeSettings(QWidget* parent) : QWidget(parent) {
auto_lane_change_timer = new AutoLaneChangeTimer();
auto_lane_change_timer->setUpdateOtherToggles(true);
auto_lane_change_timer->showDescription();
connect(auto_lane_change_timer, &SPOptionControl::updateLabels, auto_lane_change_timer, &AutoLaneChangeTimer::refresh);
connect(auto_lane_change_timer, &OptionControlSP::updateLabels, auto_lane_change_timer, &AutoLaneChangeTimer::refresh);
connect(auto_lane_change_timer, &AutoLaneChangeTimer::updateOtherToggles, this, &LaneChangeSettings::updateToggles);
list->addItem(auto_lane_change_timer);
// Pause Lateral Below Speed w/ Blinker
pause_lateral_speed = new PauseLateralSpeed();
pause_lateral_speed->showDescription();
connect(pause_lateral_speed, &SPOptionControl::updateLabels, pause_lateral_speed, &PauseLateralSpeed::refresh);
connect(pause_lateral_speed, &OptionControlSP::updateLabels, pause_lateral_speed, &PauseLateralSpeed::refresh);
for (auto &[param, title, desc, icon] : toggle_defs) {
auto toggle = new ParamControlSP(param, title, desc, icon, this);
@@ -97,7 +97,7 @@ void LaneChangeSettings::updateToggles() {
}
// Auto Lane Change Timer (ALCT)
AutoLaneChangeTimer::AutoLaneChangeTimer() : SPOptionControl (
AutoLaneChangeTimer::AutoLaneChangeTimer() : OptionControlSP (
"AutoLaneChangeTimer",
tr("Auto Lane Change by Blinker"),
tr("Set a timer to delay the auto lane change operation when the blinker is used. No nudge on the steering wheel is required to auto lane change if a timer is set. Default is Nudge.\nPlease use caution when using this feature. Only use the blinker when traffic and road conditions permit."),
@@ -127,7 +127,7 @@ void AutoLaneChangeTimer::refresh() {
}
}
PauseLateralSpeed::PauseLateralSpeed() : SPOptionControl (
PauseLateralSpeed::PauseLateralSpeed() : OptionControlSP (
"PauseLateralSpeed",
"",
tr("Pause lateral actuation with blinker when traveling below the desired speed selected. Default is 20 MPH or 32 km/h."),
@@ -4,7 +4,7 @@
#include "selfdrive/ui/sunnypilot/qt/widgets/sp_priv_controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
class AutoLaneChangeTimer : public SPOptionControl {
class AutoLaneChangeTimer : public OptionControlSP {
Q_OBJECT
public:
@@ -19,7 +19,7 @@ private:
Params params;
};
class PauseLateralSpeed : public SPOptionControl {
class PauseLateralSpeed : public OptionControlSP {
Q_OBJECT
public:
@@ -32,7 +32,7 @@ MadsSettings::MadsSettings(QWidget* parent) : QWidget(parent) {
// Disengage Lateral on Brake (DLOB)
std::vector<QString> dlob_settings_texts{tr("Remain Active"), tr("Pause Steering")};
dlob_settings = new ButtonParamControl(
dlob_settings = new ButtonParamControlSP(
"DisengageLateralOnBrake",
tr("Steering Mode After Braking"),
tr("Choose how Automatic Lane Centering (ALC) behaves after the brake pedal is manually pressed in sunnypilot.\n\nRemain Active: ALC will remain active even after the brake pedal is pressed.\nPause Steering: ALC will be paused after the brake pedal is manually pressed."),
@@ -54,7 +54,7 @@ MadsSettings::MadsSettings(QWidget* parent) : QWidget(parent) {
}
// trigger offroadTransition when going onroad/offroad
connect(uiState(), &UIState::offroadTransition, dlob_settings, &ButtonParamControl::setEnabled);
connect(uiState(), &UIState::offroadTransition, dlob_settings, &ButtonParamControlSP::setEnabled);
main_layout->addWidget(new ScrollView(list, this));
}
@@ -21,5 +21,5 @@ private:
Params params;
std::map<std::string, ParamControlSP*> toggles;
ButtonParamControl *dlob_settings;
ButtonParamControlSP *dlob_settings;
};
@@ -100,7 +100,7 @@ TogglesPanelSP::TogglesPanelSP(SettingsWindow *parent) : TogglesPanel(parent) {
std::vector<QString> longi_button_texts{tr("Aggressive"), tr("Moderate"), tr("Standard"), tr("Relaxed")};
long_personality_setting = new ButtonParamControl("LongitudinalPersonality", tr("Driving Personality"),
long_personality_setting = new ButtonParamControlSP("LongitudinalPersonality", tr("Driving Personality"),
tr("Standard is recommended. In moderate/aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. "
"In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with "
"your steering wheel distance button."),
@@ -111,7 +111,7 @@ TogglesPanelSP::TogglesPanelSP(SettingsWindow *parent) : TogglesPanel(parent) {
// accel controller
std::vector<QString> accel_personality_texts{tr("Sport"), tr("Normal"), tr("Eco"), tr("Stock")};
accel_personality_setting = new ButtonParamControl("AccelPersonality", tr("Acceleration Personality"),
accel_personality_setting = new ButtonParamControlSP("AccelPersonality", tr("Acceleration Personality"),
tr("Normal is recommended. In sport mode, sunnypilot will provide aggressive acceleration for a dynamic driving experience. "
"In eco mode, sunnypilot will apply smoother and more relaxed acceleration. On supported cars, you can cycle through these "
"acceleration personality within Onroad Settings on the driving screen."),
@@ -14,7 +14,8 @@ private slots:
private:
std::map<std::string, ParamControlSP*> toggles;
ButtonParamControl *accel_personality_setting;
ButtonParamControlSP *long_personality_setting;
ButtonParamControlSP *accel_personality_setting;
ParamWatcher *param_watcher;
void updateToggles() override;
@@ -13,7 +13,7 @@ SlcSettings::SlcSettings(QWidget* parent) : QWidget(parent) {
ListWidget *list = new ListWidget(this, false);
std::vector<QString> speed_limit_engage_texts{tr("Auto"), tr("User Confirm")};
speed_limit_engage_settings = new ButtonParamControl(
speed_limit_engage_settings = new ButtonParamControlSP(
"SpeedLimitEngageType", tr("Engage Mode"),
"",
"../assets/offroad/icon_blank.png",
@@ -24,7 +24,7 @@ SlcSettings::SlcSettings(QWidget* parent) : QWidget(parent) {
list->addItem(speed_limit_engage_settings);
std::vector<QString> speed_limit_offset_settings_texts{tr("Default"), tr("Fixed"), tr("Percentage")};
speed_limit_offset_settings = new ButtonParamControl(
speed_limit_offset_settings = new ButtonParamControlSP(
"SpeedLimitOffsetType", tr("Limit Offset"), tr("Set speed limit slightly higher than actual speed limit for a more natural drive."),
"../assets/offroad/icon_blank.png",
speed_limit_offset_settings_texts,
@@ -33,11 +33,11 @@ SlcSettings::SlcSettings(QWidget* parent) : QWidget(parent) {
list->addItem(speed_limit_offset_settings);
slvo = new SpeedLimitValueOffset();
connect(slvo, &SPOptionControl::updateLabels, slvo, &SpeedLimitValueOffset::refresh);
connect(slvo, &OptionControlSP::updateLabels, slvo, &SpeedLimitValueOffset::refresh);
list->addItem(slvo);
connect(speed_limit_offset_settings, &ButtonParamControl::buttonToggled, this, &SlcSettings::updateToggles);
connect(speed_limit_offset_settings, &ButtonParamControl::buttonToggled, slvo, &SpeedLimitValueOffset::refresh);
connect(speed_limit_offset_settings, &ButtonParamControlSP::buttonToggled, this, &SlcSettings::updateToggles);
connect(speed_limit_offset_settings, &ButtonParamControlSP::buttonToggled, slvo, &SpeedLimitValueOffset::refresh);
param_watcher = new ParamWatcher(this);
@@ -101,7 +101,7 @@ void SlcSettings::updateToggles() {
}
// Speed Limit Control Custom Offset
SpeedLimitValueOffset::SpeedLimitValueOffset() : SPOptionControl (
SpeedLimitValueOffset::SpeedLimitValueOffset() : OptionControlSP (
"SpeedLimitValueOffset",
"",
"",
@@ -5,7 +5,7 @@
#include "selfdrive/ui/qt/widgets/scrollview.h"
#include "selfdrive/ui/qt/util.h"
class SpeedLimitValueOffset : public SPOptionControl {
class SpeedLimitValueOffset : public OptionControlSP {
Q_OBJECT
public:
@@ -36,8 +36,8 @@ private:
std::map<std::string, ParamControlSP*> toggles;
SpeedLimitValueOffset *slvo;
ButtonParamControl *speed_limit_offset_settings;
ButtonParamControl *speed_limit_engage_settings;
ButtonParamControlSP *speed_limit_offset_settings;
ButtonParamControlSP *speed_limit_engage_settings;
ParamWatcher *param_watcher;
QString slcDescriptionBuilder(QString param, std::vector<QString> descriptions) {
@@ -12,7 +12,7 @@ SpeedLimitPolicySettings::SpeedLimitPolicySettings(QWidget* parent) : QWidget(pa
ListWidget *list = new ListWidget(this, false);
speed_limit_policy = new ButtonParamControl(
speed_limit_policy = new ButtonParamControlSP(
"SpeedLimitControlPolicy",
tr("Speed Limit Source Policy"),
"",
@@ -21,7 +21,7 @@ SpeedLimitPolicySettings::SpeedLimitPolicySettings(QWidget* parent) : QWidget(pa
250
);
speed_limit_policy->showDescription();
connect(speed_limit_policy, &ButtonParamControl::buttonToggled, this, &SpeedLimitPolicySettings::updateToggles);
connect(speed_limit_policy, &ButtonParamControlSP::buttonToggled, this, &SpeedLimitPolicySettings::updateToggles);
list->addItem(speed_limit_policy);
param_watcher = new ParamWatcher(this);
@@ -1,7 +1,7 @@
#pragma once
#include "selfdrive/ui/ui.h"
#include "selfdrive/ui/qt/widgets/controls.h"
#include "selfdrive/ui/sunnypilot/qt/widgets/sp_priv_controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
#include "selfdrive/ui/qt/util.h"
@@ -23,7 +23,7 @@ public slots:
private:
Params params;
ButtonParamControl *speed_limit_policy;
ButtonParamControlSP *speed_limit_policy;
ParamWatcher *param_watcher;
QString speedLimitPolicyDescriptionBuilder(QString param, std::vector<QString> descriptions) {
@@ -13,7 +13,7 @@ SpeedLimitWarningSettings::SpeedLimitWarningSettings(QWidget* parent) : QWidget(
ListWidget *list = new ListWidget(this, false);
std::vector<QString> speed_limit_warning_texts{tr("Off"), tr("Display"), tr("Chime")};
speed_limit_warning_settings = new ButtonParamControl(
speed_limit_warning_settings = new ButtonParamControlSP(
"SpeedLimitWarningType", tr("Speed Limit Warning"),
"",
"../assets/offroad/icon_blank.png",
@@ -32,7 +32,7 @@ SpeedLimitWarningSettings::SpeedLimitWarningSettings(QWidget* parent) : QWidget(
list->addItem(speed_limit_warning_flash);
std::vector<QString> speed_limit_warning_offset_settings_texts{tr("Default"), tr("Fixed"), tr("Percentage")};
speed_limit_warning_offset_settings = new ButtonParamControl(
speed_limit_warning_offset_settings = new ButtonParamControlSP(
"SpeedLimitWarningOffsetType", tr("Warning Offset"),
tr("Select the desired offset to warn the driver when the vehicle is driving faster than the speed limit."),
"../assets/offroad/icon_blank.png",
@@ -42,13 +42,13 @@ SpeedLimitWarningSettings::SpeedLimitWarningSettings(QWidget* parent) : QWidget(
list->addItem(speed_limit_warning_offset_settings);
slwvo = new SpeedLimitWarningValueOffset();
connect(slwvo, &SPOptionControl::updateLabels, slwvo, &SpeedLimitWarningValueOffset::refresh);
connect(slwvo, &OptionControlSP::updateLabels, slwvo, &SpeedLimitWarningValueOffset::refresh);
list->addItem(slwvo);
connect(speed_limit_warning_settings, &ButtonParamControl::buttonToggled, this, &SpeedLimitWarningSettings::updateToggles);
connect(speed_limit_warning_settings, &ButtonParamControlSP::buttonToggled, this, &SpeedLimitWarningSettings::updateToggles);
connect(speed_limit_warning_offset_settings, &ButtonParamControl::buttonToggled, this, &SpeedLimitWarningSettings::updateToggles);
connect(speed_limit_warning_offset_settings, &ButtonParamControl::buttonToggled, slwvo, &SpeedLimitWarningValueOffset::refresh);
connect(speed_limit_warning_offset_settings, &ButtonParamControlSP::buttonToggled, this, &SpeedLimitWarningSettings::updateToggles);
connect(speed_limit_warning_offset_settings, &ButtonParamControlSP::buttonToggled, slwvo, &SpeedLimitWarningValueOffset::refresh);
param_watcher = new ParamWatcher(this);
@@ -86,7 +86,7 @@ void SpeedLimitWarningSettings::updateToggles() {
}
// Speed Limit Control Custom Offset
SpeedLimitWarningValueOffset::SpeedLimitWarningValueOffset() : SPOptionControl (
SpeedLimitWarningValueOffset::SpeedLimitWarningValueOffset() : OptionControlSP (
"SpeedLimitWarningValueOffset",
"",
"",
@@ -5,7 +5,7 @@
#include "selfdrive/ui/qt/widgets/scrollview.h"
#include "selfdrive/ui/qt/util.h"
class SpeedLimitWarningValueOffset : public SPOptionControl {
class SpeedLimitWarningValueOffset : public OptionControlSP {
Q_OBJECT
public:
@@ -36,9 +36,9 @@ private:
std::map<std::string, ParamControlSP*> toggles;
SpeedLimitWarningValueOffset *slwvo;
ButtonParamControl *speed_limit_warning_offset_settings;
ButtonParamControlSP *speed_limit_warning_offset_settings;
ParamControlSP *speed_limit_warning_flash;
ButtonParamControl *speed_limit_warning_settings;
ButtonParamControlSP *speed_limit_warning_settings;
ParamWatcher *param_watcher;
QString speedLimitWarningDescriptionBuilder(QString param, std::vector<QString> descriptions) {
@@ -235,14 +235,14 @@ SunnypilotPanel::SunnypilotPanel(QWidget *parent) : QFrame(parent) {
// Controls: Torque - FRICTION
friction = new TorqueFriction();
connect(friction, &SPOptionControl::updateLabels, friction, &TorqueFriction::refresh);
connect(friction, &OptionControlSP::updateLabels, friction, &TorqueFriction::refresh);
// Controls: Torque - LAT_ACCEL_FACTOR
lat_accel_factor = new TorqueMaxLatAccel();
connect(lat_accel_factor, &SPOptionControl::updateLabels, lat_accel_factor, &TorqueMaxLatAccel::refresh);
connect(lat_accel_factor, &OptionControlSP::updateLabels, lat_accel_factor, &TorqueMaxLatAccel::refresh);
std::vector<QString> dlp_settings_texts{tr("Laneful"), tr("Laneless"), tr("Auto")};
dlp_settings = new ButtonParamControl(
dlp_settings = new ButtonParamControlSP(
"DynamicLaneProfile", tr("Dynamic Lane Profile"), "",
"../assets/offroad/icon_blank.png",
dlp_settings_texts,
@@ -567,7 +567,7 @@ void SunnypilotPanel::updateToggles() {
}
// toggle names to update when CustomTorqueLateral is flipped
std::vector<SPAbstractControl*> customTorqueGroup{friction, lat_accel_factor};
std::vector<AbstractControlSP*> customTorqueGroup{friction, lat_accel_factor};
for (const auto& customTorqueControl : customTorqueGroup) {
customTorqueControl->setVisible(!(nnff_toggle->isToggled() || !custom_torque_lateral->isToggled()));
customTorqueControl->setEnabled(!(nnff_toggle->isToggled() || !custom_torque_lateral->isToggled()));
@@ -581,7 +581,7 @@ void SunnypilotPanel::updateToggles() {
dlp_settings->setDescription((model_use_lateral_planner ? "" : dlp_incompatible_desc + "<br><br>") + dlp_description);
}
TorqueFriction::TorqueFriction() : SPOptionControl (
TorqueFriction::TorqueFriction() : OptionControlSP (
"TorqueFriction",
tr("FRICTION"),
tr("Adjust Friction for the Torque Lateral Controller. <b>Live</b>: Override self-tune values; <b>Offline</b>: Override self-tune offline values at car restart."),
@@ -597,7 +597,7 @@ void TorqueFriction::refresh() {
setLabel(QString::number(torqueFrictionVal));
}
TorqueMaxLatAccel::TorqueMaxLatAccel() : SPOptionControl (
TorqueMaxLatAccel::TorqueMaxLatAccel() : OptionControlSP (
"TorqueMaxLatAccel",
tr("LAT_ACCEL_FACTOR"),
tr("Adjust Max Lateral Acceleration for the Torque Lateral Controller. <b>Live</b>: Override self-tune values; <b>Offline</b>: Override self-tune offline values at car restart."),
@@ -12,7 +12,7 @@
#include "selfdrive/ui/sunnypilot/qt/widgets/sp_priv_controls.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
class TorqueFriction : public SPOptionControl {
class TorqueFriction : public OptionControlSP {
Q_OBJECT
public:
@@ -24,7 +24,7 @@ private:
Params params;
};
class TorqueMaxLatAccel : public SPOptionControl {
class TorqueMaxLatAccel : public OptionControlSP {
Q_OBJECT
public:
@@ -65,7 +65,7 @@ private:
TorqueFriction *friction;
TorqueMaxLatAccel *lat_accel_factor;
ButtonParamControl *dlp_settings;
ButtonParamControlSP *dlp_settings;
ScrollView *scrollView = nullptr;
@@ -73,7 +73,7 @@ VisualsPanel::VisualsPanel(QWidget *parent) : ListWidget(parent) {
// Visuals: Developer UI Info (Dev UI)
std::vector<QString> dev_ui_settings_texts{tr("Off"), tr("5 Metrics"), tr("10 Metrics")};
dev_ui_settings = new ButtonParamControl(
dev_ui_settings = new ButtonParamControlSP(
"DevUIInfo", tr("Developer UI"), tr("Display real-time parameters and metrics from various sources."),
"../assets/offroad/icon_blank.png",
dev_ui_settings_texts,
@@ -83,7 +83,7 @@ VisualsPanel::VisualsPanel(QWidget *parent) : ListWidget(parent) {
// Visuals: Display Metrics above Chevron
std::vector<QString> chevron_info_settings_texts{tr("Off"), tr("Distance"), tr("Speed"), tr("Distance\nSpeed")};
chevron_info_settings = new ButtonParamControl(
chevron_info_settings = new ButtonParamControlSP(
"ChevronInfo", tr("Display Metrics Below Chevron"), tr("Display useful metrics below the chevron that tracks the lead car (only applicable to cars with openpilot longitudinal control)."),
"../assets/offroad/icon_blank.png",
chevron_info_settings_texts,
@@ -107,7 +107,7 @@ VisualsPanel::VisualsPanel(QWidget *parent) : ListWidget(parent) {
}
std::vector<QString> sidebar_temp_texts{tr("Off"), tr("RAM"), tr("CPU"), tr("GPU"), tr("Max")};
sidebar_temp_setting = new ButtonParamControl(
sidebar_temp_setting = new ButtonParamControlSP(
"SidebarTemperatureOptions", tr("Display Temperature on Sidebar"), "",
"../assets/offroad/icon_blank.png",
sidebar_temp_texts,
@@ -13,7 +13,7 @@ private:
Params params;
std::map<std::string, ParamControlSP*> toggles;
ButtonParamControl *dev_ui_settings;
ButtonParamControl *chevron_info_settings;
ButtonParamControl *sidebar_temp_setting;
ButtonParamControlSP *dev_ui_settings;
ButtonParamControlSP *chevron_info_settings;
ButtonParamControlSP *sidebar_temp_setting;
};
@@ -12,6 +12,54 @@ QFrame *horizontal_line(QWidget *parent) {
return line;
}
AbstractControlSP::AbstractControlSP(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) {
QVBoxLayout *main_layout = new QVBoxLayout(this);
main_layout->setMargin(0);
hlayout = new QHBoxLayout;
hlayout->setMargin(0);
hlayout->setSpacing(0);
// title
if (!title.isEmpty()) {
title_label = new QPushButton(title);
title_label->setFixedHeight(120);
title_label->setStyleSheet("font-size: 50px; font-weight: 450; text-align: left; border: none;");
main_layout->addWidget(title_label, 1);
connect(title_label, &QPushButton::clicked, [=]() {
if (!description->isVisible()) {
emit showDescriptionEvent();
}
if (!description->text().isEmpty()) {
description->setVisible(!description->isVisible());
}
});
} else {
main_layout->addSpacing(20);
}
main_layout->addLayout(hlayout);
main_layout->addSpacing(2);
// description
description = new QLabel(desc);
description->setContentsMargins(0, 20, 40, 20);
description->setStyleSheet("font-size: 40px; color: grey");
description->setWordWrap(true);
description->setVisible(false);
main_layout->addWidget(description);
main_layout->addStretch();
}
void AbstractControlSP::hideEvent(QHideEvent *e) {
if (description != nullptr) {
description->hide();
}
}
ParamControlSP::ParamControlSP(const QString &param, const QString &title, const QString &desc, const QString &icon, QWidget *parent)
: ParamControl(param, title, desc, icon, parent) {
@@ -12,3 +12,307 @@ public:
bool isToggled() { return params.getBool(key); }
};
class AbstractControlSP : public QFrame {
Q_OBJECT
public:
void setDescription(const QString &desc) {
if (description) description->setText(desc);
}
void setTitle(const QString &title) {
title_label->setText(title);
}
const QString getDescription() {
return description->text();
}
public slots:
void showDescription() {
description->setVisible(true);
}
void hideDescription() {
description->setVisible(false);
}
signals:
void showDescriptionEvent();
protected:
AbstractControlSP(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr);
void hideEvent(QHideEvent *e) override;
QHBoxLayout *hlayout;
QPushButton *title_label;
private:
QLabel *description = nullptr;
};
class ButtonParamControlSP : public AbstractControlSP {
Q_OBJECT
public:
ButtonParamControlSP(const QString &param, const QString &title, const QString &desc, const QString &icon,
const std::vector<QString> &button_texts, const int minimum_button_width = 300) : AbstractControlSP(title, desc, icon), button_texts(button_texts) {
const QString style = R"(
QPushButton {
border-radius: 20px;
font-size: 50px;
font-weight: 450;
height:150px;
padding: 0 25 0 25;
color: #FFFFFF;
}
QPushButton:pressed {
background-color: #4a4a4a;
}
QPushButton:checked:enabled {
background-color: #696868;
}
QPushButton:disabled {
color: #33FFFFFF;
}
QPushButton:checked:disabled {
background-color: #121212;
color: #33FFFFFF;
}
)";
key = param.toStdString();
int value = atoi(params.get(key).c_str());
button_group = new QButtonGroup(this);
button_group->setExclusive(true);
for (int i = 0; i < button_texts.size(); i++) {
QPushButton *button = new QPushButton(button_texts[i], this);
button->setCheckable(true);
button->setChecked(i == value);
button->setStyleSheet(style);
button->setMinimumWidth(minimum_button_width);
if (i == 0) hlayout->addSpacing(2);
hlayout->addWidget(button);
button_group->addButton(button, i);
}
hlayout->setAlignment(Qt::AlignLeft);
QObject::connect(button_group, QOverload<int>::of(&QButtonGroup::buttonClicked), [=](int id) {
params.put(key, std::to_string(id));
emit buttonToggled(id);
});
}
void setEnabled(bool enable) {
for (auto btn : button_group->buttons()) {
btn->setEnabled(enable);
}
button_group_enabled = enable;
update();
}
void setCheckedButton(int id) {
button_group->button(id)->setChecked(true);
}
void refresh() {
int value = atoi(params.get(key).c_str());
if (value >= button_texts.size()) {
value = button_texts.size() - 1;
}
if (value < 0) {
value = 0;
}
button_group->button(value)->setChecked(true);
}
void showEvent(QShowEvent *event) override {
refresh();
}
void setButton(QString param) {
key = param.toStdString();
int value = atoi(params.get(key).c_str());
for (int i = 0; i < button_group->buttons().size(); i++) {
button_group->buttons()[i]->setChecked(i == value);
}
}
void setDisabledSelectedButton(std::string val) {
int value = atoi(val.c_str());
for (int i = 0; i < button_group->buttons().size(); i++) {
button_group->buttons()[i]->setEnabled(i != value);
}
}
protected:
void paintEvent(QPaintEvent *event) override {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
// Calculate the total width and height for the background rectangle
int w = 0;
int h = 150;
for (int i = 0; i < hlayout->count(); ++i) {
QPushButton *button = qobject_cast<QPushButton *>(hlayout->itemAt(i)->widget());
if (button) {
w += button->width();
}
}
// Draw the rectangle
QRect rect(0 + 2, h - 24, w, h);
p.setPen(QPen(QColor(button_group_enabled ? "#696868" : "#121212"), 3));
p.drawRoundedRect(rect, 20, 20);
}
signals:
void buttonToggled(int btn_id);
private:
std::string key;
Params params;
QButtonGroup *button_group;
std::vector<QString> button_texts;
bool button_group_enabled = true;
};
class OptionControlSP : public AbstractControlSP {
Q_OBJECT
private:
struct MinMaxValue {
int min_value;
int max_value;
};
public:
OptionControlSP(const QString &param, const QString &title, const QString &desc, const QString &icon,
const MinMaxValue &range, const int per_value_change = 1) : _title(title), AbstractControlSP(title, desc, icon) {
const QString style = R"(
QPushButton {
border-radius: 20px;
font-size: 60px;
font-weight: 500;
width: 150px;
height: 150px;
padding: -3 25 3 25;
color: #FFFFFF;
font-weight: bold;
}
QPushButton:pressed {
color: #5C5C5C;
}
QPushButton:disabled {
color: #5C5C5C;
}
)";
label.setStyleSheet(label_enabled_style);
label.setFixedWidth(300);
label.setAlignment(Qt::AlignCenter);
const std::vector<QString> button_texts{"", ""};
key = param.toStdString();
value = atoi(params.get(key).c_str());
button_group = new QButtonGroup(this);
button_group->setExclusive(true);
for (int i = 0; i < button_texts.size(); i++) {
QPushButton *button = new QPushButton(button_texts[i], this);
button->setStyleSheet(style + ((i == 0) ? "QPushButton { text-align: left; }" :
"QPushButton { text-align: right; }"));
hlayout->addWidget(button, 0, ((i == 0) ? Qt::AlignLeft : Qt::AlignRight) | Qt::AlignVCenter);
if (i == 0) {
hlayout->addWidget(&label, 0, Qt::AlignCenter);
}
button_group->addButton(button, i);
QObject::connect(button, &QPushButton::clicked, [=]() {
int change_value = (i == 0) ? -per_value_change : per_value_change;
key = param.toStdString();
value = atoi(params.get(key).c_str());
value += change_value;
value = std::clamp(value, range.min_value, range.max_value);
params.put(key, QString::number(value).toStdString());
button_group->button(0)->setEnabled(!(value <= range.min_value));
button_group->button(1)->setEnabled(!(value >= range.max_value));
updateLabels();
if (request_update) {
emit updateOtherToggles();
}
});
}
hlayout->setAlignment(Qt::AlignLeft);
}
void setUpdateOtherToggles(bool _update) {
request_update = _update;
}
inline void setLabel(const QString &text) { label.setText(text); }
void setEnabled(bool enabled) {
for (auto btn : button_group->buttons()) {
btn->setEnabled(enabled);
}
label.setEnabled(enabled);
label.setStyleSheet(enabled ? label_enabled_style : label_disabled_style);
button_enabled = enabled;
update();
}
protected:
void paintEvent(QPaintEvent *event) override {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
// Calculate the total width and height for the background rectangle
int w = 0;
int h = 150;
for (int i = 0; i < hlayout->count(); ++i) {
QWidget *widget = qobject_cast<QWidget *>(hlayout->itemAt(i)->widget());
if (widget) {
w += widget->width();
}
}
// Draw the rectangle
QRect rect(0, !_title.isEmpty() ? (h - 24) : 20, w, h);
p.setBrush(QColor(button_enabled ? "#b24a4a4a" : "#121212")); // Background color
p.setPen(QPen(Qt::NoPen));
p.drawRoundedRect(rect, 20, 20);
}
signals:
void updateLabels();
void updateOtherToggles();
private:
std::string key;
int value;
QButtonGroup *button_group;
QLabel label;
Params params;
std::map<QString, QString> option_label = {};
bool request_update = false;
QString _title = "";
const QString label_enabled_style = "font-size: 50px; font-weight: 450; color: #FFFFFF;";
const QString label_disabled_style = "font-size: 50px; font-weight: 450; color: #5C5C5C;";
bool button_enabled = true;
};