ui: offroad experimental mode button (#26498)

* draft

* draft

* before qpushbutton

* icon, clean up button, clicked goes to toggles

* fix icon

* add imgs

* img

* make square

* works with layouts!

* fix gradient

* this looks good

* clean up

* clean up

* remove padding around couch

* use scene's experimental_model, new onroad design

* rename widget

* def want 3

* update translations

* add img

* add 25px of padding!

* make 300px (no change)

* clean up old images

* 5 px smaller

* add white img

* fix from merge

* no style sheets

* see how this looks on device

* aliased vertical line (clean up)

* clean up

* imgs

* couch

* delete

* bye bye

* expand toggle support

* clean up

* fix dynamic icon

* make exp icon dynamic

* order

* move to offroad
old-commit-hash: 58b84fb401
taco v0.9.0
Shane Smiskol 3 years ago committed by GitHub
parent ac0055307f
commit dcd22dda7a
  1. 3
      selfdrive/assets/fonts/JetBrainsMono-Medium.ttf
  2. 3
      selfdrive/assets/img_couch.svg
  3. 3
      selfdrive/assets/img_experimental.svg
  4. 3
      selfdrive/assets/img_experimental_grey.svg
  5. 3
      selfdrive/assets/img_experimental_white.svg
  6. 2
      selfdrive/ui/SConscript
  7. 19
      selfdrive/ui/qt/home.cc
  8. 5
      selfdrive/ui/qt/home.h
  9. 75
      selfdrive/ui/qt/offroad/experimental_mode.cc
  10. 31
      selfdrive/ui/qt/offroad/experimental_mode.h
  11. 23
      selfdrive/ui/qt/offroad/settings.cc
  12. 5
      selfdrive/ui/qt/offroad/settings.h
  13. 6
      selfdrive/ui/qt/onroad.cc
  14. 1
      selfdrive/ui/qt/onroad.h
  15. 2
      selfdrive/ui/qt/sidebar.h
  16. 4
      selfdrive/ui/qt/window.cc
  17. 2
      selfdrive/ui/qt/window.h
  18. 11
      selfdrive/ui/translations/main_ja.ts
  19. 11
      selfdrive/ui/translations/main_ko.ts
  20. 11
      selfdrive/ui/translations/main_pt-BR.ts
  21. 11
      selfdrive/ui/translations/main_zh-CHS.ts
  22. 11
      selfdrive/ui/translations/main_zh-CHT.ts

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64708889e701acf7f2f43fd9c3696eb7f2c849ae67693ce581ad8f92433b3b24
size 204140

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ea87cc840ba1b0b96351bbde97af171c3cda462559459e186a5689f9f4aba82e
size 2311

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c26afadff128244567a7cf98f1c998f97056b19209301ff7fc8851eb807fb748
size 2193

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5ae28a53171567c8a0d52eec75cc49004cb8dd19dcab9a360784718ab8ec7c02
size 1931

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:99be696be983700d7eb1768bd1c840198a4eb9525b71e28efea49f13c358e519
size 1891

@ -58,7 +58,7 @@ qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_libs)
qt_src = ["main.cc", "qt/sidebar.cc", "qt/onroad.cc", "qt/body.cc",
"qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
"qt/offroad/software_settings.cc", "qt/offroad/onboarding.cc",
"qt/offroad/driverview.cc"]
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc"]
qt_env.Program("_ui", qt_src + [asset_obj], LIBS=qt_libs)
if GetOption('test'):
qt_src.remove("main.cc") # replaced by test_runner

@ -4,6 +4,7 @@
#include <QMouseEvent>
#include <QVBoxLayout>
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/drive_stats.h"
#include "selfdrive/ui/qt/widgets/prime.h"
@ -22,7 +23,8 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
slayout = new QStackedLayout();
main_layout->addLayout(slayout);
home = new OffroadHome();
home = new OffroadHome(this);
QObject::connect(home, &OffroadHome::openSettings, this, &HomeWindow::openSettings);
slayout->addWidget(home);
onroad = new OnroadWindow(this);
@ -128,11 +130,24 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
main_layout->addSpacing(25);
center_layout = new QStackedLayout();
// Vertical experimental button and drive stats layout
QWidget* statsAndExperimentalModeButtonWidget = new QWidget(this);
QVBoxLayout* statsAndExperimentalModeButton = new QVBoxLayout(statsAndExperimentalModeButtonWidget);
statsAndExperimentalModeButton->setSpacing(30);
statsAndExperimentalModeButton->setMargin(0);
ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this);
QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings);
statsAndExperimentalModeButton->addWidget(experimental_mode, 1);
statsAndExperimentalModeButton->addWidget(new DriveStats, 1);
// Horizontal experimental + drive stats and setup widget
QWidget* statsAndSetupWidget = new QWidget(this);
QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget);
statsAndSetup->setMargin(0);
statsAndSetup->setSpacing(30);
statsAndSetup->addWidget(new DriveStats, 1);
statsAndSetup->addWidget(statsAndExperimentalModeButtonWidget, 1);
statsAndSetup->addWidget(new SetupWidget);
center_layout->addWidget(statsAndSetupWidget);

