OSDN Git Service

Editors: Refactor indenters out of the editors for better reusability.
authorLeandro Melo <leandro.melo@nokia.com>
Fri, 5 Nov 2010 13:27:16 +0000 (14:27 +0100)
committerLeandro Melo <leandro.melo@nokia.com>
Fri, 5 Nov 2010 13:28:38 +0000 (14:28 +0100)
Reviewed-by: ckamm
19 files changed:
src/plugins/cppeditor/cppeditor.cpp
src/plugins/cppeditor/cppeditor.h
src/plugins/cppeditor/cppeditor.pro
src/plugins/cppeditor/cppqtstyleindenter.cpp [new file with mode: 0644]
src/plugins/cppeditor/cppqtstyleindenter.h [new file with mode: 0644]
src/plugins/qmljseditor/qmljseditor.cpp
src/plugins/qmljseditor/qmljseditor.h
src/plugins/qmljseditor/qmljseditor.pro
src/plugins/qmljseditor/qmljsindenter.cpp [new file with mode: 0644]
src/plugins/qmljseditor/qmljsindenter.h [new file with mode: 0644]
src/plugins/texteditor/basetexteditor.cpp
src/plugins/texteditor/basetexteditor.h
src/plugins/texteditor/basetexteditor_p.h
src/plugins/texteditor/indenter.cpp
src/plugins/texteditor/indenter.h
src/plugins/texteditor/normalindenter.cpp
src/plugins/texteditor/normalindenter.h
src/plugins/texteditor/plaintexteditor.cpp
src/plugins/texteditor/plaintexteditor.h

index 6175232..74798b8 100644 (file)
@@ -35,6 +35,7 @@
 #include "cppquickfix.h"
 #include "cpplocalsymbols.h"
 #include "cppquickfixcollector.h"
+#include "cppqtstyleindenter.h"
 
 #include <AST.h>
 #include <Control.h>
@@ -414,6 +415,7 @@ CPPEditor::CPPEditor(QWidget *parent)
     setMarksVisible(true);
     setCodeFoldingSupported(true);
     setCodeFoldingVisible(true);
+    setIndenter(new CppQtStyleIndenter);
     baseTextDocument()->setSyntaxHighlighter(new CppHighlighter);
 
     m_modelManager = CppTools::CppModelManagerInterface::instance();
@@ -1405,17 +1407,6 @@ QModelIndex CPPEditor::outlineModelIndex()
     return m_outlineModelIndex;
 }
 
-bool CPPEditor::isElectricCharacter(QChar ch) const
-{
-    if (ch == QLatin1Char('{') ||
-        ch == QLatin1Char('}') ||
-        ch == QLatin1Char(':') ||
-        ch == QLatin1Char('#')) {
-        return true;
-    }
-    return false;
-}
-
 QString CPPEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text,
                                        QChar la, int *skippedChars) const
 {
@@ -1500,61 +1491,6 @@ bool CPPEditor::isInComment(const QTextCursor &cursor) const
     return false;
 }
 
