1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 or (at your option) any later version |
20 | ** approved by the KDE Free Qt Foundation. The licenses are as published by |
21 | ** the Free Software Foundation and appearing in the file LICENSE.GPL3 |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include "tcinputmethod_p.h" |
31 | #include <QtVirtualKeyboard/qvirtualkeyboardinputengine.h> |
32 | #include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h> |
33 | #if defined(HAVE_TCIME_CANGJIE) |
34 | #include "cangjiedictionary.h" |
35 | #include "cangjietable.h" |
36 | #endif |
37 | #if defined(HAVE_TCIME_ZHUYIN) |
38 | #include "zhuyindictionary.h" |
39 | #include "zhuyintable.h" |
40 | #endif |
41 | #include "phrasedictionary.h" |
42 | #include <QLoggingCategory> |
43 | |
44 | #include <QLibraryInfo> |
45 | #include <QFileInfo> |
46 | |
47 | #include <array> |
48 | |
49 | QT_BEGIN_NAMESPACE |
50 | namespace QtVirtualKeyboard { |
51 | |
52 | Q_LOGGING_CATEGORY(lcTCIme, "qt.virtualkeyboard.tcime" ) |
53 | |
54 | using namespace tcime; |
55 | |
56 | class TCInputMethodPrivate |
57 | { |
58 | Q_DECLARE_PUBLIC(TCInputMethod) |
59 | public: |
60 | |
61 | TCInputMethodPrivate(TCInputMethod *q_ptr) : |
62 | q_ptr(q_ptr), |
63 | inputMode(QVirtualKeyboardInputEngine::InputMode::Latin), |
64 | wordDictionary(nullptr), |
65 | highlightIndex(-1) |
66 | {} |
67 | |
68 | bool setCandidates(const QStringList &values, bool highlightDefault) |
69 | { |
70 | bool candidatesChanged = candidates != values; |
71 | candidates = values; |
72 | highlightIndex = !candidates.isEmpty() && highlightDefault ? 0 : -1; |
73 | return candidatesChanged; |
74 | } |
75 | |
76 | bool clearCandidates() |
77 | { |
78 | if (candidates.isEmpty()) |
79 | return false; |
80 | |
81 | candidates.clear(); |
82 | highlightIndex = -1; |
83 | return true; |
84 | } |
85 | |
86 | QString pickHighlighted() const |
87 | { |
88 | return (highlightIndex >= 0 && highlightIndex < candidates.count()) ? candidates[highlightIndex] : QString(); |
89 | } |
90 | |
91 | void reset() |
92 | { |
93 | if (clearCandidates()) { |
94 | Q_Q(TCInputMethod); |
95 | emit q->selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
96 | emit q->selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: highlightIndex); |
97 | } |
98 | input.clear(); |
99 | } |
100 | |
101 | bool compose(const QChar &c) |
102 | { |
103 | bool accept; |
104 | Q_Q(TCInputMethod); |
105 | QVirtualKeyboardInputContext *ic = q->inputContext(); |
106 | switch (inputMode) |
107 | { |
108 | #if defined(HAVE_TCIME_CANGJIE) |
109 | case QVirtualKeyboardInputEngine::InputMode::Cangjie: |
110 | accept = composeCangjie(ic, c); |
111 | break; |
112 | #endif |
113 | #if defined(HAVE_TCIME_ZHUYIN) |
114 | case QVirtualKeyboardInputEngine::InputMode::Zhuyin: |
115 | accept = composeZhuyin(ic, c); |
116 | break; |
117 | #endif |
118 | default: |
119 | accept = false; |
120 | break; |
121 | } |
122 | return accept; |
123 | } |
124 | |
125 | #if defined(HAVE_TCIME_CANGJIE) |
126 | bool composeCangjie(QVirtualKeyboardInputContext *ic, const QChar &c) |
127 | { |
128 | bool accept = false; |
129 | if (!input.contains(c: QChar(0x91CD)) && CangjieTable::isLetter(c)) { |
130 | if (input.length() < (cangjieDictionary.simplified() ? CangjieTable::MAX_SIMPLIFIED_CODE_LENGTH : CangjieTable::MAX_CODE_LENGTH)) { |
131 | input.append(c); |
132 | ic->setPreeditText(text: input); |
133 | if (setCandidates(values: wordDictionary->getWords(input), highlightDefault: true)) { |
134 | Q_Q(TCInputMethod); |
135 | emit q->selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
136 | emit q->selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: highlightIndex); |
137 | } |
138 | } |
139 | accept = true; |
140 | } else if (c.unicode() == 0x91CD) { |
141 | if (input.isEmpty()) { |
142 | input.append(c); |
143 | ic->setPreeditText(text: input); |
144 | checkSpecialCharInput(); |
145 | } |
146 | accept = true; |
147 | } else if (c.unicode() == 0x96E3) { |
148 | if (input.length() == 1) { |
149 | Q_ASSERT(input.at(0).unicode() == 0x91CD); |
150 | input.append(c); |
151 | ic->setPreeditText(text: input); |
152 | checkSpecialCharInput(); |
153 | } |
154 | accept = true; |
155 | } |
156 | return accept; |
157 | } |
158 | |
159 | bool checkSpecialCharInput() |
160 | { |
161 | if (input.length() == 1 && input.at(i: 0).unicode() == 0x91CD) { |
162 | static const QStringList specialChars1 = QStringList() |
163 | << QChar(0xFF01) << QChar(0x2018) << QChar(0x3000) << QChar(0xFF0C) |
164 | << QChar(0x3001) << QChar(0x3002) << QChar(0xFF0E) << QChar(0xFF1B) |
165 | << QChar(0xFF1A) << QChar(0xFF1F) << QChar(0x300E) << QChar(0x300F) |
166 | << QChar(0x3010) << QChar(0x3011) << QChar(0xFE57) << QChar(0x2026) |
167 | << QChar(0x2025) << QChar(0xFE50) << QChar(0xFE51) << QChar(0xFE52) |
168 | << QChar(0x00B7) << QChar(0xFE54) << QChar(0x2574) << QChar(0x2027) |
169 | << QChar(0x2032) << QChar(0x2035) << QChar(0x301E) << QChar(0x301D) |
170 | << QChar(0x201D) << QChar(0x201C) << QChar(0x2019) << QChar(0xFE55) |
171 | << QChar(0xFE5D) << QChar(0xFE5E) << QChar(0xFE59) << QChar(0xFE5A) |
172 | << QChar(0xFE5B) << QChar(0xFE5C) << QChar(0xFE43) << QChar(0xFE44); |
173 | Q_Q(TCInputMethod); |
174 | if (setCandidates(values: specialChars1, highlightDefault: true)) { |
175 | emit q->selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
176 | emit q->selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: highlightIndex); |
177 | } |
178 | q->inputContext()->setPreeditText(text: candidates[highlightIndex]); |
179 | return true; |
180 | } else if (input.length() == 2 && input.at(i: 0).unicode() == 0x91CD && input.at(i: 1).unicode() == 0x96E3) { |
181 | static const QStringList specialChars2 = QStringList() |
182 | << QChar(0x3008) << QChar(0x3009) << QChar(0xFE31) << QChar(0x2013) |
183 | << QChar(0xFF5C) << QChar(0x300C) << QChar(0x300D) << QChar(0xFE40) |
184 | << QChar(0xFE3F) << QChar(0x2014) << QChar(0xFE3E) << QChar(0xFE3D) |
185 | << QChar(0x300A) << QChar(0x300B) << QChar(0xFE3B) << QChar(0xFE3C) |
186 | << QChar(0xFE56) << QChar(0xFE30) << QChar(0xFE39) << QChar(0xFE3A) |
187 | << QChar(0x3014) << QChar(0x3015) << QChar(0xFE37) << QChar(0xFE38) |
188 | << QChar(0xFE41) << QChar(0xFE42) << QChar(0xFF5B) << QChar(0xFF5D) |
189 | << QChar(0xFE35) << QChar(0xFE36) << QChar(0xFF08) << QChar(0xFF09) |
190 | << QChar(0xFE4F) << QChar(0xFE34) << QChar(0xFE33); |
191 | Q_Q(TCInputMethod); |
192 | if (setCandidates(values: specialChars2, highlightDefault: true)) { |
193 | emit q->selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
194 | emit q->selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: highlightIndex); |
195 | } |
196 | q->inputContext()->setPreeditText(text: candidates[highlightIndex]); |
197 | return true; |
198 | } |
199 | return false; |
200 | } |
201 | #endif |
202 | |
203 | #if defined(HAVE_TCIME_ZHUYIN) |
204 | bool composeZhuyin(QVirtualKeyboardInputContext *ic, const QChar &c) |
205 | { |
206 | if (ZhuyinTable::isTone(c)) { |
207 | if (input.isEmpty()) |
208 | // Tones are accepted only when there's text in composing. |
209 | return false; |
210 | |
211 | auto strippedTones = ZhuyinTable::stripTones(input); |
212 | if (!strippedTones.ok) |
213 | // Tones cannot be composed if there's no syllables. |
214 | return false; |
215 | |
216 | // Replace the original tone with the new tone, but the default tone |
217 | // character should not be composed into the composing text. |
218 | QChar tone = strippedTones.pair[1].at(n: 0); |
219 | if (c == ZhuyinTable::DEFAULT_TONE) { |
220 | if (tone != ZhuyinTable::DEFAULT_TONE) |
221 | input.remove(i: input.length() - 1, len: 1); |
222 | } else { |
223 | if (tone == ZhuyinTable::DEFAULT_TONE) |
224 | input.append(c); |
225 | else |
226 | input.replace(i: input.length() - 1, len: 1, after: c); |
227 | } |
228 | } else if (ZhuyinTable::getInitials(initials: c) > 0) { |
229 | // Insert the initial or replace the original initial. |
230 | if (input.isEmpty() || !ZhuyinTable::getInitials(initials: input.at(i: 0))) |
231 | input.insert(i: 0, c); |
232 | else |
233 | input.replace(i: 0, len: 1, after: c); |
234 | } else if (ZhuyinTable::getFinals(finals: QStringView(&c, 1)) > 0) { |
235 | // Replace the finals in the decomposed of syllables and tones. |
236 | std::array<QChar, 4> decomposed = decomposeZhuyin(); |
237 | if (ZhuyinTable::isYiWuYuFinals(c)) { |
238 | decomposed[1] = c; |
239 | } else { |
240 | decomposed[2] = c; |
241 | } |
242 | |
243 | // Compose back the text after the finals replacement. |
244 | input.clear(); |
245 | for (QChar ch : decomposed) { |
246 | if (!ch.isNull()) |
247 | input.append(c: ch); |
248 | } |
249 | } else { |
250 | return false; |
251 | } |
252 | |
253 | ic->setPreeditText(text: input); |
254 | if (setCandidates(values: wordDictionary->getWords(input), highlightDefault: true)) { |
255 | Q_Q(TCInputMethod); |
256 | emit q->selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
257 | emit q->selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: highlightIndex); |
258 | } |
259 | |
260 | return true; |
261 | } |
262 | |
263 | std::array<QChar, 4> decomposeZhuyin() |
264 | { |
265 | std::array<QChar, 4> results = {}; |
266 | auto strippedTones = ZhuyinTable::stripTones(input); |
267 | if (strippedTones.ok) { |
268 | // Decompose tones. |
269 | QChar tone = strippedTones.pair[1].at(n: 0); |
270 | if (tone != ZhuyinTable::DEFAULT_TONE) |
271 | results[3] = tone; |
272 | |
273 | // Decompose initials. |
274 | QStringView syllables = strippedTones.pair[0]; |
275 | if (ZhuyinTable::getInitials(initials: syllables.at(n: 0)) > 0) { |
276 | results[0] = syllables.at(n: 0); |
277 | syllables = syllables.mid(pos: 1); |
278 | } |
279 | |
280 | // Decompose finals. |
281 | if (!syllables.isEmpty()) { |
282 | if (ZhuyinTable::isYiWuYuFinals(c: syllables.at(n: 0))) { |
283 | results[1] = syllables.at(n: 0); |
284 | if (syllables.length() > 1) |
285 | results[2] = syllables.at(n: 1); |
286 | } else { |
287 | results[2] = syllables.at(n: 0); |
288 | } |
289 | } |
290 | } |
291 | return results; |
292 | } |
293 | #endif |
294 | |
295 | TCInputMethod *q_ptr; |
296 | QVirtualKeyboardInputEngine::InputMode inputMode; |
297 | #if defined(HAVE_TCIME_CANGJIE) |
298 | CangjieDictionary cangjieDictionary; |
299 | #endif |
300 | #if defined(HAVE_TCIME_ZHUYIN) |
301 | ZhuyinDictionary zhuyinDictionary; |
302 | #endif |
303 | PhraseDictionary phraseDictionary; |
304 | WordDictionary *wordDictionary; |
305 | QString input; |
306 | QStringList candidates; |
307 | int highlightIndex; |
308 | }; |
309 | |
310 | /*! |
311 | \class QtVirtualKeyboard::TCInputMethod |
312 | \internal |
313 | */ |
314 | |
315 | TCInputMethod::TCInputMethod(QObject *parent) : |
316 | QVirtualKeyboardAbstractInputMethod(parent), |
317 | d_ptr(new TCInputMethodPrivate(this)) |
318 | { |
319 | } |
320 | |
321 | TCInputMethod::~TCInputMethod() |
322 | { |
323 | } |
324 | |
325 | bool TCInputMethod::simplified() const |
326 | { |
327 | #if defined(HAVE_TCIME_CANGJIE) |
328 | Q_D(const TCInputMethod); |
329 | return d->cangjieDictionary.simplified(); |
330 | #else |
331 | return false; |
332 | #endif |
333 | } |
334 | |
335 | void TCInputMethod::setSimplified(bool simplified) |
336 | { |
337 | qCDebug(lcTCIme) << "TCInputMethod::setSimplified(): " << simplified; |
338 | #if defined(HAVE_TCIME_CANGJIE) |
339 | Q_D(TCInputMethod); |
340 | if (d->cangjieDictionary.simplified() != simplified) { |
341 | d->reset(); |
342 | QVirtualKeyboardInputContext *ic = inputContext(); |
343 | if (ic) |
344 | ic->clear(); |
345 | d->cangjieDictionary.setSimplified(simplified); |
346 | emit simplifiedChanged(); |
347 | } |
348 | #else |
349 | Q_UNUSED(simplified) |
350 | #endif |
351 | } |
352 | |
353 | QList<QVirtualKeyboardInputEngine::InputMode> TCInputMethod::inputModes(const QString &locale) |
354 | { |
355 | Q_UNUSED(locale) |
356 | return QList<QVirtualKeyboardInputEngine::InputMode>() |
357 | #if defined(HAVE_TCIME_ZHUYIN) |
358 | << QVirtualKeyboardInputEngine::InputMode::Zhuyin |
359 | #endif |
360 | #if defined(HAVE_TCIME_CANGJIE) |
361 | << QVirtualKeyboardInputEngine::InputMode::Cangjie |
362 | #endif |
363 | ; |
364 | } |
365 | |
366 | bool TCInputMethod::setInputMode(const QString &locale, QVirtualKeyboardInputEngine::InputMode inputMode) |
367 | { |
368 | Q_UNUSED(locale) |
369 | Q_D(TCInputMethod); |
370 | if (d->inputMode == inputMode) |
371 | return true; |
372 | update(); |
373 | bool result = false; |
374 | d->inputMode = inputMode; |
375 | d->wordDictionary = nullptr; |
376 | #if defined(HAVE_TCIME_CANGJIE) |
377 | if (inputMode == QVirtualKeyboardInputEngine::InputMode::Cangjie) { |
378 | if (d->cangjieDictionary.isEmpty()) { |
379 | QString cangjieDictionary(qEnvironmentVariable(varName: "QT_VIRTUALKEYBOARD_CANGJIE_DICTIONARY" )); |
380 | if (!QFileInfo::exists(file: cangjieDictionary)) { |
381 | cangjieDictionary = QLatin1String(":///QtQuick/VirtualKeyboard/3rdparty/tcime/data/qt/dict_cangjie.dat" ); |
382 | if (!QFileInfo::exists(file: cangjieDictionary)) |
383 | cangjieDictionary = QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/qtvirtualkeyboard/tcime/dict_cangjie.dat" ); |
384 | } |
385 | d->cangjieDictionary.load(fileName: cangjieDictionary); |
386 | } |
387 | d->wordDictionary = &d->cangjieDictionary; |
388 | } |
389 | #endif |
390 | #if defined(HAVE_TCIME_ZHUYIN) |
391 | if (inputMode == QVirtualKeyboardInputEngine::InputMode::Zhuyin) { |
392 | if (d->zhuyinDictionary.isEmpty()) { |
393 | QString zhuyinDictionary(qEnvironmentVariable(varName: "QT_VIRTUALKEYBOARD_ZHUYIN_DICTIONARY" )); |
394 | if (!QFileInfo::exists(file: zhuyinDictionary)) { |
395 | zhuyinDictionary = QLatin1String(":///QtQuick/VirtualKeyboard/3rdparty/tcime/data/qt/dict_zhuyin.dat" ); |
396 | if (!QFileInfo::exists(file: zhuyinDictionary)) |
397 | zhuyinDictionary = QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/qtvirtualkeyboard/tcime/dict_zhuyin.dat" ); |
398 | } |
399 | d->zhuyinDictionary.load(fileName: zhuyinDictionary); |
400 | } |
401 | d->wordDictionary = &d->zhuyinDictionary; |
402 | } |
403 | #endif |
404 | result = d->wordDictionary && !d->wordDictionary->isEmpty(); |
405 | if (result && d->phraseDictionary.isEmpty()) { |
406 | QString phraseDictionary(qEnvironmentVariable(varName: "QT_VIRTUALKEYBOARD_PHRASE_DICTIONARY" )); |
407 | if (!QFileInfo::exists(file: phraseDictionary)) { |
408 | phraseDictionary = QLatin1String(":///QtQuick/VirtualKeyboard/3rdparty/tcime/data/qt/dict_phrases.dat" ); |
409 | if (!QFileInfo::exists(file: phraseDictionary)) |
410 | phraseDictionary = QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/qtvirtualkeyboard/tcime/dict_phrases.dat" ); |
411 | } |
412 | d->phraseDictionary.load(fileName: phraseDictionary); |
413 | } |
414 | if (!result) |
415 | inputMode = QVirtualKeyboardInputEngine::InputMode::Latin; |
416 | return result; |
417 | } |
418 | |
419 | bool TCInputMethod::setTextCase(QVirtualKeyboardInputEngine::TextCase textCase) |
420 | { |
421 | Q_UNUSED(textCase) |
422 | return true; |
423 | } |
424 | |
425 | bool TCInputMethod::keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers) |
426 | { |
427 | Q_UNUSED(key) |
428 | Q_UNUSED(text) |
429 | Q_UNUSED(modifiers) |
430 | Q_D(TCInputMethod); |
431 | QVirtualKeyboardInputContext *ic = inputContext(); |
432 | bool accept = false; |
433 | switch (key) { |
434 | case Qt::Key_Context1: |
435 | // Do nothing on symbol mode switch |
436 | accept = true; |
437 | break; |
438 | |
439 | case Qt::Key_Enter: |
440 | case Qt::Key_Return: |
441 | update(); |
442 | break; |
443 | |
444 | case Qt::Key_Tab: |
445 | case Qt::Key_Space: |
446 | if (!d->input.isEmpty()) { |
447 | accept = true; |
448 | if (d->highlightIndex >= 0) { |
449 | QString finalWord = d->pickHighlighted(); |
450 | d->reset(); |
451 | inputContext()->commit(text: finalWord); |
452 | if (d->setCandidates(values: d->phraseDictionary.getWords(input: finalWord.left(n: 1)), highlightDefault: false)) { |
453 | emit selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
454 | emit selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: d->highlightIndex); |
455 | } |
456 | } |
457 | } else { |
458 | update(); |
459 | } |
460 | break; |
461 | |
462 | case Qt::Key_Backspace: |
463 | if (!d->input.isEmpty()) { |
464 | d->input.remove(i: d->input.length() - 1, len: 1); |
465 | ic->setPreeditText(text: d->input); |
466 | #if defined(HAVE_TCIME_CANGJIE) |
467 | if (!d->checkSpecialCharInput()) { |
468 | #endif |
469 | if (d->setCandidates(values: d->wordDictionary->getWords(input: d->input), highlightDefault: true)) { |
470 | emit selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
471 | emit selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: d->highlightIndex); |
472 | } |
473 | #if defined(HAVE_TCIME_CANGJIE) |
474 | } |
475 | #endif |
476 | accept = true; |
477 | } else if (d->clearCandidates()) { |
478 | emit selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
479 | emit selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: d->highlightIndex); |
480 | } |
481 | break; |
482 | |
483 | default: |
484 | if (text.length() == 1) |
485 | accept = d->compose(c: text.at(i: 0)); |
486 | if (!accept) |
487 | update(); |
488 | break; |
489 | } |
490 | return accept; |
491 | } |
492 | |
493 | QList<QVirtualKeyboardSelectionListModel::Type> TCInputMethod::selectionLists() |
494 | { |
495 | return QList<QVirtualKeyboardSelectionListModel::Type>() << QVirtualKeyboardSelectionListModel::Type::WordCandidateList; |
496 | } |
497 | |
498 | int TCInputMethod::selectionListItemCount(QVirtualKeyboardSelectionListModel::Type type) |
499 | { |
500 | Q_UNUSED(type) |
501 | Q_D(TCInputMethod); |
502 | return d->candidates.count(); |
503 | } |
504 | |
505 | QVariant TCInputMethod::selectionListData(QVirtualKeyboardSelectionListModel::Type type, int index, QVirtualKeyboardSelectionListModel::Role role) |
506 | { |
507 | QVariant result; |
508 | Q_D(TCInputMethod); |
509 | switch (role) { |
510 | case QVirtualKeyboardSelectionListModel::Role::Display: |
511 | result = QVariant(d->candidates.at(i: index)); |
512 | break; |
513 | case QVirtualKeyboardSelectionListModel::Role::WordCompletionLength: |
514 | result.setValue(0); |
515 | break; |
516 | default: |
517 | result = QVirtualKeyboardAbstractInputMethod::selectionListData(type, index, role); |
518 | break; |
519 | } |
520 | return result; |
521 | } |
522 | |
523 | void TCInputMethod::selectionListItemSelected(QVirtualKeyboardSelectionListModel::Type type, int index) |
524 | { |
525 | Q_UNUSED(type) |
526 | Q_D(TCInputMethod); |
527 | QString finalWord = d->candidates.at(i: index); |
528 | reset(); |
529 | inputContext()->commit(text: finalWord); |
530 | if (d->setCandidates(values: d->phraseDictionary.getWords(input: finalWord.left(n: 1)), highlightDefault: false)) { |
531 | emit selectionListChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList); |
532 | emit selectionListActiveItemChanged(type: QVirtualKeyboardSelectionListModel::Type::WordCandidateList, index: d->highlightIndex); |
533 | } |
534 | } |
535 | |
536 | void TCInputMethod::reset() |
537 | { |
538 | Q_D(TCInputMethod); |
539 | d->reset(); |
540 | } |
541 | |
542 | void TCInputMethod::update() |
543 | { |
544 | Q_D(TCInputMethod); |
545 | if (d->highlightIndex >= 0) { |
546 | QString finalWord = d->pickHighlighted(); |
547 | d->reset(); |
548 | inputContext()->commit(text: finalWord); |
549 | } else { |
550 | inputContext()->clear(); |
551 | d->reset(); |
552 | } |
553 | } |
554 | |
555 | } // namespace QtVirtualKeyboard |
556 | QT_END_NAMESPACE |
557 | |