ui: prime widget design (#21755)

* new setup widget

* set fixed width and align right

more closely match

* text wrapping fixes

* prime widget draft

* rename

* remove username

* fix weights

* ad

* qr

* pressed color

* cleanup

* simplify

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: 6fc999fc53
commatwo_master
sshane 4 years ago committed by GitHub
parent 6fac6698d5
commit bbd63268df
  1. 2
      selfdrive/ui/SConscript
  2. 6
      selfdrive/ui/qt/home.cc
  3. 196
      selfdrive/ui/qt/widgets/prime.cc
  4. 3
      selfdrive/ui/qt/widgets/prime.h

@ -21,7 +21,7 @@ if arch == "Darwin":
widgets_src = ["qt/util.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", 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/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/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#phonelibs/qrcode/QrCode.cc", "qt/api.cc",
"qt/request_repeater.cc"] "qt/request_repeater.cc"]

@ -8,7 +8,7 @@
#include "selfdrive/common/params.h" #include "selfdrive/common/params.h"
#include "selfdrive/ui/qt/util.h" #include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/drive_stats.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 // HomeWindow: the container for the offroad and onroad UIs
@ -122,8 +122,8 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget); QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget);
statsAndSetup->setMargin(0); statsAndSetup->setMargin(0);
statsAndSetup->setSpacing(30); statsAndSetup->setSpacing(30);
statsAndSetup->addWidget(new DriveStats, 11); statsAndSetup->addWidget(new DriveStats, 1);
statsAndSetup->addWidget(new SetupWidget, 8); statsAndSetup->addWidget(new SetupWidget);
center_layout->addWidget(statsAndSetupWidget); center_layout->addWidget(statsAndSetupWidget);

