diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index ff927de4f..ad7c2d06f 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -27,5 +27,5 @@ else: else: qt_libs += ["GL"] - qt_src = ["qt/ui.cc", "qt/window.cc", "qt/offroad/settings.cc", "qt/qt_sound.cc"] + src + qt_src = ["qt/ui.cc", "qt/window.cc", "qt/qt_sound.cc", "qt/offroad/settings.cc", "qt/offroad/onboarding.cc"] + src qt_env.Program("_ui", qt_src, LIBS=qt_libs + libs) diff --git a/selfdrive/ui/qt/offroad/onboarding.cc b/selfdrive/ui/qt/offroad/onboarding.cc new file mode 100644 index 000000000..b35de4519 --- /dev/null +++ b/selfdrive/ui/qt/offroad/onboarding.cc @@ -0,0 +1,103 @@ +#include + +#include "onboarding.hpp" + +#include +#include +#include +#include +#include + +#include "common/params.h" + + +QWidget * OnboardingWindow::terms_screen() { + QVBoxLayout *main_layout = new QVBoxLayout(); + main_layout->setMargin(30); + main_layout->setSpacing(30); + + QLabel *title = new QLabel("Review Terms"); + title->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + title->setStyleSheet(R"( + QLabel { + font-size: 80px; + text-align: left; + margin: 0; + padding: 0; + } + )"); + main_layout->addWidget(title); + + QLabel *terms = new QLabel("See terms at https://my.comma.ai/terms"); + terms->setAlignment(Qt::AlignCenter); + terms->setStyleSheet(R"( + QLabel { + font-size: 35px; + border-radius: 10px; + text-align: center; + background-color: #292929; + } + )"); + main_layout->addWidget(terms, Qt::AlignTop); + + QHBoxLayout *btn_layout = new QHBoxLayout(); + //btn_layout->setSpacing(30); + + QPushButton *decline_btn = new QPushButton("Decline"); + btn_layout->addWidget(decline_btn); + QPushButton *accept_btn = new QPushButton("Accept"); + btn_layout->addWidget(accept_btn); + main_layout->addLayout(btn_layout); + + QObject::connect(accept_btn, &QPushButton::released, [=]() { + Params().write_db_value("HasAcceptedTerms", LATEST_TERMS_VERSION); + updateActiveScreen(); + }); + + QWidget *widget = new QWidget; + widget->setLayout(main_layout); + widget->setStyleSheet(R"( + QLabel { + color: white; + } + QPushButton { + font-size: 50px; + padding: 50px; + border-radius: 10px; + background-color: #292929; + } + )"); + + return widget; +} + +void OnboardingWindow::updateActiveScreen() { + + Params params = Params(); + + bool accepted_terms = params.get("HasAcceptedTerms", false).compare(LATEST_TERMS_VERSION) == 0; + + if (accepted_terms) { + emit onboardingDone(); + } +} + +OnboardingWindow::OnboardingWindow(QWidget *parent) : QWidget(parent) { + + // Onboarding flow: terms -> account pairing -> training + + + QStackedLayout *main_layout = new QStackedLayout; + main_layout->addWidget(terms_screen()); + setLayout(main_layout); + setStyleSheet(R"( + * { + background-color: black; + } + )"); + + // TODO: implement the training guide + Params().write_db_value("CompletedTrainingVersion", LATEST_TRAINING_VERSION); + + updateActiveScreen(); +} diff --git a/selfdrive/ui/qt/offroad/onboarding.hpp b/selfdrive/ui/qt/offroad/onboarding.hpp new file mode 100644 index 000000000..7fdf4e140 --- /dev/null +++ b/selfdrive/ui/qt/offroad/onboarding.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + + +// TODO: this is defined in python too +#define LATEST_TERMS_VERSION "2" +#define LATEST_TRAINING_VERSION "0.2.0" + +class OnboardingWindow : public QWidget { + Q_OBJECT + +public: + explicit OnboardingWindow(QWidget *parent = 0); + +signals: + void onboardingDone(); + +private: + QWidget * terms_screen(); + +private slots: + void updateActiveScreen(); +}; diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index fc1362c14..3c659091e 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -137,8 +137,9 @@ QWidget * device_panel() { QPushButton *clear_cal_btn = new QPushButton("Reset Calibration"); device_layout->addWidget(clear_cal_btn); - QObject::connect(clear_cal_btn, &QPushButton::released, - [=]() { Params().delete_db_value("CalibrationParams"); }); + QObject::connect(clear_cal_btn, &QPushButton::released, [=]() { + Params().delete_db_value("CalibrationParams"); + }); std::map power_btns = { {"Power Off", "sudo poweroff"}, @@ -154,7 +155,6 @@ QWidget * device_panel() { #endif } - QWidget *widget = new QWidget; widget->setLayout(device_layout); widget->setStyleSheet(R"( diff --git a/selfdrive/ui/qt/window.cc b/selfdrive/ui/qt/window.cc index 2be3552b5..a9ce85db9 100644 --- a/selfdrive/ui/qt/window.cc +++ b/selfdrive/ui/qt/window.cc @@ -8,11 +8,10 @@ #include #include -#include -#include #include "window.hpp" #include "offroad/settings.hpp" +#include "offroad/onboarding.hpp" #include "paint.hpp" #include "common/util.h" @@ -38,18 +37,24 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { set_core_affinity(7); #endif - GLWindow * glWindow = new GLWindow(this); + GLWindow *glWindow = new GLWindow(this); main_layout->addWidget(glWindow); - SettingsWindow * settingsWindow = new SettingsWindow(this); + SettingsWindow *settingsWindow = new SettingsWindow(this); main_layout->addWidget(settingsWindow); + OnboardingWindow *onboardingWindow = new OnboardingWindow(this); + main_layout->addWidget(onboardingWindow); main_layout->setMargin(0); setLayout(main_layout); QObject::connect(glWindow, SIGNAL(openSettings()), this, SLOT(openSettings())); QObject::connect(settingsWindow, SIGNAL(closeSettings()), this, SLOT(closeSettings())); + // start at onboarding + //main_layout->setCurrentWidget(onboardingWindow); + QObject::connect(onboardingWindow, SIGNAL(onboardingDone()), this, SLOT(closeSettings())); + setStyleSheet(R"( * { color: white;