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();
}
}
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();
+ }
+}
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());
}
#include "syntaxhighlighter.h"
#include "basetextdocument.h"
+#include "basetextdocumentlayout.h"
#include <qtextdocument.h>
#include <qtextlayout.h>
}
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) {
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
{
+ foldValidator.reset();
+
rehighlightPending = false;
QTextBlock block = doc->findBlock(from);
}
formatChanges.clear();
+
+ foldValidator.finalize();
}
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
q->highlightBlock(block.text());
applyFormatChanges(from, charsRemoved, charsAdded);
+ foldValidator.process(currentBlock);
+
currentBlock = QTextBlock();
}
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()));
}
}