ui: toggle confirmation and dialog redesign (#26331)

* toggle confirmation

* change text

* not for e2e

* get current description

* remove are you sure

* merge rich text and confirmation dialogs

* add some line breaks

* font colour

* fix padding a little

* revert

* updated toggle design
old-commit-hash: 91a1f1a91e
taco
Cameron Clough 3 years ago committed by GitHub
parent cfa80ee10c
commit f46b6ed70a
  1. 20
      selfdrive/ui/qt/offroad/settings.cc
  2. 16
      selfdrive/ui/qt/widgets/controls.h
  3. 50
      selfdrive/ui/qt/widgets/input.cc
  4. 12
      selfdrive/ui/qt/widgets/input.h
  5. 18
      selfdrive/ui/translations/main_ja.ts
  6. 18
      selfdrive/ui/translations/main_ko.ts
  7. 18
      selfdrive/ui/translations/main_pt-BR.ts
  8. 18
      selfdrive/ui/translations/main_zh-CHS.ts
  9. 18
      selfdrive/ui/translations/main_zh-CHT.ts

@ -27,49 +27,56 @@
#include "selfdrive/ui/qt/widgets/input.h" #include "selfdrive/ui/qt/widgets/input.h"
TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
// param, title, desc, icon // param, title, desc, icon, confirm
std::vector<std::tuple<QString, QString, QString, QString>> toggle_defs{ std::vector<std::tuple<QString, QString, QString, QString, bool>> toggle_defs{
{ {
"OpenpilotEnabledToggle", "OpenpilotEnabledToggle",
tr("Enable openpilot"), tr("Enable openpilot"),
tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off."), tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off."),
"../assets/offroad/icon_openpilot.png", "../assets/offroad/icon_openpilot.png",
false,
}, },
{ {
"IsLdwEnabled", "IsLdwEnabled",
tr("Enable Lane Departure Warnings"), tr("Enable Lane Departure Warnings"),
tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."), tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."),
"../assets/offroad/icon_warning.png", "../assets/offroad/icon_warning.png",
false,
}, },
{ {
"IsMetric", "IsMetric",
tr("Use Metric System"), tr("Use Metric System"),
tr("Display speed in km/h instead of mph."), tr("Display speed in km/h instead of mph."),
"../assets/offroad/icon_metric.png", "../assets/offroad/icon_metric.png",
false,
}, },
{ {
"RecordFront", "RecordFront",
tr("Record and Upload Driver Camera"), tr("Record and Upload Driver Camera"),
tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."), tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."),
"../assets/offroad/icon_monitoring.png", "../assets/offroad/icon_monitoring.png",
false,
}, },
{ {
"DisengageOnAccelerator", "DisengageOnAccelerator",
tr("Disengage On Accelerator Pedal"), tr("Disengage On Accelerator Pedal"),
tr("When enabled, pressing the accelerator pedal will disengage openpilot."), tr("When enabled, pressing the accelerator pedal will disengage openpilot."),
"../assets/offroad/icon_disengage_on_accelerator.svg", "../assets/offroad/icon_disengage_on_accelerator.svg",
false,
}, },
{ {
"EndToEndLong", "EndToEndLong",
tr("🌮 End-to-end longitudinal (extremely alpha) 🌮"), tr("🌮 End-to-end longitudinal (extremely alpha) 🌮"),
"", "",
"../assets/offroad/icon_road.png", "../assets/offroad/icon_road.png",
false,
}, },
{ {
"ExperimentalLongitudinalEnabled", "ExperimentalLongitudinalEnabled",
tr("Experimental openpilot longitudinal control"), tr("Experimental openpilot longitudinal control"),
tr("<b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b>"), tr("<b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b>"),
"../assets/offroad/icon_speed_limit.png", "../assets/offroad/icon_speed_limit.png",
true,
}, },
#ifdef ENABLE_MAPS #ifdef ENABLE_MAPS
{ {
@ -77,19 +84,20 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
tr("Show ETA in 24h Format"), tr("Show ETA in 24h Format"),
tr("Use 24h format instead of am/pm"), tr("Use 24h format instead of am/pm"),
"../assets/offroad/icon_metric.png", "../assets/offroad/icon_metric.png",
false,
}, },
{ {
"NavSettingLeftSide", "NavSettingLeftSide",
tr("Show Map on Left Side of UI"), tr("Show Map on Left Side of UI"),
tr("Show map on left side when in split screen view."), tr("Show map on left side when in split screen view."),
"../assets/offroad/icon_road.png", "../assets/offroad/icon_road.png",
false,
}, },
#endif #endif
}; };
for (auto &[param, title, desc, icon] : toggle_defs) { for (auto &[param, title, desc, icon, confirm] : toggle_defs) {
auto toggle = new ParamControl(param, title, desc, icon, this); auto toggle = new ParamControl(param, title, desc, icon, confirm, this);
bool locked = params.getBool((param + "Lock").toStdString()); bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked); toggle->setEnabled(!locked);
@ -181,7 +189,7 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) {
auto regulatoryBtn = new ButtonControl(tr("Regulatory"), tr("VIEW"), ""); auto regulatoryBtn = new ButtonControl(tr("Regulatory"), tr("VIEW"), "");
connect(regulatoryBtn, &ButtonControl::clicked, [=]() { connect(regulatoryBtn, &ButtonControl::clicked, [=]() {
const std::string txt = util::read_file("../assets/offroad/fcc.html"); const std::string txt = util::read_file("../assets/offroad/fcc.html");
RichTextDialog::alert(QString::fromStdString(txt), this); ConfirmationDialog::rich(QString::fromStdString(txt), this);
}); });
addItem(regulatoryBtn); addItem(regulatoryBtn);
} }

