Files
qad/libs/virtual_keyboard/virtual_keyboard.cpp

167 lines
4.0 KiB
C++

#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);
}