diff --git a/selfdrive/assets/offroad/icon_wifi_uploading.svg b/selfdrive/assets/offroad/icon_wifi_uploading.svg new file mode 100644 index 0000000000..b9392dfe7c --- /dev/null +++ b/selfdrive/assets/offroad/icon_wifi_uploading.svg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bedd579f56c65fffe2ad571f92843b6d103826fe173f8f5b58fc2200d2ad8850 +size 1663 diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index f54d72ae31..f46e3d5873 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -20,7 +20,7 @@ if arch == "Darwin": qt_env['FRAMEWORKS'] += ['OpenCL'] qt_util = qt_env.Library("qt_util", ["#selfdrive/ui/qt/api.cc", "#selfdrive/ui/qt/util.cc"], LIBS=base_libs) -widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", +widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/wifi.cc", "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc", "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc", diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 2b8974f73a..587e2f445e 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include "selfdrive/ui/qt/offroad/experimental_mode.h" @@ -136,21 +137,34 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { home_layout->setContentsMargins(0, 0, 0, 0); home_layout->setSpacing(30); - // left: ExperimentalModeButton, DriveStats - QWidget* left_widget = new QWidget(this); - QVBoxLayout* left_column = new QVBoxLayout(left_widget); - left_column->setContentsMargins(0, 0, 0, 0); - left_column->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); - left_column->addWidget(experimental_mode, 1); - left_column->addWidget(new DriveStats, 1); + right_column->addWidget(experimental_mode, 1); - home_layout->addWidget(left_widget, 1); + SetupWidget *setup_widget = new SetupWidget; + QObject::connect(setup_widget, &SetupWidget::openSettings, this, &OffroadHome::openSettings); + right_column->addWidget(setup_widget, 1); - // right: SetupWidget - home_layout->addWidget(new SetupWidget); + home_layout->addWidget(right_widget, 1); } center_layout->addWidget(home_widget); @@ -170,7 +184,7 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { setStyleSheet(R"( * { - color: white; + color: white; } OffroadHome { background-color: black; diff --git a/selfdrive/ui/qt/widgets/prime.cc b/selfdrive/ui/qt/widgets/prime.cc index fb4aea2b1c..86bd918e0c 100644 --- a/selfdrive/ui/qt/widgets/prime.cc +++ b/selfdrive/ui/qt/widgets/prime.cc @@ -14,6 +14,7 @@ #include "selfdrive/ui/qt/request_repeater.h" #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/widgets/wifi.h" using qrcodegen::QrCode; @@ -123,26 +124,18 @@ PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QFrame(parent) { QWidget *primeWidget = new QWidget; primeWidget->setObjectName("primeWidget"); QVBoxLayout *primeLayout = new QVBoxLayout(primeWidget); - primeLayout->setContentsMargins(60, 50, 60, 50); + primeLayout->setContentsMargins(56, 40, 56, 40); + primeLayout->setSpacing(20); QLabel *subscribed = new QLabel(tr("✓ SUBSCRIBED")); subscribed->setStyleSheet("font-size: 41px; font-weight: bold; color: #86FF4E;"); - primeLayout->addWidget(subscribed, 0, Qt::AlignTop); - - primeLayout->addSpacing(60); + primeLayout->addWidget(subscribed); QLabel *commaPrime = new QLabel(tr("comma prime")); commaPrime->setStyleSheet("font-size: 75px; font-weight: bold;"); - primeLayout->addWidget(commaPrime, 0, Qt::AlignTop); - - primeLayout->addSpacing(20); - - QLabel *connectUrl = new QLabel(tr("CONNECT.COMMA.AI")); - connectUrl->setStyleSheet("font-size: 41px; font-family: Inter SemiBold; color: #A0A0A0;"); - primeLayout->addWidget(connectUrl, 0, Qt::AlignTop); + primeLayout->addWidget(commaPrime); mainLayout->addWidget(primeWidget); - mainLayout->addStretch(); } @@ -195,8 +188,8 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { QFrame* finishRegistration = new QFrame; finishRegistration->setObjectName("primeWidget"); QVBoxLayout* finishRegistationLayout = new QVBoxLayout(finishRegistration); - finishRegistationLayout->setSpacing(40); - finishRegistationLayout->setContentsMargins(64, 64, 64, 64); + finishRegistationLayout->setSpacing(38); + finishRegistationLayout->setContentsMargins(64, 48, 64, 48); QLabel* registrationTitle = new QLabel(tr("Finish Setup")); registrationTitle->setStyleSheet("font-size: 75px; font-weight: bold;"); @@ -204,7 +197,7 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { QLabel* registrationDescription = new QLabel(tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.")); registrationDescription->setWordWrap(true); - registrationDescription->setStyleSheet("font-size: 55px; font-weight: light;"); + registrationDescription->setStyleSheet("font-size: 50px; font-weight: light;"); finishRegistationLayout->addWidget(registrationDescription); finishRegistationLayout->addStretch(); @@ -234,15 +227,24 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { outer_layout->setContentsMargins(0, 0, 0, 0); outer_layout->addWidget(mainLayout); - primeAd = new PrimeAdWidget; - mainLayout->addWidget(primeAd); + QWidget *content = new QWidget; + QVBoxLayout *content_layout = new QVBoxLayout(content); + content_layout->setContentsMargins(0, 0, 0, 0); + content_layout->setSpacing(30); primeUser = new PrimeUserWidget; - mainLayout->addWidget(primeUser); + content_layout->addWidget(primeUser); - mainLayout->setCurrentWidget(uiState()->primeType() ? (QWidget*)primeUser : (QWidget*)primeAd); + WiFiPromptWidget *wifi_prompt = new WiFiPromptWidget; + QObject::connect(wifi_prompt, &WiFiPromptWidget::openSettings, this, &SetupWidget::openSettings); + content_layout->addWidget(wifi_prompt); + content_layout->addStretch(); + + mainLayout->addWidget(content); + + primeUser->setVisible(uiState()->primeType()); + mainLayout->setCurrentIndex(1); - setFixedWidth(750); setStyleSheet(R"( #primeWidget { border-radius: 10px; @@ -282,10 +284,7 @@ void SetupWidget::replyFinished(const QString &response, bool success) { } else { popup->reject(); - if (prime_type) { - mainLayout->setCurrentWidget(primeUser); - } else { - mainLayout->setCurrentWidget(primeAd); - } + primeUser->setVisible(prime_type); + mainLayout->setCurrentIndex(1); } } diff --git a/selfdrive/ui/qt/widgets/prime.h b/selfdrive/ui/qt/widgets/prime.h index 9c7b4460fc..b41bab1695 100644 --- a/selfdrive/ui/qt/widgets/prime.h +++ b/selfdrive/ui/qt/widgets/prime.h @@ -69,10 +69,12 @@ class SetupWidget : public QFrame { public: explicit SetupWidget(QWidget* parent = 0); +signals: + void openSettings(int index = 0, const QString ¶m = ""); + private: PairingPopup *popup; QStackedWidget *mainLayout; - PrimeAdWidget *primeAd; PrimeUserWidget *primeUser; private slots: diff --git a/selfdrive/ui/qt/widgets/wifi.cc b/selfdrive/ui/qt/widgets/wifi.cc new file mode 100644 index 0000000000..b717a00d98 --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.cc @@ -0,0 +1,103 @@ +#include "selfdrive/ui/qt/widgets/wifi.h" + +#include +#include +#include +#include + +WiFiPromptWidget::WiFiPromptWidget(QWidget *parent) : QFrame(parent) { + stack = new QStackedLayout(this); + + // Setup Wi-Fi + QFrame *setup = new QFrame; + QVBoxLayout *setup_layout = new QVBoxLayout(setup); + setup_layout->setContentsMargins(56, 40, 56, 40); + setup_layout->setSpacing(20); + { + QHBoxLayout *title_layout = new QHBoxLayout; + title_layout->setSpacing(32); + { + QLabel *icon = new QLabel; + QPixmap *pixmap = new QPixmap("../assets/offroad/icon_wifi_strength_full.svg"); + icon->setPixmap(pixmap->scaledToWidth(80, Qt::SmoothTransformation)); + title_layout->addWidget(icon); + + QLabel *title = new QLabel(tr("Setup Wi-Fi")); + title->setStyleSheet("font-size: 64px; font-weight: 600;"); + title_layout->addWidget(title); + title_layout->addStretch(); + } + setup_layout->addLayout(title_layout); + + QLabel *desc = new QLabel(tr("Connect to Wi-Fi to upload driving data and help improve openpilot")); + desc->setStyleSheet("font-size: 40px; font-weight: 400;"); + desc->setWordWrap(true); + setup_layout->addWidget(desc); + + QPushButton *settings_btn = new QPushButton(tr("Open Settings")); + connect(settings_btn, &QPushButton::clicked, [=]() { emit openSettings(1); }); + settings_btn->setStyleSheet(R"( + QPushButton { + font-size: 48px; + font-weight: 500; + border-radius: 10px; + background-color: #465BEA; + padding: 32px; + } + QPushButton:pressed { + background-color: #3049F4; + } + )"); + setup_layout->addWidget(settings_btn); + } + stack->addWidget(setup); + + // Uploading data + QWidget *uploading = new QWidget; + QVBoxLayout *uploading_layout = new QVBoxLayout(uploading); + uploading_layout->setContentsMargins(64, 56, 64, 56); + uploading_layout->setSpacing(36); + { + QHBoxLayout *title_layout = new QHBoxLayout; + { + QLabel *title = new QLabel(tr("Uploading training data")); + title->setStyleSheet("font-size: 64px; font-weight: 600;"); + title->setWordWrap(true); + title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + title_layout->addWidget(title); + title_layout->addStretch(); + + QLabel *icon = new QLabel; + QPixmap *pixmap = new QPixmap("../assets/offroad/icon_wifi_uploading.svg"); + icon->setPixmap(pixmap->scaledToWidth(120, Qt::SmoothTransformation)); + title_layout->addWidget(icon); + } + uploading_layout->addLayout(title_layout); + + QLabel *desc = new QLabel(tr("Your data is used to train driving models and help improve openpilot")); + desc->setStyleSheet("font-size: 48px; font-weight: 400;"); + desc->setWordWrap(true); + uploading_layout->addWidget(desc); + } + stack->addWidget(uploading); + + setStyleSheet(R"( + WiFiPromptWidget { + background-color: #333333; + border-radius: 10px; + } + )"); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &WiFiPromptWidget::updateState); +} + +void WiFiPromptWidget::updateState(const UIState &s) { + if (!isVisible()) return; + + auto &sm = *(s.sm); + + auto network_type = sm["deviceState"].getDeviceState().getNetworkType(); + auto uploading = network_type == cereal::DeviceState::NetworkType::WIFI || + network_type == cereal::DeviceState::NetworkType::ETHERNET; + stack->setCurrentIndex(uploading ? 1 : 0); +} diff --git a/selfdrive/ui/qt/widgets/wifi.h b/selfdrive/ui/qt/widgets/wifi.h new file mode 100644 index 0000000000..60c865f2b8 --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#include "selfdrive/ui/ui.h" + +class WiFiPromptWidget : public QFrame { + Q_OBJECT + +public: + explicit WiFiPromptWidget(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + +public slots: + void updateState(const UIState &s); + +protected: + QStackedLayout *stack; +}; diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 5bec3f674a..71f3df7597 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -517,10 +517,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1076,6 +1072,29 @@ This may take up to a minute. Aktualisierung fehlgeschlagen + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 43e4974784..019eb1b71b 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -518,10 +518,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1070,6 +1066,29 @@ This may take up to a minute. 更新失敗 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index c985fae0e9..cab5e2ada6 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -518,10 +518,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1071,6 +1067,29 @@ This may take up to a minute. 업데이트 실패 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 9eeedea29c..70f06670a9 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -519,10 +519,6 @@ trabalho definido comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1075,6 +1071,29 @@ Isso pode levar até um minuto. Falha na atualização + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 9302047ab0..f6924b3c57 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -516,10 +516,6 @@ location set comma prime comma prime - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1068,6 +1064,29 @@ This may take up to a minute. 更新失败 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 5d17a7b86a..243a91ebd1 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -518,10 +518,6 @@ location set comma prime comma 高級會員 - - CONNECT.COMMA.AI - CONNECT.COMMA.AI - QObject @@ -1070,6 +1066,29 @@ This may take up to a minute. 更新失敗 + + WiFiPromptWidget + + Setup Wi-Fi + + + + Connect to Wi-Fi to upload driving data and help improve openpilot + + + + Open Settings + + + + Uploading training data + + + + Your data is used to train driving models and help improve openpilot + + + WifiUI