11 #include <QDomDocument>
26 #define LOC QString("MythUIVirtualKeyboard: ")
28 static 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}
113 parentScreen = qobject_cast<MythUIType *>(
m_parentEdit->parent());
117 editArea.y() + parentScreen->
GetArea().y()));
123 if (editArea.y() - area.height() - 5 > 0)
125 newPos = QPoint(editArea.x() + editArea.width() / 2 - area.width() / 2,
126 editArea.y() - area.height() - 5);
130 newPos = QPoint(editArea.x() + editArea.width() / 2 - area.width() / 2,
131 editArea.y() + editArea.height() + 5);
136 newPos = QPoint(screensize.width() / 2 - area.width() / 2, 5);
140 newPos = QPoint(screensize.width() / 2 - area.width() / 2, screensize.height() - 5 - area.height());
144 newPos = QPoint(screensize.width() / 2 - area.width() / 2, screensize.height() / 2 - area.height() / 2);
149 if (editArea.y() + editArea.height() + area.height() + 5 < screensize.height())
151 newPos = QPoint(editArea.x() + editArea.width() / 2 - area.width() / 2,
152 editArea.y() + editArea.height() + 5);
156 newPos = QPoint(editArea.x() + editArea.width() / 2 - area.width() / 2,
157 editArea.y() - area.height() - 5);
165 if (newPos.x() + area.width() + 5 > screensize.width())
166 newPos.
setX(screensize.width() - area.width() - 5);
169 if (newPos.y() + area.height() + 5 > screensize.width())
170 newPos.
setY(screensize.width() - area.height() - 5);
179 QString language = lang.toLower();
181 QString defFile = QString(
"keyboard/%1.xml").arg(language);
183 if (!
GetMythUI()->FindThemeFile(defFile))
185 LOG(VB_GENERAL, LOG_ERR,
186 "No keyboard definition file found for: " + language);
189 defFile =
"keyboard/en_us.xml";
190 if (!
GetMythUI()->FindThemeFile(defFile))
192 LOG(VB_GENERAL, LOG_ERR,
193 "Cannot find definitions file: " + defFile);
198 LOG(VB_GENERAL, LOG_NOTICE,
"Loading definitions from: " + defFile);
200 QDomDocument doc(
"keydefinitions");
202 if (!
file.open(QIODevice::ReadOnly))
204 LOG(VB_GENERAL, LOG_ERR,
"Failed to open definitions file: " + defFile);
207 if (!doc.setContent(&
file))
209 LOG(VB_GENERAL, LOG_ERR,
210 "Failed to parse definitions file: " + defFile);
216 QDomElement docElem = doc.documentElement();
217 QDomNode n = docElem.firstChild();
220 QDomElement e = n.toElement();
223 if (e.tagName() ==
"key")
241 QString name = element.attribute(
"name");
242 QString
type = element.attribute(
"type");
244 QDomNode n = element.firstChild();
247 QDomElement e = n.toElement();
250 if (e.tagName() ==
"move")
252 left = e.attribute(
"left");
253 right = e.attribute(
"right");
254 up = e.attribute(
"up");
255 down = e.attribute(
"down");
257 else if (e.tagName() ==
"char")
259 normal = e.attribute(
"normal");
260 shift = e.attribute(
"shift");
261 alt = e.attribute(
"alt");
262 altshift = e.attribute(
"altshift");
265 LOG(VB_GENERAL, LOG_ERR,
"Unknown element in key definition");
288 for (
auto *child : qAsConst(*children))
293 if (
m_keyMap.contains(button->objectName()))
300 if (key.
type ==
"shift")
310 else if (key.
type ==
"char")
312 else if (key.
type ==
"done")
314 else if (key.
type ==
"del")
316 else if (key.
type ==
"lock")
322 else if (key.
type ==
"alt")
328 else if (key.
type ==
"comp")
334 else if (key.
type ==
"moveleft")
336 else if (key.
type ==
"moveright")
338 else if (key.
type ==
"back")
344 LOG(VB_GENERAL, LOG_WARNING,
345 QString(
"WARNING - Key '%1' not found in map")
346 .arg(button->objectName()));
354 bool handled =
false;
361 bool keyFound =
false;
372 for (
int i = 0; i < actions.size() && !handled; i++)
374 QString
action = actions[i];
382 else if (
action ==
"DOWN")
387 else if (
action ==
"LEFT")
392 else if (
action ==
"RIGHT")
422 for (
const auto & comp :
comps)
432 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
452 auto *
event =
new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, c);
493 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
504 auto *
event =
new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier,
"");
540 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_newlineKey.key(),
555 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_upKey.key(),
556 m_upKey.keyboardModifiers(),
"");
562 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_leftKey.key(),
576 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_downKey.key(),
583 auto *
event =
new QKeyEvent(QEvent::KeyPress,
m_rightKey.key(),
594 while (c.length() > 0)
596 if (c.startsWith(
"0x"))
598 QString sCode = c.left(6);
600 short nCode = sCode.toShort(&bOK, 16);
610 LOG(VB_GENERAL, LOG_ERR, QString(
"bad char code (%1)")
640 #
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
641 KeyEventDefinition *keyDef,
643 QKeyCombination *keyDef,
648 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
649 QStringList keys = keylist.split(
',', QString::SkipEmptyParts);
651 QStringList keys = keylist.split(
',', Qt::SkipEmptyParts);
656 QKeySequence a(keys[0]);
659 LOG(VB_GENERAL, LOG_ERR,
660 QString(
"loadEventKeyDefinitions bad key (%1)").arg(keys[0]));
664 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
665 keyDef->keyCode = a[0];
667 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
668 QStringList parts = keys[0].split(
'+');
669 for (
int j = 0; j < parts.count(); j++)
671 if (parts[j].toUpper() ==
"CTRL")
672 modifiers |= Qt::ControlModifier;
673 if (parts[j].toUpper() ==
"SHIFT")
674 modifiers |= Qt::ShiftModifier;
675 if (parts[j].toUpper() ==
"ALT")
676 modifiers |= Qt::AltModifier;
677 if (parts[j].toUpper() ==
"META")
678 modifiers |= Qt::MetaModifier;
681 keyDef->modifiers = modifiers;