aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLeandro Melo <leandro.melo@nokia.com>2011-08-12 12:13:23 +0200
committerLeandro T. C. Melo <leandro.melo@nokia.com>2011-08-15 10:21:52 +0200
commit3945b9a70f7dde57016d4f74cc7b50af7ad35253 (patch)
tree16cd2db7c018c88f421d9e942eab5d12ed4826f1 /src
parent916317a9fb4a8ebb8ee29fcca00c357db35e051f (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/plugins/cppeditor/cpphighlighter.cpp4
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.cpp66
-rw-r--r--src/plugins/texteditor/basetextdocumentlayout.h16
-rw-r--r--src/plugins/texteditor/syntaxhighlighter.cpp10
4 files changed, 96 insertions, 0 deletions
diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp
index c105e2859d0..a413892fb51 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 f6357e9035d..d0d6fe04ba3 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 fb115bc3e4d..6930e5d0a78 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 f10b2037860..876433ea7b2 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()));
}
}