void SpellCheckerCore::replaceWordsInCurrentEditor(const WordList &wordsToReplace, const QString &replacementWord) { if(wordsToReplace.count() == 0) { Q_ASSERT(wordsToReplace.count() != 0); return; } if(d->currentEditor == NULL) { Q_ASSERT(d->currentEditor != NULL); return; } TextEditor::TextEditorWidget* editorWidget = qobject_cast<TextEditor::TextEditorWidget*>(d->currentEditor->widget()); if(editorWidget == NULL) { Q_ASSERT(editorWidget != NULL); return; } QTextCursor cursor = editorWidget->textCursor(); /* Iterate the words and replace all one by one */ foreach(const Word& wordToReplace, wordsToReplace) { editorWidget->gotoLine(wordToReplace.lineNumber, wordToReplace.columnNumber - 1); int wordStartPos = editorWidget->textCursor().position(); editorWidget->gotoLine(wordToReplace.lineNumber, wordToReplace.columnNumber + wordToReplace.length - 1); int wordEndPos = editorWidget->textCursor().position(); cursor.beginEditBlock(); cursor.setPosition(wordStartPos); cursor.setPosition(wordEndPos, QTextCursor::KeepAnchor); cursor.removeSelectedText(); cursor.insertText(replacementWord); cursor.endEditBlock(); }
void SpellCheckerCore::giveSuggestionsForWordUnderCursor() { if( d->currentEditor.isNull() == true ) { return; } Word word; WordList wordsToReplace; bool wordMistake = isWordUnderCursorMistake( word ); if( wordMistake == false ) { return; } getAllOccurrencesOfWord( word, wordsToReplace ); SuggestionsDialog dialog( word.text, word.suggestions, wordsToReplace.count() ); SuggestionsDialog::ReturnCode code = static_cast<SuggestionsDialog::ReturnCode>( dialog.exec() ); switch( code ) { case SuggestionsDialog::Rejected: /* Cancel and exit */ return; case SuggestionsDialog::Accepted: /* Clear the list and only add the one to replace */ wordsToReplace.clear(); wordsToReplace.append( word ); break; case SuggestionsDialog::AcceptAll: /* Do nothing since the list of words is already valid */ break; } QString replacement = dialog.replacementWord(); replaceWordsInCurrentEditor( wordsToReplace, replacement ); }
void SpellCheckerCore::replaceWordsInCurrentEditor( const WordList& wordsToReplace, const QString& replacementWord ) { if( wordsToReplace.count() == 0 ) { Q_ASSERT( wordsToReplace.count() != 0 ); return; } if( d->currentEditor == nullptr ) { Q_ASSERT( d->currentEditor != nullptr ); return; } TextEditor::TextEditorWidget* editorWidget = qobject_cast<TextEditor::TextEditorWidget*>( d->currentEditor->widget() ); if( editorWidget == nullptr ) { Q_ASSERT( editorWidget != nullptr ); return; } QTextCursor cursor = editorWidget->textCursor(); /* Iterate the words and replace all one by one */ for( const Word& wordToReplace: wordsToReplace ) { editorWidget->gotoLine( int32_t( wordToReplace.lineNumber ), int32_t( wordToReplace.columnNumber ) - 1 ); int wordStartPos = editorWidget->textCursor().position(); editorWidget->gotoLine( int32_t( wordToReplace.lineNumber ), int32_t( wordToReplace.columnNumber ) + wordToReplace.length - 1 ); int wordEndPos = editorWidget->textCursor().position(); cursor.beginEditBlock(); cursor.setPosition( wordStartPos ); cursor.setPosition( wordEndPos, QTextCursor::KeepAnchor ); cursor.removeSelectedText(); cursor.insertText( replacementWord ); cursor.endEditBlock(); } /* If more than one suggestion was replaced, show a notification */ if( wordsToReplace.count() > 1 ) { Utils::FadingIndicator::showText( editorWidget, tr( "%1 occurrences replaced." ).arg( wordsToReplace.count() ), Utils::FadingIndicator::SmallText ); } }
bool SpellCheckerCore::getAllOccurrencesOfWord(const Word &word, WordList& words) { if(d->currentEditor.isNull() == true) { return false; } WordList wl; QString currentFileName = d->currentEditor->document()->filePath().toString(); wl = d->spellingMistakesModel->mistakesForFile(currentFileName); if(wl.isEmpty() == true) { return false; } WordList::ConstIterator iter = wl.constBegin(); while(iter != wl.constEnd()) { const Word& currentWord = iter.value(); if(currentWord.text == word.text) { words.append(currentWord); } ++iter; } return (wl.count() > 0); }
void SpellCheckProcessor::process(QFutureInterface<WordList> &future) { #ifdef BENCH_TIME QElapsedTimer timer; timer.start(); #endif /* BENCH_TIME */ WordListConstIter misspelledIter; WordListConstIter prevMisspelledIter; Word misspelledWord; WordList misspelledWords; WordList words = d_wordList; WordListConstIter wordIter = words.constBegin(); bool spellingMistake; future.setProgressRange(0, words.count() + 1); while(wordIter != d_wordList.constEnd()) { /* Get the word at the current iterator position. * After this is done, move the iterator to the next position and * increment the progress value. This is done so that one can call * 'continue' anywhere after this in the loop without having to worry * about advancing the iterator since this will already be done and * correct for the next iteration. */ misspelledWord = (*wordIter); ++wordIter; future.setProgressValue(future.progressValue() + 1); /* Check if the future was cancelled */ if(future.isCanceled() == true) { return; } spellingMistake = d_spellChecker->isSpellingMistake(misspelledWord.text); /* Check to see if the char after the word is a period. If it is, * add the period to the word an see if it passes the checker. */ if((spellingMistake == true) && (misspelledWord.charAfter == QLatin1Char('.'))) { /* Recheck the word with the period added */ spellingMistake = d_spellChecker->isSpellingMistake(misspelledWord.text + QLatin1Char('.')); } if(spellingMistake == true) { /* The word is a spelling mistake, check if the word was a mistake * the previous time that this file was processed. If it was the * suggestions can be reused without having to get the suggestions * through the spell checker since this is slow compared to the rest * of the processing. */ prevMisspelledIter = d_previousMistakes.find(misspelledWord.text); if(prevMisspelledIter != d_previousMistakes.constEnd()) { misspelledWord.suggestions = (*prevMisspelledIter).suggestions; misspelledWords.append(misspelledWord); continue; } /* The word was not in the previous iteration, search for the word * in the list of words that were already checked in this iteration * and identified as spelling mistakes. If there are words that are * repeated and misspelled, this can reduce the time to process * the file since the time to get suggestions is rather slow. * If there are no repeating mistakes then this might add unneeded * overhead. */ misspelledIter = misspelledWords.find(misspelledWord.text); if(misspelledIter != misspelledWords.constEnd()) { misspelledWord.suggestions = (*misspelledIter).suggestions; /* Add the word to the local list of misspelled words. */ misspelledWords.append(misspelledWord); continue; } /* At this point the word is a mistake for the first time. It was neither * a mistake in the previous pass of the file nor did the word occur previously * in this file, use the spell checker to get the suggestions for the word. */ d_spellChecker->getSuggestionsForWord(misspelledWord.text, misspelledWord.suggestions); /* Add the word to the local list of misspelled words. */ misspelledWords.append(misspelledWord); } } #ifdef BENCH_TIME qDebug() << "File: " << d_fileName << "\n - time : " << timer.elapsed() << "\n - count: " << misspelledWords.size(); #endif /* BENCH_TIME */ future.reportResult(misspelledWords); }