1
mirror of https://invent.kde.org/network/falkon.git synced 2024-09-21 17:52:10 +02:00

[spellcheck] Adding Speller object into MainApplication.

This commit is contained in:
nowrep 2013-02-05 15:41:10 +01:00
parent fc41e1516d
commit 074bd928c7
6 changed files with 161 additions and 118 deletions

View File

@ -53,6 +53,7 @@
#include "checkboxdialog.h"
#include "registerqappassociation.h"
#include "html5permissions/html5permissionsmanager.h"
#include "qtwebkit/spellcheck/speller.h"
#ifdef Q_OS_MAC
#include <QFileOpenEvent>
@ -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<QupZilla*> 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;
}

View File

@ -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<MainApplication*>(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;

View File

@ -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;
}

View File

@ -28,8 +28,7 @@ class SpellCheck : public QWebSpellChecker
Q_OBJECT
public:
SpellCheck();
~SpellCheck();
explicit SpellCheck();
bool isContinousSpellCheckingEnabled() const;
void toggleContinousSpellChecking();

View File

@ -16,165 +16,191 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "speller.h"
#include "settings.h"
#include "mainapplication.h"
#include "qztools.h"
#include <QStringList>
#include <QTextCodec>
#include <QTextStream>
#include <QFile>
#include <QRegExp>
#include <QLocale>
#include <QDebug>
#include <QDirIterator>
#include <hunspell/hunspell.hxx>
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::Language> Speller::availableLanguages() const
{
return s_langugage;
QList<Language> 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;
}

View File

@ -19,6 +19,7 @@
#define SPELLER_H
#include <QStringList>
#include <QFile>
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<Language> 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