summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xBuildTools/InstallSwiftDependencies.sh10
-rw-r--r--BuildTools/SCons/SConscript.boot2
-rw-r--r--SwifTools/HunspellChecker.cpp146
-rw-r--r--SwifTools/HunspellChecker.h28
-rw-r--r--SwifTools/MacOSXChecker.h7
-rw-r--r--SwifTools/MacOSXChecker.mm16
-rw-r--r--SwifTools/SpellChecker.h16
-rw-r--r--SwifTools/SpellCheckerFactory.cpp18
-rw-r--r--SwifTools/SpellCheckerFactory.h2
-rw-r--r--Swift/Controllers/SettingConstants.cpp6
-rw-r--r--Swift/Controllers/SettingConstants.h6
-rw-r--r--Swift/QtUI/QtSpellCheckerWindow.cpp77
-rw-r--r--Swift/QtUI/QtSpellCheckerWindow.h18
-rw-r--r--Swift/QtUI/QtSpellCheckerWindow.ui45
-rw-r--r--Swift/QtUI/QtTextEdit.cpp22
15 files changed, 265 insertions, 154 deletions
diff --git a/BuildTools/InstallSwiftDependencies.sh b/BuildTools/InstallSwiftDependencies.sh
index 2c1570f..391efe2 100755
--- a/BuildTools/InstallSwiftDependencies.sh
+++ b/BuildTools/InstallSwiftDependencies.sh
@@ -10,20 +10,20 @@ then
SYSTEM_DISTRO=$(lsb_release -i -s)
if [ "$SYSTEM_DISTRO" == "Debian" ]
then
- sudo apt-get install pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools libminiupnpc-dev libnatpmp-dev
+ sudo apt-get install pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools libminiupnpc-dev libnatpmp-dev libhunspell-dev
elif [ "$SYSTEM_DISTRO" == "Ubuntu" ]
then
- sudo apt-get install pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools
+ sudo apt-get install pkg-config libssl-dev qt5-default libqt5x11extras5-dev libqt5webkit5-dev qtmultimedia5-dev qttools5-dev-tools libhunspell-dev
elif [ "$SYSTEM_DISTRO" == "Arch" ]
then
- sudo pacman -S qt5-base qt5-x11extras qt5-webkit qt5-multimedia qt5-tools
+ sudo pacman -S qt5-base qt5-x11extras qt5-webkit qt5-multimedia qt5-tools hunspell
elif [ "$SYSTEM_DISTRO" == "openSUSE project" ]
then
- sudo zypper in pkg-config libopenssl-devel libQt5Core-devel libQt5WebKit5-devel libQt5WebKitWidgets-devel libqt5-qtmultimedia-devel libqt5-qtx11extras-devel libqt5-qttools-devel libQt5Gui-devel libQt5Network-devel libQt5DBus-devel python-xml
+ sudo zypper in pkg-config libopenssl-devel libQt5Core-devel libQt5WebKit5-devel libQt5WebKitWidgets-devel libqt5-qtmultimedia-devel libqt5-qtx11extras-devel libqt5-qttools-devel libQt5Gui-devel libQt5Network-devel libQt5DBus-devel python-xml hunspell-devel
elif [ "$SYSTEM_DISTRO" == "Fedora" ]
then
sudo dnf groups install "C Development Tools and Libraries"
- sudo dnf install openssl-devel qt5-qtbase-devel qt5-linguist qt5-qtwebkit-devel qt5-qtmultimedia-devel qt5-qtx11extras-devel
+ sudo dnf install openssl-devel qt5-qtbase-devel qt5-linguist qt5-qtwebkit-devel qt5-qtmultimedia-devel qt5-qtx11extras-devel hunspell-devel
else
echo "Unsupported Linux distribution."
fi
diff --git a/BuildTools/SCons/SConscript.boot b/BuildTools/SCons/SConscript.boot
index c335934..13a49b8 100644
--- a/BuildTools/SCons/SConscript.boot
+++ b/BuildTools/SCons/SConscript.boot
@@ -48,7 +48,7 @@ vars.Add("openssl_libnames", "Comma-separated openssl library names to override
vars.Add("openssl_include", "Location of OpenSSL include files (if not under (openssl)/include)", None)
vars.Add("openssl_libdir", "Location of OpenSSL library files (if not under (openssl)/lib)", None)
vars.Add(PackageVariable("hunspell_prefix", "Hunspell location", False))
-vars.Add(BoolVariable("hunspell_enable", "Build with Hunspell support", False))
+vars.Add(BoolVariable("hunspell_enable", "Build with Hunspell support", True))
vars.Add(PathVariable("boost_includedir", "Boost headers location", None, PathVariable.PathAccept))
vars.Add(PathVariable("boost_libdir", "Boost library location", None, PathVariable.PathAccept))
vars.Add(BoolVariable("boost_bundled_enable", "Allow use of bundled Boost as last resort", "true"))
diff --git a/SwifTools/HunspellChecker.cpp b/SwifTools/HunspellChecker.cpp
index fb1a5d6..1de369b 100644
--- a/SwifTools/HunspellChecker.cpp
+++ b/SwifTools/HunspellChecker.cpp
@@ -15,47 +15,151 @@
#include <algorithm>
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/regex.hpp>
#include <hunspell/hunspell.hxx>
+#include <Swiften/Base/Log.h>
+
namespace Swift {
-HunspellChecker::HunspellChecker(const char* affix_path, const char* dictionary_path) {
- speller_ = new Hunspell(affix_path, dictionary_path);
+static std::vector<std::string> recursiveFileSearch(const std::vector<std::string>& paths, const boost::regex& regex) {
+ std::vector<std::string> matches;
+
+ for (auto& path : paths) {
+ if (boost::filesystem::exists(path)) {
+ boost::cmatch what;
+ for (auto filename : boost::make_iterator_range(boost::filesystem::directory_iterator(path), boost::filesystem::directory_iterator())) {
+ if (boost::filesystem::is_regular_file(filename) && boost::regex_match(filename.path().c_str(), what, regex)) {
+ matches.push_back(filename.path().string());
+ }
+ }
+ }
+ }
+ return matches;
+}
+
+HunspellChecker::HunspellChecker() {
}
HunspellChecker::~HunspellChecker() {
- delete speller_;
+}
+
+std::vector<std::string> HunspellChecker::hunspellDictionaryPaths() const {
+ // The following list of paths comes from the source of the Hunspell command line tool.
+ std::vector<std::string> paths = {
+ "/usr/share/hunspell",
+ "/usr/share/myspell",
+ "/usr/share/myspell/dicts",
+ "/Library/Spelling",
+ "/opt/openoffice.org/basis3.0/share/dict/ooo",
+ "/usr/lib/openoffice.org/basis3.0/share/dict/ooo",
+ "/opt/openoffice.org2.4/share/dict/ooo",
+ "/usr/lib/openoffice.org2.4/share/dict/ooo",
+ "/opt/openoffice.org2.3/share/dict/ooo",
+ "/usr/lib/openoffice.org2.3/share/dict/ooo",
+ "/opt/openoffice.org2.2/share/dict/ooo",
+ "/usr/lib/openoffice.org2.2/share/dict/ooo",
+ "/opt/openoffice.org2.1/share/dict/ooo",
+ "/usr/lib/openoffice.org2.1/share/dict/ooo",
+ "/opt/openoffice.org2.0/share/dict/ooo",
+ "/usr/lib/openoffice.org2.0/share/dict/ooo"
+ };
+
+ if (std::getenv("DICPATH")) {
+ std::string dicpathEnvironment(std::getenv("DICPATH"));
+ std::vector<std::string> dicpaths;
+ boost::split(dicpaths,dicpathEnvironment,boost::is_any_of(":"));
+ paths.insert(paths.begin(), dicpaths.begin(), dicpaths.end());
+ }
+
+ return paths;
+}
+
+bool HunspellChecker::isAutomaticallyDetectingLanguage() {
+ return false;
+}
+
+void HunspellChecker::setActiveLanguage(const std::string& language) {
+ auto dictionaries = detectedDictionaries();
+ if (dictionaries.find(language) != dictionaries.end()) {
+ SWIFT_LOG(debug) << "Initialized Hunspell with dic,aff files " << dictionaries[language].dicPath << " , " << dictionaries[language].affPath << std::endl;
+ speller_ = std::unique_ptr<Hunspell>(new Hunspell(dictionaries[language].affPath.c_str(), dictionaries[language].dicPath.c_str()));
+ activeLangauge_ = language;
+ }
+ else {
+ SWIFT_LOG(warning) << "Unsupported language '" << language << "'" << std::endl;
+ }
+}
+
+std::string HunspellChecker::activeLanguage() const {
+ return activeLangauge_.get_value_or("");
+}
+
+std::vector<std::string> HunspellChecker::supportedLanguages() const {
+ std::vector<std::string> languages;
+
+ for (const auto& n : detectedDictionaries()) {
+ languages.push_back(n.first);
+ }
+
+ return languages;
+}
+
+std::unordered_map<std::string, HunspellChecker::Dictionary> HunspellChecker::detectedDictionaries() const {
+ std::unordered_map<std::string, HunspellChecker::Dictionary> dictionaries;
+
+ auto dictionaryFiles = recursiveFileSearch(hunspellDictionaryPaths(), boost::regex(".*\\.dic$"));
+ for (const auto& dictionary : dictionaryFiles) {
+ std::string correspondingAffixPath = dictionary;
+ boost::replace_last(correspondingAffixPath, ".dic", ".aff");
+ if (boost::filesystem::is_regular_file(correspondingAffixPath)) {
+ auto filenameWithoutExtension = boost::filesystem::basename(dictionary);
+ dictionaries[filenameWithoutExtension] = {dictionary, correspondingAffixPath};
+ }
+ }
+
+ return dictionaries;
}
bool HunspellChecker::isCorrect(const std::string& word) {
- return speller_->spell(word.c_str());
+ if (speller_) {
+ return speller_->spell(word.c_str());
+ }
+ else {
+ return true;
+ }
}
void HunspellChecker::getSuggestions(const std::string& word, std::vector<std::string>& list) {
- char **suggestList = NULL;
- int words_returned = 0;
- if (!word.empty()) {
- words_returned = speller_->suggest(&suggestList, word.c_str());
- if (suggestList != NULL) {
- for (int i = 0; i < words_returned; ++i) {
- list.push_back(suggestList[i]);
- free(suggestList[i]);
+ if (speller_) {
+ char **suggestList = NULL;
+ int words_returned = 0;
+ if (!word.empty()) {
+ words_returned = speller_->suggest(&suggestList, word.c_str());
+ if (suggestList != NULL) {
+ for (int i = 0; i < words_returned; ++i) {
+ list.push_back(suggestList[i]);
+ free(suggestList[i]);
+ }
+ free(suggestList);
}
- free(suggestList);
}
}
}
void HunspellChecker::checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) {
- if (!fragment.empty()) {
- parser_->check(fragment, misspelledPositions);
- for (PositionPairList::iterator it = misspelledPositions.begin(); it != misspelledPositions.end();) {
- if (isCorrect(fragment.substr(boost::get<0>(*it), boost::get<1>(*it) - boost::get<0>(*it)))) {
- it = misspelledPositions.erase(it);
- }
- else {
- ++it;
+ if (speller_) {
+ if (!fragment.empty()) {
+ parser_.check(fragment, misspelledPositions);
+ for (PositionPairList::iterator it = misspelledPositions.begin(); it != misspelledPositions.end();) {
+ if (isCorrect(fragment.substr(boost::get<0>(*it), boost::get<1>(*it) - boost::get<0>(*it)))) {
+ it = misspelledPositions.erase(it);
+ }
+ else {
+ ++it;
+ }
}
}
}
diff --git a/SwifTools/HunspellChecker.h b/SwifTools/HunspellChecker.h
index 076b468..2d4831e 100644
--- a/SwifTools/HunspellChecker.h
+++ b/SwifTools/HunspellChecker.h
@@ -12,10 +12,13 @@
#pragma once
+#include <memory>
+#include <string>
+#include <unordered_map>
#include <vector>
#include <boost/algorithm/string.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <boost/optional.hpp>
#include <SwifTools/SpellChecker.h>
@@ -24,12 +27,31 @@ class Hunspell;
namespace Swift {
class HunspellChecker : public SpellChecker {
public:
- HunspellChecker(const char* affix_path, const char* dict_path);
+ HunspellChecker();
virtual ~HunspellChecker();
+
+ virtual bool isAutomaticallyDetectingLanguage();
+
+ virtual void setActiveLanguage(const std::string& language);
+ virtual std::string activeLanguage() const;
+ virtual std::vector<std::string> supportedLanguages() const;
+
virtual bool isCorrect(const std::string& word);
virtual void getSuggestions(const std::string& word, std::vector<std::string>& list);
virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions);
+
private:
- Hunspell* speller_;
+ struct Dictionary {
+ std::string dicPath;
+ std::string affPath;
+ };
+
+ std::unordered_map<std::string, Dictionary> detectedDictionaries() const;
+ std::vector<std::string> hunspellDictionaryPaths() const;
+
+ private:
+ std::unique_ptr<Hunspell> speller_;
+ boost::optional<std::string> activeLangauge_;
+
};
}
diff --git a/SwifTools/MacOSXChecker.h b/SwifTools/MacOSXChecker.h
index be9a32a..7587c99 100644
--- a/SwifTools/MacOSXChecker.h
+++ b/SwifTools/MacOSXChecker.h
@@ -23,6 +23,13 @@ namespace Swift {
public:
MacOSXChecker();
virtual ~MacOSXChecker();
+
+ virtual bool isAutomaticallyDetectingLanguage();
+
+ virtual void setActiveLanguage(const std::string& language);
+ virtual std::string activeLanguage() const;
+ virtual std::vector<std::string> supportedLanguages() const;
+
virtual bool isCorrect(const std::string& word);
virtual void getSuggestions(const std::string& word, std::vector<std::string>& list);
virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions);
diff --git a/SwifTools/MacOSXChecker.mm b/SwifTools/MacOSXChecker.mm
index 5f4f9c3..519f06c 100644
--- a/SwifTools/MacOSXChecker.mm
+++ b/SwifTools/MacOSXChecker.mm
@@ -13,6 +13,7 @@
#include <SwifTools/MacOSXChecker.h>
#include <algorithm>
+#include <cassert>
#include <boost/algorithm/string.hpp>
@@ -33,6 +34,21 @@ bool MacOSXChecker::isCorrect(const std::string& /*word*/) {
return false;
}
+bool MacOSXChecker::isAutomaticallyDetectingLanguage() {
+ return true;
+}
+
+void MacOSXChecker::setActiveLanguage(const std::string& /*language*/) {
+ assert(false);
+}
+
+std::string MacOSXChecker::activeLanguage() const {
+ assert(false);
+}
+std::vector<std::string> MacOSXChecker::supportedLanguages() const {
+ assert(false);
+}
+
void MacOSXChecker::getSuggestions(const std::string& word, std::vector<std::string>& list) {
NSSpellChecker* spellChecker = [NSSpellChecker sharedSpellChecker];
NSString* wordString = [[NSString alloc] initWithUTF8String: word.c_str()];
diff --git a/SwifTools/SpellChecker.h b/SwifTools/SpellChecker.h
index 415d3f6..664fc63 100644
--- a/SwifTools/SpellChecker.h
+++ b/SwifTools/SpellChecker.h
@@ -14,24 +14,28 @@
#include <vector>
-#include <boost/algorithm/string.hpp>
-#include <boost/tuple/tuple.hpp>
-
#include <SwifTools/SpellParser.h>
namespace Swift {
class SpellChecker {
public:
SpellChecker() {
- parser_ = new SpellParser();
}
+
virtual ~SpellChecker() {
- delete parser_;
}
+
+ virtual bool isAutomaticallyDetectingLanguage() = 0;
+
+ virtual void setActiveLanguage(const std::string& language) = 0;
+ virtual std::string activeLanguage() const = 0;
+ virtual std::vector<std::string> supportedLanguages() const = 0;
+
virtual bool isCorrect(const std::string& word) = 0;
virtual void getSuggestions(const std::string& word, std::vector<std::string>& list) = 0;
virtual void checkFragment(const std::string& fragment, PositionPairList& misspelledPositions) = 0;
+
protected:
- SpellParser *parser_;
+ SpellParser parser_;
};
}
diff --git a/SwifTools/SpellCheckerFactory.cpp b/SwifTools/SpellCheckerFactory.cpp
index e53447e..bfd3d4a 100644
--- a/SwifTools/SpellCheckerFactory.cpp
+++ b/SwifTools/SpellCheckerFactory.cpp
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2016 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include <boost/filesystem/operations.hpp>
#include <SwifTools/SpellChecker.h>
@@ -23,17 +29,11 @@ SpellCheckerFactory::SpellCheckerFactory() {
}
#ifdef HAVE_HUNSPELL
-SpellChecker* SpellCheckerFactory::createSpellChecker(const std::string& dictFile) {
- std::string affixFile(dictFile);
- boost::replace_all(affixFile, ".dic", ".aff");
- if ((boost::filesystem::exists(dictFile)) && (boost::filesystem::exists(affixFile))) {
- return new HunspellChecker(affixFile.c_str(), dictFile.c_str());
- }
- // If dictionaries don't exist disable the checker
- return NULL;
+SpellChecker* SpellCheckerFactory::createSpellChecker() {
+ return new HunspellChecker();
}
#elif defined(SWIFTEN_PLATFORM_MACOSX)
-SpellChecker* SpellCheckerFactory::createSpellChecker(const std::string& /*dictFile*/) {
+SpellChecker* SpellCheckerFactory::createSpellChecker() {
return new MacOSXChecker();
}
#endif
diff --git a/SwifTools/SpellCheckerFactory.h b/SwifTools/SpellCheckerFactory.h
index 2e1711a..eb2ade6 100644
--- a/SwifTools/SpellCheckerFactory.h
+++ b/SwifTools/SpellCheckerFactory.h
@@ -28,6 +28,6 @@ namespace Swift {
class SpellCheckerFactory {
public:
SpellCheckerFactory();
- SpellChecker* createSpellChecker(const std::string& dictFile);
+ SpellChecker* createSpellChecker();
};
}
diff --git a/Swift/Controllers/SettingConstants.cpp b/Swift/Controllers/SettingConstants.cpp
index 9807abc..d9766cf 100644
--- a/Swift/Controllers/SettingConstants.cpp
+++ b/Swift/Controllers/SettingConstants.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 Isode Limited.
+ * Copyright (c) 2012-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -21,9 +21,7 @@ const SettingsProvider::Setting<std::string> SettingConstants::EXPANDED_ROSTER_G
const SettingsProvider::Setting<bool> SettingConstants::PLAY_SOUNDS("playSounds", true);
const SettingsProvider::Setting<std::string> SettingConstants::HIGHLIGHT_RULES("highlightRules", "@");
const SettingsProvider::Setting<bool> SettingConstants::SPELL_CHECKER("spellChecker", false);
-const SettingsProvider::Setting<std::string> SettingConstants::DICT_PATH("dictPath", "/usr/share/myspell/dicts/");
-const SettingsProvider::Setting<std::string> SettingConstants::PERSONAL_DICT_PATH("personaldictPath", "/home/");
-const SettingsProvider::Setting<std::string> SettingConstants::DICT_FILE("dictFile", "en_US.dic");
+const SettingsProvider::Setting<std::string> SettingConstants::SPELL_CHECKER_LANGUAGE("spellCheckerLanguage", "en_US");
const SettingsProvider::Setting<std::string> SettingConstants::INVITE_AUTO_ACCEPT_MODE("inviteAutoAcceptMode", "presence");
const SettingsProvider::Setting<std::string> SettingConstants::TRELLIS_GRID_SIZE("trellisGridSize", "");
const SettingsProvider::Setting<std::string> SettingConstants::TRELLIS_GRID_POSITIONS("trellisGridPositions", "");
diff --git a/Swift/Controllers/SettingConstants.h b/Swift/Controllers/SettingConstants.h
index 9343b7b..ace481b 100644
--- a/Swift/Controllers/SettingConstants.h
+++ b/Swift/Controllers/SettingConstants.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 Isode Limited.
+ * Copyright (c) 2012-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -58,9 +58,7 @@ namespace Swift {
*/
static const SettingsProvider::Setting<std::string> HIGHLIGHT_RULES;
static const SettingsProvider::Setting<bool> SPELL_CHECKER;
- static const SettingsProvider::Setting<std::string> DICT_PATH;
- static const SettingsProvider::Setting<std::string> PERSONAL_DICT_PATH;
- static const SettingsProvider::Setting<std::string> DICT_FILE;
+ static const SettingsProvider::Setting<std::string> SPELL_CHECKER_LANGUAGE;
/**
* The #INVITE_AUTO_ACCEPT_MODE setting specifies how to handle invites to chat rooms.
*
diff --git a/Swift/QtUI/QtSpellCheckerWindow.cpp b/Swift/QtUI/QtSpellCheckerWindow.cpp
index 9232b19..ed7e7e8 100644
--- a/Swift/QtUI/QtSpellCheckerWindow.cpp
+++ b/Swift/QtUI/QtSpellCheckerWindow.cpp
@@ -18,6 +18,8 @@
#include <QStringList>
#include <QTimer>
+#include <Swiften/Base/Log.h>
+
#include <Swift/Controllers/SettingConstants.h>
#include <Swift/Controllers/Settings/SettingsProvider.h>
@@ -38,7 +40,6 @@ QtSpellCheckerWindow::QtSpellCheckerWindow(SettingsProvider* settings, QWidget*
connect(ui_.spellChecker, SIGNAL(toggled(bool)), this, SLOT(handleChecker(bool)));
connect(ui_.cancel, SIGNAL(clicked()), this, SLOT(handleCancel()));
connect(ui_.apply, SIGNAL(clicked()), this, SLOT(handleApply()));
- connect(ui_.pathButton, SIGNAL(clicked()), this, SLOT(handlePathButton()));
setFromSettings();
}
@@ -48,27 +49,39 @@ void QtSpellCheckerWindow::shrinkWindow() {
void QtSpellCheckerWindow::setFromSettings() {
ui_.spellChecker->setChecked(settings_->getSetting(SettingConstants::SPELL_CHECKER));
- ui_.pathContent->setText(P2QSTRING(settings_->getSetting(SettingConstants::DICT_PATH)));
- ui_.currentLanguageValue->setText(P2QSTRING(settings_->getSetting(SettingConstants::DICT_FILE)));
- std::string currentPath = settings_->getSetting(SettingConstants::DICT_PATH);
- QString filename = "*.dic";
- QDir dictDirectory = QDir(P2QSTRING(currentPath));
- QStringList files = dictDirectory.entryList(QStringList(filename), QDir::Files);
- showFiles(files);
setEnabled(settings_->getSetting(SettingConstants::SPELL_CHECKER));
}
+void QtSpellCheckerWindow::setSupportedLanguages(const std::vector<std::string>& languages) {
+ languageItems_.clear();
+ ui_.languageView->clear();
+ for (const auto& shortLang : languages) {
+ auto locale = QLocale(P2QSTRING(shortLang));
+ auto label = QString("%1 ( %2 )").arg(locale.nativeLanguageName(), locale.nativeCountryName());
+
+ QListWidgetItem* item = new QListWidgetItem(label);
+ item->setData(Qt::UserRole, P2QSTRING(shortLang));
+ languageItems_[shortLang] = item;
+ ui_.languageView->addItem(item);
+ }
+}
+
+void QtSpellCheckerWindow::setActiveLanguage(const std::string& language) {
+ SWIFT_LOG_ASSERT(languageItems_.find(language) != languageItems_.end(), warning) << "Language '" << language << "' is not available." << std::endl;
+ if (languageItems_.find(language) != languageItems_.end()) {
+ languageItems_[language]->setSelected(true);
+ }
+}
+
+void QtSpellCheckerWindow::setAutomaticallyIdentifiesLanguage(bool isAutomaticallyIdentifying) {
+ ui_.languageView->setHidden(isAutomaticallyIdentifying);
+}
+
void QtSpellCheckerWindow::handleChecker(bool state) {
setEnabled(state);
}
void QtSpellCheckerWindow::setEnabled(bool state) {
- ui_.pathContent->setEnabled(state);
- ui_.languageView->setEnabled(state);
- ui_.pathButton->setEnabled(state);
- ui_.pathLabel->setEnabled(state);
- ui_.currentLanguage->setEnabled(state);
- ui_.currentLanguageValue->setEnabled(state);
ui_.language->setEnabled(state);
}
@@ -76,7 +89,7 @@ void QtSpellCheckerWindow::handleApply() {
settings_->storeSetting(SettingConstants::SPELL_CHECKER, ui_.spellChecker->isChecked());
QList<QListWidgetItem* > selectedLanguage = ui_.languageView->selectedItems();
if (!selectedLanguage.empty()) {
- settings_->storeSetting(SettingConstants::DICT_FILE, Q2PSTRING((selectedLanguage.first())->text()));
+ settings_->storeSetting(SettingConstants::SPELL_CHECKER_LANGUAGE, Q2PSTRING(selectedLanguage.first()->data(Qt::UserRole).toString()));
}
this->done(0);
}
@@ -85,38 +98,4 @@ void QtSpellCheckerWindow::handleCancel() {
this->done(0);
}
-void QtSpellCheckerWindow::handlePathButton() {
- std::string currentPath = settings_->getSetting(SettingConstants::DICT_PATH);
- QString dirpath = QFileDialog::getExistingDirectory(this, tr("Dictionary Path"), P2QSTRING(currentPath));
- if (dirpath != P2QSTRING(currentPath)) {
- ui_.languageView->clear();
- settings_->storeSetting(SettingConstants::DICT_FILE, "");
- ui_.currentLanguageValue->setText(" ");
- }
- if (!dirpath.isEmpty()) {
- if (!dirpath.endsWith("/")) {
- dirpath.append("/");
- }
- settings_->storeSetting(SettingConstants::DICT_PATH, Q2PSTRING(dirpath));
- QDir dictDirectory = QDir(dirpath);
- ui_.pathContent->setText(dirpath);
- QString filename = "*.dic";
- QStringList files = dictDirectory.entryList(QStringList(filename), QDir::Files);
- showFiles(files);
- }
-}
-
-void QtSpellCheckerWindow::handlePersonalPathButton() {
- std::string currentPath = settings_->getSetting(SettingConstants::PERSONAL_DICT_PATH);
- QString filename = QFileDialog::getOpenFileName(this, tr("Select Personal Dictionary"), P2QSTRING(currentPath), tr("(*.dic"));
- settings_->storeSetting(SettingConstants::PERSONAL_DICT_PATH, Q2PSTRING(filename));
-}
-
-void QtSpellCheckerWindow::showFiles(const QStringList& files) {
- ui_.languageView->clear();
- for (int i = 0; i < files.size(); ++i) {
- ui_.languageView->insertItem(i, files[i]);
- }
-}
-
}
diff --git a/Swift/QtUI/QtSpellCheckerWindow.h b/Swift/QtUI/QtSpellCheckerWindow.h
index 846dcbb..86ebd40 100644
--- a/Swift/QtUI/QtSpellCheckerWindow.h
+++ b/Swift/QtUI/QtSpellCheckerWindow.h
@@ -12,29 +12,41 @@
#pragma once
+#include <string>
+#include <unordered_map>
+#include <vector>
+
#include <QDialog>
#include <Swift/QtUI/ui_QtSpellCheckerWindow.h>
+class QListWidgetItem;
+
namespace Swift {
class SettingsProvider;
class QtSpellCheckerWindow : public QDialog, protected Ui::QtSpellCheckerWindow {
Q_OBJECT
public:
QtSpellCheckerWindow(SettingsProvider* settings, QWidget* parent = nullptr);
+
+ void setSupportedLanguages(const std::vector<std::string>& languages);
+ void setActiveLanguage(const std::string& language);
+ void setAutomaticallyIdentifiesLanguage(bool isAutomaticallyIdentifying);
+
public slots:
void handleChecker(bool state);
void handleCancel();
- void handlePathButton();
- void handlePersonalPathButton();
void handleApply();
+
private slots:
void shrinkWindow();
+
private:
void setEnabled(bool state);
void setFromSettings();
- void showFiles(const QStringList& files);
+
SettingsProvider* settings_;
Ui::QtSpellCheckerWindow ui_;
+ std::unordered_map<std::string, QListWidgetItem*> languageItems_;
};
}
diff --git a/Swift/QtUI/QtSpellCheckerWindow.ui b/Swift/QtUI/QtSpellCheckerWindow.ui
index b7f5161..dcb70fa 100644
--- a/Swift/QtUI/QtSpellCheckerWindow.ui
+++ b/Swift/QtUI/QtSpellCheckerWindow.ui
@@ -25,45 +25,6 @@
<widget class="QWidget" name="hunspellOptions" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="pathLabel">
- <property name="text">
- <string>Dictionary Path:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="pathContent"/>
- </item>
- <item>
- <widget class="QPushButton" name="pathButton">
- <property name="text">
- <string>Change</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <item>
- <widget class="QLabel" name="currentLanguage">
- <property name="text">
- <string>Current Language:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="currentLanguageValue">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="language">
@@ -73,7 +34,11 @@
</widget>
</item>
<item>
- <widget class="QListWidget" name="languageView"/>
+ <widget class="QListWidget" name="languageView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ </widget>
</item>
</layout>
</item>
diff --git a/Swift/QtUI/QtTextEdit.cpp b/Swift/QtUI/QtTextEdit.cpp
index 846dcbc..3143192 100644
--- a/Swift/QtUI/QtTextEdit.cpp
+++ b/Swift/QtUI/QtTextEdit.cpp
@@ -179,17 +179,17 @@ void QtTextEdit::addSuggestions(QMenu* menu, QContextMenuEvent* event)
#ifdef HAVE_SPELLCHECKER
-void QtTextEdit::setUpSpellChecker()
-{
+void QtTextEdit::setUpSpellChecker() {
delete highlighter_;
highlighter_ = nullptr;
delete checker_;
checker_ = nullptr;
if (settings_->getSetting(SettingConstants::SPELL_CHECKER)) {
- std::string dictPath = settings_->getSetting(SettingConstants::DICT_PATH);
- std::string dictFile = settings_->getSetting(SettingConstants::DICT_FILE);
- checker_ = SpellCheckerFactory().createSpellChecker(dictPath + dictFile);
+ checker_ = SpellCheckerFactory().createSpellChecker();
if (checker_) {
+ if (!checker_->isAutomaticallyDetectingLanguage()) {
+ checker_->setActiveLanguage(settings_->getSetting(SettingConstants::SPELL_CHECKER_LANGUAGE));
+ }
highlighter_ = new QtSpellCheckHighlighter(document(), checker_);
}
else {
@@ -213,12 +213,18 @@ void QtTextEdit::spellCheckerSettingsWindow() {
spellCheckerWindow_->raise();
spellCheckerWindow_->activateWindow();
}
+ if (checker_) {
+ spellCheckerWindow_->setAutomaticallyIdentifiesLanguage(checker_->isAutomaticallyDetectingLanguage());
+ if (!checker_->isAutomaticallyDetectingLanguage()) {
+ spellCheckerWindow_->setSupportedLanguages(checker_->supportedLanguages());
+ spellCheckerWindow_->setActiveLanguage(checker_->activeLanguage());
+ }
+ }
}
void QtTextEdit::handleSettingChanged(const std::string& settings) {
- if (settings == SettingConstants::SPELL_CHECKER.getKey()
- || settings == SettingConstants::DICT_PATH.getKey()
- || settings == SettingConstants::DICT_FILE.getKey()) {
+ if (settings == SettingConstants::SPELL_CHECKER.getKey() ||
+ settings == SettingConstants::SPELL_CHECKER_LANGUAGE.getKey()) {
#ifdef HAVE_SPELLCHECKER
setUpSpellChecker();
if (highlighter_) {