add QAD::VirtualKeyboard library, vkbd for widgets with JSON-based description
This commit is contained in:
166
libs/virtual_keyboard/virtual_keyboard.cpp
Normal file
166
libs/virtual_keyboard/virtual_keyboard.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "virtual_keyboard.h"
|
||||
|
||||
#include "ui_virtual_keyboard.h"
|
||||
#include "virtual_keyboard_layout.h"
|
||||
#include "virtual_keyboard_layout_page.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStyle>
|
||||
#include <QStyleFactory>
|
||||
#include <pibase.h>
|
||||
#include <picout.h>
|
||||
#include <piliterals_time.h>
|
||||
|
||||
|
||||
VirtualKeyboard::VirtualKeyboard(QWidget * parent): QWidget(parent) {
|
||||
ui = new Ui::VirtualKeyboard();
|
||||
ui->setupUi(this);
|
||||
ui->stackedPages->setStyle(QStyleFactory::create("Fusion"));
|
||||
connect(qApp, &QApplication::focusChanged, this, [this](QWidget * old, QWidget * now) {
|
||||
if (watched) {
|
||||
watched->removeEventFilter(this);
|
||||
watched = nullptr;
|
||||
}
|
||||
if (!now || !layout) {
|
||||
setKeyboardVisible(false);
|
||||
return;
|
||||
}
|
||||
if (!now->inputMethodQuery(Qt::ImCursorPosition).isValid()) {
|
||||
setKeyboardVisible(false);
|
||||
return;
|
||||
}
|
||||
watched = now;
|
||||
auto imh = Qt::InputMethodHints(watched->inputMethodQuery(Qt::ImHints).toInt());
|
||||
layout->setDefaultPage();
|
||||
setKeyboardVisible(true);
|
||||
layout->applyHints(imh);
|
||||
watched->installEventFilter(this);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboard::~VirtualKeyboard() {
|
||||
if (watched) {
|
||||
watched->removeEventFilter(this);
|
||||
watched = nullptr;
|
||||
}
|
||||
destroy();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::init(QString layout_path) {
|
||||
destroy();
|
||||
QFile f(layout_path);
|
||||
if (!f.open(QIODevice::ReadOnly)) return;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(f.readAll());
|
||||
layout = new VirtualKeyboardLayout(doc.object());
|
||||
auto pages = layout->getPages();
|
||||
for (auto p: pages)
|
||||
ui->stackedPages->addWidget(p);
|
||||
connect(layout, &VirtualKeyboardLayout::gotoPageRequest, this, [this](QString pagename) {
|
||||
auto page = layout->getPageByName(pagename);
|
||||
if (!page) return;
|
||||
ui->stackedPages->setCurrentWidget(page);
|
||||
layout->setCurrentPage(page);
|
||||
});
|
||||
connect(layout, &VirtualKeyboardLayout::hideRequest, this, [this]() { setKeyboardVisible(false); });
|
||||
layout->setDefaultPage();
|
||||
// piCout << pages.size();
|
||||
adjust();
|
||||
}
|
||||
|
||||
|
||||
bool VirtualKeyboard::eventFilter(QObject * o, QEvent * e) {
|
||||
if (e->type() == QEvent::MouseButtonPress) setKeyboardVisible(true);
|
||||
return QWidget::eventFilter(o, e);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::changeEvent(QEvent * e) {
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange: ui->retranslateUi(this); break;
|
||||
case QEvent::Show: ui->retranslateUi(this); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::resizeEvent(QResizeEvent * e) {
|
||||
if (prev_width == width()) return;
|
||||
prev_width = width();
|
||||
adjust();
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::showEvent(QShowEvent * e) {
|
||||
if (first_show) {
|
||||
first_show = false;
|
||||
if (layout_path_.isEmpty()) init(":/virtual_keyboard/default.json");
|
||||
}
|
||||
QWidget::showEvent(e);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::destroy() {
|
||||
piDeleteSafety(layout);
|
||||
while (ui->stackedPages->count() > 0)
|
||||
delete ui->stackedPages->widget(0);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::adjust() {
|
||||
if (!layout) return;
|
||||
auto pages = layout->getPages();
|
||||
int cols = 0;
|
||||
for (auto p: pages)
|
||||
cols = piMaxi(cols, p->buttonColumns());
|
||||
if (cols < 1) return;
|
||||
int spacing = style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing, nullptr, this);
|
||||
int pixel_width = width() - spacing * (cols - 1) - ui->verticalLayout->margin() * 2;
|
||||
int bw = piMaxi(2, pixel_width / cols);
|
||||
ui->stackedPages->setStyleSheet(QString("font:%1px").arg(bw / 2));
|
||||
for (auto p: pages)
|
||||
p->setButtonsSize(bw);
|
||||
// piCout << cols << spacing << bw;
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::setKeyboardVisible(bool yes) {
|
||||
if (always_visible || !isEnabled()) return;
|
||||
if (yes) {
|
||||
stopIndexedTimer(0);
|
||||
setVisible(true);
|
||||
} else startIndexedTimer(0, 10_Hz, [this]{
|
||||
if (QApplication::mouseButtons() != 0) return;
|
||||
stopIndexedTimer(0);
|
||||
setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::setLayoutPath(const QString & path) {
|
||||
layout_path_ = path;
|
||||
init(layout_path_);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::setAlwaysVisible(bool yes) {
|
||||
always_visible = yes;
|
||||
if (yes) show();
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::setEnabled(bool yes) {
|
||||
if (!yes) hide();
|
||||
QWidget::setEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboard::setDisabled(bool yes) {
|
||||
if (yes) hide();
|
||||
QWidget::setDisabled(yes);
|
||||
}
|
||||
Reference in New Issue
Block a user