diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 548be88a7..15a9d76a5 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -21,7 +21,7 @@ if arch == "Darwin": widgets_src = ["qt/util.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", - "qt/widgets/offroad_alerts.cc", "qt/widgets/setup.cc", "qt/widgets/keyboard.cc", + "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc", "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#phonelibs/qrcode/QrCode.cc", "qt/api.cc", "qt/request_repeater.cc"] diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index 55665af78..428b5e202 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -8,7 +8,7 @@ #include "selfdrive/common/params.h" #include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/widgets/drive_stats.h" -#include "selfdrive/ui/qt/widgets/setup.h" +#include "selfdrive/ui/qt/widgets/prime.h" // HomeWindow: the container for the offroad and onroad UIs @@ -122,8 +122,8 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget); statsAndSetup->setMargin(0); statsAndSetup->setSpacing(30); - statsAndSetup->addWidget(new DriveStats, 11); - statsAndSetup->addWidget(new SetupWidget, 8); + statsAndSetup->addWidget(new DriveStats, 1); + statsAndSetup->addWidget(new SetupWidget); center_layout->addWidget(statsAndSetupWidget); diff --git a/selfdrive/ui/qt/widgets/setup.cc b/selfdrive/ui/qt/widgets/prime.cc similarity index 52% rename from selfdrive/ui/qt/widgets/setup.cc rename to selfdrive/ui/qt/widgets/prime.cc index 1bbe3f5e1..bf9a1e3c5 100644 --- a/selfdrive/ui/qt/widgets/setup.cc +++ b/selfdrive/ui/qt/widgets/prime.cc @@ -1,4 +1,4 @@ -#include "selfdrive/ui/qt/widgets/setup.h" +#include "selfdrive/ui/qt/widgets/prime.h" #include #include @@ -61,32 +61,52 @@ void PairingQRWidget::updateQrCode(const QString &text) { PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) { mainLayout = new QVBoxLayout(this); - mainLayout->setMargin(30); + mainLayout->setMargin(0); + mainLayout->setSpacing(30); - QLabel* commaPrime = new QLabel("COMMA PRIME"); - mainLayout->addWidget(commaPrime, 0, Qt::AlignTop); + // subscribed prime layout + QWidget *primeWidget = new QWidget; + primeWidget->setObjectName("primeWidget"); + QVBoxLayout *primeLayout = new QVBoxLayout(primeWidget); + primeLayout->setMargin(0); + primeWidget->setContentsMargins(60, 50, 60, 50); - username = new QLabel(); - username->setStyleSheet("font-size: 55px;"); // TODO: fit width - mainLayout->addWidget(username, 0, Qt::AlignTop); + QLabel* subscribed = new QLabel("✓ SUBSCRIBED"); + subscribed->setStyleSheet("font-size: 41px; font-weight: bold; color: #86FF4E;"); + primeLayout->addWidget(subscribed, 0, Qt::AlignTop); - mainLayout->addSpacing(100); + primeLayout->addSpacing(60); + + QLabel* commaPrime = new QLabel("comma prime"); + commaPrime->setStyleSheet("font-size: 75px; font-weight: bold;"); + primeLayout->addWidget(commaPrime, 0, Qt::AlignTop); + + primeLayout->addSpacing(20); + + QLabel* connectUrl = new QLabel("CONNECT.COMMA.AI"); + connectUrl->setStyleSheet("font-size: 41px; font-family: Inter SemiBold; color: #A0A0A0;"); + primeLayout->addWidget(connectUrl, 0, Qt::AlignTop); + + mainLayout->addWidget(primeWidget); + + // comma points layout + QWidget *pointsWidget = new QWidget; + pointsWidget->setObjectName("primeWidget"); + QVBoxLayout *pointsLayout = new QVBoxLayout(pointsWidget); + pointsLayout->setMargin(0); + pointsWidget->setContentsMargins(60, 50, 60, 50); QLabel* commaPoints = new QLabel("COMMA POINTS"); - commaPoints->setStyleSheet(R"( - color: #b8b8b8; - )"); - mainLayout->addWidget(commaPoints, 0, Qt::AlignTop); + commaPoints->setStyleSheet("font-size: 41px; font-family: Inter SemiBold;"); + pointsLayout->addWidget(commaPoints, 0, Qt::AlignTop); - points = new QLabel(); - mainLayout->addWidget(points, 0, Qt::AlignTop); + points = new QLabel("210"); + points->setStyleSheet("font-size: 91px; font-weight: bold;"); + pointsLayout->addWidget(points, 0, Qt::AlignTop); - setStyleSheet(R"( - QLabel { - font-size: 70px; - font-weight: 500; - } - )"); + mainLayout->addWidget(pointsWidget); + + mainLayout->addStretch(); // set up API requests std::string dongleId = Params().get("DongleId"); @@ -100,42 +120,51 @@ PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) { void PrimeUserWidget::replyFinished(const QString &response) { QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); if (doc.isNull()) { - qDebug() << "JSON Parse failed on getting username and points"; + qDebug() << "JSON Parse failed on getting points"; return; } QJsonObject json = doc.object(); - QString points_str = QString::number(json["points"].toInt()); - QString username_str = json["username"].toString(); - if (username_str.length()) { - username_str = "@" + username_str; - } - - username->setText(username_str); - points->setText(points_str); + points->setText(QString::number(json["points"].toInt())); } -PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QWidget(parent) { +PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QFrame(parent) { QVBoxLayout* main_layout = new QVBoxLayout(this); - main_layout->setMargin(30); - main_layout->setSpacing(15); + main_layout->setContentsMargins(80, 90, 80, 60); + main_layout->setSpacing(0); - main_layout->addWidget(new QLabel("Upgrade now"), 1, Qt::AlignTop); + QLabel *upgrade = new QLabel("Upgrade Now"); + upgrade->setStyleSheet("font-size: 75px; font-weight: bold;"); + main_layout->addWidget(upgrade, 0, Qt::AlignTop); + main_layout->addSpacing(50); - QLabel* description = new QLabel("Become a comma prime member at connect.comma.ai and get premium features!"); - description->setStyleSheet(R"( - font-size: 50px; - color: #b8b8b8; - )"); + QLabel *description = new QLabel("Become a comma prime member at connect.comma.ai"); + description->setStyleSheet("font-size: 60px; font-weight: light; color: white;"); description->setWordWrap(true); - main_layout->addWidget(description, 2, Qt::AlignTop); - - QVector features = {"✓ REMOTE ACCESS", "✓ 14 DAYS OF STORAGE", "✓ DEVELOPER PERKS"}; - for (auto &f: features) { - QLabel* feature = new QLabel(f); - feature->setStyleSheet(R"(font-size: 40px;)"); - main_layout->addWidget(feature, 0, Qt::AlignBottom); + main_layout->addWidget(description, 0, Qt::AlignTop); + + main_layout->addStretch(); + + QLabel *features = new QLabel("PRIME FEATURES:"); + features->setStyleSheet("font-size: 41px; font-weight: bold; color: #E5E5E5;"); + main_layout->addWidget(features, 0, Qt::AlignBottom); + main_layout->addSpacing(30); + + QVector bullets = {"Remote access", "14 days of storage", "Developer perks"}; + for (auto &b: bullets) { + const QString check = " "; + QLabel *l = new QLabel(check + b); + l->setAlignment(Qt::AlignLeft); + l->setStyleSheet("font-size: 50px; margin-bottom: 15px;"); + main_layout->addWidget(l, 0, Qt::AlignBottom); } + + setStyleSheet(R"( + PrimeAdWidget { + border-radius: 10px; + background-color: #333333; + } + )"); } @@ -145,26 +174,36 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { // Unpaired, registration prompt layout QWidget* finishRegistration = new QWidget; + finishRegistration->setObjectName("primeWidget"); QVBoxLayout* finishRegistationLayout = new QVBoxLayout(finishRegistration); - finishRegistationLayout->setMargin(30); + finishRegistationLayout->setContentsMargins(30, 75, 30, 45); + finishRegistationLayout->setSpacing(0); - QLabel* registrationDescription = new QLabel("Pair your device with the comma connect app"); - registrationDescription->setWordWrap(true); - registrationDescription->setAlignment(Qt::AlignCenter); - registrationDescription->setStyleSheet(R"( - font-size: 55px; - font-weight: 400; - )"); + QLabel* registrationTitle = new QLabel("Finish Setup"); + registrationTitle->setStyleSheet("font-size: 75px; font-weight: bold; margin-left: 55px;"); + finishRegistationLayout->addWidget(registrationTitle); + + finishRegistationLayout->addSpacing(30); + QLabel* registrationDescription = new QLabel("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; margin-left: 55px;"); finishRegistationLayout->addWidget(registrationDescription); - QPushButton* finishButton = new QPushButton("Finish setup"); - finishButton->setFixedHeight(200); + finishRegistationLayout->addStretch(); + + QPushButton* finishButton = new QPushButton("Pair device"); + finishButton->setFixedHeight(220); finishButton->setStyleSheet(R"( - border-radius: 30px; - font-size: 55px; - font-weight: 500; - background: #585858; + QPushButton { + font-size: 55px; + font-weight: 400; + border-radius: 10px; + background-color: #465BEA; + } + QPushButton:pressed { + background-color: #3049F4; + } )"); finishRegistationLayout->addWidget(finishButton); QObject::connect(finishButton, &QPushButton::clicked, this, &SetupWidget::showQrCode); @@ -174,19 +213,23 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { // Pairing QR code layout QWidget* q = new QWidget; + q->setObjectName("primeWidget"); QVBoxLayout* qrLayout = new QVBoxLayout(q); + qrLayout->setContentsMargins(90, 90, 90, 90); - qrLayout->addSpacing(30); - QLabel* qrLabel = new QLabel("Scan QR code to pair!"); - qrLabel->setWordWrap(true); + QLabel* qrLabel = new QLabel("Scan the QR code to pair."); qrLabel->setAlignment(Qt::AlignHCenter); - qrLabel->setStyleSheet(R"( - font-size: 55px; - font-weight: 400; - )"); - qrLayout->addWidget(qrLabel, 0, Qt::AlignTop); + qrLabel->setStyleSheet("font-size: 47px; font-weight: light;"); + qrLayout->addWidget(qrLabel); + qrLayout->addSpacing(50); + + qrLayout->addWidget(new PairingQRWidget); + qrLayout->addStretch(); - qrLayout->addWidget(new PairingQRWidget, 1); + // setup widget + QVBoxLayout *outer_layout = new QVBoxLayout(this); + outer_layout->setContentsMargins(0, 0, 0, 0); + outer_layout->addWidget(mainLayout); mainLayout->addWidget(q); @@ -198,17 +241,11 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { mainLayout->setCurrentWidget(primeAd); - QVBoxLayout *main_layout = new QVBoxLayout(this); - main_layout->addWidget(mainLayout); - + setFixedWidth(750); setStyleSheet(R"( - SetupWidget { - background-color: #292929; - } - * { - font-size: 90px; - font-weight: 500; - border-radius: 40px; + #primeWidget { + border-radius: 10px; + background-color: #333333; } )"); @@ -249,12 +286,9 @@ void SetupWidget::replyFinished(const QString &response) { } QJsonObject json = doc.object(); - bool is_paired = json["is_paired"].toBool(); - bool is_prime = json["prime"].toBool(); - - if (!is_paired) { + if (!json["is_paired"].toBool()) { mainLayout->setCurrentIndex(showQr); - } else if (!is_prime) { + } else if (!json["prime"].toBool()) { showQr = false; mainLayout->setCurrentWidget(primeAd); } else { diff --git a/selfdrive/ui/qt/widgets/setup.h b/selfdrive/ui/qt/widgets/prime.h similarity index 94% rename from selfdrive/ui/qt/widgets/setup.h rename to selfdrive/ui/qt/widgets/prime.h index 02c47bd3e..27b2b6e54 100644 --- a/selfdrive/ui/qt/widgets/setup.h +++ b/selfdrive/ui/qt/widgets/prime.h @@ -27,14 +27,13 @@ public: private: QVBoxLayout* mainLayout; - QLabel* username; QLabel* points; private slots: void replyFinished(const QString &response); }; -class PrimeAdWidget : public QWidget { +class PrimeAdWidget : public QFrame { Q_OBJECT public: explicit PrimeAdWidget(QWidget* parent = 0);