void KPrAttributeHeight::initCache(KPrAnimationCache *animationCache, int step, KPrShapeAnimation * shapeAnimation, qreal startValue, qreal endValue)
{
    qreal v1 = 0.0, v2 = 0.0, tx = 0.0, ty = 0.0;
    KoShape * shape = shapeAnimation->shape();
    KoTextBlockData * textBlockData = shapeAnimation->textBlockData();

    if (textBlockData) {
        if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) {
            QTextDocument *textDocument = textShapeData->document();
            for (int i = 0; i < textDocument->blockCount(); i++) {
                QTextBlock textBlock = textDocument->findBlockByNumber(i);
                if (textBlock.userData() == textBlockData) {
                    QTextLayout *layout = textBlock.layout();
                    v1 = startValue * animationCache->pageSize().height() / layout->boundingRect().height();
                    v2 = endValue * animationCache->pageSize().height() / layout->boundingRect().height();
                    tx = layout->minimumWidth() * animationCache->zoom() / 2;
                    ty = layout->boundingRect().height() * animationCache->zoom() / 2;
                }
            }
        }
    }
    else {
        v1 = startValue * animationCache->pageSize().height() / shape->size().height();
        v2 = endValue * animationCache->pageSize().height() / shape->size().height();
        tx = shape->size().width() * animationCache->zoom() / 2;
        ty = shape->size().height() * animationCache->zoom() / 2;
    }
    animationCache->init(step, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v1).translate(-tx, -ty));
    animationCache->init(step + 1, shape, textBlockData, "transform", QTransform().translate(tx, ty).scale(1, v2).translate(-tx, -ty));
}
Example #2
0
QTextBlock QTextDocumentProto::findBlockByNumber(int blockNumber) const
{
  QTextDocument *item = qscriptvalue_cast<QTextDocument*>(thisObject());
  if (item)
    return item->findBlockByNumber(blockNumber);
  return QTextBlock();
}
void KPrAttributeHeight::updateCache(KPrAnimationCache *cache, KPrShapeAnimation *shapeAnimation, qreal value)
{
    qreal tx = 0.0, ty = 0.0;
    KoShape * shape = shapeAnimation->shape();
    KoTextBlockData * textBlockData = shapeAnimation->textBlockData();
    QTransform transform;
    if (textBlockData) {
        if (KoTextShapeData *textShapeData = dynamic_cast<KoTextShapeData*>(shape->userData())) {
            QTextDocument *textDocument = textShapeData->document();
            for (int i = 0; i < textDocument->blockCount(); i++) {
                QTextBlock textBlock = textDocument->findBlockByNumber(i);
                if (textBlock.userData() == textBlockData) {
                    QTextLayout *layout = textBlock.layout();
                    value = value * cache->pageSize().height() / layout->boundingRect().height();
                    tx = layout->minimumWidth() * cache->zoom() / 2;
                    ty = layout->boundingRect().height() * cache->zoom() / 2;
                }
            }
        }
    }
    else {
        value = value * cache->pageSize().height() / shape->size().height();
        tx = shape->size().width() * cache->zoom() / 2;
        ty = shape->size().height() * cache->zoom() / 2;
    }
    transform.translate(tx, ty).scale(1, value).translate(-tx, -ty);
    cache->update(shape, shapeAnimation->textBlockData(), "transform", transform);
}
void SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
        SyntaxHighlighter *highlighter,
        const QFuture<HighlightingResult> &future)
{
    // find block number of last result
    int lastBlockNumber = 0;
    for (int i = future.resultCount() - 1; i >= 0; --i) {
        const HighlightingResult &result = future.resultAt(i);
        if (result.line) {
            lastBlockNumber = result.line - 1;
            break;
        }
    }

    QTextDocument *doc = highlighter->document();

    const int firstBlockToClear = lastBlockNumber + 1;
    if (firstBlockToClear <= doc->blockCount())
        return;

    QTextBlock b = doc->findBlockByNumber(firstBlockToClear);

    while (b.isValid()) {
        QVector<QTextLayout::FormatRange> noFormats;
        highlighter->setExtraFormats(b, noFormats);
        b = b.next();
    }
}
Example #5
0
void TextEdit::go_to_line(int line)
{
    QTextDocument *document = textEdit->document();
    QTextCursor cursor(document);
    int position = document->findBlockByNumber (line).position();
    cursor.setPosition(position,QTextCursor::MoveAnchor);
    cursor.select(QTextCursor::LineUnderCursor);
    textEdit->setTextCursor(cursor);
    textEdit->setFocus();
}
Example #6
0
QString CodeEditor::getCode()
{
	QTextDocument *doc = this->document();
	int bc = doc->blockCount();
	QString str;
	for(int i=0; i<bc; ++i){
		QTextBlock block = doc->findBlockByNumber(i);
		QString s = block.text();
		str.append(s);
		if(!s.trimmed().isEmpty())
			str.append('\n');
	}

	return str;
}
QPair<int, int> getFirstAndLastVisiblePosition(Editor *editor)
{
  QTextCursor cursor = editor->textCursor();
  QTextDocument *doc = editor->document();
  int currentLine = doc->findBlock(cursor.position()).blockNumber();
  int cursorHeight = editor->cursorRect().height();
  int lineCountToFirstVisibleLine = editor->cursorRect().top() / cursorHeight;
  int firstVisibleLineNum = currentLine - lineCountToFirstVisibleLine;
  if (firstVisibleLineNum < 0) {
    firstVisibleLineNum = 0;
  }
  int maxLineNumOnScreen = (editor->viewport()->height() / cursorHeight);
  if (maxLineNumOnScreen < 1) {
    maxLineNumOnScreen = 1;
  }
  int firstPos = doc->findBlockByNumber(firstVisibleLineNum).position();
  int lastVisibleLineNum = firstVisibleLineNum + maxLineNumOnScreen - 1;
  QTextBlock lastVisibleTextBlock = doc->findBlockByNumber(lastVisibleLineNum);
  if (!lastVisibleTextBlock.isValid()) {
    lastVisibleTextBlock = doc->lastBlock();
  }
  int lastPos = lastVisibleTextBlock.position() + lastVisibleTextBlock.length() - 1;
  return QPair<int, int>(firstPos, lastPos);
}
Example #8
0
void FakeVimProxy::indentRegion(int beginBlock, int endBlock, QChar typedChar) {
    QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(m_widget);
    if (!ed)
        return;

    const auto indentSize = theFakeVimSetting(FakeVim::Internal::ConfigShiftWidth)
            ->value().toInt();

    QTextDocument *doc = ed->document();
    QTextBlock startBlock = doc->findBlockByNumber(beginBlock);

    // Record line lengths for mark adjustments
    QVector<int> lineLengths(endBlock - beginBlock + 1);
    QTextBlock block = startBlock;

    for (int i = beginBlock; i <= endBlock; ++i) {
        const auto line = block.text();
        lineLengths[i - beginBlock] = line.length();
        if (typedChar.unicode() == 0 && line.simplified().isEmpty()) {
            // clear empty lines
            QTextCursor cursor(block);
            while (!cursor.atBlockEnd())
                cursor.deleteChar();
        } else {
            const auto previousBlock = block.previous();
            const auto previousLine = previousBlock.isValid() ? previousBlock.text() : QString();

            int indent = firstNonSpace(previousLine);
            if (typedChar == '}')
                indent = std::max(0, indent - indentSize);
            else if ( previousLine.endsWith("{") )
                indent += indentSize;
            const auto indentString = QString(" ").repeated(indent);

            QTextCursor cursor(block);
            cursor.beginEditBlock();
            cursor.movePosition(QTextCursor::StartOfBlock);
            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, firstNonSpace(line));
            cursor.removeSelectedText();
            cursor.insertText(indentString);
            cursor.endEditBlock();
        }
        block = block.next();
    }
}
void BaseTextEditModifier::indent(int offset, int length)
{
    if (length == 0 || offset < 0 || offset + length >= text().length())
        return;

    if (TextEditor::TextEditorWidget *baseTextEditorWidget = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit())) {

        TextEditor::TextDocument *baseTextEditorDocument = baseTextEditorWidget->textDocument();
        QTextDocument *textDocument = baseTextEditorWidget->document();

        int startLine = -1;
        int endLine = -1;
        int column;

        baseTextEditorWidget->convertPosition(offset, &startLine, &column); //get line
        baseTextEditorWidget->convertPosition(offset + length, &endLine, &column); //get line

        QTextDocument *doc = baseTextEditorDocument->document();
        QTextCursor tc(doc);
        tc.beginEditBlock();

        if (startLine > 0) {
            TextEditor::TabSettings tabSettings = baseTextEditorDocument->tabSettings();
            for (int i = startLine; i <= endLine; i++) {
                QTextBlock start = textDocument->findBlockByNumber(i);

                if (start.isValid()) {
                    QmlJSEditor::Internal::Indenter indenter;
                    indenter.indentBlock(textDocument, start, QChar::Null, tabSettings);
                }
            }
        }

        tc.endEditBlock();
    }
}
void CodeFoldingPanel::paintEvent(QPaintEvent *e)
{
    QTextDocument *doc = editorWidget()->document();
    TextDocumentLayout *documentLayout = qobject_cast<TextDocumentLayout*>(doc->documentLayout());
    if(!documentLayout)
        return;

    QPalette pal = areaWidget()->palette();
    pal.setCurrentColorGroup(QPalette::Active);
    QPainter painter(this);
    const QFontMetrics fm(areaWidget()->font());

    const int collapseColumnWidth = d->m_codeFoldingVisible ? foldBoxWidth(fm): 0;
    const int extraAreaWidth = d->m_extraArea->width() - collapseColumnWidth;

    painter.fillRect(e->rect(), pal.color(QPalette::Background));

    QTextBlock block = editorWidget()->firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = editorWidget()->blockBoundingGeometry(block).translated(editorWidget()->contentOffset()).top();
    qreal bottom = top;

    while (block.isValid() && top <= e->rect().bottom()) {

        top = bottom;
        const qreal height = editorWidget()->blockBoundingRect(block).height();
        bottom = top + height;
        QTextBlock nextBlock = block.next();

        QTextBlock nextVisibleBlock = nextBlock;
        int nextVisibleBlockNumber = blockNumber + 1;

        if (!nextVisibleBlock.isVisible()) {
            // invisible blocks do have zero line count
            nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber());
            nextVisibleBlockNumber = nextVisibleBlock.blockNumber();
        }

        if (bottom < e->rect().top()) {
            block = nextVisibleBlock;
            blockNumber = nextVisibleBlockNumber;
            continue;
        }

        painter.setPen(pal.color(QPalette::Dark));

        painter.save();
        painter.setRenderHint(QPainter::Antialiasing, false);

        int extraAreaHighlightFoldBlockNumber = -1;
        int extraAreaHighlightFoldEndBlockNumber = -1;
        bool endIsVisible = false;
        if (!d->m_highlightBlocksInfo.isEmpty()) {
            extraAreaHighlightFoldBlockNumber =  d->m_highlightBlocksInfo.open.last();
            extraAreaHighlightFoldEndBlockNumber =  d->m_highlightBlocksInfo.close.first();
            endIsVisible = doc->findBlockByNumber(extraAreaHighlightFoldEndBlockNumber).isVisible();

//                    QTextBlock before = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1);
//                    if (TextBlockUserData::hasCollapseAfter(before)) {
//                        extraAreaHighlightCollapseBlockNumber--;
//                    }
        }

        TextBlockUserData *nextBlockUserData = TextDocumentLayout::testUserData(nextBlock);

        bool drawBox = nextBlockUserData
                       && TextDocumentLayout::foldingIndent(block) < nextBlockUserData->foldingIndent();



        bool active = blockNumber == extraAreaHighlightFoldBlockNumber;

        bool drawStart = active;
        bool drawEnd = blockNumber == extraAreaHighlightFoldEndBlockNumber || (drawStart && !endIsVisible);
        bool hovered = blockNumber >= extraAreaHighlightFoldBlockNumber
                       && blockNumber <= extraAreaHighlightFoldEndBlockNumber;

        int boxWidth = foldBoxWidth(fm);
        if (hovered) {
            int itop = qRound(top);
            int ibottom = qRound(bottom);
            QRect box = QRect(extraAreaWidth + 1, itop, boxWidth - 2, ibottom - itop);
            drawRectBox(&painter, box, drawStart, drawEnd, pal);
        }

        if (drawBox) {
            bool expanded = nextBlock.isVisible();
            int size = boxWidth/4;
            QRect box(extraAreaWidth + size, top + size,
                      2 * (size) + 1, 2 * (size) + 1);
            d->drawFoldingMarker(&painter, pal, box, expanded, active, hovered);
        }


        painter.restore();

        block = nextVisibleBlock;
        blockNumber = nextVisibleBlockNumber;
    }
}
void SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
        SyntaxHighlighter *highlighter,
        const QFuture<HighlightingResult> &future,
        int from, int to,
        const QHash<int, QTextCharFormat> &kindToFormat)
{
    if (to <= from)
        return;

    const int firstResultBlockNumber = future.resultAt(from).line - 1;

    // blocks between currentBlockNumber and the last block with results will
    // be cleaned of additional extra formats if they have no results
    int currentBlockNumber = 0;
    for (int i = from - 1; i >= 0; --i) {
        const HighlightingResult &result = future.resultAt(i);
        const int blockNumber = result.line - 1;
        if (blockNumber < firstResultBlockNumber) {
            // stop! found where last format stopped
            currentBlockNumber = blockNumber + 1;
            // add previous results for the same line to avoid undoing their formats
            from = i + 1;
            break;
        }
    }

    QTextDocument *doc = highlighter->document();
    QTC_ASSERT(currentBlockNumber < doc->blockCount(), return);
    QTextBlock b = doc->findBlockByNumber(currentBlockNumber);

    HighlightingResult result = future.resultAt(from);
    for (int i = from; i < to && b.isValid(); ) {
        const int blockNumber = result.line - 1;
        QTC_ASSERT(blockNumber < doc->blockCount(), return);

        // clear formats of blocks until blockNumber
        while (currentBlockNumber < blockNumber) {
            QVector<QTextLayout::FormatRange> noFormats;
            highlighter->setExtraFormats(b, noFormats);
            b = b.next();
            ++currentBlockNumber;
        }

        // collect all the formats for the current line
        QVector<QTextLayout::FormatRange> formats;
        formats.reserve(to - from);
        forever {
            QTextLayout::FormatRange formatRange;

            formatRange.format = textCharFormatForResult(result, kindToFormat);
            if (formatRange.format.isValid()) {
                formatRange.start = result.column - 1;
                formatRange.length = result.length;
                formats.append(formatRange);
            }

            ++i;
            if (i >= to)
                break;
            result = future.resultAt(i);
            const int nextBlockNumber = result.line - 1;
            if (nextBlockNumber != blockNumber)
                break;
        }
        highlighter->setExtraFormats(b, formats);
        b = b.next();
        ++currentBlockNumber;
    }
}
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 );
}
void LiteWordCompleter::completionPrefixChanged(QString prefix,bool force)
{
    LiteCompleter::completionPrefixChanged(prefix,force);

    if (m_bExternalMode) {
        return;
    }

    if (!m_editor) {
        return;
    }
    if (!m_bSearchSeparator) {
        if (prefix.indexOf(".") >= 0) {
            return;
        }
    }

    bool isSep = false;
    if (prefix.startsWith("@.")) {
        isSep = true;
        prefix = prefix.mid(1);
    }

    QTextCursor tc = m_editor->textCursor();
    QTextDocument *doc = m_editor->document();
    int maxNumber = tc.blockNumber();
    int blockNumber = tc.blockNumber();
    QTextBlock block = doc->firstBlock();
    if (maxNumber < 500) {
        maxNumber = 500;
    } else {
        int firstNumber = maxNumber-500;
        if (firstNumber > 0) {
            block = doc->findBlockByNumber(firstNumber);
        }
    }
    QRegExp rx("([\\w\\-\\_\\.]+)");
    Qt::CaseSensitivity cs = m_completer->caseSensitivity();
    int count = 0;
    while (block.isValid()) {
        if (block.blockNumber() >= maxNumber) {
            break;
        }
        if (block.blockNumber() == blockNumber) {
            block = block.next();
            continue;
        }
        QString line = block.text().trimmed();
        if (!line.isEmpty())  {
             int pos = 0;
             while ((pos = rx.indexIn(line, pos)) != -1) {
                 QString cap = rx.cap(1);
                 if (cap.length() < 20 && cap.startsWith(prefix,cs)) {
                     if (isSep) {
                         cap = "@"+cap;
                     }
                     count++;
                     appendItem(cap,m_icon,true);
                 }
                 pos += rx.matchedLength();
             }
        }
        block = block.next();
    }
    if (count > 0) {
        this->updateCompleterModel();
        this->showPopup();
    }
}
Example #14
0
void VMdEditor::updateHeaders(const QVector<VElementRegion> &p_headerRegions)
{
    QTextDocument *doc = document();

    QVector<VTableOfContentItem> headers;
    QVector<int> headerBlockNumbers;
    QVector<QString> headerSequences;
    if (!p_headerRegions.isEmpty()) {
        headers.reserve(p_headerRegions.size());
        headerBlockNumbers.reserve(p_headerRegions.size());
        headerSequences.reserve(p_headerRegions.size());
    }

    // Assume that each block contains only one line
    // Only support # syntax for now
    QRegExp headerReg(VUtils::c_headerRegExp);
    int baseLevel = -1;
    for (auto const & reg : p_headerRegions) {
        QTextBlock block = doc->findBlock(reg.m_startPos);
        if (!block.isValid()) {
            continue;
        }

        if (!block.contains(reg.m_endPos - 1)) {
            qWarning() << "header accross multiple blocks, starting from block"
                       << block.blockNumber()
                       << block.text();
        }

        if ((block.userState() == HighlightBlockState::Normal)
            && headerReg.exactMatch(block.text())) {
            int level = headerReg.cap(1).length();
            VTableOfContentItem header(headerReg.cap(2).trimmed(),
                                       level,
                                       block.blockNumber(),
                                       headers.size());
            headers.append(header);
            headerBlockNumbers.append(block.blockNumber());
            headerSequences.append(headerReg.cap(3));

            if (baseLevel == -1) {
                baseLevel = level;
            } else if (baseLevel > level) {
                baseLevel = level;
            }
        }
    }

    m_headers.clear();

    bool autoSequence = m_config.m_enableHeadingSequence
                        && !isReadOnly()
                        && m_file->isModifiable();
    int headingSequenceBaseLevel = g_config->getHeadingSequenceBaseLevel();
    if (headingSequenceBaseLevel < 1 || headingSequenceBaseLevel > 6) {
        headingSequenceBaseLevel = 1;
    }

    QVector<int> seqs(7, 0);
    QRegExp preReg(VUtils::c_headerPrefixRegExp);
    int curLevel = baseLevel - 1;
    for (int i = 0; i < headers.size(); ++i) {
        VTableOfContentItem &item = headers[i];
        while (item.m_level > curLevel + 1) {
            curLevel += 1;

            // Insert empty level which is an invalid header.
            m_headers.append(VTableOfContentItem(c_emptyHeaderName,
                                                 curLevel,
                                                 -1,
                                                 m_headers.size()));
            if (autoSequence) {
                addHeaderSequence(seqs, curLevel, headingSequenceBaseLevel);
            }
        }

        item.m_index = m_headers.size();
        m_headers.append(item);
        curLevel = item.m_level;
        if (autoSequence) {
            addHeaderSequence(seqs, item.m_level, headingSequenceBaseLevel);

            QString seqStr = headerSequenceStr(seqs);
            if (headerSequences[i] != seqStr) {
                // Insert correct sequence.
                insertSequenceToHeader(doc->findBlockByNumber(headerBlockNumbers[i]),
                                       headerReg,
                                       preReg,
                                       seqStr);
            }
        }
    }

    emit headersChanged(m_headers);

    updateCurrentHeader();
}