19 #include "QtSpell.hpp"
20 #include "TextEditChecker_p.hpp"
21 #include "UndoRedoStack.hpp"
24 #include <QPlainTextEdit>
34 testCursor.movePosition(NextCharacter, MoveAnchor, num - 1);
36 testCursor.setPosition(testCursor.position());
37 testCursor.movePosition(NextCharacter, KeepAnchor);
38 return testCursor.selectedText();
45 testCursor.movePosition(PreviousCharacter, MoveAnchor, num - 1);
47 testCursor.setPosition(testCursor.position());
48 testCursor.movePosition(PreviousCharacter, KeepAnchor);
49 return testCursor.selectedText();
54 movePosition(StartOfWord, moveMode);
59 if(
prevChar().contains(m_wordRegEx)){
60 movePosition(WordLeft, moveMode);
62 movePosition(NextCharacter, moveMode);
67 movePosition(WordLeft, moveMode, 2);
73 movePosition(EndOfWord, moveMode);
78 if(
nextChar().contains(m_wordRegEx)){
79 movePosition(WordRight, moveMode);
81 movePosition(PreviousCharacter, moveMode);
86 movePosition(WordRight, moveMode, 2);
98 m_undoRedoInProgress =
false;
99 m_noSpellingProperty = -1;
109 setTextEdit(textEdit ?
new TextEditProxyT<QTextEdit>(textEdit) :
reinterpret_cast<TextEditProxyT<QTextEdit>*
>(0));
114 setTextEdit(textEdit ?
new TextEditProxyT<QPlainTextEdit>(textEdit) :
reinterpret_cast<TextEditProxyT<QPlainTextEdit>*
>(0));
119 if(!textEdit && m_textEdit){
120 disconnect(m_textEdit->object(), SIGNAL(destroyed()),
this, SLOT(slotDetachTextEdit()));
121 disconnect(m_textEdit->object(), SIGNAL(textChanged()),
this, SLOT(slotCheckDocumentChanged()));
122 disconnect(m_textEdit->object(), SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slotShowContextMenu(QPoint)));
123 disconnect(m_textEdit->document(), SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
124 m_textEdit->setContextMenuPolicy(m_oldContextMenuPolicy);
125 m_textEdit->removeEventFilter(
this);
128 QTextCursor cursor = m_textEdit->textCursor();
129 cursor.movePosition(QTextCursor::Start);
130 cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
131 QTextCharFormat fmt = cursor.charFormat();
132 QTextCharFormat defaultFormat = QTextCharFormat();
133 fmt.setFontUnderline(defaultFormat.fontUnderline());
134 fmt.setUnderlineColor(defaultFormat.underlineColor());
135 fmt.setUnderlineStyle(defaultFormat.underlineStyle());
136 cursor.setCharFormat(fmt);
138 bool undoWasEnabled = m_undoRedoStack != 0;
142 m_textEdit = textEdit;
144 m_document = m_textEdit->document();
145 connect(m_textEdit->object(), SIGNAL(destroyed()),
this, SLOT(slotDetachTextEdit()));
146 connect(m_textEdit->object(), SIGNAL(textChanged()),
this, SLOT(slotCheckDocumentChanged()));
147 connect(m_textEdit->object(), SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(slotShowContextMenu(QPoint)));
148 connect(m_textEdit->document(), SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
149 m_oldContextMenuPolicy = m_textEdit->contextMenuPolicy();
151 m_textEdit->setContextMenuPolicy(Qt::CustomContextMenu);
152 m_textEdit->installEventFilter(
this);
157 bool TextEditChecker::eventFilter(QObject* obj, QEvent* event)
159 if(event->type() == QEvent::KeyPress){
160 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
161 if(keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == Qt::CTRL){
164 }
else if(keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == (Qt::CTRL | Qt::SHIFT)){
169 return QObject::eventFilter(obj, event);
175 QTextCursor tmpCursor(m_textEdit->textCursor());
176 tmpCursor.movePosition(QTextCursor::End);
177 end = tmpCursor.position();
181 m_textEdit->document()->blockSignals(
true);
183 qDebug() <<
"Checking range " << start <<
" - " << end;
185 QTextCharFormat errorFmt;
186 errorFmt.setFontUnderline(
true);
187 errorFmt.setUnderlineColor(Qt::red);
188 errorFmt.setUnderlineStyle(QTextCharFormat::WaveUnderline);
189 QTextCharFormat defaultFormat = QTextCharFormat();
192 cursor.beginEditBlock();
193 cursor.setPosition(start);
194 while(cursor.position() < end) {
197 QString word = cursor.selectedText();
198 if(noSpellingPropertySet(cursor)) {
200 qDebug() <<
"Skipping word:" << word <<
"(" << cursor.anchor() <<
"-" << cursor.position() <<
")";
203 qDebug() <<
"Checking word:" << word <<
"(" << cursor.anchor() <<
"-" << cursor.position() <<
"), correct:" << correct;
206 cursor.mergeCharFormat(errorFmt);
208 QTextCharFormat fmt = cursor.charFormat();
209 fmt.setFontUnderline(defaultFormat.fontUnderline());
210 fmt.setUnderlineColor(defaultFormat.underlineColor());
211 fmt.setUnderlineStyle(defaultFormat.underlineStyle());
212 cursor.setCharFormat(fmt);
215 while(cursor.position() < end && !cursor.isWordChar(cursor.nextChar())){
216 cursor.movePosition(QTextCursor::NextCharacter);
219 cursor.endEditBlock();
221 m_textEdit->document()->blockSignals(
false);
224 bool TextEditChecker::noSpellingPropertySet(
const QTextCursor &cursor)
const
226 if(m_noSpellingProperty < QTextFormat::UserProperty) {
229 if(cursor.charFormat().intProperty(m_noSpellingProperty) == 1) {
232 const QList<QTextLayout::FormatRange>& formats = cursor.block().layout()->additionalFormats();
233 int pos = cursor.positionInBlock();
234 foreach(
const QTextLayout::FormatRange& range, formats) {
235 if(pos > range.start && pos <= range.start + range.length && range.format.intProperty(m_noSpellingProperty) == 1) {
245 m_undoRedoStack->clear();
251 if(enabled == (m_undoRedoStack != 0)){
255 delete m_undoRedoStack;
260 m_undoRedoStack =
new UndoRedoStack(m_textEdit);
269 cursor.setPosition(pos);
271 cursor.moveWordEnd(QTextCursor::KeepAnchor);
273 *start = cursor.anchor();
275 *end = cursor.position();
276 return cursor.selectedText();
281 QTextCursor cursor(m_textEdit->textCursor());
282 cursor.setPosition(start);
283 cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, end - start);
284 cursor.insertText(word);
287 void TextEditChecker::slotShowContextMenu(
const QPoint &pos)
289 QPoint globalPos = m_textEdit->mapToGlobal(pos);
290 QMenu* menu = m_textEdit->createStandardContextMenu();
291 int wordPos = m_textEdit->cursorForPosition(pos).position();
292 showContextMenu(menu, globalPos, wordPos);
295 void TextEditChecker::slotCheckDocumentChanged()
297 if(m_document != m_textEdit->document()) {
298 bool undoWasEnabled = m_undoRedoStack != 0;
301 disconnect(m_document, SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
303 m_document = m_textEdit->document();
304 connect(m_document, SIGNAL(contentsChange(
int,
int,
int)),
this, SLOT(slotCheckRange(
int,
int,
int)));
309 void TextEditChecker::slotDetachTextEdit()
311 bool undoWasEnabled = m_undoRedoStack != 0;
323 void TextEditChecker::slotCheckRange(
int pos,
int removed,
int added)
325 if(m_undoRedoStack != 0 && !m_undoRedoInProgress){
326 m_undoRedoStack->handleContentsChange(pos, removed, added);
330 TextCursor c(m_textEdit->textCursor());
331 c.movePosition(QTextCursor::End);
332 int len = c.position();
333 if(pos == 0 && added > len){
341 c.setPosition(pos + added, QTextCursor::KeepAnchor);
342 c.moveWordEnd(QTextCursor::KeepAnchor);
343 QTextCharFormat fmt = c.charFormat();
344 QTextCharFormat defaultFormat = QTextCharFormat();
345 fmt.setFontUnderline(defaultFormat.fontUnderline());
346 fmt.setUnderlineColor(defaultFormat.underlineColor());
347 fmt.setUnderlineStyle(defaultFormat.underlineStyle());
348 c.setCharFormat(fmt);
355 if(m_undoRedoStack != 0){
356 m_undoRedoInProgress =
true;
357 m_undoRedoStack->undo();
358 m_textEdit->ensureCursorVisible();
359 m_undoRedoInProgress =
false;
365 if(m_undoRedoStack != 0){
366 m_undoRedoInProgress =
true;
367 m_undoRedoStack->redo();
368 m_textEdit->ensureCursorVisible();
369 m_undoRedoInProgress =
false;