From 92672e17a52d0c86e693183627c8c6b8fa44fb86 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Wed, 3 Dec 2014 00:54:24 +0100 Subject: Fix spell checking by using QSyntaxHighlighter. This fixes spell checking not interfering with Qt's undo stack management anymore. Test-Information: Tested on OS X 10.9.5 with Qt 5.3.2. Change-Id: Icc3aa9f7213856388e4da317525c75ac97da72e3 diff --git a/Swift/QtUI/QtSpellCheckHighlighter.cpp b/Swift/QtUI/QtSpellCheckHighlighter.cpp new file mode 100644 index 0000000..dba6100 --- /dev/null +++ b/Swift/QtUI/QtSpellCheckHighlighter.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include + +#include + +#include + +namespace Swift { + +QtSpellCheckHighlighter::QtSpellCheckHighlighter(QTextDocument* parent, SpellChecker* spellChecker) : QSyntaxHighlighter(parent), checker_(spellChecker) { + +} + +QtSpellCheckHighlighter::~QtSpellCheckHighlighter() { + +} + +void QtSpellCheckHighlighter::highlightBlock(const QString& text) { + misspelledPositions_.clear(); + std::string fragment = Q2PSTRING(text); + checker_->checkFragment(fragment, misspelledPositions_); + + QTextCharFormat spellingErrorFormat; + spellingErrorFormat.setUnderlineColor(QColor(Qt::red)); + spellingErrorFormat.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); + + foreach (PositionPair position, misspelledPositions_) { + setFormat(boost::get<0>(position), boost::get<1>(position) - boost::get<0>(position), spellingErrorFormat); + }; +} + +PositionPairList QtSpellCheckHighlighter::getMisspelledPositions() const { + return misspelledPositions_; +} + +} diff --git a/Swift/QtUI/QtSpellCheckHighlighter.h b/Swift/QtUI/QtSpellCheckHighlighter.h new file mode 100644 index 0000000..c1cfc70 --- /dev/null +++ b/Swift/QtUI/QtSpellCheckHighlighter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include + +class QString; +class QTextDocument; + +namespace Swift { + +class SpellChecker; + +class QtSpellCheckHighlighter : public QSyntaxHighlighter { + Q_OBJECT + +public: + QtSpellCheckHighlighter(QTextDocument* parent, SpellChecker* spellChecker); + virtual ~QtSpellCheckHighlighter(); + + PositionPairList getMisspelledPositions() const; + +protected: + virtual void highlightBlock(const QString& text); + +private: + SpellChecker* checker_; + PositionPairList misspelledPositions_; +}; + + +} diff --git a/Swift/QtUI/QtTextEdit.cpp b/Swift/QtUI/QtTextEdit.cpp index 8551f3d..98d735e 100644 --- a/Swift/QtUI/QtTextEdit.cpp +++ b/Swift/QtUI/QtTextEdit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -29,9 +29,8 @@ namespace Swift { -QtTextEdit::QtTextEdit(SettingsProvider* settings, QWidget* parent) : QTextEdit(parent) { +QtTextEdit::QtTextEdit(SettingsProvider* settings, QWidget* parent) : QTextEdit(parent), checker_(NULL), highlighter_(NULL) { connect(this, SIGNAL(textChanged()), this, SLOT(handleTextChanged())); - checker_ = NULL; settings_ = settings; #ifdef HAVE_SPELLCHECKER setUpSpellChecker(); @@ -73,35 +72,6 @@ void QtTextEdit::keyPressEvent(QKeyEvent* event) { } else { QTextEdit::keyPressEvent(event); -#ifdef HAVE_SPELLCHECKER - if (settings_->getSetting(SettingConstants::SPELL_CHECKER)) { - underlineMisspells(); - } -#endif - } -} - -void QtTextEdit::underlineMisspells() { - QTextCursor cursor = textCursor(); - misspelledPositions_.clear(); - QTextCharFormat normalFormat; - cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1); - cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor, 1); - cursor.setCharFormat(normalFormat); - if (checker_ == NULL) { - return; - } - QTextCharFormat spellingErrorFormat; - spellingErrorFormat.setUnderlineColor(QColor(Qt::red)); - spellingErrorFormat.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); - std::string fragment = Q2PSTRING(cursor.selectedText()); - checker_->checkFragment(fragment, misspelledPositions_); - foreach (PositionPair position, misspelledPositions_) { - cursor.setPosition(boost::get<0>(position), QTextCursor::MoveAnchor); - cursor.setPosition(boost::get<1>(position), QTextCursor::KeepAnchor); - cursor.setCharFormat(spellingErrorFormat); - cursor.clearSelection(); - cursor.setCharFormat(normalFormat); } } @@ -123,7 +93,8 @@ void QtTextEdit::replaceMisspelledWord(const QString& word, int cursorPosition) } PositionPair QtTextEdit::getWordFromCursor(int cursorPosition) { - for (PositionPairList::iterator it = misspelledPositions_.begin(); it != misspelledPositions_.end(); ++it) { + PositionPairList misspelledPositions = highlighter_->getMisspelledPositions(); + for (PositionPairList::iterator it = misspelledPositions.begin(); it != misspelledPositions.end(); ++it) { if (cursorPosition >= boost::get<0>(*it) && cursorPosition <= boost::get<1>(*it)) { return *it; } @@ -208,6 +179,9 @@ void QtTextEdit::setUpSpellChecker() std::string dictPath = settings_->getSetting(SettingConstants::DICT_PATH); std::string dictFile = settings_->getSetting(SettingConstants::DICT_FILE); checker_ = SpellCheckerFactory().createSpellChecker(dictPath + dictFile); + delete highlighter_; + highlighter_ = NULL; + highlighter_ = new QtSpellCheckHighlighter(document(), checker_); } } #endif @@ -231,7 +205,7 @@ void QtTextEdit::handleSettingChanged(const std::string& settings) { || settings == SettingConstants::DICT_FILE.getKey()) { #ifdef HAVE_SPELLCHECKER setUpSpellChecker(); - underlineMisspells(); + highlighter_->rehighlight(); #endif } } diff --git a/Swift/QtUI/QtTextEdit.h b/Swift/QtUI/QtTextEdit.h index a8df4d3..5f16453 100644 --- a/Swift/QtUI/QtTextEdit.h +++ b/Swift/QtUI/QtTextEdit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,40 +11,49 @@ #include #include +#include + #include #include namespace Swift { class SpellChecker; class QtSpellCheckerWindow; + class QtTextEdit : public QTextEdit { Q_OBJECT public: QtTextEdit(SettingsProvider* settings, QWidget* parent = 0); virtual ~QtTextEdit(); virtual QSize sizeHint() const; + signals: void wordCorrected(QString& word); void returnPressed(); void unhandledKeyPressEvent(QKeyEvent* event); + public slots: void handleSettingChanged(const std::string& settings); + protected: virtual void keyPressEvent(QKeyEvent* event); virtual void contextMenuEvent(QContextMenuEvent* event); + private slots: void handleTextChanged(); + private: - SpellChecker *checker_; - std::vector replaceWordActions_; - PositionPairList misspelledPositions_; - SettingsProvider *settings_; - QPointer spellCheckerWindow_; void addSuggestions(QMenu* menu, QContextMenuEvent* event); void replaceMisspelledWord(const QString& word, int cursorPosition); void setUpSpellChecker(); - void underlineMisspells(); void spellCheckerSettingsWindow(); PositionPair getWordFromCursor(int cursorPosition); + + private: + SpellChecker* checker_; + QtSpellCheckHighlighter* highlighter_; + std::vector replaceWordActions_; + SettingsProvider* settings_; + QPointer spellCheckerWindow_; }; } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 26e738a..80daaea 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -192,7 +192,8 @@ sources = [ "QtAffiliationEditor.cpp", "QtUISettingConstants.cpp", "QtURLValidator.cpp", - "QtResourceHelper.cpp" + "QtResourceHelper.cpp", + "QtSpellCheckHighlighter.cpp" ] # QtVCardWidget -- cgit v0.10.2-6-g49f6