From a71436649c2ec4bdd3732ee81cacd4165b1d8c00 Mon Sep 17 00:00:00 2001
From: mae <qt-info@nokia.com>
Date: Thu, 23 Apr 2009 17:28:53 +0200
Subject: [PATCH] removed the folding ribbon from the default configuration,
 instead turned a new block highlighting mechanism on.

---
 src/plugins/texteditor/basetexteditor.cpp  | 141 ++++++++++++++++++---
 src/plugins/texteditor/basetexteditor.h    |   4 +
 src/plugins/texteditor/basetexteditor_p.h  |  16 +++
 src/plugins/texteditor/displaysettings.cpp |   8 +-
 4 files changed, 150 insertions(+), 19 deletions(-)

diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index 9724ccf0b7f..081d343764a 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -188,6 +188,10 @@ BaseTextEditor::BaseTextEditor(QWidget *parent)
     d->m_parenthesesMatchingTimer->setSingleShot(true);
     connect(d->m_parenthesesMatchingTimer, SIGNAL(timeout()), this, SLOT(_q_matchParentheses()));
 
+    d->m_highlightBlocksTimer = new QTimer(this);
+    d->m_highlightBlocksTimer->setSingleShot(true);
+    connect(d->m_highlightBlocksTimer, SIGNAL(timeout()), this, SLOT(_q_highlightBlocks()));
+
 
     d->m_searchResultFormat.setBackground(QColor(0xffef0b));
 
@@ -429,6 +433,23 @@ bool DocumentMarker::addMark(TextEditor::ITextMark *mark, int line)
     return false;
 }
 
+int BaseTextEditorPrivate::visualIndent(const QTextBlock &block) const
+{
+    if (!block.isValid())
+        return 0;
+    const QTextDocument *document = block.document();
+    int i = 0;
+    while (i < block.length()) {
+        if (!document->characterAt(block.position() + i).isSpace()) {
+            QTextCursor cursor(block);
+            cursor.setPosition(block.position() + i);
+            return q->cursorRect(cursor).x();
+        }
+        ++i;
+    }
+
+    return 0;
+}
 
 TextEditor::TextMarks DocumentMarker::marksAt(int line) const
 {
@@ -1198,8 +1219,11 @@ bool BaseTextEditor::lineSeparatorsAllowed() const
 
 void BaseTextEditor::setHighlightBlocks(bool b)
 {
-    d->m_highlightBlocks = b & d->m_codeFoldingSupported;
-    viewport()->update();
+    if (d->m_highlightBlocks == b)
+        return;
+    d->m_highlightBlocks = b;
+    d->m_highlightBlocksInfo = BaseTextEditorPrivateHighlightBlocks();
+    _q_highlightBlocks();
 }
 
 bool BaseTextEditor::highlightBlocks() const
@@ -1755,22 +1779,28 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
     QTextBlock visibleCollapsedBlock;
     QPointF visibleCollapsedBlockOffset;
 
+
+
     while (block.isValid()) {
 
         QRectF r = blockBoundingRect(block).translated(offset);
         
         if (d->m_highlightBlocks) {
-            QTextBlock previousBlock = block.previous();
-            if (previousBlock.isValid()){
-                int thisBraceDepth = block.userState();
-                if (thisBraceDepth >= 0)
-                    thisBraceDepth >>= 8;
-                int braceDepth = block.previous().userState();
-                if (braceDepth >= 0)
-                    braceDepth >>= 8;
-                int minBraceDepth = qMin(thisBraceDepth, braceDepth);
-                if (minBraceDepth > 0) {
-                    painter.fillRect(r, calcBlendColor(baseColor, minBraceDepth));
+
+            int n = block.blockNumber();
+            int depth = 0;
+            foreach (int i, d->m_highlightBlocksInfo.open)
+                if (n >= i)
+                    ++depth;
+            foreach (int i, d->m_highlightBlocksInfo.close)
+                if (n > i)
+                    --depth;
+
+            int count = d->m_highlightBlocksInfo.visualIndent.size();
+            if (count) {
+                for(int i = 0; i <= depth; ++i) {
+                    int vi = i > 0 ? d->m_highlightBlocksInfo.visualIndent.at(i-1) : 0;
+                    painter.fillRect(r.adjusted(vi, 0, 0, 0), calcBlendColor(baseColor, count - i));
                 }
             }
         }
@@ -1814,7 +1844,7 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
                     else
                         selections.append(o);
                 } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection)
-                           && block.contains(range.cursor.position())) {
+                    && block.contains(range.cursor.position())) {
                     // for full width selections we don't require an actual selection, just
                     // a position to specify the line. that's more convenience in usage.
                     QTextLayout::FormatRange o;
@@ -1881,7 +1911,6 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
             // invisible blocks do have zero line count
             block = doc->findBlockByLineNumber(block.firstLineNumber());
         }
-
     }
 
     if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
