diff --git a/common/params_keys.h b/common/params_keys.h index 8121e610f..76b5033fd 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -146,6 +146,7 @@ inline static std::unordered_map keys = { {"OffroadMode", CLEAR_ON_MANAGER_START}, {"QuickBootToggle", PERSISTENT | BACKUP}, {"QuietMode", PERSISTENT | BACKUP}, + {"ShowAdvancedControls", PERSISTENT | BACKUP}, // MADS params {"Mads", PERSISTENT | BACKUP}, diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.cc index 4c4e18a5f..f781a015c 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.cc +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.cc @@ -7,6 +7,17 @@ #include "selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h" DeveloperPanelSP::DeveloperPanelSP(SettingsWindow *parent) : DeveloperPanel(parent) { + + // Advanced Controls Toggle + showAdvancedControls = new ParamControlSP("ShowAdvancedControls", tr("Show Advanced Controls"), tr("Toggle visibility of advanced sunnypilot controls.\nThis only toggles the visibility of the controls; it does not toggle the actual control enabled/disabled state."), ""); + addItem(showAdvancedControls); + + QObject::connect(showAdvancedControls, &ParamControlSP::toggleFlipped, this, [=](bool) { + AbstractControlSP::UpdateAllAdvancedControls(); + updateToggles(!uiState()->scene.started); + }); + showAdvancedControls->showDescription(); + // Github Runner Toggle enableGithubRunner = new ParamControlSP("EnableGithubRunner", tr("Enable GitHub runner service"), tr("Enables or disables the github runner service."), ""); addItem(enableGithubRunner); @@ -57,11 +68,13 @@ void DeveloperPanelSP::updateToggles(bool offroad) { : tr("Quickboot mode requires updates to be disabled.
Enable 'Disable Updates' in the Software panel first.")); enableGithubRunner->setVisible(!is_release); - errorLogBtn->setVisible(!is_release && !is_tested); + errorLogBtn->setVisible(!is_release); + showAdvancedControls->setEnabled(true); } void DeveloperPanelSP::showEvent(QShowEvent *event) { DeveloperPanel::showEvent(event); updateToggles(!uiState()->scene.started); + AbstractControlSP::UpdateAllAdvancedControls(); prebuiltToggle->showDescription(); } diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h index 1e375aa8d..d63fe18d0 100644 --- a/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/developer_panel.h @@ -20,6 +20,7 @@ private: ButtonControlSP *errorLogBtn; ParamControlSP *prebuiltToggle; Params params; + ParamControlSP *showAdvancedControls; private slots: void updateToggles(bool offroad); diff --git a/selfdrive/ui/sunnypilot/qt/widgets/controls.cc b/selfdrive/ui/sunnypilot/qt/widgets/controls.cc index d873913b5..28374f3a9 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/controls.cc +++ b/selfdrive/ui/sunnypilot/qt/widgets/controls.cc @@ -30,9 +30,24 @@ QFrame *vertical_space(int height, QWidget *parent) { } // AbstractControlSP +std::vector AbstractControlSP::advanced_controls_; +AbstractControlSP::~AbstractControlSP() { UnregisterAdvancedControl(this); } -AbstractControlSP::AbstractControlSP(const QString &title, const QString &desc, const QString &icon, QWidget *parent) - : AbstractControl(title, desc, icon, parent) { +void AbstractControlSP::RegisterAdvancedControl(AbstractControlSP *ctrl) { advanced_controls_.push_back(ctrl); } + +void AbstractControlSP::UnregisterAdvancedControl(AbstractControlSP *ctrl) { + advanced_controls_.erase(std::remove(advanced_controls_.begin(), advanced_controls_.end(), ctrl), advanced_controls_.end()); +} + +void AbstractControlSP::UpdateAllAdvancedControls() { + bool visibility = Params().getBool("ShowAdvancedControls"); + advanced_controls_.erase(std::remove(advanced_controls_.begin(), advanced_controls_.end(), nullptr), advanced_controls_.end()); + for (auto *ctrl : advanced_controls_) ctrl->setVisible(visibility); +} + +AbstractControlSP::AbstractControlSP(const QString &title, const QString &desc, const QString &icon, QWidget *parent, bool advancedControl) + : AbstractControl(title, desc, icon, parent), isAdvancedControl(advancedControl) { + if (isAdvancedControl) RegisterAdvancedControl(this); main_layout = new QVBoxLayout(this); main_layout->setMargin(0); @@ -82,8 +97,8 @@ void AbstractControlSP::hideEvent(QHideEvent *e) { } } -AbstractControlSP_SELECTOR::AbstractControlSP_SELECTOR(const QString &title, const QString &desc, const QString &icon, QWidget *parent) - : AbstractControlSP(title, desc, icon, parent) { +AbstractControlSP_SELECTOR::AbstractControlSP_SELECTOR(const QString &title, const QString &desc, const QString &icon, QWidget *parent, bool advancedControl) + : AbstractControlSP(title, desc, icon, parent, advancedControl) { if (title_label != nullptr) { delete title_label; @@ -169,8 +184,8 @@ void AbstractControlSP_SELECTOR::hideEvent(QHideEvent *e) { // controls -ButtonControlSP::ButtonControlSP(const QString &title, const QString &text, const QString &desc, QWidget *parent) - : AbstractControlSP(title, desc, "", parent) { +ButtonControlSP::ButtonControlSP(const QString &title, const QString &text, const QString &desc, QWidget *parent, bool advancedControl) + : AbstractControlSP(title, desc, "", parent, advancedControl) { btn.setText(text); btn.setStyleSheet(R"( @@ -225,8 +240,8 @@ void ElidedLabelSP::paintEvent(QPaintEvent *event) { // ParamControlSP -ParamControlSP::ParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent) - : ToggleControlSP(title, desc, icon, false, parent) { +ParamControlSP::ParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent, bool advancedControl) + : ToggleControlSP(title, desc, icon, false, parent, advancedControl){ key = param.toStdString(); QObject::connect(this, &ParamControlSP::toggleFlipped, this, &ParamControlSP::toggleClicked); diff --git a/selfdrive/ui/sunnypilot/qt/widgets/controls.h b/selfdrive/ui/sunnypilot/qt/widgets/controls.h index 29b6e6e6e..a840febfe 100644 --- a/selfdrive/ui/sunnypilot/qt/widgets/controls.h +++ b/selfdrive/ui/sunnypilot/qt/widgets/controls.h @@ -57,6 +57,7 @@ class AbstractControlSP : public AbstractControl { Q_OBJECT public: + ~AbstractControlSP(); void setDescription(const QString &desc) override { if (description) description->setText(desc); } @@ -81,13 +82,30 @@ public slots: description->setVisible(true); } + void setVisible(bool visible) override { + bool _visible = visible; + if (isAdvancedControl && !params.getBool("ShowAdvancedControls")) { + _visible = false; + } + AbstractControl::setVisible(_visible); + } + + static void RegisterAdvancedControl(AbstractControlSP *ctrl); + static void UnregisterAdvancedControl(AbstractControlSP *ctrl); + static void UpdateAllAdvancedControls(); + protected: - AbstractControlSP(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr); + AbstractControlSP(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr, bool advancedControl = false); void hideEvent(QHideEvent *e) override; QVBoxLayout *main_layout; ElidedLabelSP *value; QLabel *description = nullptr; + bool isAdvancedControl; + +private: + Params params; + static std::vector advanced_controls_; }; // AbstractControlSP_SELECTOR @@ -97,7 +115,7 @@ class AbstractControlSP_SELECTOR : public AbstractControlSP { protected: QSpacerItem *spacingItem = new QSpacerItem(44, 44, QSizePolicy::Minimum, QSizePolicy::Fixed); - AbstractControlSP_SELECTOR(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr); + AbstractControlSP_SELECTOR(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr, bool advancedControl = false); void hideEvent(QHideEvent *e) override; }; @@ -123,7 +141,7 @@ class ButtonControlSP : public AbstractControlSP { Q_OBJECT public: - ButtonControlSP(const QString &title, const QString &text, const QString &desc = "", QWidget *parent = nullptr); + ButtonControlSP(const QString &title, const QString &text, const QString &desc = "", QWidget *parent = nullptr, bool advancedControl = false); inline void setText(const QString &text) { btn.setText(text); } inline QString text() const { return btn.text(); } inline void click() { btn.click(); } @@ -142,7 +160,7 @@ class ToggleControlSP : public AbstractControlSP { Q_OBJECT public: - ToggleControlSP(const QString &title, const QString &desc = "", const QString &icon = "", const bool state = false, QWidget *parent = nullptr) : AbstractControlSP(title, desc, icon, parent) { + ToggleControlSP(const QString &title, const QString &desc = "", const QString &icon = "", const bool state = false, QWidget *parent = nullptr, bool advancedControl = false) : AbstractControlSP(title, desc, icon, parent, advancedControl) { // space between toggle and title icon_label = new QLabel(this); hlayout->addWidget(icon_label); @@ -173,7 +191,7 @@ class ParamControlSP : public ToggleControlSP { Q_OBJECT public: - ParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr); + ParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr, bool advancedControl = false); void setConfirmation(bool _confirm, bool _store_confirm) { confirm = _confirm; store_confirm = _store_confirm; @@ -219,7 +237,7 @@ class MultiButtonControlSP : public AbstractControlSP_SELECTOR { public: MultiButtonControlSP(const QString &title, const QString &desc, const QString &icon, - const std::vector &button_texts, const int minimum_button_width = 225, const bool inline_layout = false) : AbstractControlSP_SELECTOR(title, desc, icon), button_texts(button_texts), is_inline_layout(inline_layout) { + const std::vector &button_texts, const int minimum_button_width = 225, const bool inline_layout = false, bool advancedControl = false) : AbstractControlSP_SELECTOR(title, desc, icon, nullptr, advancedControl), button_texts(button_texts), is_inline_layout(inline_layout) { const QString style = R"( QPushButton { border-radius: 20px; @@ -371,8 +389,8 @@ class ButtonParamControlSP : public MultiButtonControlSP { Q_OBJECT public: ButtonParamControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, - const std::vector &button_texts, const int minimum_button_width = 225, const bool inline_layout = false) : MultiButtonControlSP(title, desc, icon, - button_texts, minimum_button_width, inline_layout) { + const std::vector &button_texts, const int minimum_button_width = 225, const bool inline_layout = false, bool advancedControl = false) : MultiButtonControlSP(title, desc, icon, + button_texts, minimum_button_width, inline_layout, advancedControl) { key = param.toStdString(); int value = atoi(params.get(key).c_str()); @@ -499,7 +517,7 @@ private: public: OptionControlSP(const QString ¶m, const QString &title, const QString &desc, const QString &icon, const MinMaxValue &range, const int per_value_change = 1, const bool inline_layout = false, - const QMap *valMap = nullptr, bool scale_float = false) : AbstractControlSP_SELECTOR(title, desc, icon, nullptr), _title(title), valueMap(valMap), is_inline_layout(inline_layout), use_float_scaling(scale_float) { + const QMap *valMap = nullptr, bool scale_float = false, bool advancedControl = false) : AbstractControlSP_SELECTOR(title, desc, icon, nullptr, advancedControl), _title(title), valueMap(valMap), is_inline_layout(inline_layout), use_float_scaling(scale_float) { const QString style = R"( QPushButton { border-radius: 20px; diff --git a/system/manager/manager.py b/system/manager/manager.py index 83c5fe2f5..c59f0118a 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -73,6 +73,7 @@ def manager_init() -> None: ("NeuralNetworkLateralControl", "0"), ("QuickBootToggle", "0"), ("QuietMode", "0"), + ("ShowAdvancedControls", "0" if build_metadata.tested_channel else "1"), ] # device boot mode