void-packages/srcpkgs/linphone-desktop/patches/0003-Replace-ispell-with-So...

334 lines
10 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 2caec486443ea86fc735be993f1eff457570e3f6 Mon Sep 17 00:00:00 2001
From: John Zimmermann <me@johnnynator.dev>
Date: Sat, 3 Aug 2024 17:47:00 +0200
Subject: [PATCH 3/3] Replace ispell with Sonnet
---
linphone-app/CMakeLists.txt | 12 +-
.../other/spell-checker/SpellChecker.hpp | 34 ++--
.../other/spell-checker/SpellCheckerLinux.cpp | 186 ++----------------
3 files changed, 26 insertions(+), 206 deletions(-)
diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt
index d2b5dcde..770234db 100644
--- a/linphone-app/CMakeLists.txt
+++ b/linphone-app/CMakeLists.txt
@@ -126,13 +126,7 @@ if(ENABLE_QT_KEYCHAIN)
endif()
if(NOT APPLE AND NOT WIN32)
- if(NOT ISPELL_TARGET_NAME)
- set(ISPELL_TARGET_NAME "ISpell")
- endif()
- find_package(${ISPELL_TARGET_NAME})
- if(NOT ISpell_FOUND)
- find_package(${ISPELL_TARGET_NAME} CONFIG REQUIRED)
- endif()
+ find_package(KF5Sonnet REQUIRED)
endif()
if(ENABLE_BUILD_VERBOSE)
@@ -198,7 +192,7 @@ if( ENABLE_QT_KEYCHAIN)
list(APPEND APP_TARGETS ${QTKEYCHAIN_TARGET_NAME})
endif()
if(NOT APPLE AND NOT WIN32)
- list(APPEND APP_TARGETS ${ISPELL_TARGET_NAME})
+ list(APPEND APP_TARGETS KF5::SonnetCore)
endif()
if (UNIX AND NOT APPLE)
list(APPEND QT5_PACKAGES DBus)
diff --git a/linphone-app/src/components/other/spell-checker/SpellChecker.hpp b/linphone-app/src/components/other/spell-checker/SpellChecker.hpp
index 84d9abdf..37a1dd8b 100644
--- a/linphone-app/src/components/other/spell-checker/SpellChecker.hpp
+++ b/linphone-app/src/components/other/spell-checker/SpellChecker.hpp
@@ -39,7 +39,7 @@
#include "components/settings/SettingsModel.hpp"
#ifdef __linux__
-#include <thread>
+#include <Sonnet/Speller>
#endif
#define SUGGESTIONS_LIMIT 10
@@ -57,7 +57,7 @@ class SpellChecker : public QSyntaxHighlighter {
public:
SpellChecker(QObject* parent = nullptr);
~SpellChecker();
-
+
// Common
static QString currentLanguage() {
QString overrideLocale = CoreManager::getInstance()->getSettingsModel()->getSpellCheckerOverrideLocale();
@@ -72,21 +72,21 @@ public:
Q_INVOKABLE void ignoreAll(QString word);
Q_INVOKABLE void replace(QString word, QString byWord, int cursorPosition);
Q_PROPERTY(QStringList redLines MEMBER redLines NOTIFY redLinesChanged);
-
+
// Native (Mac/Windows) or ISpell
Q_INVOKABLE void learn(QString word);
Q_INVOKABLE QStringList suggestionsForWord(QString word);
bool isValid(QString word);
-
+
protected:
void highlightBlock(const QString &text) override;
-
+
public slots:
void highlightAfterGracePeriod();
-
+
signals:
void redLinesChanged();
-
+
private:
QTextCharFormat errorFormater;
QTimer *graceTimer;
@@ -111,24 +111,12 @@ private:
#ifdef _WIN32
ISpellChecker* mNativeSpellChecker = nullptr;
#endif
-
-// ISpell linux
+
+// nuspell linux
#ifdef __linux__
- static int gISpell_sc_read_fd;
- static int gISpell_sc_write_fd;
- static int gISpell_app_read_fd;
- static int gISpell_app_write_fd;
- static std::thread *gISpellCheckerThread;
- static QHash<QString,QStringList> gISpellSuggestions;
- static std::string gISpellCheckeCurrentLanguage;
- static std::string gIspellDictionariesFolder;
- void stopISpellChecker();
- static std::shared_ptr<linphone::Config> gISpellSelfDictionary;
- bool isLearnt(QString word);
- bool wordValidWithFrVariants(QString word);
- bool validSplittedOn(QString pattern, QString word);
+ Sonnet::Speller dict;
#endif
-
+
};
diff --git a/linphone-app/src/components/other/spell-checker/SpellCheckerLinux.cpp b/linphone-app/src/components/other/spell-checker/SpellCheckerLinux.cpp
index a9a56a48..4cb586dd 100644
--- a/linphone-app/src/components/other/spell-checker/SpellCheckerLinux.cpp
+++ b/linphone-app/src/components/other/spell-checker/SpellCheckerLinux.cpp
@@ -18,196 +18,34 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#include "SpellChecker.hpp"
-#include <libispell.h>
-#include "app/paths/Paths.hpp"
-#include <unistd.h>
-#include <cstdio>
-#include <string>
+#include <Sonnet/Speller>
#include <linphone++/linphone.hh>
-#include "utils/Utils.hpp"
-#include <QCryptographicHash>
-
-int SpellChecker::gISpell_sc_read_fd = 0;
-int SpellChecker::gISpell_sc_write_fd = 0;
-int SpellChecker::gISpell_app_read_fd = 0;
-int SpellChecker::gISpell_app_write_fd = 0;
-std::thread *SpellChecker::gISpellCheckerThread = nullptr;
-QHash<QString,QStringList> SpellChecker::gISpellSuggestions;
-std::string SpellChecker::gISpellCheckeCurrentLanguage;
-std::shared_ptr<linphone::Config> SpellChecker::gISpellSelfDictionary = linphone::Factory::get()->createConfig(Paths::getISpellOwnDictsDirPath());
-std::string SpellChecker::gIspellDictionariesFolder;
-
-
-bool open_channel(int& read_fd, int& write_fd) {
- int vals[2];
- int errc = pipe(vals);
- if(errc) {
- return false;
- } else {
- read_fd = vals[0];
- write_fd = vals[1];
- return true;
- }
-}
-
-void SpellChecker::stopISpellChecker() {
- QString stop("__spellchecker_stop__");
- auto message = stop.toStdString();
- ssize_t amnt_written = write(gISpell_sc_write_fd, message.data(), message.size());
- if(amnt_written != message.size()) {
- qWarning() << LOG_TAG << "Linux ispell unable to stop spell checker";
- }
- gISpellCheckerThread->join();
- gISpellCheckerThread = nullptr;
- mAvailable = false;
-}
void SpellChecker::setLanguage() {
-
- QString locale = SpellChecker::currentLanguage().toLower().mid(0,2);
-
- if (gISpellCheckeCurrentLanguage == locale.toStdString() && gISpellCheckerThread != nullptr) {
- mAvailable = true;
- return;
- }
-
- if (gISpellCheckerThread != nullptr) // Language change
- stopISpellChecker();
-
- QString dict = Paths::getISpellDictsDirPath()+locale+".hash";
- gIspellDictionariesFolder = Paths::getISpellDictsDirPath().toStdString();
-
- if (!QFile::exists(dict)) {
- qWarning() << LOG_TAG << "Linux ispell language not supported " << SpellChecker::currentLanguage() << dict;
- mAvailable = false;
- return;
- }
-
- if (!open_channel(gISpell_sc_read_fd, gISpell_sc_write_fd) ||
- !open_channel(gISpell_app_read_fd, gISpell_app_write_fd)) {
- qWarning() << LOG_TAG << "Linux ispell language unable to open channels";
- mAvailable = false;
- return;
- }
-
- gISpellCheckeCurrentLanguage = locale.toStdString();
- gISpellCheckerThread = new std::thread(bc_spell_checker,
- gIspellDictionariesFolder.data(),
- gISpellCheckeCurrentLanguage.data(),
- gISpell_sc_read_fd,
- gISpell_app_write_fd);
-
- mAvailable = true;
- qDebug() << LOG_TAG << "Linux ispell language loaded from " << dict;
-}
-
-// Few special situation in French language not detected by the fr.hash.
-
-bool SpellChecker::wordValidWithFrVariants(QString word) {
- if (word.toLower().contains("qu'")) {
- QString replace = word.toLower().replace("qu'","que ");
- if (isValid(replace)||validSplittedOn(" ",replace))
- return true;
- }
- if (word.toLower().contains("s'")) {
- QString replace = word.toLower().replace("s'","se ");
- if (isValid(replace)||validSplittedOn(" ",replace))
- return true;
- }
- return false;
-}
-bool SpellChecker::validSplittedOn(QString pattern, QString word) {
- if (!word.contains(pattern))
- return false;
- auto split = word.split(pattern);
- return isValid(split[0]) && isValid(split[1]);
+ dict = Sonnet::Speller(SpellChecker::currentLanguage());
+ mAvailable = dict.isValid();
+ qDebug() << LOG_TAG << "Linux ispell language loaded: " << SpellChecker::currentLanguage();
}
bool SpellChecker::isValid(QString word) {
-
- if (!mAvailable || word.length() == 1 || isLearnt(word))
- return true;
-
- // no letters in word -> valid
- QString wordCopy = word;
- auto iterator = std::remove_if(wordCopy.begin(), wordCopy.end(), [](const QChar& c){ return !c.isLetter();});
- wordCopy.chop(std::distance(iterator, wordCopy.end()));
- if (wordCopy.isEmpty())
- return true;
-
- // Some preformating
-
- word = word.replace("","'");
- word = word.replace("(","");
- word = word.replace(")","");
- word = word.replace("","'");
-
- while (word.endsWith(".") || word.endsWith("!") || word.endsWith(",") || word.endsWith(","))
- word.chop(1);
-
- while (word.startsWith(".") || word.startsWith("!") || word.startsWith(",") || word.startsWith(",")) {
- word = word.mid(1);
- }
-
- // submit word to ispell
- auto message = word.toStdString();
- ssize_t amnt_written = write(gISpell_sc_write_fd, message.data(), message.size());
- if(amnt_written != message.size()) {
- qWarning() << LOG_TAG << "Linux ispell unable to communicate with spell checker thread";
+
+ if (!mAvailable || word.length() == 1)
return true;
- }
-
- // wait and read ispell result
- constexpr int buffer_size = 1024;
- char buffer[buffer_size] = {0};
- ssize_t amnt_read = read(gISpell_app_read_fd, &buffer[0], buffer_size);
- QString returned = QString::fromUtf8(buffer);
- if (returned == "1") {
+
+ if(dict.isCorrect(word)) {
return true;
- } else {
- if (!gISpellSuggestions.contains(word)) { // Record returned suggestions if any
- QStringList returnedUggestions = returned.split(", ");
- returnedUggestions.removeFirst();
- gISpellSuggestions.insert(word,returnedUggestions);
- }
- return (gISpellCheckeCurrentLanguage == "fr" && wordValidWithFrVariants(word)) ||
- validSplittedOn("'",word) ||
- validSplittedOn("-",word);
- }
+ }
+ return false;
}
void SpellChecker::learn(QString word){
- QCryptographicHash hash( QCryptographicHash::Sha1 ); // Hash to avoid fancy character conflict with config format.
- hash.addData(word.toUtf8());
- auto hashString = Utils::appStringToCoreString(hash.result().toHex());
- gISpellSelfDictionary->setInt("words",hashString,1);
- gISpellSelfDictionary->sync();
+ dict.addToPersonal(word);
highlightDocument();
}
-bool SpellChecker::isLearnt(QString word){
- QCryptographicHash hash( QCryptographicHash::Sha1 ); // Hash to avoid fancy character conflict with config format.
- hash.addData(word.toUtf8());
- auto hashString = Utils::appStringToCoreString(hash.result().toHex());
- return gISpellSelfDictionary->getInt("words",hashString,0) == 1;
-}
-
QStringList SpellChecker::suggestionsForWord(QString word) {
- QStringList suggestions;
- if (!gISpellSuggestions.contains(word))
- return suggestions;
- QListIterator<QString> itr (gISpellSuggestions.value(word));
- while (itr.hasNext()) {
- QString suggestion = itr.next();
- if (!suggestion.contains("+"))
- suggestions << suggestion;
- if (suggestions.length() >= SUGGESTIONS_LIMIT) {
- return suggestions;
- }
- }
- return suggestions;
+ return dict.suggest(word);
}
--
2.46.0