diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index a667e29fbaa..39b38036055 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -668,8 +668,6 @@ public: void transformSelection(TransformationMethod method); - void transformSelectedLines(ListTransformationMethod method); - void slotUpdateExtraAreaWidth(std::optional 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(); diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 2af45826368..51f3cadec88 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -426,7 +426,7 @@ public: void uppercaseSelection(); void lowercaseSelection(); - void sortSelectedLines(); + void sortLines(); void cleanWhitespace(); diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp index 49b83b8a756..f16c94249bb 100644 --- a/src/plugins/texteditor/texteditoractionhandler.cpp +++ b/src/plugins/texteditor/texteditoractionhandler.cpp @@ -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, diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 262ce6a5c45..e2115261882 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -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"; diff --git a/tests/system/suite_tools/tst_sort/test.py b/tests/system/suite_tools/tst_sort/test.py index a8eac9fa830..f2eed1eeae6 100644 --- a/tests/system/suite_tools/tst_sort/test.py +++ b/tests/system/suite_tools/tst_sort/test.py @@ -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')