@@ -2390,6 +2419,10 @@ void BaseTextEditor::slotCursorPositionChanged()
     }
 
     setExtraSelections(CurrentLineSelection, extraSelections);
+
+    if (d->m_highlightBlocks) {
+        d->m_highlightBlocksTimer->start(100);
+    }
 }
 
 void BaseTextEditor::slotUpdateBlockNotify(const QTextBlock &block)
@@ -3139,6 +3172,67 @@ bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool sel
     return false;
 }
 
+bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor)
+{
+    QTextBlock block = cursor->block();
+    int position = cursor->position();
+    int ignore = 0;
+    while (block.isValid()) {
+        Parentheses parenList = TextEditDocumentLayout::parentheses(block);
+        if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) {
+            for (int i = parenList.count()-1; i >= 0; --i) {
+                Parenthesis paren = parenList.at(i);
+                if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}')
+                    && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-'))
+                    continue;
+                if (block == cursor->block() &&
+                    (position - block.position() <= paren.pos))
+                        continue;
+                if (paren.type == Parenthesis::Closed) {
+                    ++ignore;
+                } else if (ignore > 0) {
+                    --ignore;
+                } else {
+                    cursor->setPosition(block.position() + paren.pos);
+                    return true;
+                }
+            }
+        }
+        block = block.previous();
+    }
+    return false;
+}
+
+bool TextBlockUserData::findNextBlockClosingParenthesis(QTextCursor *cursor)
+{
+    QTextBlock block = cursor->block();
+    int position = cursor->position();
+    int ignore = 0;
+    while (block.isValid()) {
+        Parentheses parenList = TextEditDocumentLayout::parentheses(block);
+        if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) {
+            for (int i = 0; i < parenList.count(); ++i) {
+                Parenthesis paren = parenList.at(i);
+                if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}')
+                    && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-'))
+                    continue;
+                if (block == cursor->block() && position - block.position() >= paren.pos)
+                    continue;
+                if (paren.type == Parenthesis::Opened) {
+                    ++ignore;
+                } else if (ignore > 0) {
+                    --ignore;
+                } else {
+                    cursor->setPosition(block.position() + paren.pos+1);
+                    return true;
+                }
+            }
+        }
+        block = block.next();
+    }
+    return false;
+}
+
 TextBlockUserData::MatchType TextBlockUserData::matchCursorBackward(QTextCursor *cursor)
 {
     cursor->clearSelection();
@@ -3274,6 +3368,23 @@ void BaseTextEditor::_q_matchParentheses()
     setExtraSelections(ParenthesesMatchingSelection, extraSelections);
 }
 
