summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp22
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h4
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp66
3 files changed, 90 insertions, 2 deletions
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 6920354e73..ba7e2ddacf 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -1279,6 +1279,13 @@ void QWidgetLineControl::internalUndo(int until)
return;
cancelPasswordEchoTimer();
internalDeselect();
+
+ // Undo works only for clearing the line when in any of password the modes
+ if (m_echoMode != QLineEdit::Normal) {
+ clear();
+ return;
+ }
+
while (m_undoState && m_undoState > until) {
Command& cmd = m_history[--m_undoState];
switch (cmd.type) {
@@ -1868,6 +1875,21 @@ void QWidgetLineControl::processKeyEvent(QKeyEvent* event)
event->accept();
}
+bool QWidgetLineControl::isUndoAvailable() const
+{
+ // For security reasons undo is not available in any password mode (NoEcho included)
+ // with the exception that the user can clear the password with undo.
+ return !m_readOnly && m_undoState
+ && (m_echoMode == QLineEdit::Normal || m_history[m_undoState - 1].type == QWidgetLineControl::Insert);
+}
+
+bool QWidgetLineControl::isRedoAvailable() const
+{
+ // Same as with undo. Disabled for password modes.
+ return !m_readOnly
+ && m_echoMode == QLineEdit::Normal
+ && m_undoState < m_history.size();
+}
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index ba3b202bda..2dce790c1e 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -125,8 +125,8 @@ public:
return (c != -1 ? c : 0);
}
- bool isUndoAvailable() const { return !m_readOnly && m_undoState; }
- bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); }
+ bool isUndoAvailable() const;
+ bool isRedoAvailable() const;
void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; }
bool isModified() const { return m_modifiedState != m_undoState; }
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index 956f970b85..ed53a133e4 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -287,6 +287,9 @@ private slots:
void inputMethodQueryImHints_data();
void inputMethodQueryImHints();
+ void undoRedoAndEchoModes_data();
+ void undoRedoAndEchoModes();
+
protected slots:
void editingFinished();
@@ -3954,5 +3957,68 @@ void tst_QLineEdit::inputMethodQueryImHints()
QCOMPARE(static_cast<Qt::InputMethodHints>(value.toInt()), hints);
}
+void tst_QLineEdit::undoRedoAndEchoModes_data()
+{
+ QTest::addColumn<int>("echoMode");
+ QTest::addColumn<QStringList>("input");
+ QTest::addColumn<QStringList>("expected");
+
+ QStringList input(QList<QString>() << "aaa" << "bbb" << "ccc");
+
+ QTest::newRow("Normal")
+ << (int) QLineEdit::Normal
+ << input
+ << QStringList(QList<QString>() << "aaa" << "ccc" << "");
+
+ QTest::newRow("NoEcho")
+ << (int) QLineEdit::NoEcho
+ << input
+ << QStringList(QList<QString>() << "" << "" << "");
+
+ QTest::newRow("Password")
+ << (int) QLineEdit::Password
+ << input
+ << QStringList(QList<QString>() << "" << "" << "");
+
+ QTest::newRow("PasswordEchoOnEdit")
+ << (int) QLineEdit::PasswordEchoOnEdit
+ << input
+ << QStringList(QList<QString>() << "" << "" << "");
+}
+
+void tst_QLineEdit::undoRedoAndEchoModes()
+{
+ QFETCH(int, echoMode);
+ QFETCH(QStringList, input);
+ QFETCH(QStringList, expected);
+
+ // create some history for the QLineEdit
+ testWidget->clear();
+ testWidget->setEchoMode(QLineEdit::EchoMode(echoMode));
+ testWidget->insert(input.at(0));
+ testWidget->selectAll();
+ testWidget->backspace();
+ testWidget->insert(input.at(1));
+
+ // test undo
+ QVERIFY(testWidget->isUndoAvailable());
+ testWidget->undo();
+ QCOMPARE(testWidget->text(), expected.at(0));
+ testWidget->insert(input.at(2));
+ testWidget->selectAll();
+ testWidget->backspace();
+ QCOMPARE(testWidget->isUndoAvailable(), echoMode == QLineEdit::Normal);
+ testWidget->undo();
+ QCOMPARE(testWidget->text(), expected.at(1));
+
+ // test redo
+ QCOMPARE(testWidget->isRedoAvailable(), echoMode == QLineEdit::Normal);
+ testWidget->redo();
+ QCOMPARE(testWidget->text(), expected.at(2));
+ QVERIFY(!testWidget->isRedoAvailable());
+ testWidget->redo();
+ QCOMPARE(testWidget->text(), expected.at(2));
+}
+
QTEST_MAIN(tst_QLineEdit)
#include "tst_qlineedit.moc"