@ -22,6 +22,9 @@ class OffroadHome : public QFrame {
public:
explicit OffroadHome(QWidget* parent = 0);
signals:
void openSettings(int index = 0, const QString &param = "");
private:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
@ -45,7 +48,7 @@ public:
explicit HomeWindow(QWidget* parent = 0);
signals:
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void closeSettings();
public slots:

@ -0,0 +1,75 @@
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QPainter>
#include <QStyle>
#include "selfdrive/ui/ui.h"
ExperimentalModeButton::ExperimentalModeButton(QWidget *parent) : QPushButton(parent) {
chill_pixmap = QPixmap("../assets/img_couch.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
experimental_pixmap = QPixmap("../assets/img_experimental_grey.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
// go to toggles and expand experimental mode description
connect(this, &QPushButton::clicked, [=]() { emit openSettings(2, "ExperimentalMode"); });
setFixedHeight(125);
QHBoxLayout *main_layout = new QHBoxLayout;
main_layout->setContentsMargins(horizontal_padding, 0, horizontal_padding, 0);
mode_label = new QLabel;
mode_icon = new QLabel;
mode_icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
main_layout->addWidget(mode_label, 1, Qt::AlignLeft);
main_layout->addWidget(mode_icon, 0, Qt::AlignRight);
setLayout(main_layout);
setStyleSheet(R"(
QPushButton {
border: none;
}
QLabel {
font-size: 45px;
font-weight: 300;
text-align: left;
font-family: JetBrainsMono;
color: #000000;
}
)");
}
void ExperimentalModeButton::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(rect(), 10, 10);
// gradient
bool pressed = isDown();
QLinearGradient gradient(rect().left(), 0, rect().right(), 0);
if (experimental_mode) {
gradient.setColorAt(0, QColor(255, 155, 63, pressed ? 0xcc : 0xff));
gradient.setColorAt(1, QColor(219, 56, 34, pressed ? 0xcc : 0xff));
} else {
gradient.setColorAt(0, QColor(20, 255, 171, pressed ? 0xcc : 0xff));
gradient.setColorAt(1, QColor(35, 149, 255, pressed ? 0xcc : 0xff));
}
p.fillPath(path, gradient);
// vertical line
p.setPen(QPen(QColor(0, 0, 0, 0x4d), 3, Qt::SolidLine));
int line_x = rect().right() - img_width - (2 * horizontal_padding);
p.drawLine(line_x, rect().bottom(), line_x, rect().top());
}
void ExperimentalModeButton::showEvent(QShowEvent *event) {
experimental_mode = params.getBool("ExperimentalMode");
mode_icon->setPixmap(experimental_mode ? experimental_pixmap : chill_pixmap);
mode_label->setText(experimental_mode ? tr("EXPERIMENTAL MODE ON") : tr("CHILL MODE ON"));
}

@ -0,0 +1,31 @@
#pragma once
#include <QLabel>
#include <QPushButton>
#include "common/params.h"
class ExperimentalModeButton : public QPushButton {
Q_OBJECT
public:
explicit ExperimentalModeButton(QWidget* parent = 0);
signals:
void openSettings(int index = 0, const QString &toggle = "");
private:
void showEvent(QShowEvent *event) override;
Params params;
bool experimental_mode;
int img_width = 100;
int horizontal_padding = 30;
QPixmap experimental_pixmap;
QPixmap chill_pixmap;
QLabel *mode_label;
QLabel *mode_icon;
protected:
void paintEvent(QPaintEvent *event) override;
};

@ -39,7 +39,7 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
"ExperimentalMode",
tr("Experimental Mode"),
"",
"../assets/offroad/icon_road.png",
"../assets/img_experimental_white.svg",
},
{
"ExperimentalLongitudinalEnabled",
@ -100,6 +100,7 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
}
// Toggles with confirmation dialogs
toggles["ExperimentalMode"]->setActiveIcon("../assets/img_experimental.svg");
toggles["ExperimentalMode"]->setConfirmation(true, true);
toggles["ExperimentalLongitudinalEnabled"]->setConfirmation(true, false);
@ -108,6 +109,10 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
});
}
void TogglesPanel::expandToggleDescription(const QString &param) {
toggles[param.toStdString()]->showDescription();
}
void TogglesPanel::showEvent(QShowEvent *event) {
updateToggles();
}
@ -299,8 +304,15 @@ void DevicePanel::poweroff() {
}
void SettingsWindow::showEvent(QShowEvent *event) {
panel_widget->setCurrentIndex(0);
nav_btns->buttons()[0]->setChecked(true);
setCurrentPanel(0);
}
void SettingsWindow::setCurrentPanel(int index, const QString &param) {
panel_widget->setCurrentIndex(index);
nav_btns->buttons()[index]->setChecked(true);
if (!param.isEmpty()) {
emit expandToggleDescription(param);
}
}
SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
@ -341,10 +353,13 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
QObject::connect(device, &DevicePanel::reviewTrainingGuide, this, &SettingsWindow::reviewTrainingGuide);
QObject::connect(device, &DevicePanel::showDriverView, this, &SettingsWindow::showDriverView);
TogglesPanel *toggles = new TogglesPanel(this);
QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription);
QList<QPair<QString, QWidget *>> panels = {
{tr("Device"), device},
{tr("Network"), new Networking(this)},
{tr("Toggles"), new TogglesPanel(this)},
{tr("Toggles"), toggles},
{tr("Software"), new SoftwarePanel(this)},
};

