diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 617523235ca65c8017d2350d323da6ae76d4c8e2..74798b8b40a4aa7ad44ca75e2459af29f513d138 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -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()) { diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 994bfacb675f809896cd75b30845581770110934..0989ee6c4155901a7f11b1c591b6d04bc96e2d83 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -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); diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 5eb1ef92e3c3373e4581059a8886f734986a3bc3..0883e69ed25bdef21463220c2cfdf8815d8d8d98 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -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 index 0000000000000000000000000000000000000000..796165c2ae101e06c566349cc652d03da84d9d18 --- /dev/null +++ b/src/plugins/cppeditor/cppqtstyleindenter.cpp @@ -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 index 0000000000000000000000000000000000000000..4c91a1aa37491954c7e33370570c75e3a373f6b4 --- /dev/null +++ b/src/plugins/cppeditor/cppqtstyleindenter.h @@ -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 diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index df0791bc4a59b5af845e599c8d8f2580617c20a1..f40858c3edc31182499f8bcc7f0684d9838e350c 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -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); diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index f22336a4dbd74c78099c98a55b718e11f2fbcc34..ec7151a56aa05f1b7e01a98256763dc54bf9aa19 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -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(); diff --git a/src/plugins/qmljseditor/qmljseditor.pro b/src/plugins/qmljseditor/qmljseditor.pro index 53c7ca2bc923232219c075e09b1c10477d16ca89..7093b3ec0eb0b6c2fdf1b7c9b446c7dd7a13d341 100644 --- a/src/plugins/qmljseditor/qmljseditor.pro +++ b/src/plugins/qmljseditor/qmljseditor.pro @@ -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 index 0000000000000000000000000000000000000000..63f0c99d5e9298779cb09b4e6dd4f2c3ddca9a70 --- /dev/null +++ b/src/plugins/qmljseditor/qmljsindenter.cpp @@ -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 index 0000000000000000000000000000000000000000..82ad7114421ff1532832844b0a44fc305ff25df5 --- /dev/null +++ b/src/plugins/qmljseditor/qmljsindenter.h @@ -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 diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 9e356311bc69a9b5f4af06ece86a529e202647d7..7457634afdf4881f104261c0b2455a3a91112474 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -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(); diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h index ec51a3f86b89884bdcafdad3612d1eb26c3d9043..77caa0ff1c379a26ae373b3307c5c6cc9762c2dd 100644 --- a/src/plugins/texteditor/basetexteditor.h +++ b/src/plugins/texteditor/basetexteditor.h @@ -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. diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h index ccdae6c4d069962bc8bb51467af87dc3602e3a1c..bc6a3365eae1ba9f2787951f85e95e299b736218 100644 --- a/src/plugins/texteditor/basetexteditor_p.h +++ b/src/plugins/texteditor/basetexteditor_p.h @@ -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 diff --git a/src/plugins/texteditor/indenter.cpp b/src/plugins/texteditor/indenter.cpp index ee2edc642ac03616ecb44d92dcdb246da487a211..8007b4209e20dd32cc0763364283c3b30901ce28 100644 --- a/src/plugins/texteditor/indenter.cpp +++ b/src/plugins/texteditor/indenter.cpp @@ -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); + } } diff --git a/src/plugins/texteditor/indenter.h b/src/plugins/texteditor/indenter.h index 51b2131b28792a01b90647e8e7daa9cb933d7d42..3a58f5691258f3502fb27740bb7c4f192bc18d6b 100644 --- a/src/plugins/texteditor/indenter.h +++ b/src/plugins/texteditor/indenter.h @@ -37,11 +37,12 @@ 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 diff --git a/src/plugins/texteditor/normalindenter.cpp b/src/plugins/texteditor/normalindenter.cpp index 7a6eb1398c798ff324ad2ec63b97867f3f6ca192..d0c84b210f74cfaa2b096d98de72253f55ffc79e 100644 --- a/src/plugins/texteditor/normalindenter.cpp +++ b/src/plugins/texteditor/normalindenter.cpp @@ -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()) { diff --git a/src/plugins/texteditor/normalindenter.h b/src/plugins/texteditor/normalindenter.h index 7014f9ce3afe88ee431d8044b296c8f25b0a75de..f66bbaef0a08b8e6239b6b17f8c443ffb5e2f2c1 100644 --- a/src/plugins/texteditor/normalindenter.h +++ b/src/plugins/texteditor/normalindenter.h @@ -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 diff --git a/src/plugins/texteditor/plaintexteditor.cpp b/src/plugins/texteditor/plaintexteditor.cpp index ea1a0b0a2c22ff8439216c0aebdd782f547f3546..2a738b9cfab5c6f47cdd327b8749f8e39d2994d6 100644 --- a/src/plugins/texteditor/plaintexteditor.cpp +++ b/src/plugins/texteditor/plaintexteditor.cpp @@ -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, diff --git a/src/plugins/texteditor/plaintexteditor.h b/src/plugins/texteditor/plaintexteditor.h index 45ae953271a114327ea71ab5bc3c482080edad30..193bba6efd9ef04b6fd6fb0d3d0ff1384c0f6e04 100644 --- a/src/plugins/texteditor/plaintexteditor.h +++ b/src/plugins/texteditor/plaintexteditor.h @@ -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; };