@ -7,6 +7,7 @@
#include <QPushButton> #include <QPushButton>
#include "common/params.h" #include "common/params.h"
#include "selfdrive/ui/qt/widgets/input.h"
#include "selfdrive/ui/qt/widgets/toggle.h" #include "selfdrive/ui/qt/widgets/toggle.h"
QFrame *horizontal_line(QWidget *parent = nullptr); QFrame *horizontal_line(QWidget *parent = nullptr);
@ -49,6 +50,10 @@ public:
value->setText(val); value->setText(val);
} }
const QString getDescription() {
return description->text();
}
public slots: public slots:
void showDescription() { void showDescription() {
description->setVisible(true); description->setVisible(true);
@ -134,10 +139,17 @@ class ParamControl : public ToggleControl {
Q_OBJECT Q_OBJECT
public: public:
ParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, false, parent) { ParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon, const bool confirm, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, false, parent) {
key = param.toStdString(); key = param.toStdString();
QObject::connect(this, &ParamControl::toggleFlipped, [=](bool state) { QObject::connect(this, &ParamControl::toggleFlipped, [=](bool state) {
params.putBool(key, state); QString content("<body><h2>" + title + "</h2><br><br>"
"<p style=\"text-align: center; margin: 0 128px;\">" + getDescription() + "</p></body>");
ConfirmationDialog dialog(content, tr("Ok"), tr("Cancel"), true, this);
if (!confirm || !state || dialog.exec()) {
params.putBool(key, state);
} else {
toggle.togglePosition();
}
}); });
} }

@ -183,17 +183,17 @@ void InputDialog::setMinLength(int length) {
// ConfirmationDialog // ConfirmationDialog
ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text, ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text,
QWidget *parent) : QDialogBase(parent) { const bool rich, QWidget *parent) : QDialogBase(parent) {
QFrame *container = new QFrame(this); QFrame *container = new QFrame(this);
container->setStyleSheet("QFrame { border-radius: 0; background-color: #ECECEC; }"); container->setStyleSheet("QFrame { background-color: #1B1B1B; color: #C9C9C9; }");
QVBoxLayout *main_layout = new QVBoxLayout(container); QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, 120, 32, 32); main_layout->setContentsMargins(32, rich ? 32 : 120, 32, 32);
QLabel *prompt = new QLabel(prompt_text, this); QLabel *prompt = new QLabel(prompt_text, this);
prompt->setWordWrap(true); prompt->setWordWrap(true);
prompt->setAlignment(Qt::AlignHCenter); prompt->setAlignment(rich ? Qt::AlignLeft : Qt::AlignHCenter);
prompt->setStyleSheet("font-size: 70px; font-weight: bold; color: black;"); prompt->setStyleSheet((rich ? "font-size: 42px; font-weight: light;" : "font-size: 70px; font-weight: bold;") + QString(" margin: 45px;"));
main_layout->addWidget(prompt, 1, Qt::AlignTop | Qt::AlignHCenter); main_layout->addWidget(rich ? (QWidget*)new ScrollView(prompt, this) : (QWidget*)prompt, 1, Qt::AlignTop);
// cancel + confirm buttons // cancel + confirm buttons
QHBoxLayout *btn_layout = new QHBoxLayout(); QHBoxLayout *btn_layout = new QHBoxLayout();
@ -213,49 +213,23 @@ ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString
} }
QVBoxLayout *outer_layout = new QVBoxLayout(this); QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(210, 170, 210, 170); int margin = rich ? 100 : 200;
outer_layout->setContentsMargins(margin, margin, margin, margin);
outer_layout->addWidget(container); outer_layout->addWidget(container);
} }
bool ConfirmationDialog::alert(const QString &prompt_text, QWidget *parent) { bool ConfirmationDialog::alert(const QString &prompt_text, QWidget *parent) {
ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), "", parent); ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), "", false, parent);
return d.exec(); return d.exec();
} }
bool ConfirmationDialog::confirm(const QString &prompt_text, QWidget *parent) { bool ConfirmationDialog::confirm(const QString &prompt_text, QWidget *parent) {
ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), tr("Cancel"), parent); ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), tr("Cancel"), false, parent);
return d.exec(); return d.exec();
} }
bool ConfirmationDialog::rich(const QString &prompt_text, QWidget *parent) {
// RichTextDialog ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), "", true, parent);
RichTextDialog::RichTextDialog(const QString &prompt_text, const QString &btn_text,
QWidget *parent) : QDialogBase(parent) {
QFrame *container = new QFrame(this);
container->setStyleSheet("QFrame { background-color: #1B1B1B; }");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, 32, 32, 32);
QLabel *prompt = new QLabel(prompt_text, this);
prompt->setWordWrap(true);
prompt->setAlignment(Qt::AlignLeft);
prompt->setTextFormat(Qt::RichText);
prompt->setStyleSheet("font-size: 42px; font-weight: light; color: #C9C9C9; margin: 45px;");
main_layout->addWidget(new ScrollView(prompt, this), 1, Qt::AlignTop);
// confirm button
QPushButton* confirm_btn = new QPushButton(btn_text);
main_layout->addWidget(confirm_btn);
QObject::connect(confirm_btn, &QPushButton::clicked, this, &QDialog::accept);
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(100, 100, 100, 100);
outer_layout->addWidget(container);
}
bool RichTextDialog::alert(const QString &prompt_text, QWidget *parent) {
auto d = RichTextDialog(prompt_text, tr("Ok"), parent);
return d.exec(); return d.exec();
} }

