From dd1a6308719929b0798447244b401376d983cfbf Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sun, 25 Nov 2018 21:58:47 +0100 Subject: [PATCH] QLineEdit: don't emit editingFinished if nothing was done When a modal dialog is called from a slot connected to the editingFinished signal, the chain of events resulting from the focus returning to this widget will make the editingFinished signal emitted again. This patch uses a new variable to keep track of the fact that there was a modification. Once editingFinished was emitted, that flag is cleared so next time the signal will be emitted again only if a modification was made to the line edit content. [ChangeLog][QtWidget][QLineEdit] Behavior change: now the editingFinished signal is emitted only once after the line edit content was edited. Fixes: QTBUG-40 Change-Id: Ia4760bad8717f1758c3939132c446b4b4c6cd498 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qlineedit.cpp | 12 ++++++++---- src/widgets/widgets/qlineedit_p.cpp | 7 +++++++ src/widgets/widgets/qlineedit_p.h | 4 +++- .../auto/widgets/widgets/qlineedit/tst_qlineedit.cpp | 10 ++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index ad3d372bd3..02aa703289 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -315,7 +315,7 @@ QString QLineEdit::text() const void QLineEdit::setText(const QString& text) { Q_D(QLineEdit); - d->control->setText(text); + d->setText(text); } /*! @@ -1483,8 +1483,11 @@ bool QLineEdit::event(QEvent * e) } else if (e->type() == QEvent::LeaveEditFocus) { d->setCursorVisible(false); d->control->setCursorBlinkEnabled(false); - if (d->control->hasAcceptableInput() || d->control->fixup()) + if (d->edited && (d->control->hasAcceptableInput() + || d->control->fixup())) { emit editingFinished(); + d->edited = false; + } } } #endif @@ -1891,7 +1894,6 @@ void QLineEdit::focusInEvent(QFocusEvent *e) /*!\reimp */ - void QLineEdit::focusOutEvent(QFocusEvent *e) { Q_D(QLineEdit); @@ -1914,8 +1916,10 @@ void QLineEdit::focusOutEvent(QFocusEvent *e) #endif if (reason != Qt::PopupFocusReason || !(QApplication::activePopupWidget() && QApplication::activePopupWidget()->parentWidget() == this)) { - if (hasAcceptableInput() || d->control->fixup()) + if (d->edited && (hasAcceptableInput() || d->control->fixup())) { emit editingFinished(); + d->edited = false; + } } #ifdef QT_KEYPAD_NAVIGATION d->control->setCancelText(QString()); diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 2a5a0c34dc..21e70db0ac 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -127,6 +127,7 @@ void QLineEditPrivate::_q_handleWindowActivate() void QLineEditPrivate::_q_textEdited(const QString &text) { Q_Q(QLineEdit); + edited = true; emit q->textEdited(text); #if QT_CONFIG(completer) if (control->completer() @@ -272,6 +273,12 @@ void QLineEditPrivate::setCursorVisible(bool visible) q->update(); } +void QLineEditPrivate::setText(const QString& text) +{ + edited = true; + control->setText(text); +} + void QLineEditPrivate::updatePasswordEchoEditing(bool editing) { Q_Q(QLineEdit); diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 12a2f1ddfd..dce5bf605a 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -151,7 +151,7 @@ public: QLineEditPrivate() : control(0), frame(1), contextMenuEnabled(1), cursorVisible(0), - dragEnabled(0), clickCausedFocus(0), hscroll(0), vscroll(0), + dragEnabled(0), clickCausedFocus(0), edited(0), hscroll(0), vscroll(0), alignment(Qt::AlignLeading | Qt::AlignVCenter), leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0), lastTextSize(0), mouseYThreshold(0) @@ -176,6 +176,7 @@ public: bool inSelection(int x) const; QRect cursorRect() const; void setCursorVisible(bool visible); + void setText(const QString& text); void updatePasswordEchoEditing(bool); @@ -202,6 +203,7 @@ public: uint cursorVisible : 1; uint dragEnabled : 1; uint clickCausedFocus : 1; + uint edited : 1; int hscroll; int vscroll; uint alignment; diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index 95799905de..7861065de9 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -3613,6 +3613,14 @@ void tst_QLineEdit::task174640_editingFinished() QTRY_VERIFY(le1->hasFocus()); QCOMPARE(editingFinishedSpy.count(), 0); + le2->setFocus(); + QTRY_VERIFY(le2->hasFocus()); + // editingFinished will not be emitted anew because no editing happened + QCOMPARE(editingFinishedSpy.count(), 0); + + le1->setFocus(); + QTRY_VERIFY(le1->hasFocus()); + QTest::keyPress(le1, Qt::Key_Plus); le2->setFocus(); QTRY_VERIFY(le2->hasFocus()); QCOMPARE(editingFinishedSpy.count(), 1); @@ -3632,6 +3640,8 @@ void tst_QLineEdit::task174640_editingFinished() delete testMenu1; QCOMPARE(editingFinishedSpy.count(), 0); QTRY_VERIFY(le1->hasFocus()); + // Ensure le1 has been edited + QTest::keyPress(le1, Qt::Key_Plus); QMenu *testMenu2 = new QMenu(le2); testMenu2->addAction("foo2");