11#include <QDomDocument>
26#define LOC QString("MythUIVirtualKeyboard: ")
28static const std::array<std::array<QString,3>,95>
comps {{
29 {
"!",
"!", (QChar)0xa1}, {
"c",
"/", (QChar)0xa2},
30 {
"l",
"-", (QChar)0xa3}, {
"o",
"x", (QChar)0xa4},
31 {
"y",
"-", (QChar)0xa5}, {
"|",
"|", (QChar)0xa6},
32 {
"s",
"o", (QChar)0xa7}, {
"\"",
"\"", (QChar)0xa8},
33 {
"c",
"o", (QChar)0xa9}, {
"-",
"a", (QChar)0xaa},
34 {
"<",
"<", (QChar)0xab}, {
"-",
"|", (QChar)0xac},
35 {
"-",
"-", (QChar)0xad}, {
"r",
"o", (QChar)0xae},
36 {
"^",
"-", (QChar)0xaf}, {
"^",
"0", (QChar)0xb0},
37 {
"+",
"-", (QChar)0xb1}, {
"^",
"2", (QChar)0xb2},
38 {
"^",
"3", (QChar)0xb3}, {
"/",
"/", (QChar)0xb4},
39 {
"/",
"u", (QChar)0xb5}, {
"P",
"!", (QChar)0xb6},
40 {
"^",
".", (QChar)0xb7}, {
",",
",", (QChar)0xb8},
41 {
"^",
"1", (QChar)0xb9}, {
"_",
"o", (QChar)0xba},
42 {
">",
">", (QChar)0xbb}, {
"1",
"4", (QChar)0xbc},
43 {
"1",
"2", (QChar)0xbd}, {
"3",
"4", (QChar)0xbe},
44 {
"?",
"?", (QChar)0xbf}, {
"A",
"`", (QChar)0xc0},
45 {
"A",
"'", (QChar)0xc1}, {
"A",
"^", (QChar)0xc2},
46 {
"A",
"~", (QChar)0xc3}, {
"A",
"\"", (QChar)0xc4},
47 {
"A",
"*", (QChar)0xc5}, {
"A",
"E", (QChar)0xc6},
48 {
"C",
",", (QChar)0xc7}, {
"E",
"`", (QChar)0xc8},
49 {
"E",
"'", (QChar)0xc9}, {
"E",
"^", (QChar)0xca},
50 {
"E",
"\"", (QChar)0xcb}, {
"I",
"`", (QChar)0xcc},
51 {
"I",
"'", (QChar)0xcd}, {
"I",
"^", (QChar)0xce},
52 {
"I",
"\"", (QChar)0xcf}, {
"D",
"-", (QChar)0xd0},
53 {
"N",
"~", (QChar)0xd1}, {
"O",
"`", (QChar)0xd2},
54 {
"O",
"'", (QChar)0xd3}, {
"O",
"^", (QChar)0xd4},
55 {
"O",
"~", (QChar)0xd5}, {
"O",
"\"", (QChar)0xd6},
56 {
"x",
"x", (QChar)0xd7}, {
"O",
"/", (QChar)0xd8},
57 {
"U",
"`", (QChar)0xd9}, {
"U",
"'", (QChar)0xda},
58 {
"U",
"^", (QChar)0xdb}, {
"U",
"\"", (QChar)0xdc},
59 {
"Y",
"'", (QChar)0xdd}, {
"T",
"H", (QChar)0xde},
60 {
"s",
"s", (QChar)0xdf}, {
"a",
"`", (QChar)0xe0},
61 {
"a",
"'", (QChar)0xe1}, {
"a",
"^", (QChar)0xe2},
62 {
"a",
"~", (QChar)0xe3}, {
"a",
"\"", (QChar)0xe4},
63 {
"a",
"*", (QChar)0xe5}, {
"a",
"e", (QChar)0xe6},
64 {
"c",
",", (QChar)0xe7}, {
"e",
"`", (QChar)0xe8},
65 {
"e",
"'", (QChar)0xe9}, {
"e",
"^", (QChar)0xea},
66 {
"e",
"\"", (QChar)0xeb}, {
"i",
"`", (QChar)0xec},
67 {
"i",
"'", (QChar)0xed}, {
"i",
"^", (QChar)0xee},
68 {
"i",
"\"", (QChar)0xef}, {
"d",
"-", (QChar)0xf0},
69 {
"n",
"~", (QChar)0xf1}, {
"o",
"`", (QChar)0xf2},
70 {
"o",
"'", (QChar)0xf3}, {
"o",
"^", (QChar)0xf4},
71 {
"o",
"~", (QChar)0xf5}, {
"o",
"\"", (QChar)0xf6},
72 {
"-",
":", (QChar)0xf7}, {
"o",
"/", (QChar)0xf8},
73 {
"u",
"`", (QChar)0xf9}, {
"u",
"'", (QChar)0xfa},
74 {
"u",
"^", (QChar)0xfb}, {
"u",
"\"", (QChar)0xfc},
75 {
"y",
"'", (QChar)0xfd}, {
"t",
"h", (QChar)0xfe},
76 {
"y",
"\"", (QChar)0xff}
81 m_parentEdit(parentEdit)
112 parentScreen = qobject_cast<MythUIType *>(
m_parentEdit->parent());
116 editArea.y() + parentScreen->
GetArea().y()));
122 if (editArea.y() - area.height() - 5 > 0)
124 newPos = QPoint(editArea.x() + (editArea.width() / 2) - (area.width() / 2),
125 editArea.y() - area.height() - 5);
129 newPos = QPoint(editArea.x() + (editArea.width() / 2) - (area.width() / 2),
130 editArea.y() + editArea.height() + 5);
135 newPos = QPoint((screensize.width() / 2) - (area.width() / 2), 5);
139 newPos = QPoint((screensize.width() / 2) - (area.width() / 2), screensize.height() - 5 - area.height());
143 newPos = QPoint((screensize.width() / 2) - (area.width() / 2), (screensize.height() / 2) - (area.height() / 2));
148 if (editArea.y() + editArea.height() + area.height() + 5 < screensize.height())
150 newPos = QPoint(editArea.x() + (editArea.width() / 2) - (area.width() / 2),
151 editArea.y() + editArea.height() + 5);
155 newPos = QPoint(editArea.x() + (editArea.width() / 2) - (area.width() / 2),
156 editArea.y() - area.height() - 5);
164 if (newPos.x() + area.width() + 5 > screensize.width())
165 newPos.
setX(screensize.width() - area.width() - 5);
168 if (newPos.y() + area.height() + 5 > screensize.width())
169 newPos.
setY(screensize.width() - area.height() - 5);
178 QString language = lang.toLower();
180 QString defFile = QString(
"keyboard/%1.xml").arg(language);
182 if (!
GetMythUI()->FindThemeFile(defFile))
184 LOG(VB_GENERAL, LOG_ERR,
185 "No keyboard definition file found for: " + language);
188 defFile =
"keyboard/en_us.xml";
189 if (!
GetMythUI()->FindThemeFile(defFile))
191 LOG(VB_GENERAL, LOG_ERR,
192 "Cannot find definitions file: " + defFile);
197 LOG(VB_GENERAL, LOG_NOTICE,
"Loading definitions from: " + defFile);
199 QDomDocument doc(
"keydefinitions");
201 if (!
file.open(QIODevice::ReadOnly))
203 LOG(VB_GENERAL, LOG_ERR,
"Failed to open definitions file: " + defFile);
206 if (!doc.setContent(&
file))
208 LOG(VB_GENERAL, LOG_ERR,
209 "Failed to parse definitions file: " + defFile);
215 QDomElement docElem = doc.documentElement();
216 QDomNode n = docElem.firstChild();
219 QDomElement e = n.toElement();
222 if (e.tagName() ==
"key")
240 QString name = element.attribute(
"name");
241 QString
type = element.attribute(
"type");
243 QDomNode n = element.firstChild();
246 QDomElement e = n.toElement();
249 if (e.tagName() ==
"move")
251 left = e.attribute(
"left");
252 right = e.attribute(
"right");
253 up = e.attribute(
"up");
254 down = e.attribute(
"down");
256 else if (e.tagName() ==
"char")
258 normal = e.attribute(
"normal");
259 shift = e.attribute(
"shift");
260 alt = e.attribute(
"alt");
261 altshift = e.attribute(
"altshift");
265 LOG(VB_GENERAL, LOG_ERR,
"Unknown element in key definition");
289 for (
auto *child : std::as_const(*children))
294 if (
m_keyMap.contains(button->objectName()))
301 if (key.
type ==
"shift")
311 else if (key.
type ==
"char")
315 else if (key.
type ==
"done")
319 else if (key.
type ==
"del")
323 else if (key.
type ==
"lock")
329 else if (key.
type ==
"alt")
335 else if (key.
type ==
"comp")
341 else if (key.
type ==
"moveleft")
345 else if (key.
type ==
"moveright")
349 else if (key.
type ==
"back")
357 LOG(VB_GENERAL, LOG_WARNING,
358 QString(
"WARNING - Key '%1' not found in map")
359 .arg(button->objectName()));
367 bool handled =
false;
374 bool keyFound =
false;
385 for (
int i = 0; i < actions.size() && !handled; i++)
387 const QString&
action = actions[i];
395 else if (
action ==
"DOWN")
400 else if (
action ==
"LEFT")
405 else if (
action ==
"RIGHT")
439 for (
const auto & comp :
comps)
449 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
469 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
510 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
521 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
557 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_newlineKey.key(),
574 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_upKey.key(),
575 m_upKey.keyboardModifiers(),
"");
581 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_leftKey.key(),
595 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_downKey.key(),
602 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_rightKey.key(),
613 while (c.length() > 0)
615 if (c.startsWith(
"0x"))
617 QString sCode = c.left(6);
619 short nCode = sCode.toShort(&bOK, 16);
630 LOG(VB_GENERAL, LOG_ERR, QString(
"bad char code (%1)")
661#
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
662 KeyEventDefinition *keyDef,
664 QKeyCombination *keyDef,
669 QStringList keys = keylist.split(
',', Qt::SkipEmptyParts);
673 QKeySequence a(keys[0]);
676 LOG(VB_GENERAL, LOG_ERR,
677 QString(
"loadEventKeyDefinitions bad key (%1)").arg(keys[0]));
681#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
682 keyDef->keyCode = a[0];
684 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
685 QStringList parts = keys[0].split(
'+');
686 for (
int j = 0; j < parts.count(); j++)
688 if (parts[j].toUpper() ==
"CTRL")
689 modifiers |= Qt::ControlModifier;
690 if (parts[j].toUpper() ==
"SHIFT")
691 modifiers |= Qt::ShiftModifier;
692 if (parts[j].toUpper() ==
"ALT")
693 modifiers |= Qt::AltModifier;
694 if (parts[j].toUpper() ==
"META")
695 modifiers |= Qt::MetaModifier;
698 keyDef->modifiers = modifiers;
QString GetLanguageAndVariant(void)
Returns the user-set language and variant.
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
static QString GetKey(const QString &Context, const QString &Action)
Wrapper around QPoint allowing us to handle percentage and other relative values for positioning in m...
void setY(const QString &sY)
void setX(const QString &sX)
Wrapper around QRect allowing us to handle percentage and other relative values for areas in mythui.
void moveTopLeft(QPoint point)
Screen in which all other widgets are contained and rendered.
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
A text entry and edit widget.
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
PopupPosition GetKeyboardPosition(void)
The base class on which all widgets and screens are based.
QList< MythUIType * > * GetAllChildren(void)
Return a list of all child widgets.
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
void SetPosition(int x, int y)
Convenience method, calls SetPosition(const MythPoint&) Override that instead to change functionality...
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
void keyPressed(QString key)
void updateKeys(bool connectSignals=false)
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
bool Create(void) override
QString getKeyText(const KeyDefinition &key) const
void moverightClicked(void)
static void loadEventKeyDefinitions(QKeyCombination *keyDef, const QString &action)
MythUIButton * m_lockButton
QMap< QString, KeyDefinition > m_keyMap
MythUIButton * m_shiftRButton
QKeyCombination m_leftKey
MythUITextEdit * m_parentEdit
MythUIButton * m_compButton
void parseKey(const QDomElement &element)
static QString decodeChar(QString c)
QKeyCombination m_downKey
PopupPosition m_preferredPos
QKeyCombination m_newlineKey
MythUIButton * m_shiftLButton
MythUIButton * m_altButton
void moveleftClicked(void)
MythUIVirtualKeyboard(MythScreenStack *parentStack, MythUITextEdit *m_parentEdit)
void loadKeyDefinitions(const QString &lang)
QKeyCombination m_rightKey
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
MythUIHelper * GetMythUI()
static const std::array< std::array< QString, 3 >, 95 > comps