From 074bd928c7b5cf156d03e848505f6258a9c203c0 Mon Sep 17 00:00:00 2001 From: nowrep Date: Tue, 5 Feb 2013 15:41:10 +0100 Subject: [PATCH] [spellcheck] Adding Speller object into MainApplication. --- src/lib/app/mainapplication.cpp | 16 ++ src/lib/app/mainapplication.h | 6 +- .../qtwebkit/spellcheck/spellcheck.cpp | 14 +- .../plugins/qtwebkit/spellcheck/spellcheck.h | 3 +- .../plugins/qtwebkit/spellcheck/speller.cpp | 206 ++++++++++-------- src/lib/plugins/qtwebkit/spellcheck/speller.h | 34 +-- 6 files changed, 161 insertions(+), 118 deletions(-) diff --git a/src/lib/app/mainapplication.cpp b/src/lib/app/mainapplication.cpp index 2801561f3..c61293f8a 100644 --- a/src/lib/app/mainapplication.cpp +++ b/src/lib/app/mainapplication.cpp @@ -53,6 +53,7 @@ #include "checkboxdialog.h" #include "registerqappassociation.h" #include "html5permissions/html5permissionsmanager.h" +#include "qtwebkit/spellcheck/speller.h" #ifdef Q_OS_MAC #include @@ -92,6 +93,7 @@ MainApplication::MainApplication(int &argc, char** argv) , m_restoreManager(0) , m_proxyStyle(0) , m_html5permissions(0) + , m_speller(0) , m_dbWriter(new DatabaseWriter(this)) , m_uaManager(new UserAgentManager) , m_isPrivateSession(false) @@ -496,6 +498,11 @@ QList MainApplication::mainWindows() return list; } +QString MainApplication::currentLanguage() +{ + return m_activeLanguage; +} + void MainApplication::sendMessages(Qz::AppMessageType mes, bool state) { emit message(mes, state); @@ -814,6 +821,14 @@ HTML5PermissionsManager* MainApplication::html5permissions() return m_html5permissions; } +Speller* MainApplication::speller() +{ + if (!m_speller) { + m_speller = new Speller(); + } + return m_speller; +} + void MainApplication::startPrivateBrowsing() { QStringList args; @@ -1089,4 +1104,5 @@ QString MainApplication::tempPath() const MainApplication::~MainApplication() { delete m_uaManager; + delete m_speller; } diff --git a/src/lib/app/mainapplication.h b/src/lib/app/mainapplication.h index 7925ed653..82b96b987 100644 --- a/src/lib/app/mainapplication.h +++ b/src/lib/app/mainapplication.h @@ -51,6 +51,7 @@ class UserAgentManager; class ProxyStyle; class RegisterQAppAssociation; class HTML5PermissionsManager; +class Speller; class QT_QUPZILLA_EXPORT MainApplication : public QtSingleApplication { @@ -77,12 +78,13 @@ public: inline static MainApplication* getInstance() { return static_cast(QCoreApplication::instance()); } inline QString currentProfilePath() { return m_activeProfil; } - inline QString currentLanguage() { return m_activeLanguage; } inline bool isPrivateSession() { return m_isPrivateSession; } inline bool isClosing() { return m_isClosing; } inline bool isStartingAfterCrash() { return m_startingAfterCrash; } inline int windowCount() { return m_mainWindows.count(); } + QString currentLanguage(); + bool checkSettingsDir(); void destroyRestoreManager(); void clearTempPath(); @@ -107,6 +109,7 @@ public: QNetworkDiskCache* networkCache(); DesktopNotificationsFactory* desktopNotifications(); HTML5PermissionsManager* html5permissions(); + Speller* speller(); DatabaseWriter* dbWriter() { return m_dbWriter; } UserAgentManager* uaManager() { return m_uaManager; } @@ -167,6 +170,7 @@ private: RestoreManager* m_restoreManager; ProxyStyle* m_proxyStyle; HTML5PermissionsManager* m_html5permissions; + Speller* m_speller; DatabaseWriter* m_dbWriter; UserAgentManager* m_uaManager; diff --git a/src/lib/plugins/qtwebkit/spellcheck/spellcheck.cpp b/src/lib/plugins/qtwebkit/spellcheck/spellcheck.cpp index 170af63f0..66f0f1793 100644 --- a/src/lib/plugins/qtwebkit/spellcheck/spellcheck.cpp +++ b/src/lib/plugins/qtwebkit/spellcheck/spellcheck.cpp @@ -20,17 +20,12 @@ #include "spellcheck.h" #include "speller.h" +#include "mainapplication.h" SpellCheck::SpellCheck() : QWebSpellChecker() - , m_speller(0) + , m_speller(mApp->speller()) { - m_speller = new Speller(); - - if (!m_speller->initialize()) { - delete m_speller; - m_speller = 0; - } } bool SpellCheck::isContinousSpellCheckingEnabled() const @@ -176,8 +171,3 @@ bool SpellCheck::startOfWord(const QTextBoundaryFinder::BoundaryReasons &reasons (type & QTextBoundaryFinder::Word); #endif } - -SpellCheck::~SpellCheck() -{ - delete m_speller; -} diff --git a/src/lib/plugins/qtwebkit/spellcheck/spellcheck.h b/src/lib/plugins/qtwebkit/spellcheck/spellcheck.h index 409d45154..32a4a4f41 100644 --- a/src/lib/plugins/qtwebkit/spellcheck/spellcheck.h +++ b/src/lib/plugins/qtwebkit/spellcheck/spellcheck.h @@ -28,8 +28,7 @@ class SpellCheck : public QWebSpellChecker Q_OBJECT public: - SpellCheck(); - ~SpellCheck(); + explicit SpellCheck(); bool isContinousSpellCheckingEnabled() const; void toggleContinousSpellChecking(); diff --git a/src/lib/plugins/qtwebkit/spellcheck/speller.cpp b/src/lib/plugins/qtwebkit/spellcheck/speller.cpp index 2b4cb17b4..7898823d8 100644 --- a/src/lib/plugins/qtwebkit/spellcheck/speller.cpp +++ b/src/lib/plugins/qtwebkit/spellcheck/speller.cpp @@ -16,165 +16,191 @@ * along with this program. If not, see . * ============================================================ */ #include "speller.h" +#include "settings.h" +#include "mainapplication.h" +#include "qztools.h" #include #include #include #include -#include +#include #include +#include #include -Hunspell* Speller::s_hunspell = 0; -QTextCodec* Speller::s_codec = 0; -QString Speller::s_dictionaryPath; -QString Speller::s_langugage; -bool Speller::s_initialized = false; - Speller::Speller() + : m_textCodec(0) + , m_hunspell(0) + , m_enabled(false) { + loadSettings(); } -bool Speller::initialize() +bool Speller::isEnabled() const { - if (s_initialized) { - return s_hunspell != 0; + return m_enabled; +} + +void Speller::loadSettings() +{ + Settings settings; + settings.beginGroup("SpellCheck"); + m_enabled = settings.value("enabled", true).toBool(); + m_dictionaryPath = settings.value("dictionaryPath", getDictionaryPath()).toString(); + m_language.code = settings.value("language", mApp->currentLanguage()).toString(); + m_language.name = nameForLanguage(m_language.code); + settings.endGroup(); + + m_userDictionary.setFileName(mApp->currentProfilePath() + "userdictionary.txt"); + initialize(); +} + +void Speller::initialize() +{ + delete m_hunspell; + m_hunspell = 0; + + if (m_dictionaryPath.isEmpty()) { + qWarning() << "SpellCheck: Cannot locate dictionary path!"; + return; } - s_dictionaryPath = getDictionaryPath(); - s_langugage = parseLanguage(s_dictionaryPath); + QString dictionary = m_dictionaryPath + m_language.code; - if (s_dictionaryPath.isEmpty() || s_langugage.isEmpty()) { - qWarning() << "SpellCheck: Initialization failed!"; - return false; + if (!dictionaryExists(dictionary)) { + qWarning() << "SpellCheck: Dictionaries for" << dictionary << "doesn't exists!"; + return; } - QString dicPath = s_dictionaryPath + ".dic"; - QString affPath = s_dictionaryPath + ".aff"; + const QString dicPath = dictionary + ".dic"; + const QString affPath = dictionary + ".aff"; - s_hunspell = new Hunspell(affPath.toLocal8Bit().constData(), + m_hunspell = new Hunspell(affPath.toLocal8Bit().constData(), dicPath .toLocal8Bit().constData()); - s_codec = QTextCodec::codecForName(s_hunspell->get_dic_encoding()); + m_textCodec = QTextCodec::codecForName(m_hunspell->get_dic_encoding()); - qDebug() << "SpellCheck: Language =" << language(); - s_initialized = true; - return true; + if (m_userDictionary.exists()) { + m_hunspell->add_dic(m_userDictionary.fileName().toLocal8Bit().constData()); + } + + qDebug() << "SpellCheck: Language =" << language().code; } -QString Speller::backend() const +Speller::Language Speller::language() const { - return QString("Hunspell"); + return m_language; } -QString Speller::language() const +QList Speller::availableLanguages() const { - return s_langugage; + QList languages; + + QDirIterator it(m_dictionaryPath, QStringList("*.dic"), + QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories); + + while (it.hasNext()) { + const QString affFilePath = it.next().replace(QLatin1String(".dic"), QLatin1String(".aff")); + + if (!QFile(affFilePath).exists()) { + continue; + } + + Language lang; + lang.code = it.fileInfo().baseName(); + lang.name = nameForLanguage(lang.code); + + languages.append(lang); + } + + return languages; } void Speller::learnWord(const QString &word) { - const char* encodedWord = s_codec->fromUnicode(word).constData(); - s_hunspell->add(encodedWord); -} + if (!m_hunspell || !m_textCodec) { + return; + } -void Speller::ignoreWordInSpellDocument(const QString &word) -{ - m_ignoredWords.append(word); + const char* encodedWord = m_textCodec->fromUnicode(word).constData(); + m_hunspell->add(encodedWord); + + if (!m_userDictionary.open(QFile::WriteOnly | QFile::Append)) { + qWarning() << "SpellCheck: Cannot open file" << m_userDictionary.fileName() << "for writing!"; + return; + } + + m_userDictionary.write(word.toUtf8()); + m_userDictionary.write("\n"); + m_userDictionary.close(); } bool Speller::isMisspelled(const QString &string) { - if (m_ignoredWords.contains(string)) { + if (!m_hunspell || !m_textCodec) { return false; } - const char* encodedString = s_codec->fromUnicode(string).constData(); - return s_hunspell->spell(encodedString) == 0; + const char* encodedString = m_textCodec->fromUnicode(string).constData(); + return m_hunspell->spell(encodedString) == 0; } QStringList Speller::suggest(const QString &word) { + if (!m_hunspell || !m_textCodec) { + return QStringList(); + } + char** suggestions; - const char* encodedWord = s_codec->fromUnicode(word).constData(); - int count = s_hunspell->suggest(&suggestions, encodedWord); + const char* encodedWord = m_textCodec->fromUnicode(word).constData(); + int count = m_hunspell->suggest(&suggestions, encodedWord); QStringList suggests; for (int i = 0; i < count; ++i) { - suggests.append(s_codec->toUnicode(suggestions[i])); + suggests.append(m_textCodec->toUnicode(suggestions[i])); } - s_hunspell->free_list(&suggestions, count); + m_hunspell->free_list(&suggestions, count); return suggests; } -bool Speller::dictionaryExists(const QString &path) +bool Speller::dictionaryExists(const QString &path) const { return QFile(path + ".dic").exists() && QFile(path + ".aff").exists(); } -QString Speller::parseLanguage(const QString &path) +QString Speller::getDictionaryPath() const { - if (path.contains(QLatin1Char('/'))) { - int pos = path.lastIndexOf(QLatin1Char('/')); - return path.mid(pos + 1); - } - else { - return path; - } -} +#ifdef QZ_WS_X11 + const QString defaultDicPath = "/usr/share/hunspell/"; +#else + const QString defaultDicPath = mApp->DATADIR + "hunspell/"; +#endif -QString Speller::getDictionaryPath() -{ - QString dictName; - QString defaultDicPath = "/usr/share/hunspell/"; - - QString env = QString::fromLocal8Bit(qgetenv("DICTIONARY")); - if (!env.isEmpty()) { - if (env.contains(QLatin1Char(','))) { - dictName = env.split(QLatin1Char(',')).first().trimmed(); - } - else { - dictName = env.trimmed(); - } - - if (dictName.contains(QLatin1Char('/')) && dictionaryExists(dictName)) { - return dictName; - } - } - - QString dicPath = QString::fromLocal8Bit(qgetenv("DICPATH")); + QString dicPath = QString::fromLocal8Bit(qgetenv("DICPATH")).trimmed(); if (!dicPath.isEmpty() && !dicPath.endsWith(QLatin1Char('/'))) { dicPath.append(QLatin1Char('/')); } - if (!dicPath.isEmpty() && dictionaryExists(dicPath + dictName)) { - return dicPath + dictName; + return dicPath.isEmpty() ? defaultDicPath : dicPath; +} + +QString Speller::nameForLanguage(const QString &code) const +{ + QLocale loc = QLocale(code); + QString name = QLocale::languageToString(loc.language()); + + if (loc.country() != QLocale::AnyCountry) { + name.append(" / " + QLocale::countryToString(loc.country())); } - if (!dictName.isEmpty()) { - if (dictionaryExists(defaultDicPath + dictName)) { - return defaultDicPath + dictName; - } - } - - QString locale = QLocale::system().name(); - - if (dictionaryExists(dicPath + locale)) { - return dicPath + locale; - } - else if (dictionaryExists(defaultDicPath + locale)) { - return defaultDicPath + locale; - } - else { - qWarning() << "SpellCheck: Cannot find dictionaries for" << defaultDicPath + locale; - } - - return QString(); + return name; } Speller::~Speller() { + delete m_hunspell; } diff --git a/src/lib/plugins/qtwebkit/spellcheck/speller.h b/src/lib/plugins/qtwebkit/spellcheck/speller.h index 7c910a4f0..354f574a5 100644 --- a/src/lib/plugins/qtwebkit/spellcheck/speller.h +++ b/src/lib/plugins/qtwebkit/spellcheck/speller.h @@ -19,6 +19,7 @@ #define SPELLER_H #include +#include class QTextCodec; class Hunspell; @@ -26,32 +27,39 @@ class Hunspell; class Speller { public: + struct Language { + QString code; + QString name; + }; + explicit Speller(); ~Speller(); - bool initialize(); + bool isEnabled() const; + void loadSettings(); - QString backend() const; - QString language() const; + Language language() const; + QList availableLanguages() const; void learnWord(const QString &word); - void ignoreWordInSpellDocument(const QString &word); bool isMisspelled(const QString &string); QStringList suggest(const QString &word); private: - bool dictionaryExists(const QString &path); - QString parseLanguage(const QString &path); - QString getDictionaryPath(); + void initialize(); - static Hunspell* s_hunspell; - static QTextCodec* s_codec; - static QString s_dictionaryPath; - static QString s_langugage; - static bool s_initialized; + bool dictionaryExists(const QString &path) const; + QString getDictionaryPath() const; + QString nameForLanguage(const QString &code) const; - QStringList m_ignoredWords; + QString m_dictionaryPath; + QTextCodec* m_textCodec; + Hunspell* m_hunspell; + + QFile m_userDictionary; + Language m_language; + bool m_enabled; }; #endif // SPELLER_H