-void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
-    Q_UNUSED(doc)
-
-    const TabSettings &ts = tabSettings();
-    CppTools::QtStyleCodeFormatter codeFormatter(ts);
-
-    codeFormatter.updateStateUntil(block);
-    int indent;
-    int padding;
-    codeFormatter.indentFor(block, &indent, &padding);
-
-    // only reindent the current line when typing electric characters if the
-    // indent is the same it would be if the line were empty
-    if (isElectricCharacter(typedChar)) {
-        int newlineIndent;
-        int newlinePadding;
-        codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
-        if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
-            return;
-    }
-
-    ts.indentLine(block, indent + padding, padding);
-}
-
-void CPPEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
-{
-    Q_UNUSED(doc)
-    Q_UNUSED(typedChar)
-
-    maybeClearSomeExtraSelections(cursor);
-    if (cursor.hasSelection()) {
-        QTextBlock block = doc->findBlock(cursor.selectionStart());
-        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
-
-        const TabSettings &ts = tabSettings();
-        CppTools::QtStyleCodeFormatter codeFormatter(ts);
-        codeFormatter.updateStateUntil(block);
-
-        QTextCursor tc = textCursor();
-        tc.beginEditBlock();
-        do {
-            int indent;
-            int padding;
-            codeFormatter.indentFor(block, &indent, &padding);
-            ts.indentLine(block, indent + padding, padding);
-            codeFormatter.updateLineStateChange(block);
-            block = block.next();
-        } while (block.isValid() && block != end);
-        tc.endEditBlock();
-    } else {
-        indentBlock(doc, cursor.block(), typedChar);
-    }
-}
-
 bool CPPEditor::event(QEvent *e)
 {
     switch (e->type()) {
index 994bfac..0989ee6 100644 (file)
@@ -207,9 +207,6 @@ protected:
 
     TextEditor::BaseTextEditorEditable *createEditableInterface();
 
-    // These override BaseTextEditor
-    virtual bool isElectricCharacter(QChar ch) const;
-
     virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text,
                                         QChar la, int *skippedChars) const;
 
@@ -252,8 +249,6 @@ private:
     void markSymbols(const QTextCursor &tc, const SemanticInfo &info);
     bool sortedOutline() const;
     CPlusPlus::Symbol *findDefinition(CPlusPlus::Symbol *symbol, const CPlusPlus::Snapshot &snapshot);
-    virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
-    virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
 
     TextEditor::ITextEditor *openCppEditorAt(const QString &fileName, int line,
                                              int column = 0);
index 5eb1ef9..0883e69 100644 (file)
@@ -22,7 +22,8 @@ HEADERS += cppplugin.h \
     cpplocalsymbols.h \
     cpptypehierarchy.h \
     cppelementevaluator.h \
-    cppquickfixcollector.h
+    cppquickfixcollector.h \
+    cppqtstyleindenter.h
 SOURCES += cppplugin.cpp \
     cppeditor.cpp \
     cpphighlighter.cpp \
@@ -38,6 +39,7 @@ SOURCES += cppplugin.cpp \
     cpplocalsymbols.cpp \
     cpptypehierarchy.cpp \
     cppelementevaluator.cpp \
-    cppquickfixcollector.cpp
+    cppquickfixcollector.cpp \
+    cppqtstyleindenter.cpp
 RESOURCES += cppeditor.qrc
 OTHER_FILES += CppEditor.mimetypes.xml
diff --git a/src/plugins/cppeditor/cppqtstyleindenter.cpp b/src/plugins/cppeditor/cppqtstyleindenter.cpp
new file mode 100644 (file)
index 0000000..796165c
--- /dev/null
@@ -0,0 +1,116 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cppqtstyleindenter.h"
+
+#include <cpptools/cppcodeformatter.h>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QChar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace CppEditor;
+using namespace Internal;
+
+CppQtStyleIndenter::CppQtStyleIndenter()
+{}
+
+CppQtStyleIndenter::~CppQtStyleIndenter()
+{}
+
+bool CppQtStyleIndenter::doIsElectricalCharacter(const QChar &ch) const
+{
+    if (ch == QLatin1Char('{') ||
+        ch == QLatin1Char('}') ||
+        ch == QLatin1Char(':') ||
+        ch == QLatin1Char('#')) {
+        return true;
+    }
+    return false;
+}
+
+void CppQtStyleIndenter::doIndentBlock(QTextDocument *doc,
+                                       const QTextBlock &block,
+                                       const QChar &typedChar,
+                                       TextEditor::BaseTextEditor *editor)
+{
+    Q_UNUSED(doc)
+
+    const TextEditor::TabSettings &ts = editor->tabSettings();
+    CppTools::QtStyleCodeFormatter codeFormatter(ts);
+
+    codeFormatter.updateStateUntil(block);
+    int indent;
+    int padding;
+    codeFormatter.indentFor(block, &indent, &padding);
+
+    // only reindent the current line when typing electric characters if the
+    // indent is the same it would be if the line were empty
+    if (isElectricCharacter(typedChar)) {
+        int newlineIndent;
+        int newlinePadding;
+        codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
+        if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
+            return;
+    }
+
+    ts.indentLine(block, indent + padding, padding);
+}
+
+void CppQtStyleIndenter::doIndent(QTextDocument *doc,
+                                  const QTextCursor &cursor,
+                                  const QChar &typedChar,
+                                  TextEditor::BaseTextEditor *editor)
+{
+    if (cursor.hasSelection()) {
+        QTextBlock block = doc->findBlock(cursor.selectionStart());
+        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+
+        const TextEditor::TabSettings &ts = editor->tabSettings();
+        CppTools::QtStyleCodeFormatter codeFormatter(ts);
+        codeFormatter.updateStateUntil(block);
+
+        QTextCursor tc = editor->textCursor();
+        tc.beginEditBlock();
+        do {
+            int indent;
+            int padding;
+            codeFormatter.indentFor(block, &indent, &padding);
+            ts.indentLine(block, indent + padding, padding);
+            codeFormatter.updateLineStateChange(block);
+            block = block.next();
+        } while (block.isValid() && block != end);
+        tc.endEditBlock();
+    } else {
+        indentBlock(doc, cursor.block(), typedChar, editor);
+    }
+}
diff --git a/src/plugins/cppeditor/cppqtstyleindenter.h b/src/plugins/cppeditor/cppqtstyleindenter.h
new file mode 100644 (file)
index 0000000..4c91a1a
--- /dev/null
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPPQTSTYLEINDENTER_H
+#define CPPQTSTYLEINDENTER_H
+
+#include <texteditor/indenter.h>
+
+namespace CppEditor {
+namespace Internal {
+
+class CppQtStyleIndenter : public TextEditor::Indenter
+{
+public:
+    CppQtStyleIndenter();
+    virtual ~CppQtStyleIndenter();
+
+private:
+    virtual bool doIsElectricalCharacter(const QChar &ch) const;
+    virtual void doIndentBlock(QTextDocument *doc,
+                               const QTextBlock &block,
+                               const QChar &typedChar,
+                               TextEditor::BaseTextEditor *editor);
+
+    virtual void doIndent(QTextDocument *doc,
+                          const QTextCursor &cursor,
+                          const QChar &typedChar,
+                          TextEditor::BaseTextEditor *editor);
+};
+
+} // Internal
+} // CppEditor
+
+#endif // CPPQTSTYLEINDENTER_H
index df0791b..f40858c 100644 (file)
@@ -38,6 +38,7 @@
 #include "qmloutlinemodel.h"
 #include "qmljsfindreferences.h"
 #include "qmljssemantichighlighter.h"
+#include "qmljsindenter.h"
 
 #include <qmljs/qmljsbind.h>
 #include <qmljs/qmljsdocument.h>
@@ -645,6 +646,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
     setMarksVisible(true);
     setCodeFoldingSupported(true);
     setCodeFoldingVisible(true);
+    setIndenter(new Indenter);
 
     m_updateDocumentTimer = new QTimer(this);
     m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
@@ -1262,15 +1264,6 @@ QString QmlJSTextEditor::wordUnderCursor() const
     return word;
 }
 
