#include "virtual_keyboard.h" #include "ui_virtual_keyboard.h" #include "virtual_keyboard_layout.h" #include "virtual_keyboard_layout_page.h" #include #include #include #include #include #include #include #include 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); }); hide(); } 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); }