@ -17,6 +17,7 @@ class SettingsWindow : public QFrame {
public:
explicit SettingsWindow(QWidget *parent = 0);
void setCurrentPanel(int index, const QString &param = "");
protected:
void showEvent(QShowEvent *event) override;
@ -25,6 +26,7 @@ signals:
void closeSettings();
void reviewTrainingGuide();
void showDriverView();
void expandToggleDescription(const QString &param);
private:
QPushButton *sidebar_alert_widget;
@ -56,6 +58,9 @@ public:
explicit TogglesPanel(SettingsWindow *parent);
void showEvent(QShowEvent *event) override;
public slots:
void expandToggleDescription(const QString &param);
private:
Params params;
std::map<std::string, ParamControl*> toggles;

@ -174,6 +174,7 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par
pm = std::make_unique<PubMaster, const std::initializer_list<const char *>>({"uiDebug"});
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size - 5, img_size - 5});
dm_img = loadPixmap("../assets/img_driver_face.png", {img_size, img_size});
}
@ -378,8 +379,9 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
// engage-ability icon
if (engageable) {
SubMaster &sm = *(uiState()->sm);
drawIcon(p, rect().right() - radius / 2 - bdr_s * 2, radius / 2 + int(bdr_s * 1.5),
engage_img, bg_colors[status], 1.0);
sm["controlsState"].getControlsState().getExperimentalMode() ? experimental_img : engage_img, blackColor(166), 1.0);
}
// dm icon
@ -409,7 +411,7 @@ void AnnotatedCameraWidget::drawIcon(QPainter &p, int x, int y, QPixmap &img, QB
p.setBrush(bg);
p.drawEllipse(x - radius / 2, y - radius / 2, radius, radius);
p.setOpacity(opacity);
p.drawPixmap(x - img_size / 2, y - img_size / 2, img);
p.drawPixmap(x - img.size().width() / 2, y - img.size().height() / 2, img);
}

@ -51,6 +51,7 @@ private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
QPixmap engage_img;
QPixmap experimental_img;
QPixmap dm_img;
const int radius = 192;
const int img_size = (radius / 2) * 1.5;

@ -20,7 +20,7 @@ public:
explicit Sidebar(QWidget* parent = 0);
signals:
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void valueChanged();
public slots:

@ -53,6 +53,7 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
QFontDatabase::addApplicationFont("../assets/fonts/Inter-Regular.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/Inter-SemiBold.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/Inter-Thin.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/JetBrainsMono-Medium.ttf");
// no outline to prevent the focus rectangle
setStyleSheet(R"(
@ -64,8 +65,9 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
setAttribute(Qt::WA_NoSystemBackground);
}
void MainWindow::openSettings() {
void MainWindow::openSettings(int index, const QString &param) {
main_layout->setCurrentWidget(settingsWindow);
settingsWindow->setCurrentPanel(index, param);
}
void MainWindow::closeSettings() {

@ -15,7 +15,7 @@ public:
private:
bool eventFilter(QObject *obj, QEvent *event) override;
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void closeSettings();
Device device;

@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -281,6 +281,17 @@
<translation> </translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -281,6 +281,17 @@
<translation>câmera iniciando</translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>

Loading…
Cancel
Save