-bool QmlJSTextEditor::isElectricCharacter(QChar ch) const
-{
-    if (ch == QLatin1Char('}')
-            || ch == QLatin1Char(']')
-            || ch == QLatin1Char(':'))
-        return true;
-    return false;
-}
-
 bool QmlJSTextEditor::isClosingBrace(const QList<Token> &tokens) const
 {
 
@@ -1283,19 +1276,6 @@ bool QmlJSTextEditor::isClosingBrace(const QList<Token> &tokens) const
     return false;
 }
 
-void QmlJSTextEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
-    Q_UNUSED(doc)
-    Q_UNUSED(typedChar)
-
-    const TextEditor::TabSettings &ts = tabSettings();
-    QmlJSEditor::QtStyleCodeFormatter codeFormatter(ts);
-
-    codeFormatter.updateStateUntil(block);
-    const int depth = codeFormatter.indentFor(block);
-    ts.indentLine(block, depth);
-}
-
 TextEditor::BaseTextEditorEditable *QmlJSTextEditor::createEditableInterface()
 {
     QmlJSEditorEditable *editable = new QmlJSEditorEditable(this);
index f22336a..ec7151a 100644 (file)
@@ -210,8 +210,6 @@ protected:
     virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
 
 private:
-    virtual bool isElectricCharacter(QChar ch) const;
-    virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
     bool isClosingBrace(const QList<QmlJS::Token> &tokens) const;
 
     void setSelectedElements();
index 53c7ca2..7093b3e 100644 (file)
@@ -34,7 +34,8 @@ HEADERS += \
     qmljscomponentnamedialog.h \
     qmljsfindreferences.h \
     qmljseditoreditable.h \
-    qmljssemantichighlighter.h
+    qmljssemantichighlighter.h \
+    qmljsindenter.h
 
 SOURCES += \
     qmljscodecompletion.cpp \
@@ -62,7 +63,8 @@ SOURCES += \
     qmljscomponentnamedialog.cpp \
     qmljsfindreferences.cpp \
     qmljseditoreditable.cpp \
-    qmljssemantichighlighter.cpp
+    qmljssemantichighlighter.cpp \
+    qmljsindenter.cpp
 
 RESOURCES += qmljseditor.qrc
 OTHER_FILES += QmlJSEditor.mimetypes.xml
diff --git a/src/plugins/qmljseditor/qmljsindenter.cpp b/src/plugins/qmljseditor/qmljsindenter.cpp
new file mode 100644 (file)
index 0000000..63f0c99
--- /dev/null
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "qmljsindenter.h"
+#include "qmljseditorcodeformatter.h"
+
+#include <texteditor/basetexteditor.h>
+#include <texteditor/tabsettings.h>
+
+#include <QtCore/QChar>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace QmlJSEditor;
+using namespace Internal;
+
+Indenter::Indenter()
+{}
+
+Indenter::~Indenter()
+{}
+
+bool Indenter::doIsElectricalCharacter(const QChar &ch) const
+{
+    if (ch == QLatin1Char('}')
+            || ch == QLatin1Char(']')
+            || ch == QLatin1Char(':'))
+        return true;
+    return false;
+}
+
+void Indenter::doIndentBlock(QTextDocument *doc,
+                             const QTextBlock &block,
+                             const QChar &typedChar,
+                             TextEditor::BaseTextEditor *editor)
+{
+    Q_UNUSED(doc)
+    Q_UNUSED(typedChar)
+    Q_UNUSED(editor)
+
+    const TextEditor::TabSettings &ts = editor->tabSettings();
+    QtStyleCodeFormatter codeFormatter(ts);
+
+    codeFormatter.updateStateUntil(block);
+    const int depth = codeFormatter.indentFor(block);
+    ts.indentLine(block, depth);
+}
diff --git a/src/plugins/qmljseditor/qmljsindenter.h b/src/plugins/qmljseditor/qmljsindenter.h
new file mode 100644 (file)
index 0000000..82ad711
--- /dev/null
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef QMLJSINDENTER_H
+#define QMLJSINDENTER_H
+
+#include <texteditor/indenter.h>
+
+namespace QmlJSEditor {
+namespace Internal {
+
+class Indenter : public TextEditor::Indenter
+{
+public:
+    Indenter();
+    virtual ~Indenter();
+
+private:
+    virtual bool doIsElectricalCharacter(const QChar &ch) const;
+    virtual void doIndentBlock(QTextDocument *doc,
+                               const QTextBlock &block,
+                               const QChar &typedChar,
+                               TextEditor::BaseTextEditor *editor);
+};
+
+} // Internal
+} // QmlJSEditor
+
+#endif // QMLJSINDENTER_H
index 9e35631..7457634 100644 (file)
@@ -42,6 +42,7 @@
 #include "syntaxhighlighter.h"
 #include "tooltip.h"
 #include "tipcontents.h"
+#include "indenter.h"
 
 #include <aggregation/aggregate.h>
 #include <coreplugin/actionmanager/actionmanager.h>
@@ -1877,6 +1878,17 @@ int BaseTextEditor::visibleWrapColumn() const
     return d->m_visibleWrapColumn;
 }
 
