add QAD::VirtualKeyboard library, vkbd for widgets with JSON-based description
This commit is contained in:
154
libs/virtual_keyboard/virtual_keyboard_layout_page.cpp
Normal file
154
libs/virtual_keyboard/virtual_keyboard_layout_page.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "virtual_keyboard_layout_page.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBoxLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QKeyEvent>
|
||||
#include <QTimer>
|
||||
|
||||
static const char property_role[] = "role";
|
||||
static const char property_page[] = "page";
|
||||
static const char property_stretch[] = "stretch";
|
||||
|
||||
|
||||
VirtualKeyboardLayoutPage::VirtualKeyboardLayoutPage(QJsonObject root) {
|
||||
auto main_lay = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
name_ = root["name"].toString();
|
||||
auto rows = root["rows"].toArray();
|
||||
for (auto row: rows) {
|
||||
auto rowa = row.toArray();
|
||||
QBoxLayout * row_lay = nullptr;
|
||||
int cur_cols = 0;
|
||||
for (auto rb: rowa) {
|
||||
auto * b = createButton(rb.toObject());
|
||||
if (!b) continue;
|
||||
if (!row_lay) row_lay = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||
buttons << b;
|
||||
row_lay->addWidget(b, b->property(property_stretch).toInt());
|
||||
++cur_cols;
|
||||
}
|
||||
if (row_lay) main_lay->addLayout(row_lay);
|
||||
columns = piMaxi(columns, cur_cols);
|
||||
}
|
||||
// qDebug() << "VirtualKeyboardLayoutPage" << name;
|
||||
setLayout(main_lay);
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboardLayoutPage::~VirtualKeyboardLayoutPage() {}
|
||||
|
||||
|
||||
void VirtualKeyboardLayoutPage::setCapital(bool yes) {
|
||||
capital = yes;
|
||||
for (auto b: buttons) {
|
||||
auto role = buttonRole(b);
|
||||
if (role == rLetter) {
|
||||
b->setText(yes ? b->text().toUpper() : b->text().toLower());
|
||||
}
|
||||
if (role == rShift) {
|
||||
// b->setText(yes ? QString::fromUtf8("⇫") : QString::fromUtf8("⇧"));
|
||||
b->setChecked(yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayoutPage::setGotoEnabled(bool yes) {
|
||||
for (auto b: buttons) {
|
||||
auto role = buttonRole(b);
|
||||
if (role == rGotoPage) b->setEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayoutPage::setCapitalEnabled(bool yes) {
|
||||
capital_enabled = yes;
|
||||
for (auto b: buttons) {
|
||||
auto role = buttonRole(b);
|
||||
if (role == rShift) b->setEnabled(yes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayoutPage::setButtonsSize(int h) {
|
||||
for (auto b: buttons) {
|
||||
b->setFixedHeight(h);
|
||||
}
|
||||
if (!isVisible()) {
|
||||
adjustSize();
|
||||
layout()->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QToolButton * VirtualKeyboardLayoutPage::createButton(QJsonObject jb) {
|
||||
QString role_str = jb["role"].toString();
|
||||
if (role_str.isEmpty()) return nullptr;
|
||||
auto ret = new QToolButton();
|
||||
int role = roleFromText(role_str);
|
||||
int stretch = jb["stretch"].toInt();
|
||||
if (stretch == 0) stretch = 1;
|
||||
auto text = jb["text"].toString();
|
||||
ret->setProperty(property_role, role);
|
||||
ret->setProperty(property_stretch, stretch);
|
||||
ret->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
ret->setFocusPolicy(Qt::NoFocus);
|
||||
ret->setMinimumSize(QSize(2, 2));
|
||||
ret->setAutoRepeat(true);
|
||||
switch (role) {
|
||||
case rBackspace: text = QString::fromUtf8("⌫"); break;
|
||||
case rReturn: text = QString::fromUtf8("⏎"); break;
|
||||
case rSpace: text = QString::fromUtf8("────"); break;
|
||||
case rShift:
|
||||
text = QString::fromUtf8("⤊");
|
||||
ret->setCheckable(true);
|
||||
break; // ⇪⇧⇫⇯⇩⬆⌨
|
||||
case rHide: text = QString::fromUtf8("⨂"); break;
|
||||
case rGotoPage: ret->setProperty(property_page, jb["page"].toString()); break;
|
||||
}
|
||||
ret->setText(text);
|
||||
connect(ret, &QToolButton::clicked, this, [this, role, ret](bool press) {
|
||||
int key = 0;
|
||||
QString text;
|
||||
switch (role) {
|
||||
case rLetter:
|
||||
text = ret->text();
|
||||
if (text.startsWith('&')) text.remove(0, 1);
|
||||
break;
|
||||
case rBackspace: key = Qt::Key_Backspace; break;
|
||||
case rReturn: key = Qt::Key_Return; break;
|
||||
case rSpace:
|
||||
key = Qt::Key_Space;
|
||||
text = " ";
|
||||
break;
|
||||
case rHide: emit hideRequest(); break;
|
||||
case rShift: setCapital(!isCapital()); break;
|
||||
case rGotoPage: emit gotoPageRequest(ret->property(property_page).toString()); break;
|
||||
}
|
||||
if (key == 0 && text.isEmpty()) return;
|
||||
QApplication::postEvent(QApplication::focusWidget(), new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier, text));
|
||||
QApplication::postEvent(QApplication::focusWidget(), new QKeyEvent(QEvent::KeyRelease, key, Qt::NoModifier, text));
|
||||
if (role == rLetter && isCapital() && capital_enabled) setCapital(false);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboardLayoutPage::Role VirtualKeyboardLayoutPage::roleFromText(QString str) {
|
||||
str = str.toLower();
|
||||
if (str == "l") return rLetter;
|
||||
if (str == "backspace") return rBackspace;
|
||||
if (str == "return") return rReturn;
|
||||
if (str == "space") return rSpace;
|
||||
if (str == "hide") return rHide;
|
||||
if (str == "shift") return rShift;
|
||||
if (str == "gotopage") return rGotoPage;
|
||||
return rInvalid;
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboardLayoutPage::Role VirtualKeyboardLayoutPage::buttonRole(QToolButton * b) const {
|
||||
if (!b) return rInvalid;
|
||||
return static_cast<Role>(b->property(property_role).toInt());
|
||||
}
|
||||
Reference in New Issue
Block a user