QLineEdit: Use existing selection when deleting a word

When using QKeySequence::DeleteEndOfWord or
QKeySequence::DeleteStartOfWord in a QLineEdit with an existing
selection, the selection was ignored which resulted in unexpected
behavior (see bugreport). This is fixed by only setting the selection
if none exists yet.
To prevent an entry in the history when the input is empty, the
selection is checked before calling del().

Fixes: QTBUG-120006
Pick-to: 6.6 6.5
Change-Id: I2e803c5eff1f0e289e93a77c58ecd78299241da7
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 1d953b2fbc3deccad6eb2a5ebe39b24908dbcf3e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Johannes Grunenberg 2023-12-11 22:39:24 +01:00 committed by Qt Cherry-pick Bot
parent a00c80e1ce
commit 1df12820fe
2 changed files with 119 additions and 3 deletions

View File

@ -1809,13 +1809,18 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
} }
else if (event == QKeySequence::DeleteEndOfWord) { else if (event == QKeySequence::DeleteEndOfWord) {
if (!isReadOnly()) { if (!isReadOnly()) {
cursorWordForward(true); if (!hasSelectedText())
del(); cursorWordForward(true);
if (hasSelectedText())
del();
} }
} }
else if (event == QKeySequence::DeleteStartOfWord) { else if (event == QKeySequence::DeleteStartOfWord) {
if (!isReadOnly()) { if (!isReadOnly()) {
cursorWordBackward(true); if (!hasSelectedText())
cursorWordBackward(true);
if (hasSelectedText()) if (hasSelectedText())
del(); del();
} }

View File

@ -294,6 +294,11 @@ private slots:
void inputRejected(); void inputRejected();
void keyReleasePropagates(); void keyReleasePropagates();
#if QT_CONFIG(shortcut)
void deleteWordByKeySequence_data();
void deleteWordByKeySequence();
#endif
protected slots: protected slots:
void editingFinished(); void editingFinished();
@ -5214,6 +5219,112 @@ void tst_QLineEdit::keyReleasePropagates()
QCOMPARE(dialog.releasedKey, Qt::Key_Alt); QCOMPARE(dialog.releasedKey, Qt::Key_Alt);
} }
#if QT_CONFIG(shortcut)
void tst_QLineEdit::deleteWordByKeySequence_data()
{
QTest::addColumn<QString>("startText");
QTest::addColumn<int>("selectionStart");
QTest::addColumn<int>("selectionEnd");
QTest::addColumn<int>("cursorPosition");
QTest::addColumn<QKeySequence::StandardKey>("key");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<int>("expectedCursorPosition");
QTest::newRow("Delete start, no selection")
<< QStringLiteral("Some Text") << 0 << 0 << 9 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Some ") << 5;
QTest::newRow("Delete end, no selection")
<< QStringLiteral("Some Text") << 0 << 0 << 5 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Some ") << 5;
QTest::newRow("Delete start from middle, no selection")
<< QStringLiteral("Some Text") << 0 << 0 << 7 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Some xt") << 5;
QTest::newRow("Delete end from middle, no selection")
<< QStringLiteral("Some Text") << 0 << 0 << 7 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Some Te") << 7;
QTest::newRow("Delete end from first, no selection")
<< QStringLiteral("Some Text") << 0 << 0 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Text") << 0;
QTest::newRow("Delete start, full selection")
<< QStringLiteral("Some Text") << 0 << 9 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("") << 0;
QTest::newRow("Delete end, full selection")
<< QStringLiteral("Some Text") << 0 << 9 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("") << 0;
QTest::newRow("Delete start, full selection, single word")
<< QStringLiteral("Some") << 0 << 4 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("") << 0;
QTest::newRow("Delete end, full selection, single word")
<< QStringLiteral("Some") << 0 << 4 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("") << 0;
QTest::newRow("Delete start, word selection")
<< QStringLiteral("Some Text") << 5 << 9 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Some ") << 5;
QTest::newRow("Delete end, word selection")
<< QStringLiteral("Some Text") << 5 << 9 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Some ") << 5;
QTest::newRow("Delete start, partial word selection")
<< QStringLiteral("Some Text") << 5 << 7 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Some xt") << 5;
QTest::newRow("Delete end, partial word selection")
<< QStringLiteral("Some Text") << 5 << 7 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Some xt") << 5;
QTest::newRow("Delete start, partial inner word selection")
<< QStringLiteral("Some Text") << 6 << 8 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Some Tt") << 6;
QTest::newRow("Delete end, partial inner word selection")
<< QStringLiteral("Some Text") << 6 << 8 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Some Tt") << 6;
QTest::newRow("Delete start, selection with space")
<< QStringLiteral("Some Text") << 3 << 9 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Som") << 3;
QTest::newRow("Delete end, selection with space")
<< QStringLiteral("Some Text") << 3 << 9 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Som") << 3;
QTest::newRow("Delete start, partial word selection with space")
<< QStringLiteral("Some Text") << 3 << 7 << 0 << QKeySequence::DeleteStartOfWord
<< QStringLiteral("Somxt") << 3;
QTest::newRow("Delete end, partial selection with space")
<< QStringLiteral("Some Text") << 3 << 7 << 0 << QKeySequence::DeleteEndOfWord
<< QStringLiteral("Somxt") << 3;
}
void tst_QLineEdit::deleteWordByKeySequence()
{
QFETCH(QString, startText);
QFETCH(int, selectionStart);
QFETCH(int, selectionEnd);
QFETCH(int, cursorPosition);
QFETCH(QKeySequence::StandardKey, key);
QFETCH(QString, expectedText);
QFETCH(int, expectedCursorPosition);
QWidget widget;
QLineEdit *lineEdit = new QLineEdit(startText, &widget);
lineEdit->setFocus();
lineEdit->setCursorPosition(cursorPosition);
if (selectionStart != selectionEnd)
lineEdit->setSelection(selectionStart, selectionEnd - selectionStart);
widget.show();
QVERIFY(QTest::qWaitForWindowActive(&widget));
QTestEventList keys;
addKeySequenceStandardKey(keys, key);
keys.simulate(lineEdit);
QCOMPARE(lineEdit->text(), expectedText);
QCOMPARE(lineEdit->selectionStart(), -1);
QCOMPARE(lineEdit->selectionEnd(), -1);
QCOMPARE(lineEdit->cursorPosition(), expectedCursorPosition);
}
#endif // QT_CONFIG(shortcut)
QTEST_MAIN(tst_QLineEdit) QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc" #include "tst_qlineedit.moc"