+void BaseTextEditor::setIndenter(Indenter *indenter)
+{
+    // clear out existing code formatter data
+    for (QTextBlock it = document()->begin(); it.isValid(); it = it.next()) {
+        TextEditor::TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(it);
+        if (userData)
+            userData->setCodeFormatterData(0);
+    }
+    d->m_indenter.reset(indenter);
+}
+
 //--------- BaseTextEditorPrivate -----------
 
 BaseTextEditorPrivate::BaseTextEditorPrivate()
@@ -3995,8 +4007,10 @@ void BaseTextEditor::zoomReset()
     emit requestZoomReset();
 }
 
-bool BaseTextEditor::isElectricCharacter(QChar) const
+bool BaseTextEditor::isElectricCharacter(QChar ch) const
 {
+    if (!d->m_indenter.isNull())
+        return d->m_indenter->isElectricCharacter(ch);
     return false;
 }
 
@@ -4256,59 +4270,26 @@ int BaseTextEditor::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
     return 1;
 }
 
-void BaseTextEditor::indentBlock(QTextDocument *, QTextBlock, QChar)
+void BaseTextEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar ch)
 {
+    if (!d->m_indenter.isNull())
+        d->m_indenter->indentBlock(doc, block, ch, this);
 }
 
 void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar)
 {
     maybeClearSomeExtraSelections(cursor);
-    if (cursor.hasSelection()) {
-        QTextBlock block = doc->findBlock(cursor.selectionStart());
-        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
-        do {
-            indentBlock(doc, block, typedChar);
-            block = block.next();
-        } while (block.isValid() && block != end);
-    } else {
-        indentBlock(doc, cursor.block(), typedChar);
-    }
+    if (!d->m_indenter.isNull())
+        d->m_indenter->indent(doc, cursor, typedChar, this);
 }
 
 void BaseTextEditor::reindent(QTextDocument *doc, const QTextCursor &cursor)
 {
     maybeClearSomeExtraSelections(cursor);
-    if (cursor.hasSelection()) {
-        QTextBlock block = doc->findBlock(cursor.selectionStart());
-        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
-
-        const TabSettings &ts = d->m_document->tabSettings();
-
-        // skip empty blocks
-        while (block.isValid() && block != end) {
-            QString bt = block.text();
-            if (ts.firstNonSpace(bt) < bt.size())
-                break;
-            indentBlock(doc, block, QChar::Null);
-            block = block.next();
-        }
-
-        int previousIndentation = ts.indentationColumn(block.text());
-        indentBlock(doc, block, QChar::Null);
-        int currentIndentation = ts.indentationColumn(block.text());
-        int delta = currentIndentation - previousIndentation;
-
-        block = block.next();
-        while (block.isValid() && block != end) {
-            ts.reindentLine(block, delta);
-            block = block.next();
-        }
-    } else {
-        indentBlock(doc, cursor.block(), QChar::Null);
-    }
+    if (!d->m_indenter.isNull())
+        d->m_indenter->reindent(doc, cursor, this);
 }
 
