From cd82993bed33982950878bffc87bad231c39fb29 Mon Sep 17 00:00:00 2001 From: "B.Melnik" Date: Fri, 10 Sep 2021 15:38:10 +0300 Subject: [PATCH] feat(Spellchecking): Update Spellchecker Closes: #3443 --- vendor/DOtherSide/lib/CMakeLists.txt | 6 +- .../lib/include/DOtherSide/DosSpellchecker.h | 34 ++-- vendor/DOtherSide/lib/src/DosSpellchecker.cpp | 147 ++++++++---------- 3 files changed, 84 insertions(+), 103 deletions(-) diff --git a/vendor/DOtherSide/lib/CMakeLists.txt b/vendor/DOtherSide/lib/CMakeLists.txt index fc47fc86b1..9f95766948 100644 --- a/vendor/DOtherSide/lib/CMakeLists.txt +++ b/vendor/DOtherSide/lib/CMakeLists.txt @@ -21,7 +21,11 @@ macro(add_target name type) set_target_properties(${name} PROPERTIES CXX_STANDARD 11 AUTOMOC ON) - target_include_directories(${name} PUBLIC include include/Qt) + if(APPLE) + target_include_directories(${name} PUBLIC include include/Qt ${CMAKE_SOURCE_DIR}/../../bottles/hunspell/include) + else() + target_include_directories(${name} PUBLIC include include/Qt) + endif() target_link_libraries(${name} PRIVATE Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick Qt5::Network) diff --git a/vendor/DOtherSide/lib/include/DOtherSide/DosSpellchecker.h b/vendor/DOtherSide/lib/include/DOtherSide/DosSpellchecker.h index 1918a941c7..13db7a4537 100644 --- a/vendor/DOtherSide/lib/include/DOtherSide/DosSpellchecker.h +++ b/vendor/DOtherSide/lib/include/DOtherSide/DosSpellchecker.h @@ -11,12 +11,12 @@ class Hunspell; #endif class QTextCodec; -class SpellChecker : public QSyntaxHighlighter +class SpellChecker : public QObject { Q_OBJECT - Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) - Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) - Q_PROPERTY(QQuickTextDocument* document READ textDocument WRITE setTextDocument NOTIFY textDocumentChanged) + Q_PROPERTY(QString lang READ lang WRITE setLang NOTIFY langChanged) + Q_PROPERTY(QString userDict READ userDict WRITE setUserDict NOTIFY userDictChanged) + public: explicit SpellChecker(QObject *parent = nullptr); ~SpellChecker(); @@ -25,30 +25,24 @@ public: Q_INVOKABLE QVariantList suggest(const QString &word); Q_INVOKABLE void ignoreWord(const QString &word); Q_INVOKABLE void addToUserWordlist(const QString &word); + Q_INVOKABLE bool isInit() const; - void setText(const QString& text); - const QString& text() const; + const QString& lang() const; + void setLang(const QString& lang); - const QString& displayText() const; - - QQuickTextDocument* textDocument() const; - void setTextDocument(QQuickTextDocument* document); + const QString& userDict() const; + void setUserDict(const QString& userDict); signals: - void textChanged(); - void displayTextChanged(); - void textDocumentChanged(); - -protected: - void highlightBlock(const QString &text) final; + void langChanged(); + void userDictChanged(); private: - void makeDisplayText(const QString& text); + void initHunspell(); private: - QString m_text; - QString m_displayText; - QString m_dictionaryPath; + QString m_lang; + QString m_userDict; QQuickTextDocument *m_document; #ifdef Q_OS_MACOS diff --git a/vendor/DOtherSide/lib/src/DosSpellchecker.cpp b/vendor/DOtherSide/lib/src/DosSpellchecker.cpp index ff3c395b65..256c71bc59 100644 --- a/vendor/DOtherSide/lib/src/DosSpellchecker.cpp +++ b/vendor/DOtherSide/lib/src/DosSpellchecker.cpp @@ -1,6 +1,9 @@ -#include "DosSpellchecker.h" +#include "../include/DOtherSide/DosSpellchecker.h" + +#ifdef Q_OS_MACOS + #include "hunspell/hunspell.hxx" +#endif -#include "hunspell.hxx" #include #include #include @@ -13,13 +16,49 @@ #include SpellChecker::SpellChecker(QObject *parent) - : QSyntaxHighlighter(parent) -{ - auto language = QLocale::system().bcp47Name(); - + : QObject(parent) #ifdef Q_OS_MACOS - QString dictFile = QApplication::applicationDirPath() + + "/dictionaries/" + language + "/index.dic"; - QString affixFile = QApplication::applicationDirPath() + + "/dictionaries/" + language + "/index.aff"; + , m_hunspell(nullptr) +#endif + , m_userDict("userDict_") +{ + +} + +SpellChecker::~SpellChecker() +{ +#ifdef Q_OS_MACOS + delete m_hunspell; +#endif +} + +bool SpellChecker::spell(const QString &word) +{ +#ifdef Q_OS_MACOS + return m_hunspell->spell(m_codec->fromUnicode(word).toStdString()); +#else + return true; +#endif +} + +bool SpellChecker::isInit() const +{ +#ifdef Q_OS_MACOS + return !m_hunspell; +#else + return true; +#endif +} + +void SpellChecker::initHunspell() +{ +#ifdef Q_OS_MACOS + if (m_hunspell) { + delete m_hunspell; + } + + QString dictFile = QApplication::applicationDirPath() + "/dictionaries/" + m_lang + "/index.dic"; + QString affixFile = QApplication::applicationDirPath() + "/dictionaries/" + m_lang + "/index.aff"; QByteArray dictFilePathBA = dictFile.toLocal8Bit(); QByteArray affixFilePathBA = affixFile.toLocal8Bit(); m_hunspell = new Hunspell(affixFilePathBA.constData(), @@ -49,7 +88,7 @@ SpellChecker::SpellChecker(QObject *parent) } m_codec = QTextCodec::codecForName(encoding.toLatin1().constData()); - QString userDict = "userDict_" + language + ".txt"; + QString userDict = m_userDict + m_lang + ".txt"; if (!userDict.isEmpty()) { QFile userDictonaryFile(userDict); @@ -70,22 +109,6 @@ SpellChecker::SpellChecker(QObject *parent) #endif } -SpellChecker::~SpellChecker() -{ -#ifdef Q_OS_MACOS - delete m_hunspell; -#endif -} - -bool SpellChecker::spell(const QString &word) -{ -#ifdef Q_OS_MACOS - return m_hunspell->spell(m_codec->fromUnicode(word).toStdString()); -#else - return true; -#endif -} - QVariantList SpellChecker::suggest(const QString &word) { int numSuggestions = 0; @@ -117,9 +140,7 @@ void SpellChecker::ignoreWord(const QString &word) void SpellChecker::addToUserWordlist(const QString &word) { #ifdef Q_OS_MACOS - auto language = QLocale::scriptToString(QLocale::system().script()); - - QString userDict = "userDict_" + language + ".txt"; + QString userDict = m_userDict + m_lang + ".txt"; if (!userDict.isEmpty()) { QFile userDictonaryFile(userDict); if (userDictonaryFile.open(QIODevice::Append)) { @@ -136,67 +157,29 @@ void SpellChecker::addToUserWordlist(const QString &word) #endif } -void SpellChecker::setText(const QString &text) +const QString& SpellChecker::lang() const { - if (m_text != text) { - m_text = text; - emit textChanged(); - makeDisplayText(m_text); + return m_lang; +} + +void SpellChecker::setLang(const QString& lang) +{ + if (m_lang != lang) { + m_lang = lang; + initHunspell(); + emit langChanged(); } } -const QString &SpellChecker::text() const +const QString& SpellChecker::userDict() const { - return m_text; + return m_userDict; } -const QString &SpellChecker::displayText() const +void SpellChecker::setUserDict(const QString& userDict) { - return m_displayText; -} - -QQuickTextDocument *SpellChecker::textDocument() const -{ - return m_document; -} - -void SpellChecker::setTextDocument(QQuickTextDocument *document) -{ - if (m_document != document) { - m_document = document; - setDocument(m_document->textDocument()); - emit textDocumentChanged(); + if (m_userDict != userDict) { + m_userDict = userDict; + emit userDictChanged(); } } - -void SpellChecker::highlightBlock(const QString &text) -{ - QTextCharFormat format; - format.setFontUnderline(true); - - QRegularExpression expression("\\S+"); - QRegularExpressionMatchIterator i = expression.globalMatch(text); - while(i.hasNext()) { - QRegularExpressionMatch match = i.next(); - if (!spell(match.captured())) { - setFormat(match.capturedStart(), match.capturedLength(), format); - } - } -} - -void SpellChecker::makeDisplayText(const QString &text) -{ - auto words = text.split(" "); - QString gPattern = "%1"; - - m_displayText = ""; // todo optimize delta - for (const auto& word: qAsConst(words)) { - if (!spell(word)) { - m_displayText.append(" " + gPattern.arg(word)); - } else { - m_displayText.append(" " + word); - } - } - - emit displayTextChanged(); -}