dragonpilot - 基於 openpilot 的開源駕駛輔助系統
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.

163 lines
4.9 KiB

#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();
if (mouseType == QEvent::MouseButtonRelease) {
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("background-color: #465BEA;");
}
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);
}
}