-
 BaseTextEditor::Link BaseTextEditor::findLinkAt(const QTextCursor &, bool)
 {
     return Link();
index ec51a3f..77caa0f 100644 (file)
@@ -68,6 +68,7 @@ class BehaviorSettings;
 class CompletionSettings;
 class DisplaySettings;
 class StorageSettings;
+class Indenter;
 
 class TEXTEDITOR_EXPORT BaseTextEditorAnimator : public QObject
 {
@@ -222,6 +223,8 @@ public:
 
     QRegion translatedLineRegion(int lineStart, int lineEnd) const;
 
+    void setIndenter(Indenter *indenter);
+
 public slots:
     void setDisplayName(const QString &title);
 
@@ -409,17 +412,16 @@ protected:
     void dragEnterEvent(QDragEnterEvent *e);
 
 public:
-    // Returns true if key triggers an indent.
-    virtual bool isElectricCharacter(QChar ch) const;
-
-    void indentInsertedText(const QTextCursor &tc);
-
     // Returns the text to complete at the cursor position, or an empty string
     virtual QString autoComplete(QTextCursor &cursor, const QString &text) const;
     // Handles backspace. When returning true, backspace processing is stopped
     virtual bool autoBackspace(QTextCursor &cursor);
     // Hook to insert special characters on enter. Returns the number of extra blocks inserted.
     virtual int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor);
+
+    void indentInsertedText(const QTextCursor &tc);
+    // Returns true if key triggers an indent.
+    virtual bool isElectricCharacter(QChar ch) const;
     // Indent a text block based on previous line. Default does nothing
     virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
     // Indent at cursor. Calls indentBlock for selection or current line.
index ccdae6c..bc6a336 100644 (file)
@@ -42,6 +42,7 @@
 #include <QtCore/QBasicTimer>
 #include <QtCore/QSharedData>
 #include <QtCore/QPointer>
+#include <QtCore/QScopedPointer>
 
 #include <QtGui/QPixmap>
 #include <QtGui/QTextEdit>
@@ -292,6 +293,8 @@ public:
 
     QPointer<BaseTextEditorAnimator> m_animator;
     int m_cursorBlockNumber;
+
+    QScopedPointer<Indenter> m_indenter;
 };
 
 } // namespace Internal
