예제 #1
0
void SpellCheckerCore::addMisspelledWords(const QString &fileName, const WordList &words)
{
    d->spellingMistakesModel->insertSpellingMistakes(fileName, words, d->filesInStartupProject.contains(fileName));
    if(d->currentFilePath == fileName) {
        d->mistakesModel->setCurrentSpellingMistakes(words);
    }

    /* Only apply the underlines to the current file. This is done so that if the
     * whole project is scanned, it does not add selections to pages that might
     * potentially never be opened. This can especially be a problem in large
     * projects.
     */
    if(d->currentFilePath != fileName) {
        return;
    }
    TextEditor::BaseTextEditor* baseEditor = qobject_cast<TextEditor::BaseTextEditor*>(d->currentEditor);
    if(baseEditor == NULL) {
        return;
    }
    TextEditor::TextEditorWidget* editorWidget = baseEditor->editorWidget();
    if(editorWidget == NULL) {
        return;
    }
    QList<QTextEdit::ExtraSelection> selections;
    foreach(const Word& word, words.values()) {
        QTextCursor cursor(editorWidget->document());
        /* Walk to the correct position using the line and column number since the
         * absolute position is not available and I do not know of a way to get/
         * calculate the absolute position from that information.
         *
         * One would think that the position from the CppDocumentParser::tokenizeWords()
         * function can be used if stored in the Word, but it is not the correct position. */
        cursor.setPosition(0);
        cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, word.lineNumber - 1);
        cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, word.columnNumber - 1);
        cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, word.length);

        /* Get the current format from the cursor, this is to make sure that the text font
         * and color stays the same, we just want to underline the mistake. */
        QTextCharFormat format = cursor.charFormat();
        format.setFontUnderline(true);
        format.setUnderlineColor(QColor(Qt::red));
        format.setUnderlineStyle(QTextCharFormat::WaveUnderline);
        format.setToolTip(word.suggestions.isEmpty() ? QLatin1String("Incorrect spelling")
                                                     : QString(QLatin1String("Incorrect spelling, did you mean '%1' ?")).arg(word.suggestions.first()));
        QTextEdit::ExtraSelection selection;
        selection.cursor = cursor;
        selection.format = format;
        selections.append(selection);
    }
    editorWidget->setExtraSelections(Core::Id(SpellChecker::Constants::SPELLCHECK_MISTAKE_ID), selections);

    /* The model updated, check if the word under the cursor is now a mistake
     * and notify the rest of the checker with this information. */
    Word word;
    bool wordIsMisspelled = isWordUnderCursorMistake(word);
    emit wordUnderCursorMistake(wordIsMisspelled, word);
}
void SpellCheckerCore::addMisspelledWords( const QString& fileName, const WordList& words )
{
  d->spellingMistakesModel->insertSpellingMistakes( fileName, words, d->filesInStartupProject.contains( fileName ) );
  if( d->currentFilePath == fileName ) {
    d->mistakesModel->setCurrentSpellingMistakes( words );
  }

  /* Only apply the underlines to the current file. This is done so that if the
   * whole project is scanned, it does not add selections to pages that might
   * potentially never be opened. This can especially be a problem in large
   * projects.
   */
  if( d->currentFilePath != fileName ) {
    return;
  }
  TextEditor::BaseTextEditor* baseEditor = qobject_cast<TextEditor::BaseTextEditor*>( d->currentEditor );
  if( baseEditor == nullptr ) {
    return;
  }
  TextEditor::TextEditorWidget* editorWidget = baseEditor->editorWidget();
  if( editorWidget == nullptr ) {
    return;
  }
  QTextDocument* document = editorWidget->document();
  if( document == nullptr ) {
    return;
  }
  QList<QTextEdit::ExtraSelection> selections;
  selections.reserve( words.size() );
  const WordList::ConstIterator wordsEnd = words.constEnd();
  for( WordList::ConstIterator wordIter = words.constBegin(); wordIter != wordsEnd; ++wordIter ) {
    const Word& word = wordIter.value();
    /* Get the QTextBlock for the line that the misspelled word is on.
     * The QTextDocument manages lines as blocks (in most cases).
     * The lineNumber of the misspelled word is 1 based (seen in the editor)
     * but the blocks on the QTextDocument are 0 based, thus minus one
     * from the line number to get the correct line.
     * If the block is valid, and the word is not longer than the number of
     * characters in the block (which should normally not be the case)
     * then the cursor is moved to the correct column, and the word is
     * underlined.
     * Again the Columns on the misspelled word is 1 based but
     * the blocks and cursor are 0 based. */
    const QTextBlock& block = document->findBlockByNumber( int32_t( word.lineNumber ) - 1 );
    if( ( block.isValid() == false )
        || ( uint32_t( block.length() ) < ( word.columnNumber - 1 + uint32_t( word.length ) ) ) ) {
      continue;
    }

    QTextCursor cursor( block );
    cursor.setPosition( cursor.position() + int32_t( word.columnNumber ) - 1 );
    cursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, word.length );
    /* Get the current format from the cursor, this is to make sure that the text font
     * and color stays the same, we just want to underline the mistake. */
    QTextCharFormat format = cursor.charFormat();
    format.setFontUnderline( true );
    static const QColor underLineColor = QColor( Qt::red );
    format.setUnderlineColor( underLineColor );
    format.setUnderlineStyle( QTextCharFormat::WaveUnderline );
    format.setToolTip( word.suggestions.isEmpty()
                       ? QStringLiteral( "Incorrect spelling" )
                       : QStringLiteral( "Incorrect spelling, did you mean '%1' ?" ).arg( word.suggestions.first() ) );
    QTextEdit::ExtraSelection selection;
    selection.cursor = cursor;
    selection.format = format;
    selections.append( selection );
  }
  editorWidget->setExtraSelections( Core::Id( SpellChecker::Constants::SPELLCHECK_MISTAKE_ID ), selections );

  /* The model updated, check if the word under the cursor is now a mistake
   * and notify the rest of the checker with this information. */
  Word word;
  bool wordIsMisspelled = isWordUnderCursorMistake( word );
  emit wordUnderCursorMistake( wordIsMisspelled, word );
}