Editor: Improve multi text cursor selection

Allow to select text with ctrl+shift+(move operation in a line)

Fixes: QTCREATORBUG-31166
Change-Id: I2ffd02ca4a25e9074cf073d1d7e6639931fe7dc7
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
David Schulz
2024-07-01 10:51:55 +02:00
parent 057a54364d
commit bb08762123
3 changed files with 48 additions and 42 deletions

View File

@@ -330,13 +330,10 @@ static QTextLine currentTextLine(const QTextCursor &cursor)
return layout->lineForTextPosition(relativePos);
}
bool MultiTextCursor::multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey)
bool MultiTextCursor::multiCursorEvent(
QKeyEvent *e, QKeySequence::StandardKey matchKey, Qt::KeyboardModifiers filterModifiers)
{
uint searchkey = (e->modifiers() | e->key())
& ~(Qt::KeypadModifier
| Qt::GroupSwitchModifier
| Qt::AltModifier
| Qt::ShiftModifier);
uint searchkey = (e->modifiers() | e->key()) & ~(filterModifiers | Qt::AltModifier);
const QList<QKeySequence> bindings = QKeySequence::keyBindings(matchKey);
return bindings.contains(QKeySequence(searchkey));
@@ -348,42 +345,42 @@ bool MultiTextCursor::handleMoveKeyEvent(QKeyEvent *e,
{
if (e->modifiers() & Qt::AltModifier && !Utils::HostOsInfo::isMacHost()) {
QTextCursor::MoveOperation op = QTextCursor::NoMove;
if (multiCursorAddEvent(e, QKeySequence::MoveToNextWord)) {
if (multiCursorEvent(e, QKeySequence::MoveToNextWord)) {
op = QTextCursor::WordRight;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToPreviousWord)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToPreviousWord)) {
op = QTextCursor::WordLeft;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfBlock)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfBlock)) {
op = QTextCursor::EndOfBlock;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfBlock)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfBlock)) {
op = QTextCursor::StartOfBlock;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToNextLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToNextLine, Qt::ShiftModifier)) {
op = QTextCursor::Down;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToPreviousLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToPreviousLine, Qt::ShiftModifier)) {
op = QTextCursor::Up;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfLine)) {
op = QTextCursor::StartOfLine;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfLine)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfLine)) {
op = QTextCursor::EndOfLine;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToStartOfDocument)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToStartOfDocument)) {
op = QTextCursor::Start;
} else if (multiCursorAddEvent(e, QKeySequence::MoveToEndOfDocument)) {
} else if (multiCursorEvent(e, QKeySequence::MoveToEndOfDocument)) {
op = QTextCursor::End;
} else {
return false;
}
const std::list<QTextCursor> cursors = m_cursorList;
for (QTextCursor cursor : cursors) {
if (camelCaseNavigationEnabled && op == QTextCursor::WordRight)
CamelCaseCursor::right(&cursor, edit, QTextCursor::MoveAnchor);
else if (camelCaseNavigationEnabled && op == QTextCursor::WordLeft)
CamelCaseCursor::left(&cursor, edit, QTextCursor::MoveAnchor);
else
cursor.movePosition(op, QTextCursor::MoveAnchor);
if (op != QTextCursor::NoMove) {
const std::list<QTextCursor> cursors = m_cursorList;
for (QTextCursor cursor : cursors) {
if (camelCaseNavigationEnabled && op == QTextCursor::WordRight)
CamelCaseCursor::right(&cursor, edit, QTextCursor::MoveAnchor);
else if (camelCaseNavigationEnabled && op == QTextCursor::WordLeft)
CamelCaseCursor::left(&cursor, edit, QTextCursor::MoveAnchor);
else
cursor.movePosition(op, QTextCursor::MoveAnchor);
addCursor(cursor);
addCursor(cursor);
}
return true;
}
return true;
}
for (auto it = m_cursorList.begin(); it != m_cursorList.end(); ++it) {
@@ -395,28 +392,28 @@ bool MultiTextCursor::handleMoveKeyEvent(QKeyEvent *e,
op = QTextCursor::Right;
} else if (e == QKeySequence::MoveToPreviousChar) {
op = QTextCursor::Left;
} else if (e == QKeySequence::SelectNextChar) {
} else if (multiCursorEvent(e, QKeySequence::SelectNextChar)) {
op = QTextCursor::Right;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectPreviousChar) {
} else if (multiCursorEvent(e, QKeySequence::SelectPreviousChar)) {
op = QTextCursor::Left;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectNextWord) {
} else if (multiCursorEvent(e, QKeySequence::SelectNextWord)) {
op = QTextCursor::WordRight;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectPreviousWord) {
} else if (multiCursorEvent(e, QKeySequence::SelectPreviousWord)) {
op = QTextCursor::WordLeft;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfLine) {
} else if (multiCursorEvent(e, QKeySequence::SelectStartOfLine)) {
op = QTextCursor::StartOfLine;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectEndOfLine) {
} else if (multiCursorEvent(e, QKeySequence::SelectEndOfLine)) {
op = QTextCursor::EndOfLine;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfBlock) {
} else if (multiCursorEvent(e, QKeySequence::SelectStartOfBlock)) {
op = QTextCursor::StartOfBlock;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectEndOfBlock) {
} else if (multiCursorEvent(e, QKeySequence::SelectEndOfBlock)) {
op = QTextCursor::EndOfBlock;
mode = QTextCursor::KeepAnchor;
} else if (e == QKeySequence::SelectStartOfDocument) {

View File

@@ -108,7 +108,10 @@ public:
const_iterator constBegin() const { return m_cursorMap.cbegin(); }
const_iterator constEnd() const { return m_cursorMap.cend(); }
static bool multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey);
static bool multiCursorEvent(
QKeyEvent *e,
QKeySequence::StandardKey matchKey,
Qt::KeyboardModifiers additionalFilterModifier = {});
private:
std::list<QTextCursor> m_cursorList;

View File

@@ -3089,15 +3089,21 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
if (ro || !isPrintableText(eventText)) {
QTextCursor::MoveOperation blockSelectionOperation = QTextCursor::NoMove;
if (e->modifiers() == (Qt::AltModifier | Qt::ShiftModifier) && !Utils::HostOsInfo::isMacHost()) {
if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToNextLine))
if (e->modifiers() == (Qt::AltModifier | Qt::ShiftModifier)
&& !Utils::HostOsInfo::isMacHost()) {
if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToNextLine, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::Down;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToPreviousLine))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToPreviousLine, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::Up;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToNextChar))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToNextChar, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::NextCharacter;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToPreviousChar))
} else if (MultiTextCursor::multiCursorEvent(
e, QKeySequence::MoveToPreviousChar, Qt::ShiftModifier)) {
blockSelectionOperation = QTextCursor::PreviousCharacter;
}
}
if (blockSelectionOperation != QTextCursor::NoMove) {