index ee2edc6..8007b42 100644 (file)
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "indenter.h"
+#include "basetexteditor.h"
 #include "tabsettings.h"
 
 using namespace TextEditor;
@@ -38,10 +39,79 @@ Indenter::Indenter()
 Indenter::~Indenter()
 {}
 
+bool Indenter::isElectricCharacter(const QChar &ch) const
+{
+    return doIsElectricalCharacter(ch);
+}
+
 void Indenter::indentBlock(QTextDocument *doc,
-                           QTextBlock block,
-                           QChar typedChar,
-                           const TabSettings &ts)
+                           const QTextBlock &block,
+                           const QChar &typedChar,
+                           BaseTextEditor *editor)
+{
+    doIndentBlock(doc, block, typedChar, editor);
+}
+
+void Indenter::indent(QTextDocument *doc,
+                      const QTextCursor &cursor,
+                      const QChar &typedChar,
+                      BaseTextEditor *editor)
+{
+    doIndent(doc, cursor, typedChar, editor);
+}
+
+void Indenter::reindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor)
+{
+    doReindent(doc, cursor, editor);
+}
+
+bool Indenter::doIsElectricalCharacter(const QChar &) const
+{
+    return false;
+}
+
+void Indenter::doIndent(QTextDocument *doc, const QTextCursor &cursor, const QChar &typedChar, BaseTextEditor *editor)
 {
-    doIndentBlock(doc, block, typedChar, ts);
+    if (cursor.hasSelection()) {
+        QTextBlock block = doc->findBlock(cursor.selectionStart());
+        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+        do {
+            indentBlock(doc, block, typedChar, editor);
+            block = block.next();
+        } while (block.isValid() && block != end);
+    } else {
+        indentBlock(doc, cursor.block(), typedChar, editor);
+    }
+}
+
+void Indenter::doReindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor)
+{
+    if (cursor.hasSelection()) {
+        QTextBlock block = doc->findBlock(cursor.selectionStart());
+        const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
+
+        const TabSettings &ts = editor->tabSettings();
+
+        // skip empty blocks
+        while (block.isValid() && block != end) {
+            QString bt = block.text();
+            if (ts.firstNonSpace(bt) < bt.size())
+                break;
+            indentBlock(doc, block, QChar::Null, editor);
+            block = block.next();
+        }
+
+        int previousIndentation = ts.indentationColumn(block.text());
+        indentBlock(doc, block, QChar::Null, editor);
+        int currentIndentation = ts.indentationColumn(block.text());
+        int delta = currentIndentation - previousIndentation;
+
+        block = block.next();
+        while (block.isValid() && block != end) {
+            ts.reindentLine(block, delta);
+            block = block.next();
+        }
+    } else {
+        indentBlock(doc, cursor.block(), QChar::Null, editor);
+    }
 }
index 51b2131..3a58f56 100644 (file)
 
 QT_BEGIN_NAMESPACE
 class QTextDocument;
+class QTextCursor;
 QT_END_NAMESPACE
 
 namespace TextEditor {
 
-class TabSettings;
+class BaseTextEditor;
 
 class TEXTEDITOR_EXPORT Indenter
 {
@@ -49,13 +50,28 @@ public:
     Indenter();
     virtual ~Indenter();
 
-    void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar, const TabSettings &ts);
+    bool isElectricCharacter(const QChar &ch) const;
+    void indentBlock(QTextDocument *doc,
+                     const QTextBlock &block,
+                     const QChar &typedChar,
+                     BaseTextEditor *editor);
+    void indent(QTextDocument *doc,
+                const QTextCursor &cursor,
+                const QChar &typedChar,
+                BaseTextEditor *editor);
+    void reindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor);
 
 private:
