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")
437 for (
const auto & comp :
comps)
447 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
467 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
508 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
519 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
555 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_newlineKey.key(),
572 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_upKey.key(),
573 m_upKey.keyboardModifiers(),
"");
579 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_leftKey.key(),
593 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_downKey.key(),
600 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_rightKey.key(),
611 while (c.length() > 0)
613 if (c.startsWith(
"0x"))
615 QString sCode = c.left(6);
617 short nCode = sCode.toShort(&bOK, 16);
628 LOG(VB_GENERAL, LOG_ERR, QString(
"bad char code (%1)")
659#
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
660 KeyEventDefinition *keyDef,
662 QKeyCombination *keyDef,
667 QStringList keys = keylist.split(
',', Qt::SkipEmptyParts);
671 QKeySequence a(keys[0]);
674 LOG(VB_GENERAL, LOG_ERR,
675 QString(
"loadEventKeyDefinitions bad key (%1)").arg(keys[0]));
679#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
680 keyDef->keyCode = a[0];
682 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
683 QStringList parts = keys[0].split(
'+');
684 for (
int j = 0; j < parts.count(); j++)
686 if (parts[j].toUpper() ==
"CTRL")
687 modifiers |= Qt::ControlModifier;
688 if (parts[j].toUpper() ==
"SHIFT")
689 modifiers |= Qt::ShiftModifier;
690 if (parts[j].toUpper() ==
"ALT")
691 modifiers |= Qt::AltModifier;
692 if (parts[j].toUpper() ==
"META")
693 modifiers |= Qt::MetaModifier;
696 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