openpilot v0.9.6 release
date: 2024-01-12T10:13:37 master commit: ba792d576a49a0899b88a753fa1c52956bedf9e6
This commit is contained in:
167
selfdrive/ui/qt/widgets/keyboard.cc
Normal file
167
selfdrive/ui/qt/widgets/keyboard.cc
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "selfdrive/ui/qt/widgets/keyboard.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QButtonGroup>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMap>
|
||||
#include <QTouchEvent>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
const QString BACKSPACE_KEY = "⌫";
|
||||
const QString ENTER_KEY = "→";
|
||||
|
||||
const QMap<QString, int> KEY_STRETCH = {{" ", 5}, {ENTER_KEY, 2}};
|
||||
|
||||
const QStringList CONTROL_BUTTONS = {"↑", "↓", "ABC", "#+=", "123", BACKSPACE_KEY, ENTER_KEY};
|
||||
|
||||
const float key_spacing_vertical = 20;
|
||||
const float key_spacing_horizontal = 15;
|
||||
|
||||
KeyButton::KeyButton(const QString &text, QWidget *parent) : QPushButton(text, parent) {
|
||||
setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
bool KeyButton::event(QEvent *event) {
|
||||
if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchEnd) {
|
||||
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
|
||||
if (!touchEvent->touchPoints().empty()) {
|
||||
const QEvent::Type mouseType = event->type() == QEvent::TouchBegin ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease;
|
||||
QMouseEvent mouseEvent(mouseType, touchEvent->touchPoints().front().pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
|
||||
QPushButton::event(&mouseEvent);
|
||||
event->accept();
|
||||
parentWidget()->update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QPushButton::event(event);
|
||||
}
|
||||
|
||||
KeyboardLayout::KeyboardLayout(QWidget* parent, const std::vector<QVector<QString>>& layout) : QWidget(parent) {
|
||||
QVBoxLayout* main_layout = new QVBoxLayout(this);
|
||||
main_layout->setMargin(0);
|
||||
main_layout->setSpacing(0);
|
||||
|
||||
QButtonGroup* btn_group = new QButtonGroup(this);
|
||||
QObject::connect(btn_group, SIGNAL(buttonClicked(QAbstractButton*)), parent, SLOT(handleButton(QAbstractButton*)));
|
||||
|
||||
for (const auto &s : layout) {
|
||||
QHBoxLayout *hlayout = new QHBoxLayout;
|
||||
hlayout->setSpacing(0);
|
||||
|
||||
if (main_layout->count() == 1) {
|
||||
hlayout->addSpacing(90);
|
||||
}
|
||||
|
||||
for (const QString &p : s) {
|
||||
KeyButton* btn = new KeyButton(p);
|
||||
if (p == BACKSPACE_KEY) {
|
||||
btn->setAutoRepeat(true);
|
||||
} else if (p == ENTER_KEY) {
|
||||
btn->setStyleSheet(R"(
|
||||
QPushButton {
|
||||
background-color: #465BEA;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #444444;
|
||||
}
|
||||
)");
|
||||
}
|
||||
btn->setFixedHeight(135 + key_spacing_vertical);
|
||||
btn_group->addButton(btn);
|
||||
hlayout->addWidget(btn, KEY_STRETCH.value(p, 1));
|
||||
}
|
||||
|
||||
if (main_layout->count() == 1) {
|
||||
hlayout->addSpacing(90);
|
||||
}
|
||||
|
||||
main_layout->addLayout(hlayout);
|
||||
}
|
||||
|
||||
setStyleSheet(QString(R"(
|
||||
QPushButton {
|
||||
font-size: 75px;
|
||||
margin-left: %1px;
|
||||
margin-right: %1px;
|
||||
margin-top: %2px;
|
||||
margin-bottom: %2px;
|
||||
padding: 0px;
|
||||
border-radius: 10px;
|
||||
color: #dddddd;
|
||||
background-color: #444444;
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background-color: #333333;
|
||||
}
|
||||
)").arg(key_spacing_vertical / 2).arg(key_spacing_horizontal / 2));
|
||||
}
|
||||
|
||||
Keyboard::Keyboard(QWidget *parent) : QFrame(parent) {
|
||||
main_layout = new QStackedLayout(this);
|
||||
main_layout->setMargin(0);
|
||||
|
||||
// lowercase
|
||||
std::vector<QVector<QString>> lowercase = {
|
||||
{"q", "w", "e", "r", "t", "y", "u", "i", "o", "p"},
|
||||
{"a", "s", "d", "f", "g", "h", "j", "k", "l"},
|
||||
{"↑", "z", "x", "c", "v", "b", "n", "m", BACKSPACE_KEY},
|
||||
{"123", " ", ".", ENTER_KEY},
|
||||
};
|
||||
main_layout->addWidget(new KeyboardLayout(this, lowercase));
|
||||
|
||||
// uppercase
|
||||
std::vector<QVector<QString>> uppercase = {
|
||||
{"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"},
|
||||
{"A", "S", "D", "F", "G", "H", "J", "K", "L"},
|
||||
{"↓", "Z", "X", "C", "V", "B", "N", "M", BACKSPACE_KEY},
|
||||
{"123", " ", ".", ENTER_KEY},
|
||||
};
|
||||
main_layout->addWidget(new KeyboardLayout(this, uppercase));
|
||||
|
||||
// numbers + specials
|
||||
std::vector<QVector<QString>> numbers = {
|
||||
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"},
|
||||
{"-", "/", ":", ";", "(", ")", "$", "&&", "@", "\""},
|
||||
{"#+=", ".", ",", "?", "!", "`", BACKSPACE_KEY},
|
||||
{"ABC", " ", ".", ENTER_KEY},
|
||||
};
|
||||
main_layout->addWidget(new KeyboardLayout(this, numbers));
|
||||
|
||||
// extra specials
|
||||
std::vector<QVector<QString>> specials = {
|
||||
{"[", "]", "{", "}", "#", "%", "^", "*", "+", "="},
|
||||
{"_", "\\", "|", "~", "<", ">", "€", "£", "¥", "•"},
|
||||
{"123", ".", ",", "?", "!", "'", BACKSPACE_KEY},
|
||||
{"ABC", " ", ".", ENTER_KEY},
|
||||
};
|
||||
main_layout->addWidget(new KeyboardLayout(this, specials));
|
||||
|
||||
main_layout->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void Keyboard::handleButton(QAbstractButton* btn) {
|
||||
const QString &key = btn->text();
|
||||
if (CONTROL_BUTTONS.contains(key)) {
|
||||
if (key == "↓" || key == "ABC") {
|
||||
main_layout->setCurrentIndex(0);
|
||||
} else if (key == "↑") {
|
||||
main_layout->setCurrentIndex(1);
|
||||
} else if (key == "123") {
|
||||
main_layout->setCurrentIndex(2);
|
||||
} else if (key == "#+=") {
|
||||
main_layout->setCurrentIndex(3);
|
||||
} else if (key == ENTER_KEY) {
|
||||
main_layout->setCurrentIndex(0);
|
||||
emit emitEnter();
|
||||
} else if (key == BACKSPACE_KEY) {
|
||||
emit emitBackspace();
|
||||
}
|
||||
} else {
|
||||
if ("A" <= key && key <= "Z") {
|
||||
main_layout->setCurrentIndex(0);
|
||||
}
|
||||
emit emitKey(key);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user