openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
11 KiB

#include "selfdrive/ui/qt/widgets/input.h"
#include <QPushButton>
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
#include <QButtonGroup>
#include "system/hardware/hw.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h"
#include "selfdrive/ui/qt/widgets/scrollview.h"
QDialogBase::QDialogBase(QWidget *parent) : QDialog(parent) {
Q_ASSERT(parent != nullptr);
parent->installEventFilter(this);
setStyleSheet(R"(
* {
outline: none;
color: white;
font-family: Inter;
}
QDialogBase {
background-color: black;
}
QPushButton {
height: 160;
font-size: 55px;
font-weight: 400;
border-radius: 10px;
color: white;
background-color: #333333;
}
QPushButton:pressed {
background-color: #444444;
}
)");
}
bool QDialogBase::eventFilter(QObject *o, QEvent *e) {
if (o == parent() && e->type() == QEvent::Hide) {
reject();
}
return QDialog::eventFilter(o, e);
}
int QDialogBase::exec() {
setMainWindow(this);
return QDialog::exec();
}
InputDialog::InputDialog(const QString &title, QWidget *parent, const QString &subtitle, bool secret) : QDialogBase(parent) {
main_layout = new QVBoxLayout(this);
main_layout->setContentsMargins(50, 55, 50, 50);
main_layout->setSpacing(0);
// build header
QHBoxLayout *header_layout = new QHBoxLayout();
QVBoxLayout *vlayout = new QVBoxLayout;
header_layout->addLayout(vlayout);
label = new QLabel(title, this);
label->setStyleSheet("font-size: 90px; font-weight: bold;");
vlayout->addWidget(label, 1, Qt::AlignTop | Qt::AlignLeft);
if (!subtitle.isEmpty()) {
sublabel = new QLabel(subtitle, this);
sublabel->setStyleSheet("font-size: 55px; font-weight: light; color: #BDBDBD;");
vlayout->addWidget(sublabel, 1, Qt::AlignTop | Qt::AlignLeft);
}
QPushButton* cancel_btn = new QPushButton(tr("Cancel"));
cancel_btn->setFixedSize(386, 125);
cancel_btn->setStyleSheet(R"(
font-size: 48px;
border-radius: 10px;
color: #E4E4E4;
background-color: #444444;
)");
header_layout->addWidget(cancel_btn, 0, Qt::AlignRight);
QObject::connect(cancel_btn, &QPushButton::clicked, this, &InputDialog::reject);
QObject::connect(cancel_btn, &QPushButton::clicked, this, &InputDialog::cancel);
main_layout->addLayout(header_layout);
// text box
main_layout->addStretch(2);
QWidget *textbox_widget = new QWidget;
textbox_widget->setObjectName("textbox");
QHBoxLayout *textbox_layout = new QHBoxLayout(textbox_widget);
textbox_layout->setContentsMargins(50, 0, 50, 0);
textbox_widget->setStyleSheet(R"(
#textbox {
margin-left: 50px;
margin-right: 50px;
border-radius: 0;
border-bottom: 3px solid #BDBDBD;
}
* {
border: none;
font-size: 80px;
font-weight: light;
background-color: transparent;
}
)");
line = new QLineEdit();
line->setStyleSheet("lineedit-password-character: 8226; lineedit-password-mask-delay: 1500;");
textbox_layout->addWidget(line, 1);
if (secret) {
eye_btn = new QPushButton();
eye_btn->setCheckable(true);
eye_btn->setFixedSize(150, 120);
QObject::connect(eye_btn, &QPushButton::toggled, [=](bool checked) {
if (checked) {
eye_btn->setIcon(QIcon(ASSET_PATH + "img_eye_closed.svg"));
eye_btn->setIconSize(QSize(81, 54));
line->setEchoMode(QLineEdit::Password);
} else {
eye_btn->setIcon(QIcon(ASSET_PATH + "img_eye_open.svg"));
eye_btn->setIconSize(QSize(81, 44));
line->setEchoMode(QLineEdit::Normal);
}
});
eye_btn->setChecked(true);
textbox_layout->addWidget(eye_btn);
}
main_layout->addWidget(textbox_widget, 0, Qt::AlignBottom);
main_layout->addSpacing(25);
k = new Keyboard(this);
QObject::connect(k, &Keyboard::emitEnter, this, &InputDialog::handleEnter);
QObject::connect(k, &Keyboard::emitBackspace, this, [=]() {
line->backspace();
});
QObject::connect(k, &Keyboard::emitKey, this, [=](const QString &key) {
line->insert(key.left(1));
});
main_layout->addWidget(k, 2, Qt::AlignBottom);
}
QString InputDialog::getText(const QString &prompt, QWidget *parent, const QString &subtitle,
bool secret, int minLength, const QString &defaultText) {
InputDialog d = InputDialog(prompt, parent, subtitle, secret);
d.line->setText(defaultText);
d.setMinLength(minLength);
const int ret = d.exec();
return ret ? d.text() : QString();
}
QString InputDialog::text() {
return line->text();
}
void InputDialog::show() {
setMainWindow(this);
}
void InputDialog::handleEnter() {
if (line->text().length() >= minLength) {
done(QDialog::Accepted);
emitText(line->text());
} else {
setMessage(tr("Need at least %n character(s)!", "", minLength), false);
}
}
void InputDialog::setMessage(const QString &message, bool clearInputField) {
label->setText(message);
if (clearInputField) {
line->setText("");
}
}
void InputDialog::setMinLength(int length) {
minLength = length;
}
// ConfirmationDialog
ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text,
QWidget *parent) : QDialogBase(parent) {
QFrame *container = new QFrame(this);
container->setStyleSheet("QFrame { border-radius: 0; background-color: #ECECEC; }");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(32, 120, 32, 32);
QLabel *prompt = new QLabel(prompt_text, this);
prompt->setWordWrap(true);
prompt->setAlignment(Qt::AlignHCenter);
prompt->setStyleSheet("font-size: 70px; font-weight: bold; color: black;");
main_layout->addWidget(prompt, 1, Qt::AlignTop | Qt::AlignHCenter);
// cancel + confirm buttons
QHBoxLayout *btn_layout = new QHBoxLayout();
btn_layout->setSpacing(30);
main_layout->addLayout(btn_layout);
if (cancel_text.length()) {
QPushButton* cancel_btn = new QPushButton(cancel_text);
btn_layout->addWidget(cancel_btn);
QObject::connect(cancel_btn, &QPushButton::clicked, this, &ConfirmationDialog::reject);
}
if (confirm_text.length()) {
QPushButton* confirm_btn = new QPushButton(confirm_text);
btn_layout->addWidget(confirm_btn);
QObject::connect(confirm_btn, &QPushButton::clicked, this, &ConfirmationDialog::accept);
}
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(210, 170, 210, 170);
outer_layout->addWidget(container);
}
bool ConfirmationDialog::alert(const QString &prompt_text, QWidget *parent) {
ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), "", parent);
return d.exec();
}
bool ConfirmationDialog::confirm(const QString &prompt_text, QWidget *parent) {
ConfirmationDialog d = ConfirmationDialog(prompt_text, tr("Ok"), tr("Cancel"), parent);
return d.exec();
}
// RichTextDialog
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();
}
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
// MultiOptionDialog
MultiOptionDialog::MultiOptionDialog(const QString &prompt_text, const QStringList &l, const QString &current, QWidget *parent) : QDialogBase(parent) {
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
QFrame *container = new QFrame(this);
container->setStyleSheet(R"(
QFrame { background-color: #1B1B1B; }
#confirm_btn[enabled="false"] { background-color: #2B2B2B; }
#confirm_btn:enabled { background-color: #465BEA; }
#confirm_btn:enabled:pressed { background-color: #3049F4; }
)");
QVBoxLayout *main_layout = new QVBoxLayout(container);
main_layout->setContentsMargins(55, 50, 55, 50);
QLabel *title = new QLabel(prompt_text, this);
title->setStyleSheet("font-size: 70px; font-weight: 500;");
main_layout->addWidget(title, 0, Qt::AlignLeft | Qt::AlignTop);
main_layout->addSpacing(25);
QWidget *listWidget = new QWidget(this);
QVBoxLayout *listLayout = new QVBoxLayout(listWidget);
listLayout->setSpacing(20);
listWidget->setStyleSheet(R"(
QPushButton {
height: 135;
padding: 0px 50px;
text-align: left;
font-size: 55px;
font-weight: 300;
border-radius: 10px;
background-color: #4F4F4F;
}
QPushButton:checked { background-color: #465BEA; }
)");
QButtonGroup *group = new QButtonGroup(listWidget);
group->setExclusive(true);
QPushButton *confirm_btn = new QPushButton(tr("Select"));
confirm_btn->setObjectName("confirm_btn");
confirm_btn->setEnabled(false);
for (const QString &s : l) {
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
QPushButton *selectionLabel = new QPushButton(s);
selectionLabel->setCheckable(true);
selectionLabel->setChecked(s == current);
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
QObject::connect(selectionLabel, &QPushButton::toggled, [=](bool checked) {
if (checked) selection = s;
if (selection != current) {
confirm_btn->setEnabled(true);
} else {
confirm_btn->setEnabled(false);
}
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
});
group->addButton(selectionLabel);
listLayout->addWidget(selectionLabel);
}
ScrollView *scroll_view = new ScrollView(listWidget, this);
scroll_view->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
main_layout->addWidget(scroll_view);
main_layout->addStretch(1);
main_layout->addSpacing(35);
// cancel + confirm buttons
QHBoxLayout *blayout = new QHBoxLayout;
main_layout->addLayout(blayout);
blayout->setSpacing(50);
QPushButton *cancel_btn = new QPushButton(tr("Cancel"));
QObject::connect(cancel_btn, &QPushButton::clicked, this, &ConfirmationDialog::reject);
QObject::connect(confirm_btn, &QPushButton::clicked, this, &ConfirmationDialog::accept);
blayout->addWidget(cancel_btn);
blayout->addWidget(confirm_btn);
QVBoxLayout *outer_layout = new QVBoxLayout(this);
outer_layout->setContentsMargins(50, 50, 50, 50);
outer_layout->addWidget(container);
}
QString MultiOptionDialog::getSelection(const QString &prompt_text, const QStringList &l, const QString &current, QWidget *parent) {
MultiOptionDialog d = MultiOptionDialog(prompt_text, l, current, parent);
UI: Internationalization support (#21212) * rough multiple language demo * more wrappings * stash * add some bad translations * updates * map from french to spanish still has same problem of needing to call setText on everything * add files * restart UI * use return code * relative path * more translations * don't loop restart * Toggle and prime translations * try on device * try QComboBox with readable style * stash * not yet scrollable * stash * dynamic translations (doesn't work for dynamic widget strings yet) * clean up multiple option selector * store languages in json * try transparent * Try transparent popup * see how this looks * tweaks * clean up * update names * Add Chinese (Simplified) translations * Do missing French translations * unit tests caught that :) * fix test * fix other test (on PC) * add entries to dialog to test * add cancel button, clean up a bit * just chinese * some clean up * use quotes * clean up * Just quit, set timeout to 0 * half a second * use exitcode * don't print if it's expected * this comment is outdated * update translations * Update translations * re-order input classes * Update line numbers * use enabled property for button style * Get rid of ListWidget * Update line numbers * Log failed to load language * Log failed to load language * Move to utils and fix english logging extra line * Update translations * spacing * looks a bit better * try this instead of exitcode fixes fix * only one function * comment * Update line numbers * fixup some japanese translations * clean up multi option dialog * Update line numbers old-commit-hash: 949de4d2b6b293d9f77d83c58212f5dee176cbf1
3 years ago
if (d.exec()) {
return d.selection;
}
return "";
}