forked from qt-creator/qt-creator
TextEditor: improve sort selected lines
Try to get a sensible scope when there is no selection when sorting lines. Use the indent level of the current block and select all blocks that are not empty with the same indent level around that block before sorting the lines. Change-Id: I68cbd95f95a0cc4425a0339b992225c3946a6858 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -668,8 +668,6 @@ public:
|
||||
|
||||
void transformSelection(TransformationMethod method);
|
||||
|
||||
void transformSelectedLines(ListTransformationMethod method);
|
||||
|
||||
void slotUpdateExtraAreaWidth(std::optional<int> width = {});
|
||||
void slotUpdateRequest(const QRect &r, int dy);
|
||||
void slotUpdateBlockNotify(const QTextBlock &);
|
||||
@@ -2420,9 +2418,72 @@ void TextEditorWidget::lowercaseSelection()
|
||||
d->transformSelection([](const QString &str) { return str.toLower(); });
|
||||
}
|
||||
|
||||
void TextEditorWidget::sortSelectedLines()
|
||||
void TextEditorWidget::sortLines()
|
||||
{
|
||||
d->transformSelectedLines([](QStringList &list) { list.sort(); });
|
||||
if (d->m_cursors.hasMultipleCursors())
|
||||
return;
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
if (!cursor.hasSelection()) {
|
||||
// try to get a sensible scope for the sort
|
||||
const QTextBlock currentBlock = cursor.block();
|
||||
QString text = currentBlock.text();
|
||||
if (text.simplified().isEmpty())
|
||||
return;
|
||||
const TabSettings ts = textDocument()->tabSettings();
|
||||
const int currentIndent = ts.columnAt(text, TabSettings::firstNonSpace(text));
|
||||
|
||||
int anchor = currentBlock.position();
|
||||
for (auto block = currentBlock.previous(); block.isValid(); block = block.previous()) {
|
||||
text = block.text();
|
||||
if (text.simplified().isEmpty()
|
||||
|| ts.columnAt(text, TabSettings::firstNonSpace(text)) != currentIndent) {
|
||||
break;
|
||||
}
|
||||
anchor = block.position();
|
||||
}
|
||||
|
||||
int pos = currentBlock.position();
|
||||
for (auto block = currentBlock.next(); block.isValid(); block = block.next()) {
|
||||
text = block.text();
|
||||
if (text.simplified().isEmpty()
|
||||
|| ts.columnAt(text, TabSettings::firstNonSpace(text)) != currentIndent) {
|
||||
break;
|
||||
}
|
||||
pos = block.position();
|
||||
}
|
||||
if (anchor == pos)
|
||||
return;
|
||||
|
||||
cursor.setPosition(anchor);
|
||||
cursor.setPosition(pos, QTextCursor::KeepAnchor);
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
}
|
||||
|
||||
const bool downwardDirection = cursor.anchor() < cursor.position();
|
||||
int startPosition = cursor.selectionStart();
|
||||
int endPosition = cursor.selectionEnd();
|
||||
|
||||
cursor.setPosition(startPosition);
|
||||
cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
startPosition = cursor.position();
|
||||
|
||||
cursor.setPosition(endPosition, QTextCursor::KeepAnchor);
|
||||
if (cursor.positionInBlock() == 0)
|
||||
cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
endPosition = qMax(cursor.position(), endPosition);
|
||||
|
||||
const QString text = cursor.selectedText();
|
||||
QStringList lines = text.split(QChar::ParagraphSeparator);
|
||||
lines.sort();
|
||||
cursor.insertText(lines.join(QChar::ParagraphSeparator));
|
||||
|
||||
// (re)select the changed lines
|
||||
// Note: this assumes the transformation did not change the length
|
||||
cursor.setPosition(downwardDirection ? startPosition : endPosition);
|
||||
cursor.setPosition(downwardDirection ? endPosition : startPosition, QTextCursor::KeepAnchor);
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void TextEditorWidget::indent()
|
||||
@@ -9039,41 +9100,6 @@ void TextEditorWidgetPrivate::transformSelection(TransformationMethod method)
|
||||
q->setMultiTextCursor(cursor);
|
||||
}
|
||||
|
||||
void TextEditorWidgetPrivate::transformSelectedLines(ListTransformationMethod method)
|
||||
{
|
||||
if (!method || m_cursors.hasMultipleCursors())
|
||||
return;
|
||||
|
||||
QTextCursor cursor = q->textCursor();
|
||||
if (!cursor.hasSelection())
|
||||
return;
|
||||
|
||||
const bool downwardDirection = cursor.anchor() < cursor.position();
|
||||
int startPosition = cursor.selectionStart();
|
||||
int endPosition = cursor.selectionEnd();
|
||||
|
||||
cursor.setPosition(startPosition);
|
||||
cursor.movePosition(QTextCursor::StartOfBlock);
|
||||
startPosition = cursor.position();
|
||||
|
||||
cursor.setPosition(endPosition, QTextCursor::KeepAnchor);
|
||||
if (cursor.positionInBlock() == 0)
|
||||
cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor);
|
||||
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
endPosition = qMax(cursor.position(), endPosition);
|
||||
|
||||
const QString text = cursor.selectedText();
|
||||
QStringList lines = text.split(QChar::ParagraphSeparator);
|
||||
method(lines);
|
||||
cursor.insertText(lines.join(QChar::ParagraphSeparator));
|
||||
|
||||
// (re)select the changed lines
|
||||
// Note: this assumes the transformation did not change the length
|
||||
cursor.setPosition(downwardDirection ? startPosition : endPosition);
|
||||
cursor.setPosition(downwardDirection ? endPosition : startPosition, QTextCursor::KeepAnchor);
|
||||
q->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void TextEditorWidget::inSnippetMode(bool *active)
|
||||
{
|
||||
*active = d->m_snippetOverlay->isVisible();
|
||||
|
@@ -426,7 +426,7 @@ public:
|
||||
void uppercaseSelection();
|
||||
void lowercaseSelection();
|
||||
|
||||
void sortSelectedLines();
|
||||
void sortLines();
|
||||
|
||||
void cleanWhitespace();
|
||||
|
||||
|
@@ -366,8 +366,8 @@ void TextEditorActionHandlerPrivate::createActions()
|
||||
[] (TextEditorWidget *w) { w->lowercaseSelection(); }, true, Tr::tr("Lowercase Selection"),
|
||||
QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+U") : Tr::tr("Alt+U")),
|
||||
G_EDIT_TEXT, advancedEditMenu);
|
||||
m_modifyingActions << registerAction(SORT_SELECTED_LINES,
|
||||
[] (TextEditorWidget *w) { w->sortSelectedLines(); }, false, Tr::tr("&Sort Selected Lines"),
|
||||
m_modifyingActions << registerAction(SORT_LINES,
|
||||
[] (TextEditorWidget *w) { w->sortLines(); }, false, Tr::tr("&Sort Lines"),
|
||||
QKeySequence(Core::useMacShortcuts ? Tr::tr("Meta+Shift+S") : Tr::tr("Alt+Shift+S")),
|
||||
G_EDIT_TEXT, advancedEditMenu);
|
||||
registerAction(FOLD,
|
||||
|
@@ -157,7 +157,7 @@ const char INSERT_LINE_ABOVE[] = "TextEditor.InsertLineAboveCurrentLine";
|
||||
const char INSERT_LINE_BELOW[] = "TextEditor.InsertLineBelowCurrentLine";
|
||||
const char UPPERCASE_SELECTION[] = "TextEditor.UppercaseSelection";
|
||||
const char LOWERCASE_SELECTION[] = "TextEditor.LowercaseSelection";
|
||||
const char SORT_SELECTED_LINES[] = "TextEditor.SortSelectedLines";
|
||||
const char SORT_LINES[] = "TextEditor.SortSelectedLines";
|
||||
const char CUT_LINE[] = "TextEditor.CutLine";
|
||||
const char COPY_LINE[] = "TextEditor.CopyLine";
|
||||
const char ADD_SELECT_NEXT_FIND_MATCH[] = "TextEditor.AddSelectionNextFindMatch";
|
||||
|
@@ -15,7 +15,7 @@ def main():
|
||||
"visible='1' window=':Qt Creator_Core::Internal::MainWindow'}", 3000)
|
||||
placeCursorToLine(editor, "bbb")
|
||||
invokeMenuItem("Edit", "Select All")
|
||||
invokeMenuItem("Edit", "Advanced", "Sort Selected Lines")
|
||||
invokeMenuItem("Edit", "Advanced", "Sort Lines")
|
||||
test.verify(waitFor("str(editor.plainText) == sorted", 2000),
|
||||
"Verify that sorted text\n%s\nmatches the expected text\n%s" % (editor.plainText, sorted))
|
||||
invokeMenuItem('File', 'Revert "unsorted.txt" to Saved')
|
||||
|
Reference in New Issue
Block a user