From b25035e51289d6f5f50ee967575c7c97c26a127c Mon Sep 17 00:00:00 2001 From: Aaron McCarthy <aaron.mccarthy@jollamobile.com> Date: Tue, 22 Jul 2014 17:39:53 +1000 Subject: [PATCH] Fix incorrect acceptableInput value on construction. The value for acceptableInput was being calculated every time the property value was read. This can lead to situations where the value returned from successive property reads is different even though no acceptableInputChanged() signal is emitted between the two calls. This can be seen during QML component construction where emission of the changed signal is suppressed until the component completes and the value of acceptableInput changes as the other properties are set. If the property is read during binding evaluation an intermediate value can be seen and the QML engine will not re-read the property until after the changed signal is emitted. This doesn't happen until the true value of the acceptableInput property is toggled. Fixed by changing the property getter to returned the precalculated value of acceptableInput and ensuring that this value is set when correctly. Change-Id: Id3ba3a34988ff50f590e4f8330b873f390eaa025 Reviewed-by: Martin Jones <martin.jones@jollamobile.com> --- src/quick/items/qquicktextinput.cpp | 27 ++++++++++++++++--- .../qquicktextinput/tst_qquicktextinput.cpp | 6 ++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index f3f9d0b5aa..37b103613d 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1199,7 +1199,7 @@ void QQuickTextInput::setInputMask(const QString &im) bool QQuickTextInput::hasAcceptableInput() const { Q_D(const QQuickTextInput); - return d->hasAcceptableInput(d->m_text) == QQuickTextInputPrivate::AcceptableInput; + return d->m_acceptableInput; } /*! @@ -2589,7 +2589,7 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event) && !persistentSelection) deselect(); - if (q->hasAcceptableInput() || fixup()) + if (hasAcceptableInput(m_text) == AcceptableInput || fixup()) emit q->editingFinished(); #ifndef QT_NO_IM @@ -3415,6 +3415,27 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo } } #endif + + if (m_maskData) { + if (m_text.length() != m_maxLength) { + m_acceptableInput = false; + } else { + for (int i = 0; i < m_maxLength; ++i) { + if (m_maskData[i].separator) { + if (m_text.at(i) != m_maskData[i].maskChar) { + m_acceptableInput = false; + break; + } + } else { + if (!isValidInput(m_text.at(i), m_maskData[i].maskChar)) { + m_acceptableInput = false; + break; + } + } + } + } + } + if (validateFromState >= 0 && wasValidInput && !m_validInput) { if (m_transactions.count()) return false; @@ -4199,7 +4220,7 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) Q_Q(QQuickTextInput); if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - if (q->hasAcceptableInput() || fixup()) { + if (hasAcceptableInput(m_text) == AcceptableInput || fixup()) { emit q->accepted(); emit q->editingFinished(); } diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index fc1be16bc8..e5ef83ba32 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -6272,13 +6272,11 @@ void tst_qquicktextinput::hasAcceptableInputMask() textInput->setText(invalid); QVERIFY(textInput->hasAcceptableInput()); - // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless - QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort); - // test requiredMask textInput->setInputMask(requiredMask); textInput->setText(invalid); - QVERIFY(!textInput->hasAcceptableInput()); + // invalid text gets the input mask applied when setting, text becomes acceptable. + QVERIFY(textInput->hasAcceptableInput()); textInput->setText(valid); QVERIFY(textInput->hasAcceptableInput()); -- GitLab