-
Jarkko Koivikko authored
[ChangeLog] Added Bulgarian keyboard layout. Change-Id: I636ba97d3fe80c94f91b269426465023a433d7bf Reviewed-by:
Mitch Curtis <mitch.curtis@qt.io>
6045966b
/****************************************************************************
**
** 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 "hunspellinputmethod_p.h"
#include "inputcontext.h"
namespace QtVirtualKeyboard {
/*!
\class QtVirtualKeyboard::HunspellInputMethod
\internal
*/
HunspellInputMethod::HunspellInputMethod(HunspellInputMethodPrivate &dd, QObject *parent) :
AbstractInputMethod(dd, parent)
{
}
HunspellInputMethod::HunspellInputMethod(QObject *parent) :
AbstractInputMethod(*new HunspellInputMethodPrivate(this), parent)
{
}
HunspellInputMethod::~HunspellInputMethod()
{
}
QList<InputEngine::InputMode> HunspellInputMethod::inputModes(const QString &locale)
{
QList<InputEngine::InputMode> result;
switch (QLocale(locale).script()) {
case QLocale::GreekScript:
result.append(InputEngine::Greek);
break;
case QLocale::CyrillicScript:
result.append(InputEngine::Cyrillic);
break;
default:
break;
}
result.append(InputEngine::Latin);
result.append(InputEngine::Numeric);
return result;
}
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
bool HunspellInputMethod::setInputMode(const QString &locale, InputEngine::InputMode inputMode)
{
Q_UNUSED(inputMode)
Q_D(HunspellInputMethod);
return d->createHunspell(locale);
}
bool HunspellInputMethod::setTextCase(InputEngine::TextCase textCase)
{
Q_UNUSED(textCase)
return true;
}
bool HunspellInputMethod::keyEvent(Qt::Key key, const QString &text, Qt::KeyboardModifiers modifiers)
{
Q_UNUSED(modifiers)
Q_D(HunspellInputMethod);
InputContext *ic = inputContext();
Qt::InputMethodHints inputMethodHints = ic->inputMethodHints();
bool accept = false;
switch (key) {
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Tab:
case Qt::Key_Space:
update();
break;
case Qt::Key_Backspace:
if (!d->word.isEmpty()) {
d->word.remove(d->word.length() - 1, 1);
ic->setPreeditText(d->word);
if (d->updateSuggestions()) {
emit selectionListChanged(SelectionListModel::WordCandidateList);
emit selectionListActiveItemChanged(SelectionListModel::WordCandidateList, d->activeWordIndex);
}
accept = true;
}
break;
default:
if (inputMethodHints.testFlag(Qt::ImhNoPredictiveText))
break;
if (d->dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded) {
update();
break;
}
if (text.length() > 0) {
QChar c = text.at(0);
bool addToWord = d->isValidInputChar(c) && (!d->word.isEmpty() || !d->isJoiner(c));
if (addToWord) {
/* Automatic space insertion. */
if (d->word.isEmpty()) {
QString surroundingText = ic->surroundingText();
int cursorPosition = ic->cursorPosition();
/* Rules for automatic space insertion:
- Surrounding text is not empty
- Cursor is at the end of the line
- No space before the cursor
- No spefic characters before the cursor; minus and apostrophe
*/
if (!surroundingText.isEmpty() && cursorPosition == surroundingText.length()) {
QChar lastChar = surroundingText.at(cursorPosition - 1);
if (!lastChar.isSpace() &&
lastChar != Qt::Key_Minus &&
d->isAutoSpaceAllowed()) {
ic->commit(" ");
}
}
}
/* Ignore possible call to update() function when sending initial
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
pre-edit text. The update is triggered if the text editor has
a selection which the pre-edit text will replace.
*/
d->ignoreUpdate = d->word.isEmpty();
d->word.append(text);
ic->setPreeditText(d->word);
d->ignoreUpdate = false;
if (d->updateSuggestions()) {
emit selectionListChanged(SelectionListModel::WordCandidateList);
emit selectionListActiveItemChanged(SelectionListModel::WordCandidateList, d->activeWordIndex);
}
accept = true;
} else if (text.length() > 1) {
bool addSpace = !d->word.isEmpty() || d->autoSpaceAllowed;
update();
d->autoSpaceAllowed = true;
if (addSpace && d->isAutoSpaceAllowed())
ic->commit(" ");
ic->commit(text);
d->autoSpaceAllowed = addSpace;
accept = true;
} else {
update();
inputContext()->sendKeyClick(key, text, modifiers);
d->autoSpaceAllowed = true;
accept = true;
}
}
break;
}
return accept;
}
QList<SelectionListModel::Type> HunspellInputMethod::selectionLists()
{
Q_D(const HunspellInputMethod);
Qt::InputMethodHints inputMethodHints = inputContext()->inputMethodHints();
if (d->dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded || inputMethodHints.testFlag(Qt::ImhNoPredictiveText) || inputMethodHints.testFlag(Qt::ImhHiddenText))
return QList<SelectionListModel::Type>();
return QList<SelectionListModel::Type>() << SelectionListModel::WordCandidateList;
}
int HunspellInputMethod::selectionListItemCount(SelectionListModel::Type type)
{
Q_UNUSED(type)
Q_D(HunspellInputMethod);
return d->wordCandidates.count();
}
QVariant HunspellInputMethod::selectionListData(SelectionListModel::Type type, int index, int role)
{
QVariant result;
Q_UNUSED(type)
Q_D(HunspellInputMethod);
switch (role) {
case SelectionListModel::DisplayRole:
result = QVariant(d->wordCandidates.at(index));
break;
case SelectionListModel::WordCompletionLengthRole:
{
const QString wordCandidate(d->wordCandidates.at(index));
int wordCompletionLength = wordCandidate.length() - d->word.length();
result.setValue((wordCompletionLength > 0 && wordCandidate.startsWith(d->word)) ? wordCompletionLength : 0);
break;
}
default:
result = AbstractInputMethod::selectionListData(type, index, role);
break;
}
return result;
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
}
void HunspellInputMethod::selectionListItemSelected(SelectionListModel::Type type, int index)
{
Q_UNUSED(type)
Q_D(HunspellInputMethod);
QString finalWord = d->wordCandidates.at(index);
reset();
inputContext()->commit(finalWord);
d->autoSpaceAllowed = true;
}
bool HunspellInputMethod::reselect(int cursorPosition, const InputEngine::ReselectFlags &reselectFlags)
{
Q_D(HunspellInputMethod);
Q_ASSERT(d->word.isEmpty());
if (d->dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded)
return false;
InputContext *ic = inputContext();
if (!ic)
return false;
const QString surroundingText = ic->surroundingText();
int replaceFrom = 0;
if (reselectFlags.testFlag(InputEngine::WordBeforeCursor)) {
for (int i = cursorPosition - 1; i >= 0; --i) {
QChar c = surroundingText.at(i);
if (!d->isValidInputChar(c))
break;
d->word.insert(0, c);
--replaceFrom;
}
while (replaceFrom < 0 && d->isJoiner(d->word.at(0))) {
d->word.remove(0, 1);
++replaceFrom;
}
}
if (reselectFlags.testFlag(InputEngine::WordAtCursor) && replaceFrom == 0) {
d->word.clear();
return false;
}
if (reselectFlags.testFlag(InputEngine::WordAfterCursor)) {
for (int i = cursorPosition; i < surroundingText.length(); ++i) {
QChar c = surroundingText.at(i);
if (!d->isValidInputChar(c))
break;
d->word.append(c);
}
while (replaceFrom > -d->word.length()) {
int lastPos = d->word.length() - 1;
if (!d->isJoiner(d->word.at(lastPos)))
break;
d->word.remove(lastPos, 1);
}
}
if (d->word.isEmpty())
return false;
if (reselectFlags.testFlag(InputEngine::WordAtCursor) && replaceFrom == -d->word.length()) {
d->word.clear();
return false;
}
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
if (d->isJoiner(d->word.at(0))) {
d->word.clear();
return false;
}
if (d->isJoiner(d->word.at(d->word.length() - 1))) {
d->word.clear();
return false;
}
ic->setPreeditText(d->word, QList<QInputMethodEvent::Attribute>(), replaceFrom, d->word.length());
d->autoSpaceAllowed = false;
if (d->updateSuggestions()) {
emit selectionListChanged(SelectionListModel::WordCandidateList);
emit selectionListActiveItemChanged(SelectionListModel::WordCandidateList, d->activeWordIndex);
}
return true;
}
void HunspellInputMethod::reset()
{
Q_D(HunspellInputMethod);
d->reset();
}
void HunspellInputMethod::update()
{
Q_D(HunspellInputMethod);
if (d->ignoreUpdate)
return;
if (!d->word.isEmpty()) {
QString finalWord = d->hasSuggestions() ? d->wordCandidates.at(d->activeWordIndex) : d->word;
d->reset();
inputContext()->commit(finalWord);
}
d->autoSpaceAllowed = false;
}
void HunspellInputMethod::updateSuggestions(const QStringList &wordList, int activeWordIndex)
{
Q_D(HunspellInputMethod);
if (d->dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded) {
update();
return;
}
d->wordCandidates.clear();
d->wordCandidates.append(wordList);
// Make sure the exact match is up-to-date
if (!d->word.isEmpty() && !d->wordCandidates.isEmpty() && d->wordCandidates.at(0) != d->word)
d->wordCandidates.replace(0, d->word);
d->activeWordIndex = activeWordIndex;
emit selectionListChanged(SelectionListModel::WordCandidateList);
emit selectionListActiveItemChanged(SelectionListModel::WordCandidateList, d->activeWordIndex);
}
void HunspellInputMethod::dictionaryLoadCompleted(bool success)
{
Q_D(HunspellInputMethod);
d->dictionaryState = success ? HunspellInputMethodPrivate::DictionaryReady :
HunspellInputMethodPrivate::DictionaryNotLoaded;
emit selectionListsChanged();
}
} // namespace QtVirtualKeyboard