From 5bcd0a2d3d7bd5576c09f3803cf0bc3d13ecef5d Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Mon, 22 Jul 2024 18:24:47 +0200 Subject: [PATCH] Refactor onboarding process and terms page in Sunnypilot The code modifications refactor the onboarding window and terms page in Sunnypilot. It includes moving OnboardingWindow to the protective area, and changing OnboardingWindowSP into a subclass of OnboardingWindow, which enhances code encapsulation and reusability. The expressions for the terms agreement pages are also refined for better readability. initial onboarding --- selfdrive/ui/qt/offroad/onboarding.cc | 20 +--- selfdrive/ui/qt/offroad/onboarding.h | 17 ++-- selfdrive/ui/qt/window.h | 2 +- selfdrive/ui/sunnypilot/SConscript | 1 + .../qt/offroad/settings/sp_priv_onboarding.cc | 97 +++++++++++++++++++ .../qt/offroad/settings/sp_priv_onboarding.h | 31 ++++++ selfdrive/ui/sunnypilot/qt/sp_priv_window.cc | 3 +- selfdrive/ui/sunnypilot/qt/sp_priv_window.h | 2 + 8 files changed, 146 insertions(+), 27 deletions(-) create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.cc create mode 100644 selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.h diff --git a/selfdrive/ui/qt/offroad/onboarding.cc b/selfdrive/ui/qt/offroad/onboarding.cc index 014e9a6f05..8bf92aa06b 100644 --- a/selfdrive/ui/qt/offroad/onboarding.cc +++ b/selfdrive/ui/qt/offroad/onboarding.cc @@ -106,8 +106,7 @@ void TermsPage::showEvent(QShowEvent *event) { text->setAttribute(Qt::WA_AlwaysStackOnTop); text->setClearColor(QColor("#1B1B1B")); - std::string tc_text = sunnypilot_tc ? "../assets/offroad/sp_tc.html" : "../assets/offroad/tc.html"; - QString text_view = util::read_file(tc_text).c_str(); + QString text_view = util::read_file("../assets/offroad/tc.html").c_str(); text->rootContext()->setContextProperty("text_view", text_view); text->setSource(QUrl::fromLocalFile("qt/offroad/text_view.qml")); @@ -186,8 +185,6 @@ void OnboardingWindow::updateActiveScreen() { setCurrentIndex(0); } else if (!training_done) { setCurrentIndex(1); - } else if (!accepted_terms_sp) { - setCurrentIndex(3); } else { emit onboardingDone(); } @@ -195,13 +192,11 @@ void OnboardingWindow::updateActiveScreen() { OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) { std::string current_terms_version = params.get("TermsVersion"); - std::string current_terms_version_sp = params.get("TermsVersionSunnypilot"); std::string current_training_version = params.get("TrainingVersion"); accepted_terms = params.get("HasAcceptedTerms") == current_terms_version; - accepted_terms_sp = params.get("HasAcceptedTermsSP") == current_terms_version_sp; training_done = params.get("CompletedTrainingVersion") == current_training_version; - TermsPage* terms = new TermsPage(false, this); + TermsPage* terms = new TermsPage(this); addWidget(terms); connect(terms, &TermsPage::acceptedTerms, [=]() { params.put("HasAcceptedTerms", current_terms_version); @@ -222,15 +217,6 @@ OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) { addWidget(declinePage); connect(declinePage, &DeclinePage::getBack, [=]() { updateActiveScreen(); }); - TermsPage* terms_sp = new TermsPage(true, this); - addWidget(terms_sp); // index = 3 - connect(terms_sp, &TermsPage::acceptedTerms, [=]() { - params.put("HasAcceptedTermsSP", current_terms_version_sp); - accepted_terms_sp = true; - updateActiveScreen(); - }); - connect(terms_sp, &TermsPage::declinedTerms, [=]() { setCurrentIndex(2); }); - setStyleSheet(R"( * { color: white; @@ -245,4 +231,4 @@ OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) { } )"); updateActiveScreen(); -} +} \ No newline at end of file diff --git a/selfdrive/ui/qt/offroad/onboarding.h b/selfdrive/ui/qt/offroad/onboarding.h index 008d86032c..098b0823a7 100644 --- a/selfdrive/ui/qt/offroad/onboarding.h +++ b/selfdrive/ui/qt/offroad/onboarding.h @@ -63,16 +63,17 @@ class TermsPage : public QFrame { Q_OBJECT public: - explicit TermsPage(bool sunnypilot = false, QWidget *parent = 0) : QFrame(parent), sunnypilot_tc(sunnypilot) {} + explicit TermsPage(QWidget *parent = 0) : QFrame(parent) {} public slots: void enableAccept(); +protected: + QPushButton *accept_btn; + private: void showEvent(QShowEvent *event) override; - QPushButton *accept_btn; - bool sunnypilot_tc = false; signals: void acceptedTerms(); @@ -98,14 +99,14 @@ class OnboardingWindow : public QStackedWidget { public: explicit OnboardingWindow(QWidget *parent = 0); inline void showTrainingGuide() { setCurrentIndex(1); } - inline bool completed() const { return accepted_terms && accepted_terms_sp && training_done; } + virtual inline bool completed() const { return accepted_terms && training_done; } -private: - void updateActiveScreen(); +protected: + virtual void updateActiveScreen(); Params params; - bool accepted_terms = false, accepted_terms_sp = false, training_done = false; + bool accepted_terms = false, training_done = false; signals: void onboardingDone(); -}; +}; \ No newline at end of file diff --git a/selfdrive/ui/qt/window.h b/selfdrive/ui/qt/window.h index 7bd3bb9f0a..ac8db59e57 100644 --- a/selfdrive/ui/qt/window.h +++ b/selfdrive/ui/qt/window.h @@ -17,6 +17,7 @@ protected: explicit MainWindow(QWidget* parent, HomeWindow* hw = nullptr, SettingsWindow* sw = nullptr, OnboardingWindow* ow = nullptr); HomeWindow *homeWindow; SettingsWindow *settingsWindow; + OnboardingWindow *onboardingWindow; virtual void closeSettings(); private: @@ -24,5 +25,4 @@ private: void openSettings(int index = 0, const QString ¶m = ""); QStackedLayout *main_layout; - OnboardingWindow *onboardingWindow; }; \ No newline at end of file diff --git a/selfdrive/ui/sunnypilot/SConscript b/selfdrive/ui/sunnypilot/SConscript index 6fe4a93d53..cce75a042a 100644 --- a/selfdrive/ui/sunnypilot/SConscript +++ b/selfdrive/ui/sunnypilot/SConscript @@ -45,6 +45,7 @@ qt_src = [ "sunnypilot/qt/sp_priv_home.cc", "sunnypilot/qt/sp_priv_offroad_home.cc", "sunnypilot/qt/sp_priv_sidebar.cc", + "sunnypilot/qt/offroad/settings/sp_priv_onboarding.cc", "sunnypilot/qt/offroad/settings/sp_priv_device_panel.cc", "sunnypilot/qt/offroad/settings/sp_priv_settings.cc", "sunnypilot/qt/onroad/sp_priv_buttons.cc", diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.cc b/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.cc new file mode 100644 index 0000000000..d30b9cb37b --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.cc @@ -0,0 +1,97 @@ +#include "selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.h" + +#include + +#include +#include +#include + +#include "common/util.h" +#include "common/params.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/input.h" + +void TermsPageSP::showEvent(QShowEvent *event) { + // late init, building QML widget takes 200ms + if (layout()) { + return; + } + + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(45, 35, 45, 45); + main_layout->setSpacing(0); + + QLabel *title = new QLabel(tr("Terms & Conditions")); + title->setStyleSheet("font-size: 90px; font-weight: 600;"); + main_layout->addWidget(title); + + main_layout->addSpacing(30); + + QQuickWidget *text = new QQuickWidget(this); + text->setResizeMode(QQuickWidget::SizeRootObjectToView); + text->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + text->setAttribute(Qt::WA_AlwaysStackOnTop); + text->setClearColor(QColor("#1B1B1B")); + + std::string tc_text = sunnypilot_tc ? "../assets/offroad/sp_tc.html" : "../assets/offroad/tc.html"; + QString text_view = util::read_file(tc_text).c_str(); + text->rootContext()->setContextProperty("text_view", text_view); + + text->setSource(QUrl::fromLocalFile("qt/offroad/text_view.qml")); + + main_layout->addWidget(text, 1); + main_layout->addSpacing(50); + + QObject *obj = (QObject*)text->rootObject(); + QObject::connect(obj, SIGNAL(scroll()), SLOT(enableAccept())); + + QHBoxLayout* buttons = new QHBoxLayout; + buttons->setMargin(0); + buttons->setSpacing(45); + main_layout->addLayout(buttons); + + QPushButton *decline_btn = new QPushButton(tr("Decline")); + buttons->addWidget(decline_btn); + QObject::connect(decline_btn, &QPushButton::clicked, this, &TermsPage::declinedTerms); + + accept_btn = new QPushButton(tr("Scroll to accept")); + accept_btn->setEnabled(false); + accept_btn->setStyleSheet(R"( + QPushButton { + background-color: #465BEA; + } + QPushButton:pressed { + background-color: #3049F4; + } + QPushButton:disabled { + background-color: #4F4F4F; + } + )"); + buttons->addWidget(accept_btn); + QObject::connect(accept_btn, &QPushButton::clicked, this, &TermsPage::acceptedTerms); +} + +void OnboardingWindowSP::updateActiveScreen() { + if(accepted_terms && training_done && !accepted_terms_sp) { + setCurrentIndex(3); + } else { + OnboardingWindow::updateActiveScreen(); + } +} + +OnboardingWindowSP::OnboardingWindowSP(QWidget *parent) : OnboardingWindow(parent) { + std::string current_terms_version_sp = params.get("TermsVersionSunnypilot"); + accepted_terms_sp = params.get("HasAcceptedTermsSP") == current_terms_version_sp; + LOGD("accepted_terms_sp: %s", params.get("HasAcceptedTermsSP").c_str()); + + auto* terms_sp = new TermsPageSP(true, parent); + addWidget(terms_sp); // index = 3 + connect(terms_sp, &TermsPageSP::acceptedTerms, [=]() { + params.put("HasAcceptedTermsSP", current_terms_version_sp); + accepted_terms_sp = true; + updateActiveScreen(); + }); + connect(terms_sp, &TermsPageSP::declinedTerms, [=]() { setCurrentIndex(2); }); + + OnboardingWindowSP::updateActiveScreen(); +} \ No newline at end of file diff --git a/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.h b/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.h new file mode 100644 index 0000000000..bd13f106ba --- /dev/null +++ b/selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_onboarding.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "common/params.h" +#include "selfdrive/ui/qt/qt_window.h" + +class TermsPageSP : public TermsPage { + Q_OBJECT + + +public: + explicit TermsPageSP(bool sunnypilot = false, QWidget *parent = 0) : TermsPage(parent), sunnypilot_tc(sunnypilot) {} + + +private: + bool sunnypilot_tc = false; + void showEvent(QShowEvent *event) override; +}; + +class OnboardingWindowSP : public OnboardingWindow { + Q_OBJECT + +public: + explicit OnboardingWindowSP(QWidget *parent = 0); + inline bool completed() const override { return accepted_terms && accepted_terms_sp && training_done; } + +private: + bool accepted_terms_sp = false; + void updateActiveScreen() override; +}; \ No newline at end of file diff --git a/selfdrive/ui/sunnypilot/qt/sp_priv_window.cc b/selfdrive/ui/sunnypilot/qt/sp_priv_window.cc index a6b7fac15a..69a35ed699 100644 --- a/selfdrive/ui/sunnypilot/qt/sp_priv_window.cc +++ b/selfdrive/ui/sunnypilot/qt/sp_priv_window.cc @@ -1,9 +1,10 @@ #include "sp_priv_window.h" MainWindowSP::MainWindowSP(QWidget *parent) : MainWindow(parent, new HomeWindowSP(parent), - new SettingsWindowSP(parent), new OnboardingWindow(parent)) { + new SettingsWindowSP(parent), new OnboardingWindowSP(parent)) { homeWindow = dynamic_cast(MainWindow::homeWindow); settingsWindow = dynamic_cast(MainWindow::settingsWindow); + onboardingWindow = dynamic_cast(MainWindow::onboardingWindow); } void MainWindowSP::closeSettings() { diff --git a/selfdrive/ui/sunnypilot/qt/sp_priv_window.h b/selfdrive/ui/sunnypilot/qt/sp_priv_window.h index cf67270cf3..73a867bde9 100644 --- a/selfdrive/ui/sunnypilot/qt/sp_priv_window.h +++ b/selfdrive/ui/sunnypilot/qt/sp_priv_window.h @@ -3,6 +3,7 @@ #include "selfdrive/ui/qt/window.h" #include "selfdrive/ui/sunnypilot/qt/sp_priv_home.h" #include "selfdrive/ui/sunnypilot/qt/offroad/settings/sp_priv_settings.h" +#include "offroad/settings/sp_priv_onboarding.h" class MainWindowSP : public MainWindow { Q_OBJECT @@ -13,5 +14,6 @@ explicit MainWindowSP(QWidget *parent = 0); private: HomeWindowSP *homeWindow; SettingsWindowSP *settingsWindow; + OnboardingWindowSP *onboardingWindow; void closeSettings() override; };