forked from qt-creator/qt-creator
Editors: Make sure folded blocks remain consistent
When folding indents change and a block becomes no longer folded we need to update the user data. This patch tries to handle general inconsistencies that might arise in such situations. Notice however that there are stil other problems to be addressed (including issues in Qt). Task-number: QTCREATORBUG-5771 Change-Id: I38b869832159598d46cde00058308c218ca31f1a Reviewed-on: http://codereview.qt.nokia.com/2908 Reviewed-by: Robert Löhning <robert.loehning@nokia.com> Reviewed-by: Matthias Ettrich
This commit is contained in:
committed by
Leandro T. C. Melo
parent
916317a9fb
commit
3945b9a70f
@@ -239,13 +239,17 @@ void CppHighlighter::highlightBlock(const QString &text)
|
|||||||
int oldState = currentState & 0xff;
|
int oldState = currentState & 0xff;
|
||||||
int oldBraceDepth = currentState >> 8;
|
int oldBraceDepth = currentState >> 8;
|
||||||
if (oldState == tokenize.state() && oldBraceDepth != braceDepth) {
|
if (oldState == tokenize.state() && oldBraceDepth != braceDepth) {
|
||||||
|
BaseTextDocumentLayout::FoldValidator foldValidor;
|
||||||
|
foldValidor.setup(qobject_cast<BaseTextDocumentLayout *>(document()->documentLayout()));
|
||||||
int delta = braceDepth - oldBraceDepth;
|
int delta = braceDepth - oldBraceDepth;
|
||||||
QTextBlock block = currentBlock().next();
|
QTextBlock block = currentBlock().next();
|
||||||
while (block.isValid() && block.userState() != -1) {
|
while (block.isValid() && block.userState() != -1) {
|
||||||
BaseTextDocumentLayout::changeBraceDepth(block, delta);
|
BaseTextDocumentLayout::changeBraceDepth(block, delta);
|
||||||
BaseTextDocumentLayout::changeFoldingIndent(block, delta);
|
BaseTextDocumentLayout::changeFoldingIndent(block, delta);
|
||||||
|
foldValidor.process(block);
|
||||||
block = block.next();
|
block = block.next();
|
||||||
}
|
}
|
||||||
|
foldValidor.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -575,3 +575,69 @@ QSizeF BaseTextDocumentLayout::documentSize() const
|
|||||||
size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
|
size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
|
||||||
return size;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -174,6 +174,22 @@ public:
|
|||||||
static bool isFolded(const QTextBlock &block);
|
static bool isFolded(const QTextBlock &block);
|
||||||
static void setFolded(const QTextBlock &block, bool folded);
|
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) {
|
static TextBlockUserData *testUserData(const QTextBlock &block) {
|
||||||
return static_cast<TextBlockUserData*>(block.userData());
|
return static_cast<TextBlockUserData*>(block.userData());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "syntaxhighlighter.h"
|
#include "syntaxhighlighter.h"
|
||||||
#include "basetextdocument.h"
|
#include "basetextdocument.h"
|
||||||
|
#include "basetextdocumentlayout.h"
|
||||||
|
|
||||||
#include <qtextdocument.h>
|
#include <qtextdocument.h>
|
||||||
#include <qtextlayout.h>
|
#include <qtextlayout.h>
|
||||||
@@ -76,10 +77,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void applyFormatChanges(int from, int charsRemoved, int charsAdded);
|
void applyFormatChanges(int from, int charsRemoved, int charsAdded);
|
||||||
|
|
||||||
QVector<QTextCharFormat> formatChanges;
|
QVector<QTextCharFormat> formatChanges;
|
||||||
QTextBlock currentBlock;
|
QTextBlock currentBlock;
|
||||||
bool rehighlightPending;
|
bool rehighlightPending;
|
||||||
bool inReformatBlocks;
|
bool inReformatBlocks;
|
||||||
|
BaseTextDocumentLayout::FoldValidator foldValidator;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool adjustRange(QTextLayout::FormatRange &range, int from, int charsRemoved, int charsAdded) {
|
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)
|
void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int charsAdded)
|
||||||
{
|
{
|
||||||
|
foldValidator.reset();
|
||||||
|
|
||||||
rehighlightPending = false;
|
rehighlightPending = false;
|
||||||
|
|
||||||
QTextBlock block = doc->findBlock(from);
|
QTextBlock block = doc->findBlock(from);
|
||||||
@@ -206,6 +211,8 @@ void SyntaxHighlighterPrivate::reformatBlocks(int from, int charsRemoved, int ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
formatChanges.clear();
|
formatChanges.clear();
|
||||||
|
|
||||||
|
foldValidator.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block, int from, int charsRemoved, int charsAdded)
|
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());
|
q->highlightBlock(block.text());
|
||||||
applyFormatChanges(from, charsRemoved, charsAdded);
|
applyFormatChanges(from, charsRemoved, charsAdded);
|
||||||
|
|
||||||
|
foldValidator.process(currentBlock);
|
||||||
|
|
||||||
currentBlock = QTextBlock();
|
currentBlock = QTextBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,6 +384,7 @@ void SyntaxHighlighter::setDocument(QTextDocument *doc)
|
|||||||
this, SLOT(_q_reformatBlocks(int,int,int)));
|
this, SLOT(_q_reformatBlocks(int,int,int)));
|
||||||
d->rehighlightPending = true;
|
d->rehighlightPending = true;
|
||||||
QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
|
QTimer::singleShot(0, this, SLOT(_q_delayedRehighlight()));
|
||||||
|
d->foldValidator.setup(qobject_cast<BaseTextDocumentLayout *>(doc->documentLayout()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user