forked from qt-creator/qt-creator
TextEditor: Fix backtab behavior of multi line selection
Check available spaces infront of current column on each line before removing the text. Fixes: QTCREATORBUG-16970 Change-Id: Ie6560ce706297f6818a84ca863abc9b106728890 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -169,35 +169,82 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor,
|
|||||||
cursor.removeSelectedText();
|
cursor.removeSelectedText();
|
||||||
} else {
|
} else {
|
||||||
// Indent or unindent at cursor position
|
// Indent or unindent at cursor position
|
||||||
|
int maxTargetColumn = -1;
|
||||||
|
|
||||||
|
class BlockIndenter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlockIndenter(const QTextBlock &_block,
|
||||||
|
const int column,
|
||||||
|
const TabSettings &_tabSettings)
|
||||||
|
: block(_block)
|
||||||
|
, text(block.text())
|
||||||
|
, tabSettings(_tabSettings)
|
||||||
|
{
|
||||||
|
indentPosition = tabSettings.positionAtColumn(text, column, nullptr, true);
|
||||||
|
spaces = tabSettings.spacesLeftFromPosition(text, indentPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void indent(const int targetColumn) const
|
||||||
|
{
|
||||||
|
const int startColumn = tabSettings.columnAt(text, indentPosition - spaces);
|
||||||
|
QTextCursor cursor(block);
|
||||||
|
cursor.setPosition(block.position() + indentPosition);
|
||||||
|
cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
|
||||||
|
cursor.removeSelectedText();
|
||||||
|
cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, 0, block));
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetColumn(bool doIndent) const
|
||||||
|
{
|
||||||
|
const int optimumTargetColumn
|
||||||
|
= tabSettings.indentedColumn(tabSettings.columnAt(block.text(), indentPosition),
|
||||||
|
doIndent);
|
||||||
|
const int minimumTargetColumn = tabSettings.columnAt(text, indentPosition - spaces);
|
||||||
|
return std::max(optimumTargetColumn, minimumTargetColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QTextBlock &textBlock() { return block; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextBlock block;
|
||||||
|
const QString text;
|
||||||
|
int indentPosition;
|
||||||
|
int spaces;
|
||||||
|
const TabSettings &tabSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<BlockIndenter> blocks;
|
||||||
|
|
||||||
for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
|
for (QTextBlock block = startBlock; block != endBlock; block = block.next()) {
|
||||||
QString text = block.text();
|
QString text = block.text();
|
||||||
|
|
||||||
int blockColumn = tabSettings.columnAt(text, text.size());
|
const int blockColumn = tabSettings.columnAt(text, text.size());
|
||||||
if (blockColumn < column) {
|
if (blockColumn < column) {
|
||||||
cursor.setPosition(block.position() + text.size());
|
cursor.setPosition(block.position() + text.size());
|
||||||
cursor.insertText(tabSettings.indentationString(blockColumn, column, 0, block));
|
cursor.insertText(tabSettings.indentationString(blockColumn, column, 0, block));
|
||||||
text = block.text();
|
text = block.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
int indentPosition = tabSettings.positionAtColumn(text, column, nullptr, true);
|
blocks.emplace_back(BlockIndenter(block, column, tabSettings));
|
||||||
int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition);
|
maxTargetColumn = std::max(maxTargetColumn, blocks.back().targetColumn(doIndent));
|
||||||
int startColumn = tabSettings.columnAt(text, indentPosition - spaces);
|
|
||||||
int targetColumn = tabSettings.indentedColumn(
|
|
||||||
tabSettings.columnAt(text, indentPosition), doIndent);
|
|
||||||
cursor.setPosition(block.position() + indentPosition);
|
|
||||||
cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor);
|
|
||||||
cursor.removeSelectedText();
|
|
||||||
cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, 0, block));
|
|
||||||
}
|
}
|
||||||
|
for (const BlockIndenter &blockIndenter : blocks)
|
||||||
|
blockIndenter.indent(maxTargetColumn);
|
||||||
|
|
||||||
// Preserve initial anchor of block selection
|
// Preserve initial anchor of block selection
|
||||||
if (blockSelection) {
|
if (blockSelection) {
|
||||||
end = cursor.position();
|
if (offset)
|
||||||
if (offset) {
|
*offset = maxTargetColumn - column;
|
||||||
*offset = tabSettings.columnAt(cursor.block().text(), cursor.positionInBlock())
|
startBlock = pos < anchor ? blocks.front().textBlock() : blocks.back().textBlock();
|
||||||
- column;
|
start = startBlock.position()
|
||||||
}
|
+ tabSettings.positionAtColumn(startBlock.text(), maxTargetColumn);
|
||||||
cursor.setPosition(start);
|
endBlock = pos > anchor ? blocks.front().textBlock() : blocks.back().textBlock();
|
||||||
cursor.setPosition(end, QTextCursor::KeepAnchor);
|
end = endBlock.position()
|
||||||
|
+ tabSettings.positionAtColumn(endBlock.text(), maxTargetColumn);
|
||||||
|
|
||||||
|
cursor.setPosition(end);
|
||||||
|
cursor.setPosition(start, QTextCursor::KeepAnchor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user