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. 200
      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",
"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"]

@ -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);

@ -1,4 +1,4 @@
#include "selfdrive/ui/qt/widgets/setup.h"
#include "selfdrive/ui/qt/widgets/prime.h"
#include <QDebug>
#include <QJsonDocument>
@ -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<QString> 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<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);
}
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 {

@ -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);
Loading…
Cancel
Save