blob: efe68a1ef92c90b90e9c5007e80b6dac5a703526 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "openwnninputmethod_p.h"
#include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h>
#include <QLoggingCategory>
#include <openwnnenginejajp.h>
#include <composingtext.h>
#include <romkan.h>
#include <romkanfullkatakana.h>
#include <romkanhalfkatakana.h>
#include <QTextFormat>
QT_BEGIN_NAMESPACE
namespace QtVirtualKeyboard {
Q_LOGGING_CATEGORY(lcOpenWnn, "qt.virtualkeyboard.openwnn")
class OpenWnnInputMethodPrivate
{
Q_DECLARE_PUBLIC(OpenWnnInputMethod)
public:
enum EngineMode {
ENGINE_MODE_DEFAULT,
ENGINE_MODE_DIRECT,
ENGINE_MODE_NO_LV2_CONV,
ENGINE_MODE_FULL_KATAKANA,
ENGINE_MODE_HALF_KATAKANA,
};
enum ConvertType {
CONVERT_TYPE_NONE = 0,
CONVERT_TYPE_RENBUN = 1,
};
enum {
MAX_COMPOSING_TEXT = 30
};
OpenWnnInputMethodPrivate(OpenWnnInputMethod *q_ptr) :
q_ptr(q_ptr),
inputMode(QVirtualKeyboardInputEngine::InputMode::Latin),
exactMatchMode(false),
converter(nullptr),
converterJAJP(),
activeConvertType(CONVERT_TYPE_NONE),
preConverter(nullptr),
enableLearning(true),
enablePrediction(true),
enableConverter(true),
disableUpdate(false),
commitCount(0),
targetLayer(ComposingText::LAYER1),
activeWordIndex(-1)
{
}
void changeEngineMode(EngineMode mode)
{
switch (mode) {
case ENGINE_MODE_DIRECT:
/* Full/Half-width number or Full-width alphabet */
converter = nullptr;
preConverter.reset();
break;
case ENGINE_MODE_NO_LV2_CONV:
converter = nullptr;
preConverter.reset(new Romkan());
break;
case ENGINE_MODE_FULL_KATAKANA:
converter = nullptr;
preConverter.reset(new RomkanFullKatakana());
break;
case ENGINE_MODE_HALF_KATAKANA:
converter = nullptr;
preConverter.reset(new RomkanHalfKatakana());
break;
default:
/* HIRAGANA input mode */
setDictionary(OpenWnnEngineJAJP::DIC_LANG_JP);
converter = &converterJAJP;
preConverter.reset(new Romkan());
break;
}
}
void setDictionary(OpenWnnEngineJAJP::DictionaryType mode)
{
converterJAJP.setDictionary(mode);
}
void breakSequence()
{
converterJAJP.breakSequence();
}
bool isEnableL2Converter()
{
return converter != nullptr && enableConverter;
}
void startConvert(ConvertType convertType)
{
if (!isEnableL2Converter())
return;
if (activeConvertType != convertType) {
if (!exactMatchMode) {
if (convertType == CONVERT_TYPE_RENBUN) {
/* not specify */
composingText.setCursor(ComposingText::LAYER1, 0);
} else {
if (activeConvertType == CONVERT_TYPE_RENBUN) {
exactMatchMode = true;
} else {
/* specify all range */
composingText.setCursor(ComposingText::LAYER1,
composingText.size(ComposingText::LAYER1));
}
}
}
if (convertType == CONVERT_TYPE_RENBUN)
/* clears variables for the prediction */
exactMatchMode = false;
/* clears variables for the convert */
commitCount = 0;
activeConvertType = convertType;
updateViewStatus(ComposingText::LAYER2, true, true);
focusNextCandidate();
}
}
void changeL2Segment(const QSharedPointer<WnnWord> &word)
{
if (word.isNull())
return;
QList<StrSegment> ss;
ss.append(composingText.getStrSegment(ComposingText::LAYER2, 0));
if (!ss[0].clause.isNull())
ss[0].clause->candidate = word->candidate;
ss[0].string = word->candidate;
composingText.replaceStrSegment(ComposingText::LAYER2, ss);
if (lcOpenWnn().isDebugEnabled())
composingText.debugout();
updateViewStatus(ComposingText::LAYER2, false, false);
}
void initializeScreen()
{
if (composingText.size(ComposingText::LAYER0) != 0) {
Q_Q(OpenWnnInputMethod);
q->inputContext()->commit(QString());
}
composingText.clear();
exactMatchMode = false;
activeConvertType = CONVERT_TYPE_NONE;
clearCandidates();
}
void updateViewStatusForPrediction(bool updateCandidates, bool updateEmptyText)
{
activeConvertType = CONVERT_TYPE_NONE;
updateViewStatus(ComposingText::LAYER1, updateCandidates, updateEmptyText);
}
void updateViewStatus(ComposingText::TextLayer layer, bool updateCandidates, bool updateEmptyText)
{
targetLayer = layer;
if (updateCandidates)
updateCandidateView();
/* set the text for displaying as the composing text */
displayText.clear();
displayText.insert(0, composingText.toString(layer));
/* add decoration to the text */
if (!displayText.isEmpty() || updateEmptyText) {
QList<QInputMethodEvent::Attribute> attributes;
int cursor = composingText.getCursor(layer);
if (cursor != 0) {
int highlightEnd = 0;
if (exactMatchMode) {
QTextCharFormat textFormat;
textFormat.setBackground(QBrush(QColor(0x66, 0xCD, 0xAA)));
textFormat.setForeground(QBrush(Qt::black));
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, cursor, textFormat));
highlightEnd = cursor;
} else if (layer == ComposingText::LAYER2) {
highlightEnd = composingText.toString(layer, 0, 0).length();
/* highlights the first segment */
QTextCharFormat textFormat;
textFormat.setBackground(QBrush(QColor(0x88, 0x88, 0xFF)));
textFormat.setForeground(QBrush(Qt::black));
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, highlightEnd, textFormat));
}
if (highlightEnd != 0 && highlightEnd < displayText.length()) {
/* highlights remaining text */
QTextCharFormat textFormat;
textFormat.setBackground(QBrush(QColor(0xF0, 0xFF, 0xFF)));
textFormat.setForeground(QBrush(Qt::black));
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, highlightEnd, displayText.length() - highlightEnd, textFormat));
}
}
QTextCharFormat textFormat;
textFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, displayText.length(), textFormat));
int displayCursor = composingText.toString(layer, 0, cursor - 1).length();
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, displayCursor, 1, QVariant()));
Q_Q(OpenWnnInputMethod);
q->inputContext()->setPreeditText(displayText, attributes);
}
}
void updateCandidateView()
{
switch (targetLayer) {
case ComposingText::LAYER0:
case ComposingText::LAYER1: /* prediction */
if (enablePrediction)
/* update the candidates view */
updatePrediction();
break;
case ComposingText::LAYER2: /* convert */
if (commitCount == 0)
converter->convert(composingText);
if (converter->makeCandidateListOf(commitCount) != 0) {
composingText.setCursor(ComposingText::LAYER2, 1);
displayCandidates();
} else {
composingText.setCursor(ComposingText::LAYER1,
composingText.toString(ComposingText::LAYER1).length());
clearCandidates();
}
break;
default:
break;
}
}
void updatePrediction()
{
int candidates = 0;
int cursor = composingText.getCursor(ComposingText::LAYER1);
if (isEnableL2Converter()) {
if (exactMatchMode)
/* exact matching */
candidates = converter->predict(composingText, 0, cursor);
else
/* normal prediction */
candidates = converter->predict(composingText, 0, -1);
}
/* update the candidates view */
if (candidates > 0)
displayCandidates();
else
clearCandidates();
}
void displayCandidates()
{
int previousActiveWordIndex = activeWordIndex;
bool wasEmpty = candidateList.isEmpty();
clearCandidates(true);
QSharedPointer<WnnWord> result;
while ((result = converter->getNextCandidate()))
candidateList.append(result);
Q_Q(OpenWnnInputMethod);
if (!candidateList.isEmpty() || !wasEmpty)
emit q->selectionListChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList);
if (previousActiveWordIndex != activeWordIndex)
emit q->selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList, activeWordIndex);
}
void clearCandidates(bool deferUpdate = false)
{
if (!candidateList.isEmpty()) {
candidateList.clear();
if (!deferUpdate) {
Q_Q(OpenWnnInputMethod);
emit q->selectionListChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList);
}
clearFocusCandidate(deferUpdate);
}
}
QSharedPointer<WnnWord> focusNextCandidate()
{
Q_Q(OpenWnnInputMethod);
if (candidateList.isEmpty())
return QSharedPointer<WnnWord>();
activeWordIndex++;
if (activeWordIndex >= candidateList.size())
activeWordIndex = 0;
emit q->selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList, activeWordIndex);
return candidateList.at(activeWordIndex);
}
void clearFocusCandidate(bool deferUpdate = false)
{
Q_Q(OpenWnnInputMethod);
if (activeWordIndex != -1) {
activeWordIndex = -1;
if (!deferUpdate)
emit q->selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList, activeWordIndex);
}
}
void fitInputType()
{
Q_Q(OpenWnnInputMethod);
enableConverter = true;
Qt::InputMethodHints inputMethodHints = q->inputContext()->inputMethodHints();
if (inputMethodHints.testFlag(Qt::ImhDigitsOnly) ||
inputMethodHints.testFlag(Qt::ImhFormattedNumbersOnly) ||
inputMethodHints.testFlag(Qt::ImhDialableCharactersOnly)) {
enableConverter = false;
}
if (inputMethodHints.testFlag(Qt::ImhLatinOnly)) {
enableConverter = false;
}
if (inputMode != QVirtualKeyboardInputEngine::InputMode::Hiragana ||
inputMethodHints.testFlag(Qt::ImhHiddenText) ||
inputMethodHints.testFlag(Qt::ImhSensitiveData) ||
inputMethodHints.testFlag(Qt::ImhNoPredictiveText)) {
if (enablePrediction) {
enablePrediction = false;
emit q->selectionListsChanged();
}
} else if (inputMode == QVirtualKeyboardInputEngine::InputMode::Hiragana && !enablePrediction) {
enablePrediction = true;
emit q->selectionListsChanged();
}
activeConvertType = CONVERT_TYPE_NONE;
}
void learnWord(WnnWord &word)
{
if (enableLearning)
converter->learn(word);
}
void learnWord(int index)
{
if (enableLearning && index < composingText.size(ComposingText::LAYER2)) {
StrSegment seg = composingText.getStrSegment(ComposingText::LAYER2, index);
if (!seg.clause.isNull()) {
converter->learn(*seg.clause);
} else {
QString stroke = composingText.toString(ComposingText::LAYER1, seg.from, seg.to);
WnnWord word(seg.string, stroke);
converter->learn(word);
}
}
}
void commitAll()
{
if (activeConvertType != CONVERT_TYPE_NONE) {
commitConvertingText();
} else {
composingText.setCursor(ComposingText::LAYER1,
composingText.size(ComposingText::LAYER1));
commitText(true);
}
}
void commitConvertingText()
{
if (activeConvertType != CONVERT_TYPE_NONE) {
Q_Q(OpenWnnInputMethod);
int size = composingText.size(ComposingText::LAYER2);
for (int i = 0; i < size; i++) {
learnWord(i);
}
QString text = composingText.toString(ComposingText::LAYER2);
disableUpdate = true;
q->inputContext()->commit(text);
disableUpdate = false;
initializeScreen();
}
}
bool commitText(bool learn = false)
{
ComposingText::TextLayer layer = targetLayer;
int cursor = composingText.getCursor(layer);
if (cursor == 0) {
return false;
}
QString tmp = composingText.toString(layer, 0, cursor - 1);
if (converter != nullptr) {
if (learn) {
if (activeConvertType == CONVERT_TYPE_RENBUN) {
learnWord(0); /* select the top of the clauses */
} else {
if (composingText.size(ComposingText::LAYER1) != 0) {
QString stroke = composingText.toString(ComposingText::LAYER1, 0, composingText.getCursor(layer) - 1);
WnnWord word(tmp, stroke);
learnWord(word);
}
}
} else {
breakSequence();
}
}
return commitText(tmp);
}
bool commitText(const WnnWord &word)
{
return commitText(word.candidate);
}
bool commitText(const QString &string)
{
Q_Q(OpenWnnInputMethod);
ComposingText::TextLayer layer = targetLayer;
disableUpdate = true;
q->inputContext()->commit(string);
disableUpdate = false;
int cursor = composingText.getCursor(layer);
if (cursor > 0) {
composingText.deleteStrSegment(layer, 0, composingText.getCursor(layer) - 1);
composingText.setCursor(layer, composingText.size(layer));
}
exactMatchMode = false;
commitCount++;
if ((layer == ComposingText::LAYER2) && (composingText.size(layer) == 0))
layer = ComposingText::LAYER1; /* for connected prediction */
if (layer == ComposingText::LAYER2) {
activeConvertType = CONVERT_TYPE_RENBUN;
updateViewStatus(layer, true, false);
focusNextCandidate();
} else {
updateViewStatusForPrediction(true, false);
}
return composingText.size(ComposingText::LAYER0) > 0;
}
bool isAlphabetLast(const QString &str)
{
if (str.isEmpty())
return false;
ushort ch = str.at(str.length() - 1).unicode();
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}
void commitTextWithoutLastAlphabet()
{
QString last = composingText.getStrSegment(targetLayer, -1).string;
if (isAlphabetLast(last)) {
composingText.moveCursor(ComposingText::LAYER1, -1);
commitText(false);
composingText.moveCursor(ComposingText::LAYER1, 1);
} else {
commitText(false);
}
}
bool processLeftKeyEvent()
{
if (composingText.size(ComposingText::LAYER1) == 0)
return false;
if (activeConvertType != CONVERT_TYPE_NONE) {
if (composingText.getCursor(ComposingText::LAYER1) > 1) {
composingText.moveCursor(ComposingText::LAYER1, -1);
}
} else if (exactMatchMode) {
composingText.moveCursor(ComposingText::LAYER1, -1);
} else {
exactMatchMode = true;
}
if (lcOpenWnn().isDebugEnabled())
composingText.debugout();
commitCount = 0; /* retry consecutive clause conversion if necessary. */
updateViewStatus(targetLayer, true, true);
if (activeConvertType != CONVERT_TYPE_NONE)
focusNextCandidate();
return true;
}
bool processRightKeyEvent()
{
if (composingText.size(ComposingText::LAYER1) == 0)
return false;
ComposingText::TextLayer layer = targetLayer;
if (exactMatchMode || activeConvertType != CONVERT_TYPE_NONE) {
int textSize = composingText.size(ComposingText::LAYER1);
if (composingText.getCursor(ComposingText::LAYER1) == textSize) {
exactMatchMode = false;
layer = ComposingText::LAYER1; /* convert -> prediction */
activeConvertType = CONVERT_TYPE_NONE;
} else {
composingText.moveCursor(ComposingText::LAYER1, 1);
}
} else {
if (composingText.getCursor(ComposingText::LAYER1) < composingText.size(ComposingText::LAYER1)) {
composingText.moveCursor(ComposingText::LAYER1, 1);
}
}
if (lcOpenWnn().isDebugEnabled())
composingText.debugout();
commitCount = 0; /* retry consecutive clause conversion if necessary. */
updateViewStatus(layer, true, true);
if (activeConvertType != CONVERT_TYPE_NONE)
focusNextCandidate();
return true;
}
OpenWnnInputMethod *q_ptr;
QVirtualKeyboardInputEngine::InputMode inputMode;
bool exactMatchMode;
QString displayText;
OpenWnnEngineJAJP *converter;
OpenWnnEngineJAJP converterJAJP;
ConvertType activeConvertType;
ComposingText composingText;
QScopedPointer<LetterConverter> preConverter;
bool enableLearning;
bool enablePrediction;
bool enableConverter;
bool disableUpdate;
int commitCount;
ComposingText::TextLayer targetLayer;
QList<QSharedPointer<WnnWord> > candidateList;
int activeWordIndex;
};
/*!
\class QtVirtualKeyboard::OpenWnnInputMethod
\internal
*/
OpenWnnInputMethod::OpenWnnInputMethod(QObject *parent) :
QVirtualKeyboardAbstractInputMethod(parent),
d_ptr(new OpenWnnInputMethodPrivate(this))
{
}
OpenWnnInputMethod::~OpenWnnInputMethod()
{
}
QList<QVirtualKeyboardInputEngine::InputMode> OpenWnnInputMethod::inputModes(const QString &locale)
{
Q_UNUSED(locale)
return QList<QVirtualKeyboardInputEngine::InputMode>()
<< QVirtualKeyboardInputEngine::InputMode::Hiragana
<< QVirtualKeyboardInputEngine::InputMode::Katakana
<< QVirtualKeyboardInputEngine::InputMode::FullwidthLatin
<< QVirtualKeyboardInputEngine::InputMode::Latin;
}
bool OpenWnnInputMethod::setInputMode(const QString &locale, QVirtualKeyboardInputEngine::InputMode inputMode)
{
Q_UNUSED(locale)
Q_D(OpenWnnInputMethod);
if (d->inputMode == inputMode)
return true;
update();
switch (inputMode) {
case QVirtualKeyboardInputEngine::InputMode::Hiragana:
d->changeEngineMode(OpenWnnInputMethodPrivate::ENGINE_MODE_DEFAULT);
break;
case QVirtualKeyboardInputEngine::InputMode::Katakana:
d->changeEngineMode(OpenWnnInputMethodPrivate::ENGINE_MODE_FULL_KATAKANA);
break;
default:
d->changeEngineMode(OpenWnnInputMethodPrivate::ENGINE_MODE_DIRECT);
break;
}
d->inputMode = inputMode;
d->fitInputType();
return true;
}
bool OpenWnnInputMethod::setTextCase(QVirtualKeyboardInputEngine::TextCase textCase)
{
Q_UNUSED(textCase)
return true;
}
bool OpenWnnInputMethod::keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
{
Q_UNUSED(key)
Q_UNUSED(text)
Q_UNUSED(modifiers)
Q_D(OpenWnnInputMethod);
if (d->preConverter == nullptr && !d->isEnableL2Converter())
return false;
switch (key) {
case Qt::Key_Left:
if (d->isEnableL2Converter() && d->composingText.size(ComposingText::LAYER1) > 0)
return d->processLeftKeyEvent();
else
return d->commitText(false);
break;
case Qt::Key_Right:
if (d->isEnableL2Converter() && d->composingText.size(ComposingText::LAYER1) > 0)
return d->processRightKeyEvent();
else
return d->commitText(false);
break;
case Qt::Key_Backspace:
if (d->composingText.size(ComposingText::LAYER1) > 0) {
if (d->activeConvertType == OpenWnnInputMethodPrivate::CONVERT_TYPE_RENBUN) {
d->composingText.setCursor(ComposingText::LAYER1,
d->composingText.toString(ComposingText::LAYER1).length());
d->exactMatchMode = false;
d->clearFocusCandidate();
} else {
if ((d->composingText.size(ComposingText::LAYER1) == 1) &&
d->composingText.getCursor(ComposingText::LAYER1) != 0) {
d->initializeScreen();
return true;
} else {
d->composingText.deleteAt(ComposingText::LAYER1, false);
}
}
if (lcOpenWnn().isDebugEnabled())
d->composingText.debugout();
d->updateViewStatusForPrediction(true, true);
return true;
}
break;
case Qt::Key_Space:
if (d->composingText.size(ComposingText::LAYER0) == 0) {
d->clearCandidates();
d->breakSequence();
} else {
if (d->targetLayer == ComposingText::LAYER2)
d->changeL2Segment(d->focusNextCandidate());
else if (d->isEnableL2Converter())
d->startConvert(OpenWnnInputMethodPrivate::CONVERT_TYPE_RENBUN);
else
return d->commitText(false);
return true;
}
break;
case Qt::Key_Return:
case Qt::Key_Enter:
if (d->composingText.size(ComposingText::LAYER0) > 0) {
d->commitText(true);
return true;
}
break;
default:
if (key < Qt::Key_Escape && !text.isEmpty() && text.at(0).isPrint()) {
if (d->composingText.size(ComposingText::LAYER1) + text.size() > OpenWnnInputMethodPrivate::MAX_COMPOSING_TEXT)
return true;
const int last = text.size() - 1;
for (int i = 0; i <= last; ++i) {
if (d->isEnableL2Converter()) {
d->commitConvertingText();
d->composingText.insertStrSegment(ComposingText::LAYER0, ComposingText::LAYER1, text.mid(i, 1));
if (d->preConverter != nullptr)
d->preConverter->convert(d->composingText);
if (i == last)
d->updateViewStatusForPrediction(true, true);
} else {
d->composingText.insertStrSegment(ComposingText::LAYER0, ComposingText::LAYER1, text.mid(i, 1));
QString layer1 = d->composingText.toString(ComposingText::LAYER1);
if (!d->isAlphabetLast(layer1)) {
d->commitText(false);
} else {
bool completed = d->preConverter->convert(d->composingText);
if (completed) {
d->commitTextWithoutLastAlphabet();
} else {
if (i == last)
d->updateViewStatusForPrediction(true, true);
}
}
}
}
if (lcOpenWnn().isDebugEnabled())
d->composingText.debugout();
return true;
}
break;
}
return false;
}
QList<QVirtualKeyboardSelectionListModel::Type> OpenWnnInputMethod::selectionLists()
{
Q_D(OpenWnnInputMethod);
if (!d->enablePrediction)
return QList<QVirtualKeyboardSelectionListModel::Type>();
return QList<QVirtualKeyboardSelectionListModel::Type>() << QVirtualKeyboardSelectionListModel::Type::WordCandidateList;
}
int OpenWnnInputMethod::selectionListItemCount(QVirtualKeyboardSelectionListModel::Type type)
{
Q_UNUSED(type)
Q_D(OpenWnnInputMethod);
return d->candidateList.size();
}
QVariant OpenWnnInputMethod::selectionListData(QVirtualKeyboardSelectionListModel::Type type, int index, QVirtualKeyboardSelectionListModel::Role role)
{
QVariant result;
Q_D(OpenWnnInputMethod);
switch (role) {
case QVirtualKeyboardSelectionListModel::Role::Display:
result = QVariant(d->candidateList.at(index)->candidate);
break;
case QVirtualKeyboardSelectionListModel::Role::WordCompletionLength:
result.setValue(0);
break;
default:
result = QVirtualKeyboardAbstractInputMethod::selectionListData(type, index, role);
break;
}
return result;
}
void OpenWnnInputMethod::selectionListItemSelected(QVirtualKeyboardSelectionListModel::Type type, int index)
{
Q_UNUSED(type)
Q_D(OpenWnnInputMethod);
// Set selected text as preeditText to place cursor at the end of selected text
inputContext()->setPreeditText(d->candidateList.at(index)->candidate);
d->commitText(*d->candidateList.at(index));
}
void OpenWnnInputMethod::reset()
{
Q_D(OpenWnnInputMethod);
d->commitAll();
d->initializeScreen();
d->fitInputType();
}
void OpenWnnInputMethod::update()
{
Q_D(OpenWnnInputMethod);
if (!d->disableUpdate)
reset();
}
} // namespace QtVirtualKeyboard
QT_END_NAMESPACE