From 5499fb26befbc7ee20ae79309231ac8e41f5dc99 Mon Sep 17 00:00:00 2001 From: infiniteCable2 Date: Thu, 27 Nov 2025 18:38:26 +0100 Subject: [PATCH] Delete settings.cc --- selfdrive/ui/qt/offroad/settings.cc | 713 ---------------------------- 1 file changed, 713 deletions(-) delete mode 100644 selfdrive/ui/qt/offroad/settings.cc diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc deleted file mode 100644 index 930d1d815..000000000 --- a/selfdrive/ui/qt/offroad/settings.cc +++ /dev/null @@ -1,713 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -#include "common/watchdog.h" -#include "common/util.h" -#include "selfdrive/ui/qt/network/networking.h" -#include "selfdrive/ui/qt/offroad/settings.h" -#include "selfdrive/ui/qt/qt_window.h" -#include "selfdrive/ui/qt/widgets/prime.h" -#include "selfdrive/ui/qt/widgets/scrollview.h" -#include "selfdrive/ui/qt/offroad/developer_panel.h" -#include "selfdrive/ui/qt/offroad/firehose.h" -#include "selfdrive/ui/sunnypilot/qt/widgets/controls.h" - -InfiniteCableTogglesPanel::InfiniteCableTogglesPanel(SettingsWindow *parent) : ListWidget(parent) { - std::vector> toggle_defs{ - { - "EnableCurvatureController", - tr("VW: Lateral Correction (Recommended)"), - tr("Enables curvature PID post-processing additionally to QFK curvature offset
"), - "../assets/icons/chffr_wheel.png", - false, - }, - { - "EnableLongComfortMode", - tr("VW: Longitudinal Comfort Mode"), - tr("Enables longitudinal jerk and accel deviation limit control for safe and comfortable driving
"), - "../assets/icons/chffr_wheel.png", - false, - }, - { - "EnableSpeedLimitControl", - tr("VW: Speed Limit Control"), - tr("Enables setting maximum speed by speed limit detection
"), - "../assets/icons/speed_limit.png", - false, - }, - { - "EnableSpeedLimitPredicative", - tr("VW: Predicative Speed Limit (pACC)"), - tr("Enables setting predicative speed limit
"), - "../assets/icons/speed_limit.png", - false, - }, - { - "EnableSLPredReactToSL", - tr("VW: Predicative - Reaction to Speed Limits"), - tr("Enables reaction to speed limits as predicative speed limit
"), - "../assets/icons/speed_limit.png", - false, - }, - { - "EnableSLPredReactToCurves", - tr("VW: Predicative - Reaction to Curves"), - tr("Enables reaction to curves as predicative speed limit (Max Speed as per lateral ISO limits)
"), - "../assets/icons/speed_limit.png", - false, - }, - { - "BatteryDetails", - tr("VW MEB: Display Battery Details"), - tr("Display battery detail panel"), - "../assets/icons/capslock-fill.png", - false, - }, - { - "ForceRHDForBSM", - tr("VW: Force RHD for BSM"), - tr("Switch BSM detection side to RHD. Driver is on the right side."), - "../assets/icons/eye_closed.png", - false, - }, - { - "EnableSmoothSteer", - tr("Steer Smoothing"), - tr("Enables S-curving on lateral control for smoother steering
"), - "../assets/icons/chffr_wheel.png", - false, - }, - { - "DarkMode", - tr("Dark Mode"), - tr("Force brightness to a minimal value"), - "../assets/icons/eye_closed.png", - false, - }, - { - "DisableScreenTimer", - tr("Onroad Screen Timeout"), - tr("The onroad screen is turned of after 10 seconds. It will be temporarily enabled on alerts"), - "../assets/icons/eye_closed.png", - false, - }, - { - "EnableAngleOffset", - tr("Enable Steer Angle Offset (Testing)"), - tr("Enables the use of manual steer angle offset selection as start value for params detection."), - "../assets/icons/eye_closed.png", - false, - }, - }; - - for (auto &[param, title, desc, icon, needs_restart] : toggle_defs) { - auto toggle = new ParamControl(param, title, desc, icon, this); - - bool locked = params.getBool((param + "Lock").toStdString()); - toggle->setEnabled(!locked); - - if (needs_restart && !locked) { - toggle->setDescription(toggle->getDescription() + tr(" Changing this setting will restart openpilot if the car is powered on.")); - - QObject::connect(uiState(), &UIState::engagedChanged, [toggle](bool engaged) { - toggle->setEnabled(!engaged); - }); - - QObject::connect(toggle, &ParamControl::toggleFlipped, [=](bool state) { - params.putBool("OnroadCycleRequested", true); - }); - } - - addItem(toggle); - toggles[param.toStdString()] = toggle; - } - - steer_offset_control = new OptionControlSP( - "AngleOffsetDegree", - tr("Steering Angle Offset"), - tr("Adjust steering angle offset params learner start value manually (in degrees). Taking effect only for onroad transition. Is refreshed with the actual learned value and saved."), - "", {-1800, 1800}, 10, false, nullptr, true, true); - - float stored_val = QString::fromStdString(params.get("AngleOffsetDegree")).toFloat(); - steer_offset_control->setLabel(QString::number(stored_val, 'f', 1) + "°"); - steer_offset_control->showDescription(); - addItem(steer_offset_control); - - bool enable_angle_offset = params.getBool("EnableAngleOffset"); - steer_offset_control->setVisible(enable_angle_offset); - - connect(uiStateSP(), &UIStateSP::uiUpdate, this, [=]() { - bool enable_steer_offset_control = params.getBool("EnableAngleOffset"); - steer_offset_control->setVisible(enable_steer_offset_control); - }); - - QObject::connect(steer_offset_control, &OptionControlSP::updateLabels, [=]() { - float val = QString::fromStdString(params.get("AngleOffsetDegree")).toFloat(); - steer_offset_control->setLabel(QString::number(val, 'f', 1) + "°"); - }); -} - -void InfiniteCableTogglesPanel::showEvent(QShowEvent *event) { - ListWidget::showEvent(event); - if (steer_offset_control) { - float val = QString::fromStdString(params.get("AngleOffsetDegree")).toFloat(); - steer_offset_control->setLabel(QString::number(val, 'f', 1) + "°"); - } -} - -void InfiniteCableTogglesPanel::expandToggleDescription(const QString ¶m) { - toggles[param.toStdString()]->showDescription(); -} - -void InfiniteCableTogglesPanel::scrollToToggle(const QString ¶m) { - if (auto it = toggles.find(param.toStdString()); it != toggles.end()) { - auto scroll_area = qobject_cast(parent()->parent()); - if (scroll_area) { - scroll_area->ensureWidgetVisible(it->second); - } - } -} - -TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { - // param, title, desc, icon, restart needed - std::vector> toggle_defs{ - { - "OpenpilotEnabledToggle", - tr("Enable sunnypilot"), - tr("Use the sunnypilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature."), - "../assets/icons/chffr_wheel.png", - true, - }, - { - "ExperimentalMode", - tr("Experimental Mode"), - "", - "../assets/icons/experimental_white.svg", - false, - }, - { - "DisengageOnAccelerator", - tr("Disengage on Accelerator Pedal"), - tr("When enabled, pressing the accelerator pedal will disengage sunnypilot."), - "../assets/icons/disengage_on_accelerator.svg", - false, - }, - { - "IsLdwEnabled", - tr("Enable Lane Departure Warnings"), - tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."), - "../assets/icons/warning.png", - false, - }, - { - "AlwaysOnDM", - tr("Always-On Driver Monitoring"), - tr("Enable driver monitoring even when sunnypilot is not engaged."), - "../assets/icons/monitoring.png", - false, - }, - { - "RecordFront", - tr("Record and Upload Driver Camera"), - tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."), - "../assets/icons/monitoring.png", - true, - }, - { - "RecordAudio", - tr("Record and Upload Microphone Audio"), - tr("Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect."), - "../assets/icons/microphone.png", - true, - }, - { - "IsMetric", - tr("Use Metric System"), - tr("Display speed in km/h instead of mph."), - "../assets/icons/metric.png", - false, - }, - }; - - - std::vector longi_button_texts{tr("Aggressive"), tr("Standard"), tr("Relaxed")}; - long_personality_setting = new ButtonParamControl("LongitudinalPersonality", tr("Driving Personality"), - tr("Standard is recommended. In aggressive mode, sunnypilot will follow lead cars closer and be more aggressive with the gas and brake. " - "In relaxed mode sunnypilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with " - "your steering wheel distance button."), - "../assets/icons/speed_limit.png", - longi_button_texts); - - // set up uiState update for personality setting - QObject::connect(uiState(), &UIState::uiUpdate, this, &TogglesPanel::updateState); - - for (auto &[param, title, desc, icon, needs_restart] : toggle_defs) { - auto toggle = new ParamControl(param, title, desc, icon, this); - - bool locked = params.getBool((param + "Lock").toStdString()); - toggle->setEnabled(!locked); - - if (needs_restart && !locked) { - toggle->setDescription(toggle->getDescription() + tr(" Changing this setting will restart openpilot if the car is powered on.")); - - QObject::connect(uiState(), &UIState::engagedChanged, [toggle](bool engaged) { - toggle->setEnabled(!engaged); - }); - - QObject::connect(toggle, &ParamControl::toggleFlipped, [=](bool state) { - params.putBool("OnroadCycleRequested", true); - }); - } - - addItem(toggle); - toggles[param.toStdString()] = toggle; - - // insert longitudinal personality after NDOG toggle - if (param == "DisengageOnAccelerator") { - addItem(long_personality_setting); - } - } - - // Toggles with confirmation dialogs -#ifndef SUNNYPILOT - toggles["ExperimentalMode"]->setActiveIcon("../assets/icons/experimental.svg"); -#endif - toggles["ExperimentalMode"]->setConfirmation(true, true); -} - -void TogglesPanel::updateState(const UIState &s) { - const SubMaster &sm = *(s.sm); - - if (sm.updated("selfdriveState")) { - auto personality = sm["selfdriveState"].getSelfdriveState().getPersonality(); - if (personality != s.scene.personality && s.scene.started && isVisible()) { - long_personality_setting->setCheckedButton(static_cast(personality)); - } - uiState()->scene.personality = personality; - } -} - -void TogglesPanel::expandToggleDescription(const QString ¶m) { - toggles[param.toStdString()]->showDescription(); -} - -void TogglesPanel::scrollToToggle(const QString ¶m) { - if (auto it = toggles.find(param.toStdString()); it != toggles.end()) { - auto scroll_area = qobject_cast(parent()->parent()); - if (scroll_area) { - scroll_area->ensureWidgetVisible(it->second); - } - } -} - -void TogglesPanel::showEvent(QShowEvent *event) { - updateToggles(); -} - -void TogglesPanel::updateToggles() { - auto experimental_mode_toggle = toggles["ExperimentalMode"]; - const QString e2e_description = QString("%1
" - "

%2


" - "%3
" - "

%4


" - "%5
") - .arg(tr("sunnypilot defaults to driving in chill mode. Experimental mode enables alpha-level features that aren't ready for chill mode. Experimental features are listed below:")) - .arg(tr("End-to-End Longitudinal Control")) - .arg(tr("Let the driving model control the gas and brakes. sunnypilot will drive as it thinks a human would, including stopping for red lights and stop signs. " - "Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; " - "mistakes should be expected.")) - .arg(tr("New Driving Visualization")) - .arg(tr("The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.")); - - const bool is_release = params.getBool("IsReleaseBranch"); - auto cp_bytes = params.get("CarParamsPersistent"); - if (!cp_bytes.empty()) { - AlignedBuffer aligned_buf; - capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); - cereal::CarParams::Reader CP = cmsg.getRoot(); - - if (hasLongitudinalControl(CP)) { - // normal description and toggle - experimental_mode_toggle->setEnabled(true); - experimental_mode_toggle->setDescription(e2e_description); - long_personality_setting->setEnabled(true); - } else { - // no long for now - experimental_mode_toggle->setEnabled(false); - long_personality_setting->setEnabled(false); - params.remove("ExperimentalMode"); - - const QString unavailable = tr("Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control."); - - QString long_desc = unavailable + " " + \ - tr("sunnypilot longitudinal control may come in a future update."); - if (CP.getAlphaLongitudinalAvailable()) { - if (is_release) { - long_desc = unavailable + " " + tr("An alpha version of sunnypilot longitudinal control can be tested, along with Experimental mode, on non-release branches."); - } else { - long_desc = tr("Enable the sunnypilot longitudinal control (alpha) toggle to allow Experimental mode."); - } - } - experimental_mode_toggle->setDescription("" + long_desc + "

" + e2e_description); - } - - experimental_mode_toggle->refresh(); - } else { - experimental_mode_toggle->setDescription(e2e_description); - } -} - -DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { - setSpacing(50); - addItem(new LabelControl(tr("Dongle ID"), getDongleId().value_or(tr("N/A")))); - addItem(new LabelControl(tr("Serial"), params.get("HardwareSerial").c_str())); - - pair_device = new ButtonControl(tr("Pair Device"), tr("PAIR"), - tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.")); - connect(pair_device, &ButtonControl::clicked, [=]() { - PairingPopup popup(this); - popup.exec(); - }); - addItem(pair_device); - - QObject::connect(uiState()->prime_state, &PrimeState::changed, [this] (PrimeState::Type type) { - pair_device->setVisible(type == PrimeState::PRIME_TYPE_UNPAIRED); - }); - -#ifndef SUNNYPILOT - // offroad-only buttons - - auto dcamBtn = new ButtonControl(tr("Driver Camera"), tr("PREVIEW"), - tr("Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)")); - connect(dcamBtn, &ButtonControl::clicked, [=]() { emit showDriverView(); }); - addItem(dcamBtn); -#endif - - resetCalibBtn = new ButtonControl(tr("Reset Calibration"), tr("RESET"), ""); - connect(resetCalibBtn, &ButtonControl::showDescriptionEvent, this, &DevicePanel::updateCalibDescription); - connect(resetCalibBtn, &ButtonControl::clicked, [&]() { - if (!uiState()->engaged()) { - if (ConfirmationDialog::confirm(tr("Are you sure you want to reset calibration?"), tr("Reset"), this)) { - // Check engaged again in case it changed while the dialog was open - if (!uiState()->engaged()) { - params.remove("CalibrationParams"); - params.remove("LiveTorqueParameters"); - params.remove("LiveParameters"); - params.remove("LiveParametersV2"); - params.remove("LiveDelay"); - params.putBool("OnroadCycleRequested", true); - updateCalibDescription(); - } - } - } else { - ConfirmationDialog::alert(tr("Disengage to Reset Calibration"), this); - } - }); - addItem(resetCalibBtn); - -#ifndef SUNNYPILOT - auto retrainingBtn = new ButtonControl(tr("Review Training Guide"), tr("REVIEW"), tr("Review the rules, features, and limitations of sunnypilot")); - connect(retrainingBtn, &ButtonControl::clicked, [=]() { - if (ConfirmationDialog::confirm(tr("Are you sure you want to review the training guide?"), tr("Review"), this)) { - emit reviewTrainingGuide(); - } - }); - addItem(retrainingBtn); - - if (Hardware::TICI()) { - auto regulatoryBtn = new ButtonControl(tr("Regulatory"), tr("VIEW"), ""); - connect(regulatoryBtn, &ButtonControl::clicked, [=]() { - const std::string txt = util::read_file("../assets/offroad/fcc.html"); - ConfirmationDialog::rich(QString::fromStdString(txt), this); - }); - addItem(regulatoryBtn); - } - - auto translateBtn = new ButtonControl(tr("Change Language"), tr("CHANGE"), ""); - connect(translateBtn, &ButtonControl::clicked, [=]() { - QMap langs = getSupportedLanguages(); - QString selection = MultiOptionDialog::getSelection(tr("Select a language"), langs.keys(), langs.key(uiState()->language), this); - if (!selection.isEmpty()) { - // put language setting, exit Qt UI, and trigger fast restart - params.put("LanguageSetting", langs[selection].toStdString()); - qApp->exit(18); - watchdog_kick(0); - } - }); - addItem(translateBtn); -#endif - - QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { - for (auto btn : findChildren()) { - if (btn != pair_device && btn != resetCalibBtn) { - btn->setEnabled(offroad); - } - } - }); - -#ifndef SUNNYPILOT - // power buttons - QHBoxLayout *power_layout = new QHBoxLayout(); - power_layout->setSpacing(30); - - QPushButton *reboot_btn = new QPushButton(tr("Reboot")); - reboot_btn->setObjectName("reboot_btn"); - power_layout->addWidget(reboot_btn); - QObject::connect(reboot_btn, &QPushButton::clicked, this, &DevicePanel::reboot); - - QPushButton *poweroff_btn = new QPushButton(tr("Power Off")); - poweroff_btn->setObjectName("poweroff_btn"); - power_layout->addWidget(poweroff_btn); - QObject::connect(poweroff_btn, &QPushButton::clicked, this, &DevicePanel::poweroff); - - if (!Hardware::PC()) { - connect(uiState(), &UIState::offroadTransition, poweroff_btn, &QPushButton::setVisible); - } - - setStyleSheet(R"( - #reboot_btn { height: 120px; border-radius: 15px; background-color: #393939; } - #reboot_btn:pressed { background-color: #4a4a4a; } - #poweroff_btn { height: 120px; border-radius: 15px; background-color: #E22C2C; } - #poweroff_btn:pressed { background-color: #FF2424; } - )"); - addItem(power_layout); -#endif -} - -void DevicePanel::updateCalibDescription() { - QString desc = tr("sunnypilot requires the device to be mounted within 4° left or right and within 5° up or 9° down."); - std::string calib_bytes = params.get("CalibrationParams"); - if (!calib_bytes.empty()) { - try { - AlignedBuffer aligned_buf; - capnp::FlatArrayMessageReader cmsg(aligned_buf.align(calib_bytes.data(), calib_bytes.size())); - auto calib = cmsg.getRoot().getLiveCalibration(); - if (calib.getCalStatus() != cereal::LiveCalibrationData::Status::UNCALIBRATED) { - double pitch = calib.getRpyCalib()[1] * (180 / M_PI); - double yaw = calib.getRpyCalib()[2] * (180 / M_PI); - desc += tr(" Your device is pointed %1° %2 and %3° %4.") - .arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? tr("down") : tr("up"), - QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? tr("left") : tr("right")); - } - } catch (kj::Exception) { - qInfo() << "invalid CalibrationParams"; - } - } - - int lag_perc = 0; - std::string lag_bytes = params.get("LiveDelay"); - if (!lag_bytes.empty()) { - try { - AlignedBuffer aligned_buf; - capnp::FlatArrayMessageReader cmsg(aligned_buf.align(lag_bytes.data(), lag_bytes.size())); - lag_perc = cmsg.getRoot().getLiveDelay().getCalPerc(); - } catch (kj::Exception) { - qInfo() << "invalid LiveDelay"; - } - } - if (lag_perc < 100) { - desc += tr("\n\nSteering lag calibration is %1% complete.").arg(lag_perc); - } else { - desc += tr("\n\nSteering lag calibration is complete."); - } - - std::string torque_bytes = params.get("LiveTorqueParameters"); - if (!torque_bytes.empty()) { - try { - AlignedBuffer aligned_buf; - capnp::FlatArrayMessageReader cmsg(aligned_buf.align(torque_bytes.data(), torque_bytes.size())); - auto torque = cmsg.getRoot().getLiveTorqueParameters(); - // don't add for non-torque cars - if (torque.getUseParams()) { - int torque_perc = torque.getCalPerc(); - if (torque_perc < 100) { - desc += tr(" Steering torque response calibration is %1% complete.").arg(torque_perc); - } else { - desc += tr(" Steering torque response calibration is complete."); - } - } - } catch (kj::Exception) { - qInfo() << "invalid LiveTorqueParameters"; - } - } - - desc += "\n\n"; - desc += tr("openpilot is continuously calibrating, resetting is rarely required. " - "Resetting calibration will restart openpilot if the car is powered on."); - resetCalibBtn->setDescription(desc); -} - -void DevicePanel::reboot() { - if (!uiState()->engaged()) { - if (ConfirmationDialog::confirm(tr("Are you sure you want to reboot?"), tr("Reboot"), this)) { - // Check engaged again in case it changed while the dialog was open - if (!uiState()->engaged()) { - params.putBool("DoReboot", true); - } - } - } else { - ConfirmationDialog::alert(tr("Disengage to Reboot"), this); - } -} - -void DevicePanel::poweroff() { - if (!uiState()->engaged()) { - if (ConfirmationDialog::confirm(tr("Are you sure you want to power off?"), tr("Power Off"), this)) { - // Check engaged again in case it changed while the dialog was open - if (!uiState()->engaged()) { - params.putBool("DoShutdown", true); - } - } - } else { - ConfirmationDialog::alert(tr("Disengage to Power Off"), this); - } -} - -void SettingsWindow::showEvent(QShowEvent *event) { - setCurrentPanel(0); -} - -void SettingsWindow::setCurrentPanel(int index, const QString ¶m) { - if (!param.isEmpty()) { - // Check if param ends with "Panel" to determine if it's a panel name - if (param.endsWith("Panel")) { - QString panelName = param; - panelName.chop(5); // Remove "Panel" suffix - - // Find the panel by name - for (int i = 0; i < nav_btns->buttons().size(); i++) { - bool panel_trimmed = false; -#ifdef SUNNYPILOT - panel_trimmed = nav_btns->buttons()[i]->text().trimmed() == tr(panelName.toStdString().c_str()); -#endif - if ((nav_btns->buttons()[i]->text() == tr(panelName.toStdString().c_str())) || panel_trimmed) { - index = i; - break; - } - } - } else { - emit expandToggleDescription(param); - emit scrollToToggle(param); - } - } - - panel_widget->setCurrentIndex(index); - nav_btns->buttons()[index]->setChecked(true); -} - -SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) { -#ifndef SUNNYPILOT - // setup two main layouts - sidebar_widget = new QWidget; - QVBoxLayout *sidebar_layout = new QVBoxLayout(sidebar_widget); - panel_widget = new QStackedWidget(); - - // close button - QPushButton *close_btn = new QPushButton(tr("×")); - close_btn->setStyleSheet(R"( - QPushButton { - font-size: 140px; - padding-bottom: 20px; - border-radius: 100px; - background-color: #292929; - font-weight: 400; - } - QPushButton:pressed { - background-color: #3B3B3B; - } - )"); - close_btn->setFixedSize(200, 200); - sidebar_layout->addSpacing(45); - sidebar_layout->addWidget(close_btn, 0, Qt::AlignCenter); - QObject::connect(close_btn, &QPushButton::clicked, this, &SettingsWindow::closeSettings); - - // setup panels - DevicePanel *device = new DevicePanel(this); - QObject::connect(device, &DevicePanel::reviewTrainingGuide, this, &SettingsWindow::reviewTrainingGuide); - QObject::connect(device, &DevicePanel::showDriverView, this, &SettingsWindow::showDriverView); - - InfiniteCableTogglesPanel *ictoggles = new InfiniteCableTogglesPanel(this); - QObject::connect(this, &SettingsWindow::expandToggleDescription, ictoggles, &InfiniteCableTogglesPanel::expandToggleDescription); - QObject::connect(this, &SettingsWindow::scrollToToggle, ictoggles, &InfiniteCableTogglesPanel::scrollToToggle); - - TogglesPanel *toggles = new TogglesPanel(this); - QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription); - QObject::connect(this, &SettingsWindow::scrollToToggle, toggles, &TogglesPanel::scrollToToggle); - - auto networking = new Networking(this); - QObject::connect(uiState()->prime_state, &PrimeState::changed, networking, &Networking::setPrimeType); - - QList> panels = { - {tr("Device"), device}, - {tr("Network"), networking}, - {tr("infiniteCableCustom"), ictoggles}, - {tr("Toggles"), toggles}, - {tr("Software"), new SoftwarePanel(this)}, - {tr("Firehose"), new FirehosePanel(this)}, - {tr("Developer"), new DeveloperPanel(this)}, - }; - - nav_btns = new QButtonGroup(this); - for (auto &[name, panel] : panels) { - QPushButton *btn = new QPushButton(name); - btn->setCheckable(true); - btn->setChecked(nav_btns->buttons().size() == 0); - btn->setStyleSheet(R"( - QPushButton { - color: grey; - border: none; - background: none; - font-size: 65px; - font-weight: 500; - } - QPushButton:checked { - color: white; - } - QPushButton:pressed { - color: #ADADAD; - } - )"); - btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - nav_btns->addButton(btn); - sidebar_layout->addWidget(btn, 0, Qt::AlignRight); - - const int lr_margin = name != tr("Network") ? 50 : 0; // Network panel handles its own margins - panel->setContentsMargins(lr_margin, 25, lr_margin, 25); - - ScrollView *panel_frame = new ScrollView(panel, this); - panel_widget->addWidget(panel_frame); - - QObject::connect(btn, &QPushButton::clicked, [=, w = panel_frame]() { - btn->setChecked(true); - panel_widget->setCurrentWidget(w); - }); - } - sidebar_layout->setContentsMargins(50, 50, 100, 50); - - // main settings layout, sidebar + main panel - QHBoxLayout *main_layout = new QHBoxLayout(this); - - sidebar_widget->setFixedWidth(500); - main_layout->addWidget(sidebar_widget); - main_layout->addWidget(panel_widget); - - setStyleSheet(R"( - * { - color: white; - font-size: 50px; - } - SettingsWindow { - background-color: black; - } - QStackedWidget, ScrollView { - background-color: #292929; - border-radius: 30px; - } - )"); -#endif -}