19 #include "QtSpell.hpp"
20 #include "TextEditChecker_p.hpp"
21 #include "UndoRedoStack.hpp"
24 #include <QPlainTextEdit>
33 testCursor.movePosition(NextCharacter, MoveAnchor, num - 1);
35 testCursor.setPosition(testCursor.position());
36 testCursor.movePosition(NextCharacter, KeepAnchor);
37 return testCursor.selectedText();
44 testCursor.movePosition(PreviousCharacter, MoveAnchor, num - 1);
46 testCursor.setPosition(testCursor.position());
47 testCursor.movePosition(PreviousCharacter, KeepAnchor);
48 return testCursor.selectedText();
53 movePosition(StartOfWord, moveMode);
58 if(
prevChar().contains(m_wordRegEx)){
59 movePosition(WordLeft, moveMode);
61 movePosition(NextCharacter, moveMode);
66 movePosition(WordLeft, moveMode, 2);
72 movePosition(EndOfWord, moveMode);
77 if(
nextChar().contains(m_wordRegEx)){
78 movePosition(WordRight, moveMode);
80 movePosition(PreviousCharacter, moveMode);
85 movePosition(WordRight, moveMode, 2);
97 m_undoRedoInProgress =
false;
107 setTextEdit(textEdit ?
new TextEditProxyT<QTextEdit>(textEdit) :
reinterpret_cast<TextEditProxyT<QTextEdit>*
>(0));
112 setTextEdit(textEdit ?
new TextEditProxyT<QPlainTextEdit>(textEdit) :
reinterpret_cast<TextEditProxyT<QPlainTextEdit>*
>(0));
117 if(!textEdit && m_textEdit){
118 disconnect(m_textEdit->object(), SIGNAL(destroyed()),
this, SLOT(slotDetachTextEdit()));
119 disconnect(m_textEdit->object(), SIGNAL(textChanged()),
this, SLOT(slotCheckDocumentChanged()));
120 disconnect(m_textEdit->object(), SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slotShowContextMenu(QPoint)));
121 disconnect(m_textEdit->document(), SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
122 m_textEdit->setContextMenuPolicy(m_oldContextMenuPolicy);
123 m_textEdit->removeEventFilter(
this);
126 QTextCursor cursor = m_textEdit->textCursor();
127 cursor.movePosition(QTextCursor::Start);
128 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
129 cursor.setCharFormat(QTextCharFormat());
131 bool undoWasEnabled = m_undoRedoStack != 0;
135 m_textEdit = textEdit;
137 m_document = m_textEdit->document();
138 connect(m_textEdit->object(), SIGNAL(destroyed()),
this, SLOT(slotDetachTextEdit()));
139 connect(m_textEdit->object(), SIGNAL(textChanged()),
this, SLOT(slotCheckDocumentChanged()));
140 connect(m_textEdit->object(), SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slotShowContextMenu(QPoint)));
141 connect(m_textEdit->document(), SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
142 m_oldContextMenuPolicy = m_textEdit->contextMenuPolicy();
144 m_textEdit->setContextMenuPolicy(Qt::CustomContextMenu);
145 m_textEdit->installEventFilter(
this);
150 bool TextEditChecker::eventFilter(QObject* obj, QEvent* event)
152 if(event->type() == QEvent::KeyPress){
153 QKeyEvent *keyEvent =
static_cast<QKeyEvent *
>(event);
154 if(keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == Qt::CTRL){
157 }
else if(keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == (Qt::CTRL | Qt::SHIFT)){
162 return QObject::eventFilter(obj, event);
168 QTextCursor tmpCursor(m_textEdit->textCursor());
169 tmpCursor.movePosition(QTextCursor::End);
170 end = tmpCursor.position();
174 m_textEdit->document()->blockSignals(
true);
176 qDebug() <<
"Checking range " << start <<
" - " << end;
178 QTextCharFormat errorFmt;
179 errorFmt.setFontUnderline(
true);
180 errorFmt.setUnderlineColor(Qt::red);
181 errorFmt.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
182 QTextCharFormat defaultFmt;
185 cursor.beginEditBlock();
186 cursor.setPosition(start);
187 while(cursor.position() < end) {
189 QString word = cursor.selectedText();
191 qDebug() <<
"Checking word:" << word <<
"(" << cursor.anchor() <<
"-" << cursor.position() <<
"), correct:" << correct;
193 cursor.setCharFormat(errorFmt);
195 cursor.setCharFormat(defaultFmt);
198 while(cursor.position() < end && !cursor.isWordChar(cursor.nextChar())){
199 cursor.movePosition(QTextCursor::NextCharacter);
202 cursor.endEditBlock();
204 m_textEdit->document()->blockSignals(
false);
210 m_undoRedoStack->clear();
216 if(enabled == (m_undoRedoStack != 0)){
220 delete m_undoRedoStack;
225 m_undoRedoStack =
new UndoRedoStack(m_textEdit);
234 cursor.setPosition(pos);
236 cursor.moveWordEnd(QTextCursor::KeepAnchor);
238 *start = cursor.anchor();
240 *end = cursor.position();
241 return cursor.selectedText();
246 QTextCursor cursor(m_textEdit->textCursor());
247 cursor.setPosition(start);
248 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, end - start);
249 cursor.insertText(word);
252 void TextEditChecker::slotShowContextMenu(
const QPoint &pos)
254 QPoint globalPos = m_textEdit->mapToGlobal(pos);
255 QMenu* menu = m_textEdit->createStandardContextMenu();
256 int wordPos = m_textEdit->cursorForPosition(pos).position();
257 showContextMenu(menu, globalPos, wordPos);
260 void TextEditChecker::slotCheckDocumentChanged()
262 if(m_document != m_textEdit->document()) {
263 bool undoWasEnabled = m_undoRedoStack != 0;
266 disconnect(m_document, SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
268 m_document = m_textEdit->document();
269 connect(m_document, SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
274 void TextEditChecker::slotDetachTextEdit()
276 bool undoWasEnabled = m_undoRedoStack != 0;
288 void TextEditChecker::slotCheckRange(
int pos,
int removed,
int added)
290 if(m_undoRedoStack != 0 && !m_undoRedoInProgress){
291 m_undoRedoStack->handleContentsChange(pos, removed, added);
295 TextCursor c(m_textEdit->textCursor());
296 c.movePosition(QTextCursor::End);
297 int len = c.position();
298 if(pos == 0 && added > len){
306 c.setPosition(pos + added, QTextCursor::KeepAnchor);
307 c.moveWordEnd(QTextCursor::KeepAnchor);
308 c.setCharFormat(QTextCharFormat());
315 if(m_undoRedoStack != 0){
316 m_undoRedoInProgress =
true;
317 m_undoRedoStack->undo();
318 m_textEdit->ensureCursorVisible();
319 m_undoRedoInProgress =
false;
325 if(m_undoRedoStack != 0){
326 m_undoRedoInProgress =
true;
327 m_undoRedoStack->redo();
328 m_textEdit->ensureCursorVisible();
329 m_undoRedoInProgress =
false;
QString prevChar(int num=1) const
Retreive the num-th previous character.
void undo()
Undo the last edit operation.
TextEditChecker(QObject *parent=0)
TextEditChecker object constructor.
void clearUndoRedo()
Clears the undo/redo stack.
void setTextEdit(QTextEdit *textEdit)
Set the QTextEdit to check.
void setUndoRedoEnabled(bool enabled)
Sets whether undo/redo functionality is enabled.
void redoAvailable(bool available)
Emitted when the redo stak changes.
void undoAvailable(bool available)
Emitted when the undo stack changes.
void insertWord(int start, int end, const QString &word)
Replaces the specified range with the specified word.
QString getWord(int pos, int *start=0, int *end=0) const
Get the word at the specified cursor position.
void checkSpelling(int start=0, int end=-1)
Check the spelling.
QString nextChar(int num=1) const
Retreive the num-th next character.
bool checkWord(const QString &word) const
Check the specified word.
void moveWordEnd(MoveMode moveMode=MoveAnchor)
Move the cursor to the end of the current word. Cursor must be inside a word. This method correctly h...
void moveWordStart(MoveMode moveMode=MoveAnchor)
Move the cursor to the start of the current word. Cursor must be inside a word. This method correctly...
void redo()
Redo the last edit operation.
An abstract class providing spell checking support.
~TextEditChecker()
TextEditChecker object destructor.