add QAD::VirtualKeyboard library, vkbd for widgets with JSON-based description
This commit is contained in:
@@ -3,8 +3,8 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
||||
cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default
|
||||
project(QAD)
|
||||
set(QAD_MAJOR 2)
|
||||
set(QAD_MINOR 28)
|
||||
set(QAD_REVISION 1)
|
||||
set(QAD_MINOR 29)
|
||||
set(QAD_REVISION 0)
|
||||
set(QAD_SUFFIX )
|
||||
set(QAD_COMPANY SHS)
|
||||
set(QAD_DOMAIN org.SHS)
|
||||
|
||||
@@ -11,6 +11,7 @@ Create imported targets:
|
||||
* QAD::SQLTable
|
||||
* QAD::TouchWidgets
|
||||
* QAD::Doc
|
||||
* QAD::VirtualKeyboard
|
||||
* QAD::PIQt
|
||||
* QAD::PIQtUtils
|
||||
|
||||
@@ -46,7 +47,7 @@ if(QAD_FIND_VERSION VERSION_GREATER QAD_VERSION)
|
||||
message(FATAL_ERROR "QAD version ${QAD_VERSION} is available, but ${QAD_FIND_VERSION} requested!")
|
||||
endif()
|
||||
|
||||
set(__libs "utils;widgets;application;blockview;graphic;graphic_analysis;graphic3d;sql;sql_table;touch_widgets;doc;map")
|
||||
set(__libs "utils;widgets;application;blockview;graphic;graphic_analysis;graphic3d;sql;sql_table;touch_widgets;doc;map;virtual_keyboard")
|
||||
if (PIP_FOUND OR BUILDING_PIP)
|
||||
list(APPEND __libs "piqt;piqt_utils")
|
||||
endif()
|
||||
@@ -65,6 +66,7 @@ set(__module_doc Doc )
|
||||
set(__module_map Map )
|
||||
set(__module_piqt PIQt )
|
||||
set(__module_piqt_utils PIQtUtils )
|
||||
set(__module_virtual_keyboard VirtualKeyboard)
|
||||
|
||||
foreach (_l ${__libs})
|
||||
set( __inc_${_l} "")
|
||||
@@ -82,6 +84,7 @@ set(__deps_sql_table "QAD::Widgets")
|
||||
set(__deps_map "QAD::Utils;QAD::PIQt")
|
||||
set(__deps_piqt "QAD::Widgets;PIP")
|
||||
set(__deps_piqt_utils "QAD::Blockview;QAD::PIQt")
|
||||
set(__deps_virtual_keyboard "QAD::PIQt")
|
||||
|
||||
#message("find QAD ${BUILDING_QAD}")
|
||||
|
||||
|
||||
BIN
icons/virtual_keyboard.png
Normal file
BIN
icons/virtual_keyboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
4
libs/virtual_keyboard/CMakeLists.txt
Normal file
4
libs/virtual_keyboard/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
find_package(PIP)
|
||||
if (PIP_FOUND)
|
||||
qad_library(virtual_keyboard "Gui;Widgets" "qad_piqt")
|
||||
endif()
|
||||
99
libs/virtual_keyboard/default.json
Normal file
99
libs/virtual_keyboard/default.json
Normal file
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"default_page": "latin",
|
||||
"pages": [
|
||||
{
|
||||
"name": "numeric",
|
||||
"rows": [
|
||||
[
|
||||
{"role": "l", "text": "1"},
|
||||
{"role": "l", "text": "2"},
|
||||
{"role": "l", "text": "3"},
|
||||
{"role": "l", "text": "4"},
|
||||
{"role": "l", "text": "5"},
|
||||
{"role": "l", "text": "6"},
|
||||
{"role": "l", "text": "7"},
|
||||
{"role": "l", "text": "8"},
|
||||
{"role": "l", "text": "9"},
|
||||
{"role": "l", "text": "0"},
|
||||
{"role": "backspace"}
|
||||
],
|
||||
[
|
||||
{"role": "l", "text": "@"},
|
||||
{"role": "l", "text": "#"},
|
||||
{"role": "l", "text": "%"},
|
||||
{"role": "l", "text": "&&"},
|
||||
{"role": "l", "text": "*"},
|
||||
{"role": "l", "text": "-"},
|
||||
{"role": "l", "text": "+"},
|
||||
{"role": "l", "text": "("},
|
||||
{"role": "l", "text": ")"},
|
||||
{"role": "return", "stretch": 2}
|
||||
],
|
||||
[
|
||||
{"role": "l", "text": "!"},
|
||||
{"role": "l", "text": "\""},
|
||||
{"role": "l", "text": "<"},
|
||||
{"role": "l", "text": ">"},
|
||||
{"role": "l", "text": "'"},
|
||||
{"role": "l", "text": ":"},
|
||||
{"role": "l", "text": ";"},
|
||||
{"role": "l", "text": "/"},
|
||||
{"role": "l", "text": "?"},
|
||||
{"role": "l", "text": "_"}
|
||||
],
|
||||
[
|
||||
{"role": "gotopage", "text": "en", "page": "latin"},
|
||||
{"role": "space", "stretch": 6},
|
||||
{"role": "hide"}
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "latin",
|
||||
"rows": [
|
||||
[
|
||||
{"role": "l", "text": "q"},
|
||||
{"role": "l", "text": "w"},
|
||||
{"role": "l", "text": "e"},
|
||||
{"role": "l", "text": "r"},
|
||||
{"role": "l", "text": "t"},
|
||||
{"role": "l", "text": "y"},
|
||||
{"role": "l", "text": "u"},
|
||||
{"role": "l", "text": "i"},
|
||||
{"role": "l", "text": "o"},
|
||||
{"role": "l", "text": "p"},
|
||||
{"role": "backspace"}
|
||||
],
|
||||
[
|
||||
{"role": "l", "text": "a"},
|
||||
{"role": "l", "text": "s"},
|
||||
{"role": "l", "text": "d"},
|
||||
{"role": "l", "text": "f"},
|
||||
{"role": "l", "text": "g"},
|
||||
{"role": "l", "text": "h"},
|
||||
{"role": "l", "text": "j"},
|
||||
{"role": "l", "text": "k"},
|
||||
{"role": "l", "text": "l"},
|
||||
{"role": "return", "stretch": 2}
|
||||
],
|
||||
[
|
||||
{"role": "l", "text": "z"},
|
||||
{"role": "l", "text": "x"},
|
||||
{"role": "l", "text": "c"},
|
||||
{"role": "l", "text": "v"},
|
||||
{"role": "l", "text": "b"},
|
||||
{"role": "l", "text": "n"},
|
||||
{"role": "l", "text": "m"},
|
||||
{"role": "shift", "stretch": 2}
|
||||
],
|
||||
[
|
||||
{"role": "gotopage", "text": "123", "page": "numeric"},
|
||||
{"role": "l", "text": ","},
|
||||
{"role": "space", "stretch": 6},
|
||||
{"role": "l", "text": "."},
|
||||
{"role": "hide"}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
1
libs/virtual_keyboard/plugin/CMakeLists.txt
Normal file
1
libs/virtual_keyboard/plugin/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
qad_plugin(virtual_keyboard "Gui;Widgets" "")
|
||||
17
libs/virtual_keyboard/plugin/qad_virtual_keyboard.cpp
Normal file
17
libs/virtual_keyboard/plugin/qad_virtual_keyboard.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "qad_virtual_keyboard.h"
|
||||
|
||||
#include "virtual_keyboard_plugin.h"
|
||||
|
||||
QADVirtualKeyboard::QADVirtualKeyboard(QObject * parent): QObject(parent) {
|
||||
m_widgets << new VirtualKeyboardPlugin(this);
|
||||
}
|
||||
|
||||
|
||||
QList<QDesignerCustomWidgetInterface *> QADVirtualKeyboard::customWidgets() const {
|
||||
return m_widgets;
|
||||
}
|
||||
|
||||
|
||||
#if QT_VERSION < 0x050000
|
||||
Q_EXPORT_PLUGIN2(qad_virtual_keyboard_plugin, QADVirtualKeyboard)
|
||||
#endif
|
||||
24
libs/virtual_keyboard/plugin/qad_virtual_keyboard.h
Normal file
24
libs/virtual_keyboard/plugin/qad_virtual_keyboard.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef qad_virtual_keyboard_h
|
||||
#define qad_virtual_keyboard_h
|
||||
|
||||
#include <QtCore/qplugin.h>
|
||||
#include <QtDesigner/QtDesigner>
|
||||
|
||||
class QADVirtualKeyboard
|
||||
: public QObject
|
||||
, public QDesignerCustomWidgetCollectionInterface {
|
||||
Q_OBJECT
|
||||
#if QT_VERSION >= 0x050000
|
||||
Q_PLUGIN_METADATA(IID "qad.virtual_keyboard")
|
||||
#endif
|
||||
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
|
||||
|
||||
public:
|
||||
explicit QADVirtualKeyboard(QObject * parent = 0);
|
||||
virtual QList<QDesignerCustomWidgetInterface *> customWidgets() const;
|
||||
|
||||
private:
|
||||
QList<QDesignerCustomWidgetInterface *> m_widgets;
|
||||
};
|
||||
|
||||
#endif
|
||||
62
libs/virtual_keyboard/plugin/virtual_keyboard_plugin.cpp
Normal file
62
libs/virtual_keyboard/plugin/virtual_keyboard_plugin.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "virtual_keyboard_plugin.h"
|
||||
|
||||
#include "virtual_keyboard.h"
|
||||
|
||||
#include <QDesignerFormEditorInterface>
|
||||
#include <QDesignerPropertyEditorInterface>
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
|
||||
VirtualKeyboardPlugin::VirtualKeyboardPlugin(QObject * parent): QObject(parent) {
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
void VirtualKeyboardPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
|
||||
if (m_initialized) return;
|
||||
|
||||
// Add extension registrations, etc. here
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
bool VirtualKeyboardPlugin::isInitialized() const {
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
QWidget * VirtualKeyboardPlugin::createWidget(QWidget * parent) {
|
||||
auto ret = new VirtualKeyboard(parent);
|
||||
ret->setAlwaysVisible(true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::name() const {
|
||||
return QLatin1String("VirtualKeyboard");
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::group() const {
|
||||
return QLatin1String("Touch Widgets");
|
||||
}
|
||||
|
||||
QIcon VirtualKeyboardPlugin::icon() const {
|
||||
return QIcon(":/icons/virtual_keyboard.png");
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::toolTip() const {
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::whatsThis() const {
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
bool VirtualKeyboardPlugin::isContainer() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::domXml() const {
|
||||
return QLatin1String("<widget class=\"VirtualKeyboard\" name=\"virtualKeyboard\">\n</widget>\n");
|
||||
}
|
||||
|
||||
QString VirtualKeyboardPlugin::includeFile() const {
|
||||
return QLatin1String("virtual_keyboard.h");
|
||||
}
|
||||
36
libs/virtual_keyboard/plugin/virtual_keyboard_plugin.h
Normal file
36
libs/virtual_keyboard/plugin/virtual_keyboard_plugin.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef virtual_keyboard_plugin_h
|
||||
#define virtual_keyboard_plugin_h
|
||||
|
||||
#include <QObject>
|
||||
#if QT_VERSION >= 0x050000
|
||||
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
|
||||
#else
|
||||
# include <QDesignerCustomWidgetInterface>
|
||||
#endif
|
||||
|
||||
class VirtualKeyboardPlugin
|
||||
: public QObject
|
||||
, public QDesignerCustomWidgetInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QDesignerCustomWidgetInterface)
|
||||
|
||||
public:
|
||||
VirtualKeyboardPlugin(QObject * parent = 0);
|
||||
|
||||
bool isContainer() const;
|
||||
bool isInitialized() const;
|
||||
QIcon icon() const;
|
||||
QString domXml() const;
|
||||
QString group() const;
|
||||
QString includeFile() const;
|
||||
QString name() const;
|
||||
QString toolTip() const;
|
||||
QString whatsThis() const;
|
||||
QWidget * createWidget(QWidget * parent);
|
||||
void initialize(QDesignerFormEditorInterface * core);
|
||||
|
||||
private:
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
54
libs/virtual_keyboard/virtual_keyboard.h
Normal file
54
libs/virtual_keyboard/virtual_keyboard.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef virtual_keyboard_h
|
||||
#define virtual_keyboard_h
|
||||
|
||||
#include "qad_virtual_keyboard_export.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <qad_timers.h>
|
||||
|
||||
namespace Ui {
|
||||
class VirtualKeyboard;
|
||||
};
|
||||
class VirtualKeyboardLayout;
|
||||
|
||||
|
||||
class QAD_VIRTUAL_KEYBOARD_EXPORT VirtualKeyboard: public QWidget, private IndexedTimer<> {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString layoutPath READ layoutPath WRITE setLayoutPath)
|
||||
|
||||
public:
|
||||
VirtualKeyboard(QWidget * parent = nullptr);
|
||||
~VirtualKeyboard();
|
||||
|
||||
const QString & layoutPath() const { return layout_path_; }
|
||||
void setLayoutPath(const QString & path);
|
||||
|
||||
bool isAlwaysVisible() const { return always_visible; }
|
||||
void setAlwaysVisible(bool yes);
|
||||
|
||||
void setEnabled(bool yes);
|
||||
void setDisabled(bool yes);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject * o, QEvent * e) override;
|
||||
void changeEvent(QEvent * e) override;
|
||||
void resizeEvent(QResizeEvent * e) override;
|
||||
void showEvent(QShowEvent * e) override;
|
||||
|
||||
void init(QString layout_path);
|
||||
void destroy();
|
||||
void adjust();
|
||||
void setKeyboardVisible(bool yes);
|
||||
|
||||
private:
|
||||
Ui::VirtualKeyboard * ui = nullptr;
|
||||
VirtualKeyboardLayout * layout = nullptr;
|
||||
QWidget * watched = nullptr;
|
||||
QString layout_path_;
|
||||
bool first_show = true, always_visible = false;
|
||||
int prev_width = -1;
|
||||
|
||||
private slots:
|
||||
};
|
||||
|
||||
#endif
|
||||
8
libs/virtual_keyboard/virtual_keyboard.qrc
Normal file
8
libs/virtual_keyboard/virtual_keyboard.qrc
Normal file
@@ -0,0 +1,8 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>../../icons/virtual_keyboard.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/virtual_keyboard">
|
||||
<file>default.json</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
74
libs/virtual_keyboard/virtual_keyboard.ui
Normal file
74
libs/virtual_keyboard/virtual_keyboard.ui
Normal file
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VirtualKeyboard</class>
|
||||
<widget class="QWidget" name="VirtualKeyboard">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>565</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QWidget{
|
||||
background-color: black;
|
||||
}
|
||||
QToolButton{
|
||||
background-color: rgb(64,64,64);
|
||||
color: white;
|
||||
}
|
||||
QToolButton:pressed{
|
||||
background-color: rgb(48,48,48);
|
||||
}
|
||||
QToolButton:disabled{
|
||||
background-color: rgb(32,32,32);
|
||||
color: rgb(128,128,128);
|
||||
}
|
||||
QToolButton:checked{
|
||||
background-color: rgb(52,52,52);
|
||||
color: rgb(92,192,92);
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedPages">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">font:14pt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
72
libs/virtual_keyboard/virtual_keyboard_layout.cpp
Normal file
72
libs/virtual_keyboard/virtual_keyboard_layout.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "virtual_keyboard_layout.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
VirtualKeyboardLayout::VirtualKeyboardLayout(QJsonObject root) {
|
||||
default_page = root["default_page"].toString();
|
||||
auto pa = root["pages"].toArray();
|
||||
for (auto p: pa) {
|
||||
auto page = new VirtualKeyboardLayoutPage(p.toObject());
|
||||
if (page->isValid()) {
|
||||
connect(page, &VirtualKeyboardLayoutPage::gotoPageRequest, this, &VirtualKeyboardLayout::gotoPageRequest);
|
||||
connect(page, &VirtualKeyboardLayoutPage::hideRequest, this, &VirtualKeyboardLayout::hideRequest);
|
||||
pages << page;
|
||||
} else
|
||||
delete page;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboardLayout::~VirtualKeyboardLayout() {
|
||||
// piDeleteAllAndClear(pages);
|
||||
}
|
||||
|
||||
|
||||
VirtualKeyboardLayoutPage * VirtualKeyboardLayout::getPageByName(QString name) const {
|
||||
for (auto p: pages)
|
||||
if (p->name() == name) return p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::setDefaultPage() {
|
||||
emit gotoPageRequest(default_page);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::setCurrentPage(VirtualKeyboardLayoutPage * p) {
|
||||
current_page = p;
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::applyHints(Qt::InputMethodHints hints) {
|
||||
// qDebug() << hints << current_page;
|
||||
if (hints.testFlag(Qt::ImhPreferNumbers) || hints.testFlag(Qt::ImhDigitsOnly)) gotoPageRequest("numeric");
|
||||
if (hints.testFlag(Qt::ImhPreferLatin) || hints.testFlag(Qt::ImhLatinOnly)) gotoPageRequest("latin");
|
||||
if (hints.testFlag(Qt::ImhPreferLowercase) || hints.testFlag(Qt::ImhLowercaseOnly) || hints.testFlag(Qt::ImhNoAutoUppercase))
|
||||
setCapital(false);
|
||||
else
|
||||
setCapital(true);
|
||||
setGotoEnabled(!hints.testFlag(Qt::ImhDigitsOnly) && !hints.testFlag(Qt::ImhLatinOnly));
|
||||
setCapitalEnabled(!hints.testFlag(Qt::ImhUppercaseOnly) && !hints.testFlag(Qt::ImhLowercaseOnly));
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::setGotoEnabled(bool yes) {
|
||||
for (auto p: pages)
|
||||
p->setGotoEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::setCapitalEnabled(bool yes) {
|
||||
for (auto p: pages)
|
||||
p->setCapitalEnabled(yes);
|
||||
}
|
||||
|
||||
|
||||
void VirtualKeyboardLayout::setCapital(bool yes) {
|
||||
for (auto p: pages)
|
||||
p->setCapital(yes);
|
||||
}
|
||||
39
libs/virtual_keyboard/virtual_keyboard_layout.h
Normal file
39
libs/virtual_keyboard/virtual_keyboard_layout.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef virtual_keyboard_layout_h
|
||||
#define virtual_keyboard_layout_h
|
||||
|
||||
#include <QWidget>
|
||||
#include "virtual_keyboard_layout_page.h"
|
||||
|
||||
|
||||
class VirtualKeyboardLayout: public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VirtualKeyboardLayout(QJsonObject root);
|
||||
~VirtualKeyboardLayout();
|
||||
|
||||
QVector<VirtualKeyboardLayoutPage * > getPages() const {return pages;}
|
||||
VirtualKeyboardLayoutPage * getPageByName(QString name) const;
|
||||
|
||||
void setDefaultPage();
|
||||
void setCurrentPage(VirtualKeyboardLayoutPage * p);
|
||||
void applyHints(Qt::InputMethodHints hints);
|
||||
|
||||
protected:
|
||||
void setGotoEnabled(bool yes);
|
||||
void setCapitalEnabled(bool yes);
|
||||
void setCapital(bool yes);
|
||||
|
||||
QVector<VirtualKeyboardLayoutPage * > pages;
|
||||
VirtualKeyboardLayoutPage * current_page = nullptr;
|
||||
QString default_page;
|
||||
|
||||
private slots:
|
||||
|
||||
signals:
|
||||
void gotoPageRequest(QString);
|
||||
void hideRequest();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
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());
|
||||
}
|
||||
55
libs/virtual_keyboard/virtual_keyboard_layout_page.h
Normal file
55
libs/virtual_keyboard/virtual_keyboard_layout_page.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef virtual_keyboard_layout_page_h
|
||||
#define virtual_keyboard_layout_page_h
|
||||
|
||||
#include <QToolButton>
|
||||
#include <pibase.h>
|
||||
|
||||
|
||||
class VirtualKeyboardLayoutPage: public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VirtualKeyboardLayoutPage(QJsonObject root);
|
||||
~VirtualKeyboardLayoutPage();
|
||||
|
||||
bool isValid() const {return !buttons.isEmpty();}
|
||||
QString name() const {return name_;}
|
||||
|
||||
bool isCapital() const {return capital;}
|
||||
void setCapital(bool yes);
|
||||
void setGotoEnabled(bool yes);
|
||||
void setCapitalEnabled(bool yes);
|
||||
|
||||
int buttonColumns() const {return columns;}
|
||||
void setButtonsSize(int h);
|
||||
|
||||
enum Role {
|
||||
rInvalid,
|
||||
rLetter,
|
||||
rBackspace,
|
||||
rReturn,
|
||||
rSpace,
|
||||
rHide,
|
||||
rShift,
|
||||
rGotoPage,
|
||||
};
|
||||
|
||||
protected:
|
||||
QToolButton * createButton(QJsonObject jb);
|
||||
Role roleFromText(QString str);
|
||||
Role buttonRole(QToolButton * b) const;
|
||||
|
||||
QVector<QToolButton * > buttons;
|
||||
QString name_;
|
||||
int columns = 0;
|
||||
bool capital = false, capital_enabled = true;
|
||||
|
||||
private slots:
|
||||
|
||||
signals:
|
||||
void gotoPageRequest(QString);
|
||||
void hideRequest();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user