#include "selfdrive/ui/qt/home.h" #include #include #include #include #include "selfdrive/common/params.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(); 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); } void HomeWindow::showSidebar(bool show) { sidebar->setVisible(show); } void HomeWindow::updateState(const UIState &s) { const SubMaster &sm = *(s.sm); // switch to the body UI if (onroad->isVisible() && sm["carParams"].getCarParams().getCarName() == "body") { slayout->setCurrentWidget(body); } } void HomeWindow::offroadTransition(bool offroad) { 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()); } } // OffroadHome: the offroad home page OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { QVBoxLayout* main_layout = new QVBoxLayout(this); main_layout->setContentsMargins(40, 40, 40, 45); // top header QHBoxLayout* header_layout = new QHBoxLayout(); header_layout->setContentsMargins(15, 15, 15, 0); header_layout->setSpacing(16); date = new QLabel(); header_layout->addWidget(date, 1, Qt::AlignHCenter | Qt::AlignLeft); update_notif = new QPushButton("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::AlignRight); 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::AlignRight); header_layout->addWidget(new QLabel(getBrandVersion()), 0, Qt::AlignHCenter | Qt::AlignRight); main_layout->addLayout(header_layout); // main content main_layout->addSpacing(25); center_layout = new QStackedLayout(); QWidget* statsAndSetupWidget = new QWidget(this); QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget); statsAndSetup->setMargin(0); statsAndSetup->setSpacing(30); statsAndSetup->addWidget(new DriveStats, 1); statsAndSetup->addWidget(new SetupWidget); center_layout->addWidget(statsAndSetupWidget); // 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() { date->setText(QDateTime::currentDateTime().toString("dddd, MMMM d")); 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 ? " ALERTS" : " ALERT")); } }