Skip to content

Commit

Permalink
QQuickTextInput: Allow going from an Acceptable to an Intermediate state
Browse files Browse the repository at this point in the history
When editing text with a validator set then it can happen that it would
no longer be in the acceptable state. This ensures that it does not
prevent editing the text when an input mask is used to go back to an
Intermediate state.

Change-Id: I6da533d18035e9da468939c28a961bc8f2f3090b
Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
  • Loading branch information
AndyShawQt committed Aug 15, 2017
1 parent 9c4bef9 commit 1b21b73
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/quick/items/qquicktextinput.cpp
Expand Up @@ -3545,18 +3545,23 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
#endif

if (m_maskData) {
m_validInput = true;
if (m_text.length() != m_maxLength) {
m_validInput = false;
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_validInput = false;
m_acceptableInput = false;
break;
}
} else {
if (!isValidInput(m_text.at(i), m_maskData[i].maskChar)) {
m_acceptableInput = false;
if (m_text.at(i) != m_blank)
m_validInput = false;
break;
}
}
Expand Down
75 changes: 75 additions & 0 deletions tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
Expand Up @@ -216,6 +216,8 @@ private slots:
void keypress_inputMask_data();
void keypress_inputMask();
void keypress_inputMethod_inputMask();
void keypress_inputMask_withValidator_data();
void keypress_inputMask_withValidator();
void hasAcceptableInputMask_data();
void hasAcceptableInputMask();
void maskCharacter_data();
Expand Down Expand Up @@ -6112,6 +6114,79 @@ void tst_qquicktextinput::negativeDimensions()
QCOMPARE(input->height(), qreal(-1));
}

void tst_qquicktextinput::keypress_inputMask_withValidator_data()
{
QTest::addColumn<QString>("mask");
QTest::addColumn<qreal>("validatorMinimum");
QTest::addColumn<qreal>("validatorMaximum");
QTest::addColumn<int>("decimals");
QTest::addColumn<QString>("validatorRegExp");
QTest::addColumn<KeyList>("keys");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QString>("expectedDisplayText");

{
KeyList keys;
// inserting '1212' then two backspaces
keys << Qt::Key_Home << "1212" << Qt::Key_Backspace << Qt::Key_Backspace;
QTest::newRow("backspaceWithInt") << QString("9999;_") << 1.0 << 9999.00 << 0 << QString()
<< keys << QString("12") << QString("12__");
}
{
KeyList keys;
// inserting '12.12' then two backspaces
keys << Qt::Key_Home << "12.12" << Qt::Key_Backspace << Qt::Key_Backspace;
QTest::newRow("backspaceWithDouble") << QString("99.99;_") << 1.0 << 99.99 << 2 << QString()
<< keys << QString("12.") << QString("12.__");
}
{
KeyList keys;
// inserting '1111.11' then two backspaces
keys << Qt::Key_Home << "1111.11" << Qt::Key_Backspace << Qt::Key_Backspace;
QTest::newRow("backspaceWithRegExp") << QString("9999.99;_") << 0.0 << 0.0 << 0
<< QString("/^[-]?((\\.\\d+)|(\\d+(\\.\\d+)?))$/")
<< keys << QString("1111.") << QString("1111.__");
}
}

void tst_qquicktextinput::keypress_inputMask_withValidator()
{
QFETCH(QString, mask);
QFETCH(qreal, validatorMinimum);
QFETCH(qreal, validatorMaximum);
QFETCH(int, decimals);
QFETCH(QString, validatorRegExp);
QFETCH(KeyList, keys);
QFETCH(QString, expectedText);
QFETCH(QString, expectedDisplayText);

QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\"\n";
if (!validatorRegExp.isEmpty())
componentStr += "validator: RegExpValidator { regExp: " + validatorRegExp + " }\n}";
else if (decimals > 0)
componentStr += QString("validator: DoubleValidator { bottom: %1; decimals: %2; top: %3 }\n}").
arg(validatorMinimum).arg(decimals).arg(validatorMaximum);
else
componentStr += QString("validator: IntValidator { bottom: %1; top: %2 }\n}").
arg((int)validatorMinimum).arg((int)validatorMaximum);

QQmlComponent textInputComponent(&engine);
textInputComponent.setData(componentStr.toLatin1(), QUrl());
QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
QVERIFY(textInput != 0);

QQuickWindow window;
textInput->setParentItem(window.contentItem());
window.show();
window.requestActivate();
QTest::qWaitForWindowActive(&window);
QVERIFY(textInput->hasActiveFocus());

simulateKeys(&window, keys);

QCOMPARE(textInput->text(), expectedText);
QCOMPARE(textInput->displayText(), expectedDisplayText);
}

void tst_qquicktextinput::setInputMask_data()
{
Expand Down

0 comments on commit 1b21b73

Please sign in to comment.