diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp index c105e2859d00cf8313b82abe3fd84c9cfadf3c21..a413892fb51ac4add6d11e7d4b0b70b068abc890 100644 --- a/src/plugins/cppeditor/cpphighlighter.cpp +++ b/src/plugins/cppeditor/cpphighlighter.cpp @@ -239,13 +239,17 @@ void CppHighlighter::highlightBlock(const QString &text) int oldState = currentState & 0xff; int oldBraceDepth = currentState >> 8; if (oldState == tokenize.state() && oldBraceDepth != braceDepth) { + BaseTextDocumentLayout::FoldValidator foldValidor; + foldValidor.setup(qobject_cast<BaseTextDocumentLayout *>(document()->documentLayout())); int delta = braceDepth - oldBraceDepth; QTextBlock block = currentBlock().next(); while (block.isValid() && block.userState() != -1) { BaseTextDocumentLayout::changeBraceDepth(block, delta); BaseTextDocumentLayout::changeFoldingIndent(block, delta); + foldValidor.process(block); block = block.next(); } + foldValidor.finalize(); } } diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp index f6357e9035d2d06cc278ff69bb4608bde6a7244e..d0d6fe04ba3096b29accf8fe5392be957eb46306 100644 --- a/src/plugins/texteditor/basetextdocumentlayout.cpp +++ b/src/plugins/texteditor/basetextdocumentlayout.cpp @@ -575,3 +575,69 @@ QSizeF BaseTextDocumentLayout::documentSize() const size.setWidth(qMax((qreal)m_requiredWidth, size.width())); return size; } + +BaseTextDocumentLayout::FoldValidator::FoldValidator() + : m_layout(0) + , m_requestDocUpdate(false) + , m_insideFold(0) +{} + +void BaseTextDocumentLayout::FoldValidator::setup(BaseTextDocumentLayout *layout) +{ + m_layout = layout; +} + +void BaseTextDocumentLayout::FoldValidator::reset() +{ + m_insideFold = 0; + m_requestDocUpdate = false; +} + +void BaseTextDocumentLayout::FoldValidator::process(QTextBlock block) +{ + if (!m_layout) + return; + + const QTextBlock &previous = block.previous(); + if (!previous.isValid()) + return; + + if ((BaseTextDocumentLayout::isFolded(previous) + && !BaseTextDocumentLayout::canFold(previous)) + || (!BaseTextDocumentLayout::isFolded(previous) + && BaseTextDocumentLayout::canFold(previous) + && !block.isVisible())) { + BaseTextDocumentLayout::setFolded(previous, !BaseTextDocumentLayout::isFolded(previous)); + } + + if (BaseTextDocumentLayout::isFolded(previous) && !m_insideFold) + m_insideFold = BaseTextDocumentLayout::foldingIndent(block); + + bool toggleVisibility = false; + if (m_insideFold) { + if (BaseTextDocumentLayout::foldingIndent(block) >= m_insideFold) { + if (block.isVisible()) + toggleVisibility = true; + } else { + m_insideFold = 0; + if (!block.isVisible()) + toggleVisibility = true; + } + } else if (!block.isVisible()) { + toggleVisibility = true; + } + + if (toggleVisibility) { + block.setVisible(!block.isVisible()); + block.setLineCount(block.isVisible() ? qMax(1, block.layout()->lineCount()) : 0); + m_requestDocUpdate = true; + } +} + +void BaseTextDocumentLayout::FoldValidator::finalize() +{ + if (m_requestDocUpdate && m_layout) { + m_layout->requestUpdate(); + m_layout->emitDocumentSizeChanged(); + } +} diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h index fb115bc3e4d1b4cf27d2e66d940c5be096931e15..6930e5d0a7869844859f3348825e4d26660f3994 100644 --- a/src/plugins/texteditor/basetextdocumentlayout.h +++ b/src/plugins/texteditor/basetextdocumentlayout.h @@ -174,6 +174,22 @@ public: static bool isFolded(const QTextBlock &block); static void setFolded(const QTextBlock &block, bool folded); + class TEXTEDITOR_EXPORT FoldValidator + { + public: + FoldValidator(); + + void setup(BaseTextDocumentLayout *layout); + void reset(); + void process(QTextBlock block); + void finalize(); + + private: + BaseTextDocumentLayout *m_layout; + bool m_requestDocUpdate; + int m_insideFold; + }; + static TextBlockUserData *testUserData(const QTextBlock &block) { return static_cast<TextBlockUserData*>(block.userData()); } diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp index f10b20378606236106f327738baa28d2fde163a1..876433ea7b267b652023c8301bdd4eae370b9b8b 100644 --- a/src/plugins/texteditor/syntaxhighlighter.cpp +++ b/src/plugins/texteditor/syntaxhighlighter.cpp @@ -31,6 +31,7 @@ #include "syntaxhighlighter.h" #include "basetextdocument.h" +#include "basetextdocumentlayout.h" #include <qtextdocument.h> #include <qtextlayout.h> @@ -76,10 +77,12 @@ public: } void applyFormatChanges(int from, int charsRemoved, int charsAdded); + QVector<QTextCharFormat> formatChanges; QTextBlock currentBlock; bool rehighlightPending; bool inReformatBlocks; + BaseTextDocumentLayout::FoldValidator foldValidator; }; static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsRemoved, int charsAdded) { @@ -180,6 +183,8 @@ void SyntaxHighlighterPrivate::_q_reformatBlocks(int from, int charsRemoved, int void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded) { + foldValidator.reset(); + rehighlightPending = false; QTextBlock block = doc->findBlock(from); @@ -206,6 +211,8 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch } formatChanges.clear(); + + foldValidator.finalize(); } void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded) @@ -220,6 +227,8 @@ void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, q->highlightBlock(block.text()); applyFormatChanges(from, charsRemoved, charsAdded); + foldValidator.process(currentBlock); + currentBlock = QTextBlock(); } @@ -375,6 +384,7 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc) this, SLOT(_q_reformatBlocks(int,int,int))); d->rehighlightPending = true; QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight())); + d->foldValidator.setup(qobject_cast<BaseTextDocumentLayout *>(doc->documentLayout())); } }