@ -55,18 +55,10 @@ class ConfirmationDialog : public QDialogBase {
public: public:
explicit ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, explicit ConfirmationDialog(const QString &prompt_text, const QString &confirm_text,
const QString &cancel_text, QWidget* parent); const QString &cancel_text, const bool rich, QWidget* parent);
static bool alert(const QString &prompt_text, QWidget *parent); static bool alert(const QString &prompt_text, QWidget *parent);
static bool confirm(const QString &prompt_text, QWidget *parent); static bool confirm(const QString &prompt_text, QWidget *parent);
}; static bool rich(const QString &prompt_text, QWidget *parent);
// larger ConfirmationDialog for rich text
class RichTextDialog : public QDialogBase {
Q_OBJECT
public:
explicit RichTextDialog(const QString &prompt_text, const QString &btn_text, QWidget* parent);
static bool alert(const QString &prompt_text, QWidget *parent);
}; };
class MultiOptionDialog : public QDialogBase { class MultiOptionDialog : public QDialogBase {

@ -463,6 +463,17 @@ location set</source>
<translation>connect.comma.ai使</translation> <translation>connect.comma.ai使</translation>
</message> </message>
</context> </context>
<context>
<name>ParamControl</name>
<message>
<source>Ok</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PrimeAdWidget</name> <name>PrimeAdWidget</name>
<message> <message>
@ -585,13 +596,6 @@ location set</source>
<translation>data</translation> <translation>data</translation>
</message> </message>
</context> </context>
<context>
<name>RichTextDialog</name>
<message>
<source>Ok</source>
<translation>OK</translation>
</message>
</context>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>

@ -463,6 +463,17 @@ location set</source>
<translation>connect.comma.ai을 </translation> <translation>connect.comma.ai을 </translation>
</message> </message>
</context> </context>
<context>
<name>ParamControl</name>
<message>
<source>Ok</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PrimeAdWidget</name> <name>PrimeAdWidget</name>
<message> <message>
@ -585,13 +596,6 @@ location set</source>
<translation> . .</translation> <translation> . .</translation>
</message> </message>
</context> </context>
<context>
<name>RichTextDialog</name>
<message>
<source>Ok</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>

@ -464,6 +464,17 @@ trabalho definido</translation>
<translation>Salve connect.comma.ai como sua página inicial para utilizar como um app</translation> <translation>Salve connect.comma.ai como sua página inicial para utilizar como um app</translation>
</message> </message>
</context> </context>
<context>
<name>ParamControl</name>
<message>
<source>Ok</source>
<translation type="unfinished">OK</translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished">Cancelar</translation>
</message>
</context>
<context> <context>
<name>PrimeAdWidget</name> <name>PrimeAdWidget</name>
<message> <message>
@ -589,13 +600,6 @@ trabalho definido</translation>
<translation>Não foi possível montar a partição de dados. Pressione confirmar para resetar seu dispositivo.</translation> <translation>Não foi possível montar a partição de dados. Pressione confirmar para resetar seu dispositivo.</translation>
</message> </message>
</context> </context>
<context>
<name>RichTextDialog</name>
<message>
<source>Ok</source>
<translation>Ok</translation>
</message>
</context>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>

@ -461,6 +461,17 @@ location set</source>
<translation> connect.comma.ai 便使</translation> <translation> connect.comma.ai 便使</translation>
</message> </message>
</context> </context>
<context>
<name>ParamControl</name>
<message>
<source>Ok</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PrimeAdWidget</name> <name>PrimeAdWidget</name>
<message> <message>
@ -583,13 +594,6 @@ location set</source>
<translation> </translation> <translation> </translation>
</message> </message>
</context> </context>
<context>
<name>RichTextDialog</name>
<message>
<source>Ok</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>

@ -463,6 +463,17 @@ location set</source>
<translation> connect.comma.ai 便 App 使</translation> <translation> connect.comma.ai 便 App 使</translation>
</message> </message>
</context> </context>
<context>
<name>ParamControl</name>
<message>
<source>Ok</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>PrimeAdWidget</name> <name>PrimeAdWidget</name>
<message> <message>
@ -585,13 +596,6 @@ location set</source>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context>
<name>RichTextDialog</name>
<message>
<source>Ok</source>
<translation></translation>
</message>
</context>
<context> <context>
<name>SettingsWindow</name> <name>SettingsWindow</name>
<message> <message>

Loading…
Cancel
Save