BaseTextDocument::~BaseTextDocument()
{
    QTextBlock block = m_document->begin();
    while (block.isValid()) {
        if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData()))
            data->documentClosing();
        block = block.next();
    }
    delete m_document;
    m_document = 0;
}
Beispiel #2
0
qreal Text::baseLine() const
      {
      if (styled())
            return SimpleText::baseLine();
      for (QTextBlock tb = _doc->begin(); tb.isValid(); tb = tb.next()) {
            const QTextLayout* tl = tb.layout();
            if (tl->lineCount())
                  return (tl->lineAt(0).ascent() + tl->position().y());
            }
      return 0.0;
      }
Beispiel #3
0
/*!
 * \brief ModelicaEditor::storeLeadingSpaces
 * Stores the leading spaces information in the text block user data.
 * \param leadingSpacesMap
 */
void ModelicaEditor::storeLeadingSpaces(QMap<int, int> leadingSpacesMap)
{
  QTextBlock block = mpPlainTextEdit->document()->firstBlock();
  while (block.isValid()) {
    TextBlockUserData *pTextBlockUserData = BaseEditorDocumentLayout::userData(block);
    if (pTextBlockUserData) {
      pTextBlockUserData->setLeadingSpaces(leadingSpacesMap.value(block.blockNumber() + 1, 0));
    }
    block = block.next();
  }
}
Beispiel #4
0
QList<int> Editor::bookmarksList()
{
  QList<int> list;
  int line = 1;
  for ( QTextBlock block = m_textEdit->document()->begin(); block.isValid(); block = block.next(), line++ ) {
    BlockUserData *blockUserData = ( BlockUserData* ) block.userData();
    if ( blockUserData && blockUserData->bookmark )
      list << line;
  }
  return list;
}
Beispiel #5
0
bool VMdEditor::scrollToBlock(int p_blockNumber)
{
    QTextBlock block = document()->findBlockByNumber(p_blockNumber);
    if (block.isValid()) {
        VEditUtils::scrollBlockInPage(this, block.blockNumber(), 0);
        moveCursor(QTextCursor::EndOfBlock);
        return true;
    }

    return false;
}
int ExpressionUnderCursor::previousBlockState(const QTextBlock &block)
{
    const QTextBlock prevBlock = block.previous();
    if (prevBlock.isValid()) {
        int state = prevBlock.userState();

        if (state != -1)
            return state;
    }
    return 0;
}
Beispiel #7
0
void TestDocumentLayout::testRestartNumbering()
{
    // create 5 items; restart the 3th. Check numbering.
    initForNewTest("a\nb\na\nb\nc");

    KoParagraphStyle h1;
    m_styleManager->add(&h1);
    KoListStyle listStyle;
    KoListLevelProperties llp;
    llp.setStyle(KoListStyle::DecimalItem);
    llp.setStartValue(1);
    listStyle.setLevelProperties(llp);
    h1.setListStyle(&listStyle);

    QTextBlock block = m_doc->begin();
    while (block.isValid()) {
        h1.applyStyle(block);
        block = block.next();
    }

    QTextCursor cursor(m_doc);
    cursor.setPosition(5);
    QCOMPARE(cursor.block().text(), QString("a"));
    QTextBlockFormat format = cursor.blockFormat();
    format.setProperty(KoParagraphStyle::RestartListNumbering, true);
    cursor.setBlockFormat(format);

    m_layout->layout();

    static const char *const values[] = { "1", "2", "1", "2", "3" };
    block = m_doc->begin();
    int i = 0;
    while (block.isValid()) {
        KoTextBlockData *data = dynamic_cast<KoTextBlockData *>(block.userData());
        QVERIFY(data);
        // qDebug() << data->counterText() << QString(values[i]);
        QCOMPARE(data->counterText(), QString(values[i++]));

        block = block.next();
    }
}
Beispiel #8
0
QString LiteEditorWidget::cursorToHtml(QTextCursor cursor) const
{
    QTextDocument *tempDocument = new QTextDocument;
    QTextCursor tempCursor(tempDocument);
    tempCursor.insertFragment(cursor.selection());

    // Apply the additional formats set by the syntax highlighter
    QTextBlock start = document()->findBlock(cursor.selectionStart());
    QTextBlock end = document()->findBlock(cursor.selectionEnd());
    end = end.next();

    const int selectionStart = cursor.selectionStart();
    const int endOfDocument = tempDocument->characterCount() - 1;
    for (QTextBlock current = start; current.isValid() && current != end; current = current.next()) {
        const QTextLayout *layout = current.layout();
        foreach (const QTextLayout::FormatRange &range, layout->additionalFormats()) {
            const int start = current.position() + range.start - selectionStart;
            const int end = start + range.length;
            if (end <= 0 || start >= endOfDocument)
                continue;
            tempCursor.setPosition(qMax(start, 0));
            tempCursor.setPosition(qMin(end, endOfDocument), QTextCursor::KeepAnchor);
            tempCursor.setCharFormat(range.format);
        }
    }

    // Reset the user states since they are not interesting
    for (QTextBlock block = tempDocument->begin(); block.isValid(); block = block.next())
        block.setUserState(-1);

    // Make sure the text appears pre-formatted
    tempCursor.setPosition(0);
    tempCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
    QTextBlockFormat blockFormat = tempCursor.blockFormat();
    blockFormat.setNonBreakableLines(true);
    tempCursor.setBlockFormat(blockFormat);
    QString html = tempCursor.selection().toHtml();//("utf-8");
    html.replace("\t","&nbsp&nbsp&nbsp&nbsp");
    delete tempDocument;
    return html;
}
Beispiel #9
0
int TikzEditor::getCursorPosition(int row, int col) const
{
	int i = 0;
	QTextBlock p = document()->begin();
	while (p.isValid())
	{
		if (row == i) break;
		i++;
		p = p.next();
	}
	return p.position() + col;
}
int CMakeIndenter::indentFor(const QTextBlock &block, const TextEditor::TabSettings &tabSettings)
{
    QTextBlock previousBlock = block.previous();
    // find the next previous block that is non-empty (contains non-whitespace characters)
    while (previousBlock.isValid() && lineIsEmpty(previousBlock.text()))
        previousBlock = previousBlock.previous();
    if (!previousBlock.isValid())
        return 0;

    const QString previousLine = previousBlock.text();
    const QString currentLine = block.text();
    int indentation = tabSettings.indentationColumn(previousLine);

    if (lineStartsBlock(previousLine))
        indentation += tabSettings.m_indentSize;
    if (lineEndsBlock(currentLine))
        indentation = qMax(0, indentation - tabSettings.m_indentSize);

    // increase/decrease/keep the indentation level depending on if we have more opening or closing parantheses
    return qMax(0, indentation + tabSettings.m_indentSize * paranthesesLevel(previousLine));
}
Beispiel #11
0
void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    QPainter painter(mLineNumberArea);

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();

    int startBlock = textCursor().blockNumber();
    int endBlock = textCursor().blockNumber();
    if(textCursor().hasSelection())
    {
        QString str = textCursor().selection().toPlainText();
        int selectedLines = str.count("\n")+1;
        if(textCursor().position() < textCursor().anchor())
            endBlock += selectedLines;
        else
            startBlock -= selectedLines;
    }
    painter.setBackgroundMode(Qt::OpaqueMode);
    QFont font = painter.font();
    QBrush background = painter.background();

    while (block.isValid() && top <= event->rect().bottom())
    {
        if (block.isVisible() && bottom >= event->rect().top())
        {
            QFont newFont = painter.font();
            QString number = QString::number(blockNumber + 1);
            if(blockNumber >= startBlock && blockNumber <= endBlock)
            {
                painter.setBackground(Qt::cyan);
                painter.setPen(Qt::darkMagenta);
                newFont.setBold(true);
            }
            else
            {
                painter.setBackground(background);
                painter.setPen(Qt::black);
            }
            painter.setFont(newFont);
            painter.drawText(0, top, mLineNumberArea->width(), fontMetrics().height(),
                             Qt::AlignRight, number);
            painter.setFont(font);
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Beispiel #12
0
void GenericCodeEditor::paintLineIndicator( QPaintEvent *e )
{
    QPalette plt( mLineIndicator->palette() );
    QRect r( e->rect() );
    QPainter p( mLineIndicator );

    p.fillRect( r, plt.color( QPalette::Button ) );
    p.setPen( plt.color(QPalette::ButtonText) );
    p.drawLine( r.topRight(), r.bottomRight() );

    QTextDocument *doc = QPlainTextEdit::document();
    QTextCursor cursor(textCursor());
    int selStartBlock, selEndBlock;
    if (cursor.hasSelection()) {
        selStartBlock = doc->findBlock(cursor.selectionStart()).blockNumber();
        selEndBlock = doc->findBlock(cursor.selectionEnd()).blockNumber();
    }
    else
        selStartBlock = selEndBlock = -1;

    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    qreal top = blockBoundingGeometry(block).translated(contentOffset()).top();
    qreal bottom = top + blockBoundingRect(block).height();

    while (block.isValid() && top <= e->rect().bottom()) {
        if (block.isVisible() && bottom >= e->rect().top()) {
            p.save();

            QRectF numRect( 0, top, mLineIndicator->width() - 1, bottom - top );

            int num = blockNumber;
            if (num >= selStartBlock && num <= selEndBlock) {
                num -= selStartBlock;
                p.setPen(Qt::NoPen);
                p.setBrush(plt.color(QPalette::Highlight));
                p.drawRect(numRect);
                p.setPen(plt.color(QPalette::HighlightedText));
            }

            QString number = QString::number(num + 1);
            p.drawText(0, top, mLineIndicator->width() - 4, bottom - top,
                       Qt::AlignRight, number);

            p.restore();
        }

        block = block.next();
        top = bottom;
        bottom = top + blockBoundingRect(block).height();
        ++blockNumber;
    }
}
Beispiel #13
0
void CodeEditor::keyPressEvent(QKeyEvent *e)
{
    // SHIFT+TAB kommt hier nie an aus nicht nachvollziehbaren Grnden. Auch in event und viewPortEvent nicht.
    // NOTE: Qt macht daraus automatisch BackTab und versendet das!
    if( e->key() == Qt::Key_Tab )
    {
        if( e->modifiers() & Qt::ControlModifier )
        {
            // Wir brauchen CTRL+TAB fr Umschalten der Scripts
            e->ignore();
            return;
        }
        if( !isReadOnly() && ( hasSelection() || textCursor().position() <= _firstNwsPos( textCursor().block() ) ) )
        {
            if( e->modifiers() == Qt::NoModifier )
            {
                indent();
                e->accept();
                return;
            }
        }
	}else if( e->key() == Qt::Key_Backtab )
    {
        if( e->modifiers() & Qt::ControlModifier )
        {
            // Wir brauchen CTRL+TAB fr Umschalten der Scripts
            e->ignore();
            return;
        }
        if( !isReadOnly() && ( hasSelection() || textCursor().position() <= _firstNwsPos( textCursor().block() ) ) )
        {
            unindent();
            e->accept();
            return;
        }
    }else if( !isReadOnly() && ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return ) )
    {
        e->accept();
        if( e->modifiers() != Qt::NoModifier )
            return; // Verschlucke Return mit Ctrl etc.
        textCursor().beginEditBlock();
        QPlainTextEdit::keyPressEvent( e ); // Lasse Qt den neuen Block einfgen
        QTextBlock prev = textCursor().block().previous();
        if( prev.isValid() )
        {
            const int ws = _firstNwsPos( prev );
            textCursor().insertText( prev.text().left( ws - prev.position() ) );
        }
        textCursor().endEditBlock();
        return;
    }
    QPlainTextEdit::keyPressEvent( e );
}
Beispiel #14
0
void LineNumberArea::paintEvent(QPaintEvent *)
{
	if ( !codeEditor->lineAreaVisble() )
		return;
	QPainter painter(this);
	painter.fillRect(rect(), Qt::lightGray);
	//code based partly on: http://john.nachtimwald.com/2009/08/15/qtextedit-with-line-numbers/
	QTextBlock block = codeEditor->document()->begin();
	int contents_y = codeEditor->verticalScrollBar()->value();
	int page_bottom = contents_y + codeEditor->viewport()->height();
	QTextBlock current_block = codeEditor->document()->findBlock(codeEditor->textCursor().position());

	int line_count = 0;
	painter.setPen(QColor(Qt::darkGray).darker()); // not exactly black
	bool bold;
	QFont font = painter.font();
	while (block.isValid()) {
		line_count += 1;
		QString number = QString::number(line_count);
		QPointF position = codeEditor->document()->documentLayout()->blockBoundingRect(block).topLeft();
		if (position.y() > page_bottom)
			break;
		int y = round(position.y()) - contents_y + codeEditor->fontMetrics().ascent();
		if (y>=0) { // the line is visible
			if (block == current_block) {
				bold = true;
				font.setBold(true);
				painter.setFont(font);
			}
			painter.drawText(codeEditor->getAreaWidth() - codeEditor->fontMetrics().width(number) - 3, y, number); // 3 - add some padding


			if (bold) {
				font.setBold(false);
				painter.setFont(font);
			}
			if (m_debugLines.indexOf(line_count) >= 0) {
				painter.setPen(QColor(Qt::red));
				painter.setBrush(QColor(Qt::red));
				int height = codeEditor->fontMetrics().ascent() ;
				painter.drawEllipse(position.x(), y - height, height, height);
				painter.setBrush(QBrush());
				painter.setPen(QColor(Qt::darkGray).darker()); // not exactly black
			}
			if (m_currentDebugLine >= 0 && line_count == m_currentDebugLine) {
				QImage image("://themes/boring/gtk-media-play-ltr.png");
				painter.drawImage(position.x(), y, image);
			}
		}
		block = block.next();
	}
}
int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
{
    QTextBlock block = cursor.block();
    const QString text = block.text().trimmed();
    if (text == "end"
            || text == "else"
            || text.startsWith("elsif")
            || text.startsWith("rescue")
            || text == "ensure") {
        Indenter indenter(const_cast<QTextDocument*>(block.document()));
        indenter.indentBlock(block, QChar(), tabSettings());
    }

    return 0;
    // This implementation is buggy
#if 0
    const QString textFromCursor = text.mid(cursor.positionInBlock()).trimmed();
    if (!textFromCursor.isEmpty())
        return 0;

    if (Language::symbolDefinition.indexIn(text) == -1
            && Language::startOfBlock.indexIn(text) == -1) {
        return 0;
    }

    int spaces = 0;
    for (const QChar c : text) {
        if (!c.isSpace())
            break;
        spaces++;
    }
    QString indent = text.left(spaces);

    QString line;
    QTextBlock nextBlock = block.next();
    while (nextBlock.isValid()) {
        line = nextBlock.text();
        if (Language::endKeyword.indexIn(line) != -1 && line.startsWith(indent))
            return 0;
        if (!line.trimmed().isEmpty())
            break;
        nextBlock = nextBlock.next();
    }

    int pos = cursor.position();
    cursor.insertBlock();
    cursor.insertText("end");
    cursor.setPosition(pos);

    return 1;
#endif
}
Beispiel #16
0
FontDia::FontDia(QTextCursor* cursor, QWidget* parent)
        : KDialog(parent),
        m_cursor(cursor)
{
    //First find out if we have more than one charFormat in our selection. If so, m_initialFormat/m_style will get initialised with the charFormat at the cursor's position. The tabs will get informed of this.

    if (m_cursor->hasSelection()) {
        int begin = qMin(m_cursor->anchor(), m_cursor->position());
        int end = qMax(m_cursor->anchor(), m_cursor->position());
        QTextBlock block = m_cursor->block().document()->findBlock(begin);
        m_uniqueFormat = true;
        QTextCursor caret(*m_cursor);
        caret.setPosition(begin+1);
        m_initialFormat = caret.charFormat();
        while (block.isValid() && block.position() < end) {
            QTextBlock::iterator iter = block.begin();
            while (! iter.atEnd()) {
                QTextFragment fragment = iter.fragment();
                if (fragment.position() >= end)
                    break;
                if (fragment.position() + fragment.length() <= begin) {
                    iter++;
                    continue;
                }
                if (!(m_uniqueFormat = (fragment.charFormat() == m_initialFormat)))
                    break;
                iter++;
            }
            if (!m_uniqueFormat)
                break;
            block = block.next();
        }
    }
    else {
        m_initialFormat = cursor->charFormat();
        m_uniqueFormat = true;
    }

    setCaption(i18n("Select Font"));
    setModal(true);
    setButtons(Ok | Cancel | Reset | Apply);
    setDefaultButton(Ok);

    m_characterGeneral = new CharacterGeneral(this, m_uniqueFormat);
    m_characterGeneral->hideStyleName(true);
    setMainWidget(m_characterGeneral);

    connect(this, SIGNAL(applyClicked()), this, SLOT(slotApply()));
    connect(this, SIGNAL(okClicked()), this, SLOT(slotOk()));
    connect(this, SIGNAL(resetClicked()), this, SLOT(slotReset()));
    initTabs();
}
Beispiel #17
0
void CodeEditer::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
{
	if (cursor.hasSelection()) {
		QTextBlock block = doc->findBlock(qMin(cursor.selectionStart(), cursor.selectionEnd()));
		const QTextBlock end = doc->findBlock(qMax(cursor.selectionStart(), cursor.selectionEnd())).next();
		do {
			indentBlock(doc, block, typedChar);
			block = block.next();
		} while (block.isValid() && block != end);
	} else {
		indentBlock(doc, cursor.block(), typedChar);
	}
}
Beispiel #18
0
/*!
    Installs the syntax highlighter on the given QTextDocument \a doc.
    A QSyntaxHighlighter can only be used with one document at a time.
*/
void QSyntaxHighlighter::setDocument(QTextDocument *doc)
{
    Q_D(QSyntaxHighlighter);
    if (d->doc) {
        disconnect(d->doc, SIGNAL(contentsChange(int,int,int)),
                   this, SLOT(_q_reformatBlocks(int,int,int)));

        QTextCursor cursor(d->doc);
        cursor.beginEditBlock();
        for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next())
            blk.layout()->clearAdditionalFormats();
        cursor.endEditBlock();
    }
Beispiel #19
0
QTextLine TabTerminal::_currentTextLine(const QTextCursor & cursor)
{
	const QTextBlock block = cursor.block();
	if (!block.isValid())
		return QTextLine();

	const QTextLayout *layout = block.layout();
	if (!layout)
		return QTextLine();

	const int relativePos = cursor.position() - block.position();
	return layout->lineForTextPosition(relativePos);
}
Beispiel #20
0
///Retourne un QTextLine indiquant la position du curseur
QTextLine RzxTextEdit::currentTextLine() const
{
	const QTextBlock block = textCursor().block();
	if (!block.isValid())
		return QTextLine();

	const QTextLayout *layout = block.layout();
	if (!layout)
		return QTextLine();

	const int relativePos = textCursor().position() - block.position();
	return layout->lineForTextPosition(relativePos);
}
Beispiel #21
0
int BackwardsScanner::previousBlockState(const QTextBlock &block)
{
    const QTextBlock prevBlock = block.previous();

    if (prevBlock.isValid()) {
        int state = prevBlock.userState();

        if (state != -1)
            return state;
    }

    return 0;
}
void CPPEditorDocument::applyFontSettings()
{
    if (TextEditor::SyntaxHighlighter *highlighter = syntaxHighlighter()) {
        // Clear all additional formats since they may have changed
        QTextBlock b = document()->firstBlock();
        while (b.isValid()) {
            QList<QTextLayout::FormatRange> noFormats;
            highlighter->setExtraAdditionalFormats(b, noFormats);
            b = b.next();
        }
    }
    BaseTextDocument::applyFontSettings(); // rehighlights and updates additional formats
}
// Reset the header state of a here-doc to 7
// and the state of its body to 6.
void Highlighter::resetHereDocStates (QTextBlock block)
{
    if (block.userState() == hereDocTempState)
    {
        block.setUserState (hereDocHeaderState);
        block = block.next();
        while (block.isValid() && block.userState() != 0)
        {
            block.setUserState (hereDocBodyState);
            block = block.next();
        }
    }
}
Beispiel #24
0
bool convertPosition(const QTextDocument *document, int pos, int *line, int *column)
{
    QTextBlock block = document->findBlock(pos);
    if (!block.isValid()) {
        (*line) = -1;
        (*column) = -1;
        return false;
    } else {
        (*line) = block.blockNumber() + 1;
        (*column) = pos - block.position();
        return true;
    }
}
Beispiel #25
0
static void indent(QTextDocument *doc, const QTextCursor &cursor)
{
    if (cursor.hasSelection()) {
        QTextBlock block = doc->findBlock(cursor.selectionStart());
        QTextBlock last = doc->findBlock(cursor.selectionEnd());
        do {
            indent(doc, block);
            block = block.next();
        } while (block.isValid() && block < last);
    } else {
        indent(doc, cursor.block());
    }
}
Beispiel #26
0
QString GitEditorWidget::fileNameForLine(int line) const
{
    // 7971b6e7 share/qtcreator/dumper/dumper.py   (hjk
    QTextBlock block = document()->findBlockByLineNumber(line - 1);
    QTC_ASSERT(block.isValid(), return source());
    static QRegExp renameExp(QLatin1String("^" CHANGE_PATTERN "\\s+([^(]+)"));
    if (renameExp.indexIn(block.text()) != -1) {
        const QString fileName = renameExp.cap(1).trimmed();
        if (!fileName.isEmpty())
            return fileName;
    }
    return source();
}
int ScCodeEditor::indentationLevel(const QTextCursor & cursor)
{
    QTextDocument *doc = QPlainTextEdit::document();
    int startBlockNum = doc->findBlock(cursor.selectionStart()).blockNumber();

    QStack<int> stack;
    int level = 0;
    int blockNum = 0;
    QTextBlock block = QPlainTextEdit::document()->begin();
    while (block.isValid()) {
        if (level > 0) {
            stack.push(level);
            level = 0;
        }

        TextBlockData *data = static_cast<TextBlockData*>(block.userData());
        if (data) {
            int count = data->tokens.size();
            for (int idx = 0; idx < count; ++idx) {
                const Token & token = data->tokens[idx];
                switch (token.type) {
                case Token::OpeningBracket:
                    if (token.character != '(' || stack.size() || token.positionInBlock)
                        level += 1;
                    break;

                case Token::ClosingBracket:
                    if (level)
                        level -= 1;
                    else if(!stack.isEmpty()) {
                        stack.top() -= 1;
                        if (stack.top() <= 0)
                            stack.pop();
                    }
                    break;

                default:
                    ;
                }
            }
        }

        if (blockNum == startBlockNum)
            return stack.size();

        block = block.next();
        ++blockNum;
    }

    return -1;
}
/*
    Returns the recommended indent for the bottom line of yyProgram
    assuming that it starts in a C-style comment, a condition that is
    tested elsewhere.

    Essentially, we're trying to align against some text on the
    previous line.
*/
int QmlJSIndenter::indentWhenBottomLineStartsInMultiLineComment()
{
    QTextBlock block = yyProgram.lastBlock().previous();
    QString blockText;

    for (; block.isValid(); block = block.previous()) {
        blockText = block.text();

        if (! isOnlyWhiteSpace(blockText))
            break;
    }

    return indentOfLine(blockText);
}
QString GitEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
{
        // Check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
    // Go back chunks.
    const QString newFileIndicator = QLatin1String("+++ b/");
    for (QTextBlock  block = inBlock; block.isValid(); block = block.previous()) {
        QString diffFileName = block.text();
        if (diffFileName.startsWith(newFileIndicator)) {
            diffFileName.remove(0, newFileIndicator.size());
            return findDiffFile(diffFileName, GitPlugin::instance()->versionControl());
        }
    }
    return QString();
}
void CodeFormatter::saveCurrentState(const QTextBlock &block)
{
    if (!block.isValid())
        return;

    BlockData blockData;
    blockData.m_blockRevision = block.revision();
    blockData.m_beginState = m_beginState;
    blockData.m_endState = m_currentState;
    blockData.m_indentDepth = m_indentDepth;

    QTextBlock saveableBlock(block);
    saveBlockData(&saveableBlock, blockData);
}