#include "selfdrive/ui/qt/home.h" #include #include #include #include #include "selfdrive/ui/qt/offroad/experimental_mode.h" #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/widgets/drive_stats.h" #include "selfdrive/ui/qt/widgets/prime.h" // HomeWindow: the container for the offroad and onroad UIs HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { QHBoxLayout *main_layout = new QHBoxLayout(this); main_layout->setMargin(0); main_layout->setSpacing(0); sidebar = new Sidebar(this); main_layout->addWidget(sidebar); QObject::connect(sidebar, &Sidebar::openSettings, this, &HomeWindow::openSettings); slayout = new QStackedLayout(); main_layout->addLayout(slayout); home = new OffroadHome(this); QObject::connect(home, &OffroadHome::openSettings, this, &HomeWindow::openSettings); slayout->addWidget(home); onroad = new OnroadWindow(this); slayout->addWidget(onroad); body = new BodyWindow(this); slayout->addWidget(body); driver_view = new DriverViewWindow(this); connect(driver_view, &DriverViewWindow::done, [=] { showDriverView(false); }); slayout->addWidget(driver_view); setAttribute(Qt::WA_NoSystemBackground); QObject::connect(uiState(), &UIState::uiUpdate, this, &HomeWindow::updateState); QObject::connect(uiState(), &UIState::offroadTransition, this, &HomeWindow::offroadTransition); QObject::connect(uiState(), &UIState::offroadTransition, sidebar, &Sidebar::offroadTransition); } void HomeWindow::showSidebar(bool show) { sidebar->setVisible(show); } void HomeWindow::updateState(const UIState &s) { const SubMaster &sm = *(s.sm); // switch to the generic robot UI if (onroad->isVisible() && !body->isEnabled() && sm["carParams"].getCarParams().getNotCar()) { body->setEnabled(true); slayout->setCurrentWidget(body); } } void HomeWindow::offroadTransition(bool offroad) { body->setEnabled(false); sidebar->setVisible(offroad); if (offroad) { slayout->setCurrentWidget(home); } else { slayout->setCurrentWidget(onroad); } } void HomeWindow::showDriverView(bool show) { if (show) { emit closeSettings(); slayout->setCurrentWidget(driver_view); } else { slayout->setCurrentWidget(home); } sidebar->setVisible(show == false); } void HomeWindow::mousePressEvent(QMouseEvent* e) { // Handle sidebar collapsing if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) { sidebar->setVisible(!sidebar->isVisible() && !onroad->isMapVisible()); } } void HomeWindow::mouseDoubleClickEvent(QMouseEvent* e) { HomeWindow::mousePressEvent(e); const SubMaster &sm = *(uiState()->sm); if (sm["carParams"].getCarParams().getNotCar()) { if (onroad->isVisible()) { slayout->setCurrentWidget(body); } else if (body->isVisible()) { slayout->setCurrentWidget(onroad); } showSidebar(false); } } // OffroadHome: the offroad home page OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { QVBoxLayout* main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(40, 40, 40, 40); // top header QHBoxLayout* header_layout = new QHBoxLayout(); header_layout->setContentsMargins(0, 0, 0, 0); header_layout->setSpacing(16); update_notif = new QPushButton(tr("UPDATE")); update_notif->setVisible(false); update_notif->setStyleSheet("background-color: #364DEF;"); QObject::connect(update_notif, &QPushButton::clicked, [=]() { center_layout->setCurrentIndex(1); }); header_layout->addWidget(update_notif, 0, Qt::AlignHCenter | Qt::AlignLeft); alert_notif = new QPushButton(); alert_notif->setVisible(false); alert_notif->setStyleSheet("background-color: #E22C2C;"); QObject::connect(alert_notif, &QPushButton::clicked, [=] { center_layout->setCurrentIndex(2); }); header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignLeft); version = new ElidedLabel(); header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight); main_layout->addLayout(header_layout); // main content main_layout->addSpacing(25); center_layout = new QStackedLayout(); QWidget *home_widget = new QWidget(this); { QHBoxLayout *home_layout = new QHBoxLayout(home_widget); home_layout->setContentsMargins(0, 0, 0, 0); home_layout->setSpacing(30); // left: DriveStats/PrimeAdWidget QStackedWidget *left_widget = new QStackedWidget(this); left_widget->addWidget(new DriveStats); left_widget->addWidget(new PrimeAdWidget); left_widget->setCurrentIndex(uiState()->primeType() ? 0 : 1); connect(uiState(), &UIState::primeTypeChanged, [=](int prime_type) { left_widget->setCurrentIndex(prime_type ? 0 : 1); }); home_layout->addWidget(left_widget, 1); // right: ExperimentalModeButton, SetupWidget QWidget* right_widget = new QWidget(this); QVBoxLayout* right_column = new QVBoxLayout(right_widget); right_column->setContentsMargins(0, 0, 0, 0); right_widget->setFixedWidth(750); right_column->setSpacing(30); ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this); QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings); right_column->addWidget(experimental_mode, 1); SetupWidget *setup_widget = new SetupWidget; QObject::connect(setup_widget, &SetupWidget::openSettings, this, &OffroadHome::openSettings); right_column->addWidget(setup_widget, 1); home_layout->addWidget(right_widget, 1); } center_layout->addWidget(home_widget); // add update & alerts widgets update_widget = new UpdateAlert(); QObject::connect(update_widget, &UpdateAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); }); center_layout->addWidget(update_widget); alerts_widget = new OffroadAlert(); QObject::connect(alerts_widget, &OffroadAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); }); center_layout->addWidget(alerts_widget); main_layout->addLayout(center_layout, 1); // set up refresh timer timer = new QTimer(this); timer->callOnTimeout(this, &OffroadHome::refresh); setStyleSheet(R"( * { color: white; } OffroadHome { background-color: black; } OffroadHome > QPushButton { padding: 15px 30px; border-radius: 5px; font-size: 40px; font-weight: 500; } OffroadHome > QLabel { font-size: 55px; } )"); } void OffroadHome::showEvent(QShowEvent *event) { refresh(); timer->start(10 * 1000); } void OffroadHome::hideEvent(QHideEvent *event) { timer->stop(); } void OffroadHome::refresh() { version->setText(getBrand() + " " + QString::fromStdString(params.get("UpdaterCurrentDescription"))); bool updateAvailable = update_widget->refresh(); int alerts = alerts_widget->refresh(); // pop-up new notification int idx = center_layout->currentIndex(); if (!updateAvailable && !alerts) { idx = 0; } else if (updateAvailable && (!update_notif->isVisible() || (!alerts && idx == 2))) { idx = 1; } else if (alerts && (!alert_notif->isVisible() || (!updateAvailable && idx == 1))) { idx = 2; } center_layout->setCurrentIndex(idx); update_notif->setVisible(updateAvailable); alert_notif->setVisible(alerts); if (alerts) { alert_notif->setText(QString::number(alerts) + (alerts > 1 ? tr(" ALERTS") : tr(" ALERT"))); } }