+void BaseTextEditor::_q_highlightBlocks()
+{
+    QTextCursor cursor = textCursor();
+    QTextCursor closeCursor = cursor;
+    BaseTextEditorPrivateHighlightBlocks highlightBlocksInfo;
+    while (TextBlockUserData::findPreviousBlockOpenParenthesis(&cursor)) {
+        highlightBlocksInfo.open.prepend(cursor.blockNumber());
+        highlightBlocksInfo.visualIndent.prepend(d->visualIndent(cursor.block()));
+        if (TextBlockUserData::findNextBlockClosingParenthesis(&closeCursor))
+            highlightBlocksInfo.close.append(closeCursor.blockNumber());
+    }
+    if (d->m_highlightBlocksInfo != highlightBlocksInfo) {
+        d->m_highlightBlocksInfo = highlightBlocksInfo;
+        viewport()->update();
+    }
+}
+
 void BaseTextEditor::setActionHack(QObject *hack)
 {
     d->m_actionHack = hack;
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 19ce6b36799..f0669a71046 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -167,6 +167,9 @@ public:
     static bool findPreviousOpenParenthesis(QTextCursor *cursor, bool select = false);
     static bool findNextClosingParenthesis(QTextCursor *cursor, bool select = false);
 
+    static bool findPreviousBlockOpenParenthesis(QTextCursor *cursor);
+    static bool findNextBlockClosingParenthesis(QTextCursor *cursor);
+
 
 private:
     TextMarks m_marks;
@@ -464,6 +467,7 @@ private:
     // parentheses matcher
 private slots:
     void _q_matchParentheses();
+    void _q_highlightBlocks();
     void slotSelectionChanged();
 };
 
diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h
index 74f158dab5e..9bff3da0f41 100644
--- a/src/plugins/texteditor/basetexteditor_p.h
+++ b/src/plugins/texteditor/basetexteditor_p.h
@@ -114,6 +114,17 @@ private:
 
 //================BaseTextEditorPrivate==============
 
+struct BaseTextEditorPrivateHighlightBlocks
+{
+    QList<int> open;
+    QList<int> close;
+    QList<int> visualIndent;
+    inline bool operator==(const BaseTextEditorPrivateHighlightBlocks &o) const {
+        return (open == o.open && close == o.close && visualIndent == o.visualIndent);
+    }
+    inline bool operator!=(const BaseTextEditorPrivateHighlightBlocks &o) const { return !(*this == o); }
+};
+
 class BaseTextEditorPrivate
 {
     BaseTextEditorPrivate(const BaseTextEditorPrivate &);
@@ -219,6 +230,11 @@ public:
     QTextCursor m_selectBlockAnchor;
 
     void moveCursorVisible(bool ensureVisible = true);
+
+    int visualIndent(const QTextBlock &block) const;
+    BaseTextEditorPrivateHighlightBlocks m_highlightBlocksInfo;
+    QTimer *m_highlightBlocksTimer;
+
 };
 
 } // namespace Internal
diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp
index 47e9ad4d474..27480d3dcc5 100644
--- a/src/plugins/texteditor/displaysettings.cpp
+++ b/src/plugins/texteditor/displaysettings.cpp
@@ -39,9 +39,9 @@ static const char * const textWrappingKey = "TextWrapping";
 static const char * const showWrapColumnKey = "ShowWrapColumn";
 static const char * const wrapColumnKey = "WrapColumn";
 static const char * const visualizeWhitespaceKey = "VisualizeWhitespace";
-static const char * const displayFoldingMarkersKey = "DisplayFoldingMarkers";
+static const char * const displayFoldingMarkersKey = "DisplayFoldingMarkersV2";
 static const char * const highlightCurrentLineKey = "HighlightCurrentLineKey";
-static const char * const highlightBlocksKey = "HighlightBlocksKey";
+static const char * const highlightBlocksKey = "HighlightBlocksKeyV2";
 static const char * const groupPostfix = "DisplaySettings";
 
 namespace TextEditor {
@@ -52,9 +52,9 @@ DisplaySettings::DisplaySettings() :
     m_showWrapColumn(false),
     m_wrapColumn(80),
     m_visualizeWhitespace(false),
-    m_displayFoldingMarkers(true),
+    m_displayFoldingMarkers(false),
     m_highlightCurrentLine(true),
-    m_highlightBlocks(false)
+    m_highlightBlocks(true)
 {
 }
 
-- 
GitLab