aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJarkko Koivikko <jarkko.koivikko@code-q.fi>2022-03-31 08:25:40 +0300
committerJarkko Koivikko <jarkko.koivikko@code-q.fi>2022-03-31 20:57:12 +0300
commitde69ef24b15fde429bbc04b7bffea667e83b8168 (patch)
treeb5907a059bfd73ad89ad5dc94e698ff59955c463 /src
parenta8f9d4b6a6c3fa05995d083482a8a6d3f2e05f93 (diff)
Cleanup direct hunspell.h include from hunspell module interface
Including the hunspellinputmethod.h module header was not possible without also having hunspell headers in the include path. This was because the module header included the hunspellworker_p.h header, which in turn had the dependency to hunspell.h. Fix this by making the following changes: - Use the common QObjectPrivate derived private class for virtual keyboard input methods QVirtualKeyboardAbstractInputMethod to enable use of private slots (to hide connections with the HunspellWorker class). - Move HunspellWordList class out of the hunspellworker_p.h header to another private header, which does not depend on the hunspell.h. - Use private slots in the HunspellInputMethodPrivate to communicate with the HunspellWorker. Change-Id: I2b2e0dc922237388108470a2ae8da3a145fa4078 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/CMakeLists.txt1
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod.cpp45
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.cpp46
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.h11
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p_p.h14
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellwordlist.cpp334
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellwordlist_p.h112
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellworker.cpp296
-rw-r--r--src/plugins/hunspell/hunspellinputmethod/hunspellworker_p.h61
9 files changed, 505 insertions, 415 deletions
diff --git a/src/plugins/hunspell/hunspellinputmethod/CMakeLists.txt b/src/plugins/hunspell/hunspellinputmethod/CMakeLists.txt
index d01f4eac..f07cf03f 100644
--- a/src/plugins/hunspell/hunspellinputmethod/CMakeLists.txt
+++ b/src/plugins/hunspell/hunspellinputmethod/CMakeLists.txt
@@ -10,6 +10,7 @@ qt_internal_add_module(HunspellInputMethodPrivate
hunspellinputmethod.cpp hunspellinputmethod_p.cpp hunspellinputmethod_p.h
hunspellinputmethod_p_p.h
hunspellworker.cpp hunspellworker_p.h
+ hunspellwordlist.cpp hunspellwordlist_p.h
qhunspellinputmethod_global.h
DEFINES
QHUNSPELLINPUTMETHOD_LIBRARY
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod.cpp b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod.cpp
index 0b365c08..d179e2a6 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod.cpp
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod.cpp
@@ -27,7 +27,7 @@
**
****************************************************************************/
-#include <QtHunspellInputMethod/private/hunspellinputmethod_p_p.h>
+#include "hunspellinputmethod_p.h"
#include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h>
#include <QLoggingCategory>
@@ -41,15 +41,13 @@ Q_LOGGING_CATEGORY(lcHunspell, "qt.virtualkeyboard.hunspell")
\internal
*/
-HunspellInputMethod::HunspellInputMethod(HunspellInputMethodPrivate *d_ptr, QObject *parent) :
- QVirtualKeyboardAbstractInputMethod(parent),
- d_ptr(d_ptr)
+HunspellInputMethod::HunspellInputMethod(HunspellInputMethodPrivate &dd, QObject *parent) :
+ QVirtualKeyboardAbstractInputMethod(dd, parent)
{
}
HunspellInputMethod::HunspellInputMethod(QObject *parent) :
- QVirtualKeyboardAbstractInputMethod(parent),
- d_ptr(new HunspellInputMethodPrivate(this))
+ QVirtualKeyboardAbstractInputMethod(*new HunspellInputMethodPrivate(this), parent)
{
}
@@ -374,40 +372,5 @@ void HunspellInputMethod::update()
d->autoSpaceAllowed = false;
}
-void HunspellInputMethod::updateSuggestions(const QSharedPointer<HunspellWordList> &wordList, int tag)
-{
- Q_D(HunspellInputMethod);
- if (d->dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded) {
- qCDebug(lcHunspell) << "updateSuggestions: skip (dictionary not loaded)";
- update();
- return;
- }
- if (d->wordCandidatesUpdateTag != tag) {
- qCDebug(lcHunspell) << "updateSuggestions: skip tag" << tag << "current" << d->wordCandidatesUpdateTag;
- return;
- }
- QString word(d->wordCandidates.wordAt(0));
- d->wordCandidates = *wordList;
- if (d->wordCandidates.wordAt(0).compare(word) != 0)
- d->wordCandidates.updateWord(0, word);
- emit selectionListChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList);
- emit selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList, d->wordCandidates.index());
-}
-
-void HunspellInputMethod::dictionaryLoadCompleted(bool success)
-{
- Q_D(HunspellInputMethod);
- QVirtualKeyboardInputContext *ic = inputContext();
- if (!ic)
- return;
-
- QList<QVirtualKeyboardSelectionListModel::Type> oldSelectionLists = selectionLists();
- d->dictionaryState = success ? HunspellInputMethodPrivate::DictionaryReady :
- HunspellInputMethodPrivate::DictionaryNotLoaded;
- QList<QVirtualKeyboardSelectionListModel::Type> newSelectionLists = selectionLists();
- if (oldSelectionLists != newSelectionLists)
- emit selectionListsChanged();
-}
-
} // namespace QtVirtualKeyboard
QT_END_NAMESPACE
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.cpp b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.cpp
index 4a54a332..9d01a7bf 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.cpp
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.cpp
@@ -27,9 +27,10 @@
**
****************************************************************************/
-#include <QtHunspellInputMethod/private/hunspellinputmethod_p_p.h>
+#include "hunspellinputmethod_p_p.h"
+#include "hunspellinputmethod_p.h"
+#include "hunspellworker_p.h"
#include <QtVirtualKeyboard/qvirtualkeyboardinputcontext.h>
-#include <hunspell/hunspell.h>
#include <QStringList>
#include <QDir>
#include <QtCore/QLibraryInfo>
@@ -94,7 +95,7 @@ bool HunspellInputMethodPrivate::createHunspell(const QString &locale)
searchPaths.append(defaultPath);
}
QSharedPointer<HunspellLoadDictionaryTask> loadDictionaryTask(new HunspellLoadDictionaryTask(locale, searchPaths));
- QObject::connect(loadDictionaryTask.data(), &HunspellLoadDictionaryTask::completed, q, &HunspellInputMethod::dictionaryLoadCompleted);
+ QObjectPrivate::connect(loadDictionaryTask.data(), &HunspellLoadDictionaryTask::completed, this, &HunspellInputMethodPrivate::dictionaryLoadCompleted);
dictionaryState = HunspellInputMethodPrivate::DictionaryLoading;
emit q->selectionListsChanged();
hunspellWorker->addTask(loadDictionaryTask);
@@ -154,8 +155,7 @@ bool HunspellInputMethodPrivate::updateSuggestions()
QSharedPointer<HunspellUpdateSuggestionsTask> updateSuggestionsTask(new HunspellUpdateSuggestionsTask());
updateSuggestionsTask->wordList = wordList;
updateSuggestionsTask->tag = ++wordCandidatesUpdateTag;
- Q_Q(HunspellInputMethod);
- QObject::connect(updateSuggestionsTask.data(), &HunspellUpdateSuggestionsTask::updateSuggestions, q, &HunspellInputMethod::updateSuggestions);
+ QObjectPrivate::connect(updateSuggestionsTask.data(), &HunspellUpdateSuggestionsTask::updateSuggestions, this, &HunspellInputMethodPrivate::updateSuggestionsCompleted);
hunspellWorker->addTask(updateSuggestionsTask);
}
}
@@ -333,5 +333,41 @@ void HunspellInputMethodPrivate::addToDictionary()
}
}
+void HunspellInputMethodPrivate::updateSuggestionsCompleted(const QSharedPointer<HunspellWordList> &wordList, int tag)
+{
+ if (dictionaryState == HunspellInputMethodPrivate::DictionaryNotLoaded) {
+ qCDebug(lcHunspell) << "updateSuggestions: skip (dictionary not loaded)";
+ Q_Q(HunspellInputMethod);
+ q->update();
+ return;
+ }
+ if (wordCandidatesUpdateTag != tag) {
+ qCDebug(lcHunspell) << "updateSuggestions: skip tag" << tag << "current" << wordCandidatesUpdateTag;
+ return;
+ }
+ QString word(wordCandidates.wordAt(0));
+ wordCandidates = *wordList;
+ if (wordCandidates.wordAt(0).compare(word) != 0)
+ wordCandidates.updateWord(0, word);
+ Q_Q(HunspellInputMethod);
+ emit q->selectionListChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList);
+ emit q->selectionListActiveItemChanged(QVirtualKeyboardSelectionListModel::Type::WordCandidateList, wordCandidates.index());
+}
+
+void HunspellInputMethodPrivate::dictionaryLoadCompleted(bool success)
+{
+ Q_Q(HunspellInputMethod);
+ QVirtualKeyboardInputContext *ic = q->inputContext();
+ if (!ic)
+ return;
+
+ QList<QVirtualKeyboardSelectionListModel::Type> oldSelectionLists = q->selectionLists();
+ dictionaryState = success ? HunspellInputMethodPrivate::DictionaryReady :
+ HunspellInputMethodPrivate::DictionaryNotLoaded;
+ QList<QVirtualKeyboardSelectionListModel::Type> newSelectionLists = q->selectionLists();
+ if (oldSelectionLists != newSelectionLists)
+ emit q->selectionListsChanged();
+}
+
} // namespace QtVirtualKeyboard
QT_END_NAMESPACE
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.h b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.h
index 6144536f..39c88f0c 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.h
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p.h
@@ -43,11 +43,11 @@
#include <QtVirtualKeyboard/qvirtualkeyboardabstractinputmethod.h>
#include <QtHunspellInputMethod/qhunspellinputmethod_global.h>
+#include <QtHunspellInputMethod/private/hunspellinputmethod_p_p.h>
QT_BEGIN_NAMESPACE
namespace QtVirtualKeyboard {
-class HunspellInputMethodPrivate;
class HunspellWordList;
class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellInputMethod : public QVirtualKeyboardAbstractInputMethod
@@ -55,7 +55,7 @@ class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellInputMethod : public QVirtualKeyboard
Q_OBJECT
Q_DECLARE_PRIVATE(HunspellInputMethod)
protected:
- HunspellInputMethod(HunspellInputMethodPrivate *d_ptr, QObject *parent);
+ HunspellInputMethod(HunspellInputMethodPrivate &dd, QObject *parent);
public:
explicit HunspellInputMethod(QObject *parent = nullptr);
~HunspellInputMethod();
@@ -77,13 +77,6 @@ public:
void reset() override;
void update() override;
-
-protected Q_SLOTS:
- void updateSuggestions(const QSharedPointer<HunspellWordList> &wordList, int tag);
- void dictionaryLoadCompleted(bool success);
-
-protected:
- QScopedPointer<HunspellInputMethodPrivate> d_ptr;
};
} // namespace QtVirtualKeyboard
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p_p.h b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p_p.h
index 763a8c43..42b862e5 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p_p.h
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellinputmethod_p_p.h
@@ -41,17 +41,21 @@
// We mean it.
//
-#include <QtHunspellInputMethod/private/hunspellinputmethod_p.h>
-#include <QtHunspellInputMethod/private/hunspellworker_p.h>
+#include <QtHunspellInputMethod/qhunspellinputmethod_global.h>
+#include <QtHunspellInputMethod/private/hunspellwordlist_p.h>
+#include <QtVirtualKeyboard/private/qvirtualkeyboardabstractinputmethod_p.h>
QT_BEGIN_NAMESPACE
namespace QtVirtualKeyboard {
-class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellInputMethodPrivate
+class HunspellInputMethod;
+class HunspellWorker;
+
+class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellInputMethodPrivate : public QVirtualKeyboardAbstractInputMethodPrivate
{
+public:
Q_DECLARE_PUBLIC(HunspellInputMethod)
-public:
HunspellInputMethodPrivate(HunspellInputMethod *q_ptr);
~HunspellInputMethodPrivate();
@@ -76,6 +80,8 @@ public:
void removeFromHunspell(const QSharedPointer<HunspellWordList> &wordList) const;
void removeFromDictionary(const QString &word);
void addToDictionary();
+ void updateSuggestionsCompleted(const QSharedPointer<HunspellWordList> &wordList, int tag);
+ void dictionaryLoadCompleted(bool success);
HunspellInputMethod *q_ptr;
QScopedPointer<HunspellWorker> hunspellWorker;
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist.cpp b/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist.cpp
new file mode 100644
index 00000000..87b3ad24
--- /dev/null
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 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 "hunspellwordlist_p.h"
+#include <QtAlgorithms>
+#include <hunspell/hunspell.h>
+
+QT_BEGIN_NAMESPACE
+namespace QtVirtualKeyboard {
+
+/*!
+ \class QtVirtualKeyboard::HunspellWordList
+ \internal
+*/
+
+HunspellWordList::HunspellWordList(int limit) :
+ _index(0),
+ _limit(limit)
+{
+}
+
+HunspellWordList::HunspellWordList(HunspellWordList &other)
+{
+ *this = other;
+}
+
+HunspellWordList &HunspellWordList::operator=(HunspellWordList &other)
+{
+ if (this != &other) {
+ QMutexLocker guard(&_lock);
+ QMutexLocker otherGuard(&other._lock);
+ _list = other._list;
+ _flags = other._flags;
+ _index = other._index;
+ _limit = other._limit;
+ _searchIndex = other._searchIndex;
+ }
+ return *this;
+}
+
+int HunspellWordList::index() const
+{
+ return _index < _list.size() ? _index : -1;
+}
+
+void HunspellWordList::setIndex(int index)
+{
+ QMutexLocker guard(&_lock);
+ _index = index;
+}
+
+bool HunspellWordList::clear()
+{
+ QMutexLocker guard(&_lock);
+ bool result = !_list.isEmpty();
+ _list.clear();
+ _flags.clear();
+ _index = 0;
+ _searchIndex.clear();
+ return result;
+}
+
+bool HunspellWordList::clearSuggestions()
+{
+ QMutexLocker guard(&_lock);
+ if (_list.isEmpty())
+ return false;
+
+ _searchIndex.clear();
+ if (_list.size() > 1) {
+ QString word = _list.at(0);
+ Flags flags = _flags.at(0);
+ _list.clear();
+ _flags.clear();
+ if (!word.isEmpty()) {
+ _index = 0;
+ _list.append(word);
+ _flags.append(flags);
+ }
+ return true;
+ } else if (_list.at(0).isEmpty()) {
+ _list.clear();
+ _flags.clear();
+ _index = 0;
+ return true;
+ }
+ return false;
+}
+
+bool HunspellWordList::hasSuggestions() const
+{
+ return _list.size() > 1;
+}
+
+int HunspellWordList::size() const
+{
+ return _list.size();
+}
+
+int HunspellWordList::isEmpty() const
+{
+ return _list.isEmpty() || _list.at(0).isEmpty();
+}
+
+bool HunspellWordList::contains(const QString &word)
+{
+ QMutexLocker guard(&_lock);
+
+ // Use index search when the search index is available.
+ // This provides a lot faster search than QList::contains().
+ // Search index is available when it has been rebuilt using
+ // rebuildSearchIndex() method. Search index is automatically
+ // cleared when the word list is modified.
+ if (!_searchIndex.isEmpty()) {
+ Q_ASSERT(_searchIndex.size() == _list.size());
+
+ SearchContext searchContext(word, _list);
+ return std::binary_search(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](const int &a, const int &b) {
+ const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
+ const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
+ return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
+ });
+ }
+
+ return _list.contains(word, Qt::CaseInsensitive);
+}
+
+QString HunspellWordList::findWordCompletion(const QString &word)
+{
+ QMutexLocker guard(&_lock);
+
+ if (!_searchIndex.isEmpty()) {
+ Q_ASSERT(_searchIndex.size() == _list.size());
+
+ SearchContext searchContext(word, _list);
+ auto match = std::lower_bound(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](const int &a, const int &b) {
+ const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
+ const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
+ return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
+ });
+
+ if (match == _searchIndex.end())
+ return QString();
+
+ if (!word.compare(_list[*match], Qt::CaseInsensitive)) {
+ match++;
+ if (match == _searchIndex.end())
+ return QString();
+ }
+
+ return _list[*match].startsWith(word, Qt::CaseInsensitive) ? _list[*match] : QString();
+ }
+
+ QString bestMatch;
+ for (int i = 0, count = _list.size(); i < count; ++i) {
+ const QString &wordB(_list[i]);
+ if (wordB.length() > bestMatch.length() &&
+ word.length() < wordB.length() &&
+ wordB.startsWith(word, Qt::CaseInsensitive))
+ bestMatch = wordB;
+ }
+
+ return bestMatch;
+}
+
+int HunspellWordList::indexOfWord(const QString &word)
+{
+ QMutexLocker guard(&_lock);
+
+ if (!_searchIndex.isEmpty()) {
+ Q_ASSERT(_searchIndex.size() == _list.size());
+
+ SearchContext searchContext(word, _list);
+ auto match = std::lower_bound(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](int a, int b) {
+ const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
+ const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
+ return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
+ });
+ return (match != _searchIndex.end()) ? *match : -1;
+ }
+
+ return _list.indexOf(word);
+}
+
+QString HunspellWordList::wordAt(int index)
+{
+ QMutexLocker guard(&_lock);
+
+ return index >= 0 && index < _list.size() ? _list.at(index) : QString();
+}
+
+void HunspellWordList::wordAt(int index, QString &word, Flags &flags)
+{
+ QMutexLocker guard(&_lock);
+ Q_ASSERT(index >= 0 && index < _list.size());
+
+ word = _list.at(index);
+ flags = _flags.at(index);
+}
+
+const HunspellWordList::Flags &HunspellWordList::wordFlagsAt(int index)
+{
+ QMutexLocker guard(&_lock);
+
+ return _flags[index];
+}
+
+void HunspellWordList::appendWord(const QString &word, const Flags &flags)
+{
+ QMutexLocker guard(&_lock);
+
+ _searchIndex.clear();
+ if (_limit > 0) {
+ while (_list.size() >= _limit) {
+ _list.removeAt(0);
+ _flags.removeAt(0);
+ }
+ }
+ _list.append(word);
+ _flags.append(flags);
+}
+
+void HunspellWordList::insertWord(int index, const QString &word, const Flags &flags)
+{
+ QMutexLocker guard(&_lock);
+ Q_ASSERT(_limit == 0);
+
+ _searchIndex.clear();
+ _list.insert(index, word);
+ _flags.insert(index, flags);
+}
+
+void HunspellWordList::updateWord(int index, const QString &word, const Flags &flags)
+{
+ Q_ASSERT(index >= 0);
+ QMutexLocker guard(&_lock);
+
+ if (index < _list.size()) {
+ if (word != _list[index])
+ _searchIndex.clear();
+ _list[index] = word;
+ _flags[index] = flags;
+ } else {
+ _searchIndex.clear();
+ _list.append(word);
+ _flags.append(flags);
+ }
+}
+
+void HunspellWordList::moveWord(int from, int to)
+{
+ QMutexLocker guard(&_lock);
+
+ if (from < 0 || from >= _list.size())
+ return;
+ if (to < 0 || to >= _list.size())
+ return;
+ if (from == to)
+ return;
+
+ _searchIndex.clear();
+ _list.move(from, to);
+ _flags.move(from, to);
+}
+
+int HunspellWordList::removeWord(const QString &word)
+{
+ QMutexLocker guard(&_lock);
+ int removeCount = 0;
+ for (int i = 0, count = _list.size(); i < count;) {
+ if (!_list[i].compare(word, Qt::CaseInsensitive)) {
+ _list.removeAt(i);
+ _flags.removeAt(i);
+ --count;
+ ++removeCount;
+ } else {
+ ++i;
+ }
+ }
+ if (removeCount > 0)
+ _searchIndex.clear();
+ return removeCount;
+}
+
+void HunspellWordList::removeWordAt(int index)
+{
+ QMutexLocker guard(&_lock);
+
+ _list.removeAt(index);
+}
+
+void HunspellWordList::rebuildSearchIndex()
+{
+ QMutexLocker guard(&_lock);
+ _searchIndex.clear();
+
+ if (_list.isEmpty())
+ return;
+
+ _searchIndex.resize(_list.size());
+ std::iota(_searchIndex.begin(), _searchIndex.end(), 0);
+
+ const QStringList list(_list);
+ std::sort(_searchIndex.begin(), _searchIndex.end(), [list](int a, int b) { return list[a].compare(list[b], Qt::CaseInsensitive) < 0; });
+}
+
+} // namespace QtVirtualKeyboard
+QT_END_NAMESPACE
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist_p.h b/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist_p.h
new file mode 100644
index 00000000..036076a1
--- /dev/null
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellwordlist_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 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$
+**
+****************************************************************************/
+
+#ifndef HUNSPELLWORDLIST_P_H
+#define HUNSPELLWORDLIST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QMutex>
+#include <QStringList>
+#include <QtHunspellInputMethod/qhunspellinputmethod_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtVirtualKeyboard {
+
+class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellWordList
+{
+public:
+ enum Flag
+ {
+ SpellCheckOk = 0x1,
+ CompoundWord = 0x2
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ HunspellWordList(int limit = 0);
+ HunspellWordList(HunspellWordList &other);
+
+ HunspellWordList &operator=(HunspellWordList &other);
+
+ int index() const;
+ void setIndex(int index);
+ bool clear();
+ bool clearSuggestions();
+ bool hasSuggestions() const;
+ int size() const;
+ int isEmpty() const;
+ bool contains(const QString &word);
+ QString findWordCompletion(const QString &word);
+ int indexOfWord(const QString &word);
+ QString wordAt(int index);
+ void wordAt(int index, QString &word, Flags &flags);
+ const Flags &wordFlagsAt(int index);
+ void appendWord(const QString &word, const Flags &flags = Flags());
+ void insertWord(int index, const QString &word, const Flags &flags = Flags());
+ void updateWord(int index, const QString &word, const Flags &flags = Flags());
+ void moveWord(int from, int to);
+ int removeWord(const QString &word);
+ void removeWordAt(int index);
+ void rebuildSearchIndex();
+
+private:
+ class SearchContext {
+ public:
+ SearchContext(const QString &word,
+ const QStringList &list) :
+ word(word),
+ list(list)
+ {}
+ const QString &word;
+ const QStringList &list;
+ };
+
+private:
+ QMutex _lock;
+ QStringList _list;
+ QList<Flags> _flags;
+ QList<int> _searchIndex;
+ int _index;
+ int _limit;
+};
+
+} // namespace QtVirtualKeyboard
+QT_END_NAMESPACE
+
+#endif // HUNSPELLWORDLIST_P_H
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellworker.cpp b/src/plugins/hunspell/hunspellinputmethod/hunspellworker.cpp
index 51926eec..16d5fd62 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellworker.cpp
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellworker.cpp
@@ -39,308 +39,12 @@
QT_BEGIN_NAMESPACE
namespace QtVirtualKeyboard {
-HunspellWordList::HunspellWordList(int limit) :
- _index(0),
- _limit(limit)
-{
-}
-
-HunspellWordList::HunspellWordList(HunspellWordList &other)
-{
- *this = other;
-}
-
-HunspellWordList &HunspellWordList::operator=(HunspellWordList &other)
-{
- if (this != &other) {
- QMutexLocker guard(&_lock);
- QMutexLocker otherGuard(&other._lock);
- _list = other._list;
- _flags = other._flags;
- _index = other._index;
- _limit = other._limit;
- _searchIndex = other._searchIndex;
- }
- return *this;
-}
-
-int HunspellWordList::index() const
-{
- return _index < _list.size() ? _index : -1;
-}
-
-void HunspellWordList::setIndex(int index)
-{
- QMutexLocker guard(&_lock);
- _index = index;
-}
-
-bool HunspellWordList::clear()
-{
- QMutexLocker guard(&_lock);
- bool result = !_list.isEmpty();
- _list.clear();
- _flags.clear();
- _index = 0;
- _searchIndex.clear();
- return result;
-}
-
-bool HunspellWordList::clearSuggestions()
-{
- QMutexLocker guard(&_lock);
- if (_list.isEmpty())
- return false;
-
- _searchIndex.clear();
- if (_list.size() > 1) {
- QString word = _list.at(0);
- Flags flags = _flags.at(0);
- _list.clear();
- _flags.clear();
- if (!word.isEmpty()) {
- _index = 0;
- _list.append(word);
- _flags.append(flags);
- }
- return true;
- } else if (_list.at(0).isEmpty()) {
- _list.clear();
- _flags.clear();
- _index = 0;
- return true;
- }
- return false;
-}
-
-bool HunspellWordList::hasSuggestions() const
-{
- return _list.size() > 1;
-}
-
-int HunspellWordList::size() const
-{
- return _list.size();
-}
-
-int HunspellWordList::isEmpty() const
-{
- return _list.isEmpty() || _list.at(0).isEmpty();
-}
-
-bool HunspellWordList::contains(const QString &word)
-{
- QMutexLocker guard(&_lock);
-
- // Use index search when the search index is available.
- // This provides a lot faster search than QList::contains().
- // Search index is available when it has been rebuilt using
- // rebuildSearchIndex() method. Search index is automatically
- // cleared when the word list is modified.
- if (!_searchIndex.isEmpty()) {
- Q_ASSERT(_searchIndex.size() == _list.size());
-
- SearchContext searchContext(word, _list);
- return std::binary_search(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](const int &a, const int &b) {
- const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
- const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
- return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
- });
- }
-
- return _list.contains(word, Qt::CaseInsensitive);
-}
-
-QString HunspellWordList::findWordCompletion(const QString &word)
-{
- QMutexLocker guard(&_lock);
-
- if (!_searchIndex.isEmpty()) {
- Q_ASSERT(_searchIndex.size() == _list.size());
-
- SearchContext searchContext(word, _list);
- auto match = std::lower_bound(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](const int &a, const int &b) {
- const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
- const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
- return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
- });
-
- if (match == _searchIndex.end())
- return QString();
-
- if (!word.compare(_list[*match], Qt::CaseInsensitive)) {
- match++;
- if (match == _searchIndex.end())
- return QString();
- }
-
- return _list[*match].startsWith(word, Qt::CaseInsensitive) ? _list[*match] : QString();
- }
-
- QString bestMatch;
- for (int i = 0, count = _list.size(); i < count; ++i) {
- const QString &wordB(_list[i]);
- if (wordB.length() > bestMatch.length() &&
- word.length() < wordB.length() &&
- wordB.startsWith(word, Qt::CaseInsensitive))
- bestMatch = wordB;
- }
-
- return bestMatch;
-}
-
-int HunspellWordList::indexOfWord(const QString &word)
-{
- QMutexLocker guard(&_lock);
-
- if (!_searchIndex.isEmpty()) {
- Q_ASSERT(_searchIndex.size() == _list.size());
-
- SearchContext searchContext(word, _list);
- auto match = std::lower_bound(_searchIndex.begin(), _searchIndex.end(), -1, [searchContext](int a, int b) {
- const QString &wordA = (a == -1) ? searchContext.word : searchContext.list[a];
- const QString &wordB = (b == -1) ? searchContext.word : searchContext.list[b];
- return wordA.compare(wordB, Qt::CaseInsensitive) < 0;
- });
- return (match != _searchIndex.end()) ? *match : -1;
- }
-
- return _list.indexOf(word);
-}
-
-QString HunspellWordList::wordAt(int index)
-{
- QMutexLocker guard(&_lock);
-
- return index >= 0 && index < _list.size() ? _list.at(index) : QString();
-}
-
-void HunspellWordList::wordAt(int index, QString &word, Flags &flags)
-{
- QMutexLocker guard(&_lock);
- Q_ASSERT(index >= 0 && index < _list.size());
-
- word = _list.at(index);
- flags = _flags.at(index);
-}
-
-const HunspellWordList::Flags &HunspellWordList::wordFlagsAt(int index)
-{
- QMutexLocker guard(&_lock);
-
- return _flags[index];
-}
-
-void HunspellWordList::appendWord(const QString &word, const Flags &flags)
-{
- QMutexLocker guard(&_lock);
-
- _searchIndex.clear();
- if (_limit > 0) {
- while (_list.size() >= _limit) {
- _list.removeAt(0);
- _flags.removeAt(0);
- }
- }
- _list.append(word);
- _flags.append(flags);
-}
-
-void HunspellWordList::insertWord(int index, const QString &word, const Flags &flags)
-{
- QMutexLocker guard(&_lock);
- Q_ASSERT(_limit == 0);
-
- _searchIndex.clear();
- _list.insert(index, word);
- _flags.insert(index, flags);
-}
-
-void HunspellWordList::updateWord(int index, const QString &word, const Flags &flags)
-{
- Q_ASSERT(index >= 0);
- QMutexLocker guard(&_lock);
-
- if (index < _list.size()) {
- if (word != _list[index])
- _searchIndex.clear();
- _list[index] = word;
- _flags[index] = flags;
- } else {
- _searchIndex.clear();
- _list.append(word);
- _flags.append(flags);
- }
-}
-
-void HunspellWordList::moveWord(int from, int to)
-{
- QMutexLocker guard(&_lock);
-
- if (from < 0 || from >= _list.size())
- return;
- if (to < 0 || to >= _list.size())
- return;
- if (from == to)
- return;
-
- _searchIndex.clear();
- _list.move(from, to);
- _flags.move(from, to);
-}
-
-int HunspellWordList::removeWord(const QString &word)
-{
- QMutexLocker guard(&_lock);
- int removeCount = 0;
- for (int i = 0, count = _list.size(); i < count;) {
- if (!_list[i].compare(word, Qt::CaseInsensitive)) {
- _list.removeAt(i);
- _flags.removeAt(i);
- --count;
- ++removeCount;
- } else {
- ++i;
- }
- }
- if (removeCount > 0)
- _searchIndex.clear();
- return removeCount;
-}
-
-void HunspellWordList::removeWordAt(int index)
-{
- QMutexLocker guard(&_lock);
-
- _list.removeAt(index);
-}
-
-void HunspellWordList::rebuildSearchIndex()
-{
- QMutexLocker guard(&_lock);
- _searchIndex.clear();
-
- if (_list.isEmpty())
- return;
-
- _searchIndex.resize(_list.size());
- std::iota(_searchIndex.begin(), _searchIndex.end(), 0);
-
- const QStringList list(_list);
- std::sort(_searchIndex.begin(), _searchIndex.end(), [list](int a, int b) { return list[a].compare(list[b], Qt::CaseInsensitive) < 0; });
-}
-
/*!
\class QtVirtualKeyboard::HunspellTask
\internal
*/
/*!
- \class QtVirtualKeyboard::HunspellWordList
- \internal
-*/
-
-/*!
\class QtVirtualKeyboard::HunspellLoadDictionaryTask
\internal
*/
diff --git a/src/plugins/hunspell/hunspellinputmethod/hunspellworker_p.h b/src/plugins/hunspell/hunspellinputmethod/hunspellworker_p.h
index 187f9f70..aa1dd078 100644
--- a/src/plugins/hunspell/hunspellinputmethod/hunspellworker_p.h
+++ b/src/plugins/hunspell/hunspellinputmethod/hunspellworker_p.h
@@ -51,7 +51,7 @@
#include <QStringDecoder>
#include <QStringEncoder>
#include <hunspell/hunspell.h>
-#include <QtHunspellInputMethod/qhunspellinputmethod_global.h>
+#include "hunspellwordlist_p.h"
QT_BEGIN_NAMESPACE
@@ -59,63 +59,6 @@ namespace QtVirtualKeyboard {
Q_DECLARE_LOGGING_CATEGORY(lcHunspell)
-class Q_HUNSPELLINPUTMETHOD_EXPORT HunspellWordList
-{
-public:
- enum Flag
- {
- SpellCheckOk = 0x1,
- CompoundWord = 0x2
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- HunspellWordList(int limit = 0);
- HunspellWordList(HunspellWordList &other);
-
- HunspellWordList &operator=(HunspellWordList &other);
-
- int index() const;
- void setIndex(int index);
- bool clear();
- bool clearSuggestions();
- bool hasSuggestions() const;
- int size() const;
- int isEmpty() const;
- bool contains(const QString &word);
- QString findWordCompletion(const QString &word);
- int indexOfWord(const QString &word);
- QString wordAt(int index);
- void wordAt(int index, QString &word, Flags &flags);
- const Flags &wordFlagsAt(int index);
- void appendWord(const QString &word, const Flags &flags = Flags());
- void insertWord(int index, const QString &word, const Flags &flags = Flags());
- void updateWord(int index, const QString &word, const Flags &flags = Flags());
- void moveWord(int from, int to);
- int removeWord(const QString &word);
- void removeWordAt(int index);
- void rebuildSearchIndex();
-
-private:
- class SearchContext {
- public:
- SearchContext(const QString &word,
- const QStringList &list) :
- word(word),
- list(list)
- {}
- const QString &word;
- const QStringList &list;
- };
-
-private:
- QMutex _lock;
- QStringList _list;
- QList<Flags> _flags;
- QList<int> _searchIndex;
- int _index;
- int _limit;
-};
-
class HunspellTask : public QObject
{
Q_OBJECT
@@ -293,6 +236,4 @@ private:
} // namespace QtVirtualKeyboard
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QSharedPointer<QT_PREPEND_NAMESPACE(QtVirtualKeyboard)::HunspellWordList>);
-
#endif // HUNSPELLWORKER_P_H