+    virtual bool doIsElectricalCharacter(const QChar &ch) const;
     virtual void doIndentBlock(QTextDocument *doc,
-                               QTextBlock block,
-                               QChar typedChar,
-                               const TabSettings &ts) = 0;
+                               const QTextBlock &block,
+                               const QChar &typedChar,
+                               BaseTextEditor *editor) = 0;
+    virtual void doIndent(QTextDocument *doc,
+                          const QTextCursor &cursor,
+                          const QChar &typedChar,
+                          BaseTextEditor *editor);
+    virtual void doReindent(QTextDocument *doc, const QTextCursor &cursor, BaseTextEditor *editor);
 };
 
 } // namespace TextEditor
index 7a6eb13..d0c84b2 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "normalindenter.h"
 #include "tabsettings.h"
+#include "basetexteditor.h"
 
 #include <QtGui/QTextDocument>
 
@@ -60,9 +61,9 @@ NormalIndenter::~NormalIndenter()
 // to do in 2 steps (indenting/wrapping)}
 //
 void NormalIndenter::doIndentBlock(QTextDocument *doc,
-                                   QTextBlock block,
-                                   QChar typedChar,
-                                   const TextEditor::TabSettings &ts)
+                                   const QTextBlock &block,
+                                   const QChar &typedChar,
+                                   BaseTextEditor *editor)
 {
     Q_UNUSED(typedChar)
 
@@ -78,6 +79,7 @@ void NormalIndenter::doIndentBlock(QTextDocument *doc,
 
     // Just use previous line.
     // Skip blank characters when determining the indentation
+    const TabSettings &ts = editor->tabSettings();
     int i = 0;
     while (i < previousText.size()) {
         if (!previousText.at(i).isSpace()) {
index 7014f9c..f66bbae 100644 (file)
@@ -42,9 +42,9 @@ public:
 
 private:
     virtual void doIndentBlock(QTextDocument *doc,
-                               QTextBlock block,
-                               QChar typedChar,
-                               const TabSettings &ts);
+                               const QTextBlock &block,
+                               const QChar &typedChar,
+                               BaseTextEditor *editor);
 };
 
 } // namespace TextEditor
index ea1a0b0..2a738b9 100644 (file)
@@ -63,13 +63,13 @@ PlainTextEditorEditable::PlainTextEditorEditable(PlainTextEditor *editor)
 PlainTextEditor::PlainTextEditor(QWidget *parent)
   : BaseTextEditor(parent),
   m_isMissingSyntaxDefinition(false),
-  m_ignoreMissingSyntaxDefinition(false),
-  m_indenter(new NormalIndenter) // Currently only "normal" indentation is supported.
+  m_ignoreMissingSyntaxDefinition(false)
 {
     setRevisionsVisible(true);
     setMarksVisible(true);
     setRequestMarkEnabled(false);
     setLineSeparatorsAllowed(true);
+    setIndenter(new NormalIndenter); // Currently only "normal" indentation is supported.
 
     setMimeType(QLatin1String(TextEditor::Constants::C_TEXTEDITOR_MIMETYPE_TEXT));
     setDisplayName(tr(Core::Constants::K_DEFAULT_TEXT_EDITOR_DISPLAY_NAME));
@@ -230,11 +230,6 @@ QString PlainTextEditor::findDefinitionId(const Core::MimeType &mimeType,
     return definitionId;
 }
 
-void PlainTextEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
-{
-    m_indenter->indentBlock(doc, block, typedChar, tabSettings());
-}
-
 void PlainTextEditor::acceptMissingSyntaxDefinitionInfo()
 {
     Core::ICore::instance()->showOptionsDialog(Constants::TEXT_EDITOR_SETTINGS_CATEGORY,
index 45ae953..193bba6 100644 (file)
@@ -89,14 +89,12 @@ signals:
 
 protected:
     virtual BaseTextEditorEditable *createEditableInterface() { return new PlainTextEditorEditable(this); }    
-    virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
 
 private:
     QString findDefinitionId(const Core::MimeType &mimeType, bool considerParents) const;
 
     bool m_isMissingSyntaxDefinition;
     bool m_ignoreMissingSyntaxDefinition;
-    QScopedPointer<Indenter> m_indenter;
     Utils::CommentDefinition m_commentDefinition;
 };