@ -1,4 +1,4 @@
#include "selfdrive/ui/qt/widgets/setup.h" #include "selfdrive/ui/qt/widgets/prime.h"
#include <QDebug> #include <QDebug>
#include <QJsonDocument> #include <QJsonDocument>
@ -61,32 +61,52 @@ void PairingQRWidget::updateQrCode(const QString &text) {
PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) { PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) {
mainLayout = new QVBoxLayout(this); mainLayout = new QVBoxLayout(this);
mainLayout->setMargin(30); mainLayout->setMargin(0);
mainLayout->setSpacing(30);
QLabel* commaPrime = new QLabel("COMMA PRIME"); // subscribed prime layout
mainLayout->addWidget(commaPrime, 0, Qt::AlignTop); QWidget *primeWidget = new QWidget;
primeWidget->setObjectName("primeWidget");
QVBoxLayout *primeLayout = new QVBoxLayout(primeWidget);
primeLayout->setMargin(0);
primeWidget->setContentsMargins(60, 50, 60, 50);
username = new QLabel(); QLabel* subscribed = new QLabel("✓ SUBSCRIBED");
username->setStyleSheet("font-size: 55px;"); // TODO: fit width subscribed->setStyleSheet("font-size: 41px; font-weight: bold; color: #86FF4E;");
mainLayout->addWidget(username, 0, Qt::AlignTop); 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"); QLabel* commaPoints = new QLabel("COMMA POINTS");
commaPoints->setStyleSheet(R"( commaPoints->setStyleSheet("font-size: 41px; font-family: Inter SemiBold;");
color: #b8b8b8; pointsLayout->addWidget(commaPoints, 0, Qt::AlignTop);
)");
mainLayout->addWidget(commaPoints, 0, Qt::AlignTop);
points = new QLabel(); points = new QLabel("210");
mainLayout->addWidget(points, 0, Qt::AlignTop); points->setStyleSheet("font-size: 91px; font-weight: bold;");
pointsLayout->addWidget(points, 0, Qt::AlignTop);
setStyleSheet(R"( mainLayout->addWidget(pointsWidget);
QLabel {
font-size: 70px; mainLayout->addStretch();
font-weight: 500;
}
)");
// set up API requests // set up API requests
std::string dongleId = Params().get("DongleId"); std::string dongleId = Params().get("DongleId");
@ -100,42 +120,51 @@ PrimeUserWidget::PrimeUserWidget(QWidget* parent) : QWidget(parent) {
void PrimeUserWidget::replyFinished(const QString &response) { void PrimeUserWidget::replyFinished(const QString &response) {
QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8());
if (doc.isNull()) { if (doc.isNull()) {
qDebug() << "JSON Parse failed on getting username and points"; qDebug() << "JSON Parse failed on getting points";
return; return;
} }
QJsonObject json = doc.object(); QJsonObject json = doc.object();
QString points_str = QString::number(json["points"].toInt()); points->setText(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);
} }
PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QWidget(parent) { PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QFrame(parent) {
QVBoxLayout* main_layout = new QVBoxLayout(this); QVBoxLayout* main_layout = new QVBoxLayout(this);
main_layout->setMargin(30); main_layout->setContentsMargins(80, 90, 80, 60);
main_layout->setSpacing(15); 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!"); QLabel *description = new QLabel("Become a comma prime member at connect.comma.ai");
description->setStyleSheet(R"( description->setStyleSheet("font-size: 60px; font-weight: light; color: white;");
font-size: 50px;
color: #b8b8b8;
)");
description->setWordWrap(true); description->setWordWrap(true);
main_layout->addWidget(description, 2, Qt::AlignTop); 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<QString> bullets = {"Remote access", "14 days of storage", "Developer perks"};
for (auto &b: bullets) {
const QString check = "<b><font color='#465BEA'>✓</font></b> ";
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);
}
QVector<QString> features = {"✓ REMOTE ACCESS", "✓ 14 DAYS OF STORAGE", "✓ DEVELOPER PERKS"}; setStyleSheet(R"(
for (auto &f: features) { PrimeAdWidget {
QLabel* feature = new QLabel(f); border-radius: 10px;
feature->setStyleSheet(R"(font-size: 40px;)"); background-color: #333333;
main_layout->addWidget(feature, 0, Qt::AlignBottom);
} }
)");
} }
@ -145,26 +174,36 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) {
// Unpaired, registration prompt layout // Unpaired, registration prompt layout
QWidget* finishRegistration = new QWidget; QWidget* finishRegistration = new QWidget;
finishRegistration->setObjectName("primeWidget");
QVBoxLayout* finishRegistationLayout = new QVBoxLayout(finishRegistration); 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"); QLabel* registrationTitle = new QLabel("Finish Setup");
registrationDescription->setWordWrap(true); registrationTitle->setStyleSheet("font-size: 75px; font-weight: bold; margin-left: 55px;");
registrationDescription->setAlignment(Qt::AlignCenter); finishRegistationLayout->addWidget(registrationTitle);
registrationDescription->setStyleSheet(R"(
font-size: 55px; finishRegistationLayout->addSpacing(30);
font-weight: 400;
)");
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); finishRegistationLayout->addWidget(registrationDescription);
QPushButton* finishButton = new QPushButton("Finish setup"); finishRegistationLayout->addStretch();
finishButton->setFixedHeight(200);
QPushButton* finishButton = new QPushButton("Pair device");
finishButton->setFixedHeight(220);
finishButton->setStyleSheet(R"( finishButton->setStyleSheet(R"(
border-radius: 30px; QPushButton {
font-size: 55px; font-size: 55px;
font-weight: 500; font-weight: 400;
background: #585858; border-radius: 10px;
background-color: #465BEA;
}
QPushButton:pressed {
background-color: #3049F4;
}
)"); )");
finishRegistationLayout->addWidget(finishButton); finishRegistationLayout->addWidget(finishButton);
QObject::connect(finishButton, &QPushButton::clicked, this, &SetupWidget::showQrCode); QObject::connect(finishButton, &QPushButton::clicked, this, &SetupWidget::showQrCode);
@ -174,19 +213,23 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) {
// Pairing QR code layout // Pairing QR code layout
QWidget* q = new QWidget; QWidget* q = new QWidget;
q->setObjectName("primeWidget");
QVBoxLayout* qrLayout = new QVBoxLayout(q); QVBoxLayout* qrLayout = new QVBoxLayout(q);
qrLayout->setContentsMargins(90, 90, 90, 90);
qrLayout->addSpacing(30); QLabel* qrLabel = new QLabel("Scan the QR code to pair.");
QLabel* qrLabel = new QLabel("Scan QR code to pair!");
qrLabel->setWordWrap(true);
qrLabel->setAlignment(Qt::AlignHCenter); qrLabel->setAlignment(Qt::AlignHCenter);
qrLabel->setStyleSheet(R"( qrLabel->setStyleSheet("font-size: 47px; font-weight: light;");
font-size: 55px; qrLayout->addWidget(qrLabel);
font-weight: 400; qrLayout->addSpacing(50);
)");
qrLayout->addWidget(qrLabel, 0, Qt::AlignTop);
qrLayout->addWidget(new PairingQRWidget, 1); qrLayout->addWidget(new PairingQRWidget);
qrLayout->addStretch();
// setup widget
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(0, 0, 0, 0);
outer_layout->addWidget(mainLayout);
mainLayout->addWidget(q); mainLayout->addWidget(q);
@ -198,17 +241,11 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) {
mainLayout->setCurrentWidget(primeAd); mainLayout->setCurrentWidget(primeAd);
QVBoxLayout *main_layout = new QVBoxLayout(this); setFixedWidth(750);
main_layout->addWidget(mainLayout);
setStyleSheet(R"( setStyleSheet(R"(
SetupWidget { #primeWidget {
background-color: #292929; border-radius: 10px;
} background-color: #333333;
* {
font-size: 90px;
font-weight: 500;
border-radius: 40px;
} }
)"); )");
@ -249,12 +286,9 @@ void SetupWidget::replyFinished(const QString &response) {
} }
QJsonObject json = doc.object(); QJsonObject json = doc.object();
bool is_paired = json["is_paired"].toBool(); if (!json["is_paired"].toBool()) {
bool is_prime = json["prime"].toBool();
if (!is_paired) {
mainLayout->setCurrentIndex(showQr); mainLayout->setCurrentIndex(showQr);
} else if (!is_prime) { } else if (!json["prime"].toBool()) {
showQr = false; showQr = false;
mainLayout->setCurrentWidget(primeAd); mainLayout->setCurrentWidget(primeAd);
} else { } else {

@ -27,14 +27,13 @@ public:
private: private:
QVBoxLayout* mainLayout; QVBoxLayout* mainLayout;
QLabel* username;
QLabel* points; QLabel* points;
private slots: private slots:
void replyFinished(const QString &response); void replyFinished(const QString &response);
}; };
class PrimeAdWidget : public QWidget { class PrimeAdWidget : public QFrame {
Q_OBJECT Q_OBJECT
public: public:
explicit PrimeAdWidget(QWidget* parent = 0); explicit PrimeAdWidget(QWidget* parent = 0);
Loading…
Cancel
Save