diff options
-rw-r--r-- | src/plugins/texteditor/tabsettings.cpp | 9 | ||||
-rw-r--r-- | src/plugins/texteditor/tabsettings.h | 2 | ||||
-rw-r--r-- | src/plugins/texteditor/textdocument.cpp | 121 | ||||
-rw-r--r-- | src/plugins/texteditor/textdocument.h | 6 | ||||
-rw-r--r-- | src/plugins/texteditor/texteditor.cpp | 31 |
5 files changed, 112 insertions, 57 deletions
diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp index 9a075f25af6..edc04739a35 100644 --- a/src/plugins/texteditor/tabsettings.cpp +++ b/src/plugins/texteditor/tabsettings.cpp @@ -198,12 +198,13 @@ int TabSettings::columnAt(const QString &text, int position) const return column; } -int TabSettings::positionAtColumn(const QString &text, int column, int *offset) const +int TabSettings::positionAtColumn(const QString &text, int column, int *offset, bool allowOverstep) const { int col = 0; int i = 0; - while (i < text.size() && col < column) { - if (text.at(i) == QLatin1Char('\t')) + int textSize = text.size(); + while ((i < textSize || allowOverstep) && col < column) { + if (i < textSize && text.at(i) == QLatin1Char('\t')) col = col - (col % m_tabSize) + m_tabSize; else ++col; @@ -228,6 +229,8 @@ int TabSettings::columnCountForText(const QString &text, int startColumn) const int TabSettings::spacesLeftFromPosition(const QString &text, int position) { + if (position >= text.size()) + return 0; int i = position; while (i > 0) { if (!text.at(i-1).isSpace()) diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h index 0522b026838..37d41f925e3 100644 --- a/src/plugins/texteditor/tabsettings.h +++ b/src/plugins/texteditor/tabsettings.h @@ -70,7 +70,7 @@ public: int lineIndentPosition(const QString &text) const; int columnAt(const QString &text, int position) const; - int positionAtColumn(const QString &text, int column, int *offset = 0) const; + int positionAtColumn(const QString &text, int column, int *offset = 0, bool allowOverstep = false) const; int columnCountForText(const QString &text, int startColumn = 0) const; int indentedColumn(int column, bool doIndent = true) const; QString indentationString(int startColumn, int targetColumn, const QTextBlock ¤tBlock = QTextBlock()) const; diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 3d5b0680314..dc3d7b4d522 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -87,7 +87,8 @@ public: { } - QTextCursor indentOrUnindent(const QTextCursor &textCursor, bool doIndent); + QTextCursor indentOrUnindent(const QTextCursor &textCursor, bool doIndent, + bool blockSelection = false, int column = 0, int *offset = 0); void resetRevisions(); void updateRevisions(); @@ -111,56 +112,84 @@ public: TextMarks m_marksCache; // Marks not owned }; -QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, bool doIndent) +QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, bool doIndent, + bool blockSelection, int columnIn, int *offset) { QTextCursor cursor = textCursor; cursor.beginEditBlock(); - if (cursor.hasSelection()) { - // Indent or unindent the selected lines - int pos = cursor.position(); - int anchor = cursor.anchor(); - int start = qMin(anchor, pos); - int end = qMax(anchor, pos); - - QTextBlock startBlock = m_document.findBlock(start); - QTextBlock endBlock = m_document.findBlock(end-1).next(); - - if (startBlock.next() == endBlock - && (start > startBlock.position() || end < endBlock.position() - 1)) { - // Only one line partially selected. + TabSettings &ts = m_tabSettings; + + // Indent or unindent the selected lines + int pos = cursor.position(); + int column = blockSelection ? columnIn + : ts.columnAt(cursor.block().text(), cursor.positionInBlock()); + int anchor = cursor.anchor(); + int start = qMin(anchor, pos); + int end = qMax(anchor, pos); + bool modified = true; + + QTextBlock startBlock = m_document.findBlock(start); + QTextBlock endBlock = m_document.findBlock(end).next(); + + const bool oneLinePartial = (startBlock.next() == endBlock) + && (start > startBlock.position() || end < endBlock.position() - 1); + + // Make sure one line selection will get processed in "for" loop + if (startBlock == endBlock) + endBlock = endBlock.next(); + + if (cursor.hasSelection() && !blockSelection && !oneLinePartial) { + for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { + const QString text = block.text(); + int indentPosition = ts.lineIndentPosition(text); + if (!doIndent && !indentPosition) + indentPosition = ts.firstNonSpace(text); + int targetColumn = ts.indentedColumn(ts.columnAt(text, indentPosition), doIndent); + cursor.setPosition(block.position() + indentPosition); + cursor.insertText(ts.indentationString(0, targetColumn, block)); + cursor.setPosition(block.position()); + cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor); cursor.removeSelectedText(); - } else { - for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { - QString text = block.text(); - int indentPosition = m_tabSettings.lineIndentPosition(text); - if (!doIndent && !indentPosition) - indentPosition = m_tabSettings.firstNonSpace(text); - int targetColumn = m_tabSettings.indentedColumn(m_tabSettings.columnAt(text, indentPosition), doIndent); - cursor.setPosition(block.position() + indentPosition); - cursor.insertText(m_tabSettings.indentationString(0, targetColumn, block)); - cursor.setPosition(block.position()); - cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); + modified = false; + } + } else if (cursor.hasSelection() && !blockSelection && oneLinePartial) { + // Only one line partially selected. + cursor.removeSelectedText(); + } else { + // Indent or unindent at cursor position + for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { + QString text = block.text(); + + int blockColumn = ts.columnAt(text, text.size()); + if (blockColumn < column) { + cursor.setPosition(block.position() + text.size()); + cursor.insertText(ts.indentationString(blockColumn, column, block)); + text = block.text(); } - cursor.endEditBlock(); - return textCursor; + + int indentPosition = ts.positionAtColumn(text, column, 0, true); + int spaces = ts.spacesLeftFromPosition(text, indentPosition); + int startColumn = ts.columnAt(text, indentPosition - spaces); + int targetColumn = ts.indentedColumn(ts.columnAt(text, indentPosition), doIndent); + cursor.setPosition(block.position() + indentPosition); + cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); + cursor.insertText(ts.indentationString(startColumn, targetColumn, block)); + } + // Preserve initial anchor of block selection + if (blockSelection) { + end = cursor.position(); + if (offset) + *offset = ts.columnAt(cursor.block().text(), cursor.positionInBlock()) - column; + cursor.setPosition(start); + cursor.setPosition(end, QTextCursor::KeepAnchor); } } - // Indent or unindent at cursor position - QTextBlock block = cursor.block(); - QString text = block.text(); - int indentPosition = cursor.positionInBlock(); - int spaces = m_tabSettings.spacesLeftFromPosition(text, indentPosition); - int startColumn = m_tabSettings.columnAt(text, indentPosition - spaces); - int targetColumn = m_tabSettings.indentedColumn(m_tabSettings.columnAt(text, indentPosition), doIndent); - cursor.setPosition(block.position() + indentPosition); - cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - cursor.insertText(m_tabSettings.indentationString(startColumn, targetColumn, block)); cursor.endEditBlock(); - return cursor; + + return modified ? cursor : textCursor; } void TextDocumentPrivate::resetRevisions() @@ -359,14 +388,16 @@ void TextDocument::autoReindent(const QTextCursor &cursor) d->m_indenter->reindent(&d->m_document, cursor, d->m_tabSettings); } -QTextCursor TextDocument::indent(const QTextCursor &cursor) +QTextCursor TextDocument::indent(const QTextCursor &cursor, bool blockSelection, int column, + int *offset) { - return d->indentOrUnindent(cursor, true); + return d->indentOrUnindent(cursor, true, blockSelection, column, offset); } -QTextCursor TextDocument::unindent(const QTextCursor &cursor) +QTextCursor TextDocument::unindent(const QTextCursor &cursor, bool blockSelection, int column, + int *offset) { - return d->indentOrUnindent(cursor, false); + return d->indentOrUnindent(cursor, false, blockSelection, column, offset); } const ExtraEncodingSettings &TextDocument::extraEncodingSettings() const diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 56715d2c9fd..987e1bcdffe 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -89,8 +89,10 @@ public: Indenter *indenter() const; void autoIndent(const QTextCursor &cursor, QChar typedChar = QChar::Null); void autoReindent(const QTextCursor &cursor); - QTextCursor indent(const QTextCursor &cursor); - QTextCursor unindent(const QTextCursor &cursor); + QTextCursor indent(const QTextCursor &cursor, bool blockSelection = false, int column = 0, + int *offset = 0); + QTextCursor unindent(const QTextCursor &cursor, bool blockSelection = false, int column = 0, + int *offset = 0); TextMarks marks() const; bool addMark(TextMark *mark); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index b7f5302fef9..514130aabcc 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -1495,12 +1495,26 @@ void TextEditorWidget::lowercaseSelection() void TextEditorWidget::indent() { - setTextCursor(textDocument()->indent(textCursor())); + int offset = 0; + doSetTextCursor(textDocument()->indent(textCursor(), d->m_inBlockSelectionMode, + d->m_blockSelection.positionColumn, &offset), + d->m_inBlockSelectionMode); + if (d->m_inBlockSelectionMode) { + d->m_blockSelection.anchorColumn += offset; + d->m_blockSelection.positionColumn += offset; + } } void TextEditorWidget::unindent() { - setTextCursor(textDocument()->unindent(textCursor())); + int offset = 0; + doSetTextCursor(textDocument()->unindent(textCursor(), d->m_inBlockSelectionMode, + d->m_blockSelection.positionColumn, &offset), + d->m_inBlockSelectionMode); + if (d->m_inBlockSelectionMode) { + d->m_blockSelection.anchorColumn += offset; + d->m_blockSelection.positionColumn += offset; + } } void TextEditorWidget::undo() @@ -2254,10 +2268,15 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) } d->m_document->autoIndent(cursor); } else { - if (e->key() == Qt::Key_Tab) - indent(); - else - unindent(); + if (d->m_inBlockSelectionMode + && d->m_blockSelection.firstVisualColumn() != d->m_blockSelection.lastVisualColumn()) { + d->removeBlockSelection(); + } else { + if (e->key() == Qt::Key_Tab) + indent(); + else + unindent(); + } } e->accept(); return; |