diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
commit | 0655209fdad022bd0f6eb20ce85522cb56506bf0 (patch) | |
tree | cdba0c1590655f5cb75a68cedff74f8a683db3a2 /tests/auto/quick | |
parent | c3babc03c99c6ca5fa210486e133eb456a405bab (diff) | |
parent | 3d8f103c2641f35e7681485102a1b59886db8934 (diff) |
Merge master into api_changes
Conflicts:
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlpropertycache.cpp
Change-Id: I5193a193fa301c0b518291645bf626a5fa07118f
Diffstat (limited to 'tests/auto/quick')
23 files changed, 1474 insertions, 208 deletions
diff --git a/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml new file mode 100644 index 0000000000..1ee76f6906 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 +Item { + id: root + width: 450; height: 600 + + Rectangle { + objectName:"rect" + id: rect + x:200 + y:500 + width: 225; height: 40 + color: "lightsteelblue" + } + PathAnimation { + id:anim + running:true + duration: 200 + + easing.type: Easing.InOutBack + + target:rect + path: Path { + PathLine { x: 0; y: 0 } + } + } +}
\ No newline at end of file diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index d71100d120..166f4b8276 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -107,6 +107,7 @@ private slots: void pauseBug(); void loopingBug(); void anchorBug(); + void pathAnimationInOutBackBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -455,6 +456,13 @@ void tst_qquickanimations::pathInterpolator() QCOMPARE(interpolator->x(), qreal(300)); QCOMPARE(interpolator->y(), qreal(300)); QCOMPARE(interpolator->angle(), qreal(0)); + + //for path interpulator the progress value must be [0,1] range. + interpolator->setProgress(1.1); + QCOMPARE(interpolator->progress(), qreal(1)); + + interpolator->setProgress(-0.000123); + QCOMPARE(interpolator->progress(), qreal(0)); } void tst_qquickanimations::pathInterpolatorBackwardJump() @@ -1171,6 +1179,22 @@ void tst_qquickanimations::runningTrueBug() QVERIFY(cloud->x() > qreal(0)); } +//QTBUG-24308 +void tst_qquickanimations::pathAnimationInOutBackBug() +{ + //ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt() + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + QVERIFY(item); + + QQuickRectangle *rect = item->findChild<QQuickRectangle *>("rect"); + QVERIFY(rect); + QTest::qWait(1000); + QCOMPARE(rect->x(), qreal(0)); + QCOMPARE(rect->y(), qreal(0)); +} + //QTBUG-12805 void tst_qquickanimations::nonTransitionBug() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml index ffe6583d2e..c33901d294 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "arc"; when: windowShown function test_angle_1() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml index 8609ad0332..84bfc1a8db 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "arcTo"; when: windowShown function test_coincide() { diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml index 6aaecbdfa5..f72e5b9eaa 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "path"; when: windowShown diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml index 2521643837..c81ef73b90 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml @@ -4,6 +4,7 @@ import "testhelper.js" as Helper Canvas { id:canvas; width:100;height:50; renderTarget:Canvas.Image; renderStrategy:Canvas.Threaded + smooth: false TestCase { name: "strokeStyle"; when: windowShown function test_default() { diff --git a/tests/auto/quick/qquickflickable/data/cancel.qml b/tests/auto/quick/qquickflickable/data/cancel.qml new file mode 100644 index 0000000000..d1c3fddbf2 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/cancel.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Flickable { + width: 200; height: 200 + contentWidth: row.width; contentHeight: row.height + + Row { + id: row + objectName: "row" + Repeater { + model: 4 + Rectangle { width: 400; height: 600; color: "yellow"; border.width: 1 } + } + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 4b157a434b..2ed42e7f0f 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -77,6 +77,7 @@ private slots: void disabled(); void flickVelocity(); void margins(); + void cancel(); private: QQmlEngine engine; @@ -440,6 +441,19 @@ void tst_qquickflickable::movingAndDragging() // wait for any motion to end QTRY_VERIFY(flickable->isMoving() == false); + // Vertical with a quick press-move-release: should cause a flick in release. + QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged())); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90)); + QTest::qWait(10); + QTest::mouseMove(canvas, QPoint(50, 40)); + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 40)); + + QCOMPARE(vFlickSpy.count(), 1); + + // wait for any motion to end + QTRY_VERIFY(flickable->isMoving() == false); + //Horizontal vDragSpy.clear(); hDragSpy.clear(); @@ -492,7 +506,7 @@ void tst_qquickflickable::movingAndDragging() vMoveSpy.clear(); hMoveSpy.clear(); moveSpy.clear(); - QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged())); + vFlickSpy.clear(); QSignalSpy hFlickSpy(flickable, SIGNAL(flickingHorizontallyChanged())); QSignalSpy flickSpy(flickable, SIGNAL(flickingChanged())); @@ -657,6 +671,41 @@ void tst_qquickflickable::margins() delete root; } +void tst_qquickflickable::cancel() +{ + QQuickView *canvas = new QQuickView; + canvas->setSource(testFileUrl("cancel.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject()); + QVERIFY(flickable != 0); + + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10, 10)); + // drag out of bounds + QTest::mouseMove(canvas, QPoint(50, 50)); + QTest::mouseMove(canvas, QPoint(100, 100)); + QTest::mouseMove(canvas, QPoint(150, 150)); + + QVERIFY(flickable->contentX() != 0); + QVERIFY(flickable->contentY() != 0); + QVERIFY(flickable->isMoving()); + QVERIFY(flickable->isDragging()); + + // grabbing mouse will cancel flickable interaction. + QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("row"); + item->grabMouse(); + + QTRY_COMPARE(flickable->contentX(), 0.); + QTRY_COMPARE(flickable->contentY(), 0.); + QTRY_VERIFY(!flickable->isMoving()); + QTRY_VERIFY(!flickable->isDragging()); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 10)); +} + + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp index f99c26803d..10f81accbf 100644 --- a/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp +++ b/tests/auto/quick/qquickfontloader/tst_qquickfontloader.cpp @@ -116,6 +116,9 @@ void tst_qquickfontloader::namedFont() void tst_qquickfontloader::localFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("tarzeau_ocr_a.ttf").toString() + "\" }"; QQmlComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); @@ -129,6 +132,9 @@ void tst_qquickfontloader::localFont() void tst_qquickfontloader::failLocalFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"" + testFileUrl("dummy.ttf").toString() + "\" }"; QTest::ignoreMessage(QtWarningMsg, QString("file::2:1: QML FontLoader: Cannot load font: \"" + testFileUrl("dummy.ttf").toString() + "\"").toUtf8().constData()); QQmlComponent component(&engine); @@ -143,6 +149,9 @@ void tst_qquickfontloader::failLocalFont() void tst_qquickfontloader::webFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/tarzeau_ocr_a.ttf\" }"; QQmlComponent component(&engine); @@ -157,6 +166,9 @@ void tst_qquickfontloader::webFont() void tst_qquickfontloader::redirWebFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif server.addRedirect("olddir/oldname.ttf","../tarzeau_ocr_a.ttf"); QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/olddir/oldname.ttf\" }"; @@ -173,6 +185,9 @@ void tst_qquickfontloader::redirWebFont() void tst_qquickfontloader::failWebFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: \"http://localhost:14448/nonexist.ttf\" }"; QTest::ignoreMessage(QtWarningMsg, "file::2:1: QML FontLoader: Cannot load font: \"http://localhost:14448/nonexist.ttf\""); QQmlComponent component(&engine); @@ -187,6 +202,9 @@ void tst_qquickfontloader::failWebFont() void tst_qquickfontloader::changeFont() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QString componentStr = "import QtQuick 2.0\nFontLoader { source: font }"; QQmlContext *ctxt = engine.rootContext(); ctxt->setContextProperty("font", testFileUrl("tarzeau_ocr_a.ttf")); @@ -226,6 +244,9 @@ void tst_qquickfontloader::changeFont() void tst_qquickfontloader::changeFontSourceViaState() { +#if defined(Q_OS_WIN) + QSKIP("Windows doesn't support font loading."); +#endif QQuickView canvas(testFileUrl("qtbug-20268.qml")); canvas.show(); canvas.requestActivateWindow(); diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 88ed94d8bc..c7b5ca6b40 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -3691,31 +3691,32 @@ void tst_QQuickGridView::margins() QQuickItem *contentItem = gridview->contentItem(); QTRY_VERIFY(contentItem != 0); - QCOMPARE(gridview->contentX(), -240+30.); - QCOMPARE(gridview->xOrigin(), 0.); + QTRY_COMPARE(gridview->contentX(), -240+50.); + QTRY_COMPARE(gridview->xOrigin(), 0.); // check end bound gridview->positionViewAtEnd(); qreal pos = gridview->contentX(); gridview->setContentX(pos - 80); gridview->returnToBounds(); - QTRY_COMPARE(gridview->contentX(), pos - 50); + QTRY_COMPARE(gridview->contentX(), pos - 30); // remove item before visible and check that left margin is maintained // and xOrigin is updated gridview->setContentX(-400); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); model.removeItems(0, 4); - QTest::qWait(100); + QTRY_COMPARE(model.count(), gridview->count()); gridview->setContentX(-240+50); gridview->returnToBounds(); QCOMPARE(gridview->xOrigin(), -100.); - QTRY_COMPARE(gridview->contentX(), -240-70.); + QTRY_COMPARE(gridview->contentX(), -240-50.); - // reduce left margin (i.e. right side due to RTL) + // reduce right margin pos = gridview->contentX(); - gridview->setLeftMargin(20); + gridview->setRightMargin(40); QCOMPARE(gridview->xOrigin(), -100.); - QTRY_COMPARE(gridview->contentX(), -240-80.); + QTRY_COMPARE(gridview->contentX(), -240-100 + 40.); // check end bound gridview->positionViewAtEnd(); @@ -3723,11 +3724,11 @@ void tst_QQuickGridView::margins() pos = gridview->contentX(); gridview->setContentX(pos - 80); gridview->returnToBounds(); - QTRY_COMPARE(gridview->contentX(), pos - 50); + QTRY_COMPARE(gridview->contentX(), pos - 30); - // reduce right margin (i.e. left side due to RTL) + // reduce left margin pos = gridview->contentX(); - gridview->setRightMargin(40); + gridview->setLeftMargin(20); QCOMPARE(gridview->xOrigin(), 0.); QTRY_COMPARE(gridview->contentX(), pos+10); diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index 9fdfa78559..abd0da8ac1 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -181,7 +181,7 @@ void tst_qquickitem::initTestCase() qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem"); } -// Focus has no effect when outside a canvas +// Focus still updates when outside a canvas void tst_qquickitem::noCanvas() { QQuickItem *root = new TestItem; @@ -201,7 +201,7 @@ void tst_qquickitem::noCanvas() scopedChild2->setFocus(true); QCOMPARE(root->hasFocus(), true); QCOMPARE(child->hasFocus(), false); - QCOMPARE(scope->hasFocus(), true); + QCOMPARE(scope->hasFocus(), false); QCOMPARE(scopedChild->hasFocus(), false); QCOMPARE(scopedChild2->hasFocus(), true); @@ -210,10 +210,10 @@ void tst_qquickitem::noCanvas() scopedChild->setFocus(true); scope->setFocus(false); QCOMPARE(root->hasFocus(), false); - QCOMPARE(child->hasFocus(), true); + QCOMPARE(child->hasFocus(), false); QCOMPARE(scope->hasFocus(), false); QCOMPARE(scopedChild->hasFocus(), true); - QCOMPARE(scopedChild2->hasFocus(), true); + QCOMPARE(scopedChild2->hasFocus(), false); delete root; } @@ -434,7 +434,7 @@ void tst_qquickitem::addedToCanvas() c1->setFocus(true); c2->setFocus(true); focusState[item].set(true, true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); focusState.active(item); FVERIFY(); @@ -458,14 +458,14 @@ void tst_qquickitem::addedToCanvas() focusState << tree << c1 << c2; c1->setFocus(true); c2->setFocus(true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); - focusState[c1].set(true, true); - focusState[c2].set(false, false); - focusState.active(c1); + focusState[c1].set(false, false); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -481,19 +481,19 @@ void tst_qquickitem::addedToCanvas() focusState << tree << c1 << c2; c1->setFocus(true); c2->setFocus(true); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); - focusState[c1].set(true, false); - focusState[c2].set(false, false); + focusState[c1].set(false, false); + focusState[c2].set(true, false); FVERIFY(); tree->setFocus(true); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState.active(c1); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -511,15 +511,15 @@ void tst_qquickitem::addedToCanvas() c1->setFocus(true); c2->setFocus(true); focusState[tree].set(true, false); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); FVERIFY(); tree->setParentItem(canvas.rootItem()); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState[c2].set(false, false); - focusState.active(c1); + focusState[c1].set(false, false); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } @@ -540,22 +540,22 @@ void tst_qquickitem::addedToCanvas() c2->setFocus(true); focusState[child].set(true, true); focusState[tree].set(true, false); - focusState[c1].set(true, false); + focusState[c1].set(false, false); focusState[c2].set(true, false); focusState.active(child); FVERIFY(); tree->setParentItem(canvas.rootItem()); focusState[tree].set(false, false); - focusState[c1].set(true, false); - focusState[c2].set(false, false); + focusState[c1].set(false, false); + focusState[c2].set(true, false); FVERIFY(); tree->setFocus(true); focusState[child].set(false, false); focusState[tree].set(true, true); - focusState[c1].set(true, true); - focusState.active(c1); + focusState[c2].set(true, true); + focusState.active(c2); FVERIFY(); } } @@ -674,6 +674,40 @@ void tst_qquickitem::changeParent() FVERIFY(); } + // child has active focus, then its fs parent changes parent to 0, then + // child is deleted, then its parent changes again to a valid parent + { + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + QQuickItem *item = new TestFocusScope(canvas.rootItem()); + QQuickItem *child = new TestItem(item); + QQuickItem *child2 = new TestItem; + + FocusState focusState; + focusState << item << child; + FVERIFY(); + + item->setFocus(true); + child->setFocus(true); + focusState[child].set(true, true); + focusState[item].set(true, true); + focusState.active(child); + FVERIFY(); + + item->setParentItem(0); + focusState[child].set(true, false); + focusState[item].set(true, false); + focusState.active(0); + FVERIFY(); + + focusState.remove(child); + delete child; + item->setParentItem(canvas.rootItem()); + focusState[item].set(true, true); + focusState.active(item); + FVERIFY(); + } } void tst_qquickitem::multipleFocusClears() diff --git a/tests/auto/quick/qquickitemlayer/data/Effect.qml b/tests/auto/quick/qquickitemlayer/data/Effect.qml index 630c8f90ed..678f86538d 100644 --- a/tests/auto/quick/qquickitemlayer/data/Effect.qml +++ b/tests/auto/quick/qquickitemlayer/data/Effect.qml @@ -2,19 +2,19 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#0000ff" Rectangle { - x: 50 - width: 50 + x: 100 + width: 100 height: 100 color: "#00ff00" } diff --git a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml index 7cc7e8b21e..a161760028 100644 --- a/tests/auto/quick/qquickitemlayer/data/SourceRect.qml +++ b/tests/auto/quick/qquickitemlayer/data/SourceRect.qml @@ -2,12 +2,12 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#ff0000" diff --git a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml index ccd515652a..427bd41310 100644 --- a/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml +++ b/tests/auto/quick/qquickitemlayer/data/TextureProvider.qml @@ -2,19 +2,19 @@ import QtQuick 2.0 Item { - width: 100 + width: 200 height: 100 Rectangle { id: box - width: 100 + width: 200 height: 100 color: "#0000ff" Rectangle { - x: 50 - width: 50 + x: 100 + width: 100 height: 100 color: "#00ff00" } diff --git a/tests/auto/quick/qquicklistview/data/margins2.qml b/tests/auto/quick/qquicklistview/data/margins2.qml index e11c803c4b..4b1f2546bf 100644 --- a/tests/auto/quick/qquicklistview/data/margins2.qml +++ b/tests/auto/quick/qquicklistview/data/margins2.qml @@ -9,9 +9,9 @@ Item { } ListView { objectName: "listview" - topMargin: 20 + topMargin: 40 bottomMargin: 20 - leftMargin: 20 + leftMargin: 40 rightMargin: 20 anchors.fill: parent diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index 202f5164af..461a6b6750 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -4290,6 +4290,13 @@ void tst_QQuickListView::marginsResize() QFETCH(qreal, start); QFETCH(qreal, end); + QPoint flickStart(20, 20); + QPoint flickEnd(20, 20); + if (orientation == QQuickListView::Vertical) + flickStart.ry() += 180; + else + flickStart.rx() += (layoutDirection == Qt::LeftToRight) ? 180 : -180; + QQuickView *canvas = getView(); canvas->setSource(testFileUrl("margins2.qml")); @@ -4316,6 +4323,14 @@ void tst_QQuickListView::marginsResize() else QTRY_COMPARE(listview->contentX(), end); + // flick past the end and check content pos still settles on correct extents + flick(canvas, flickStart, flickEnd, 180); + QTRY_VERIFY(listview->isMoving() == false); + if (orientation == QQuickListView::Vertical) + QTRY_COMPARE(listview->contentY(), end); + else + QTRY_COMPARE(listview->contentX(), end); + // back to top - top margin should be visible. listview->setCurrentIndex(0); if (orientation == QQuickListView::Vertical) @@ -4323,6 +4338,14 @@ void tst_QQuickListView::marginsResize() else QTRY_COMPARE(listview->contentX(), start); + // flick past the beginning and check content pos still settles on correct extents + flick(canvas, flickEnd, flickStart, 180); + QTRY_VERIFY(listview->isMoving() == false); + if (orientation == QQuickListView::Vertical) + QTRY_COMPARE(listview->contentY(), start); + else + QTRY_COMPARE(listview->contentX(), start); + releaseView(canvas); } @@ -4333,9 +4356,11 @@ void tst_QQuickListView::marginsResize_data() QTest::addColumn<qreal>("start"); QTest::addColumn<qreal>("end"); - QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -20.0 << 1020.0; - QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -20.0 << 1020.0; - QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1220.0; + // in Right to Left mode, leftMargin still means leftMargin - it doesn't reverse to mean rightMargin + + QTest::newRow("vertical") << QQuickListView::Vertical << Qt::LeftToRight << -40.0 << 1020.0; + QTest::newRow("horizontal") << QQuickListView::Horizontal << Qt::LeftToRight << -40.0 << 1020.0; + QTest::newRow("horizontal, rtl") << QQuickListView::Horizontal << Qt::RightToLeft << -180.0 << -1240.0; } void tst_QQuickListView::snapToItem_data() diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index bdf47fa9e9..01781f7b54 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -929,7 +929,7 @@ void tst_QQuickLoader::asynchronous_clear() QVERIFY(!loader->item()); QCOMPARE(loader->status(), QQuickLoader::Loading); - QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1); + QTRY_COMPARE(engine.incubationController()->incubatingObjectCount(), 1); // clear before component created root->setProperty("comp", ""); @@ -942,7 +942,7 @@ void tst_QQuickLoader::asynchronous_clear() QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0); // check loading component - root->setProperty("comp", "Rect120x60.qml"); + root->setProperty("comp", "BigComponent.qml"); QMetaObject::invokeMethod(root, "loadComponent"); QVERIFY(!loader->item()); @@ -953,6 +953,8 @@ void tst_QQuickLoader::asynchronous_clear() QCOMPARE(loader->progress(), 1.0); QCOMPARE(loader->status(), QQuickLoader::Ready); QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1); + + delete root; } void tst_QQuickLoader::simultaneousSyncAsync() diff --git a/tests/auto/quick/qquickpathview/data/dragpath.qml b/tests/auto/quick/qquickpathview/data/dragpath.qml index f9c6615b04..6ba778bb80 100644 --- a/tests/auto/quick/qquickpathview/data/dragpath.qml +++ b/tests/auto/quick/qquickpathview/data/dragpath.qml @@ -14,6 +14,7 @@ PathView { preferredHighlightBegin: 0.5 preferredHighlightEnd: 0.5 Text { + objectName: "text" text: "current index: " + parent.currentIndex } } diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 8866cafd80..613156b2f5 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -123,6 +123,7 @@ private slots: void creationContext(); void currentOffsetOnInsertion(); void asynchronous(); + void cancelDrag(); }; class TestObject : public QObject @@ -1453,6 +1454,41 @@ void tst_QQuickPathView::missingPercent() delete obj; } +void tst_QQuickPathView::cancelDrag() +{ + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("dragpath.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(canvas, qGuiApp->focusWindow()); + + QQuickPathView *pathview = qobject_cast<QQuickPathView*>(canvas->rootObject()); + QVERIFY(pathview != 0); + + // drag between snap points + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(10,100)); + QTest::qWait(100); + QTest::mouseMove(canvas, QPoint(30, 100)); + QTest::mouseMove(canvas, QPoint(85, 100)); + + QTRY_VERIFY(pathview->offset() != qFloor(pathview->offset())); + QTRY_VERIFY(pathview->isMoving()); + + // steal mouse grab - cancels PathView dragging + QQuickItem *item = canvas->rootObject()->findChild<QQuickItem*>("text"); + item->grabMouse(); + + // returns to a snap point. + QTRY_VERIFY(pathview->offset() == qFloor(pathview->offset())); + QTRY_VERIFY(!pathview->isMoving()); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(40,100)); + + delete canvas; +} + + QTEST_MAIN(tst_QQuickPathView) #include "tst_qquickpathview.moc" diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index 77f0ec190d..affb355837 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -107,6 +107,8 @@ private slots: void implicitSize_data(); void implicitSize(); void contentSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); void lineLaidOut(); @@ -1069,11 +1071,11 @@ void tst_qquicktext::smooth() for (int i = 0; i < standard.size(); i++) { { - QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + standard.at(i) + "\" }"; + QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + standard.at(i) + "\" }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), true); + QCOMPARE(textObject->smooth(), false); delete textObject; } @@ -1082,7 +1084,7 @@ void tst_qquicktext::smooth() QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), false); + QCOMPARE(textObject->smooth(), true); delete textObject; } @@ -1090,11 +1092,11 @@ void tst_qquicktext::smooth() for (int i = 0; i < richText.size(); i++) { { - QString componentStr = "import QtQuick 2.0\nText { smooth: true; text: \"" + richText.at(i) + "\" }"; + QString componentStr = "import QtQuick 2.0\nText { smooth: false; text: \"" + richText.at(i) + "\" }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), true); + QCOMPARE(textObject->smooth(), false); delete textObject; } @@ -1103,7 +1105,7 @@ void tst_qquicktext::smooth() QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickText *textObject = qobject_cast<QQuickText*>(textComponent.create()); - QCOMPARE(textObject->smooth(), false); + QCOMPARE(textObject->smooth(), true); delete textObject; } @@ -1548,29 +1550,36 @@ void tst_qquicktext::implicitSize_data() QTest::addColumn<QString>("width"); QTest::addColumn<QString>("wrap"); QTest::addColumn<QString>("elide"); - QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight"; - QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight"; - QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone"; - QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight"; - QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight"; - QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone"; + QTest::addColumn<QString>("format"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 50" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("plain, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("plain, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.NoWrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("richtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" <<" 0" << "Text.NoWrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "50" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText"; + QTest::newRow("plain_wrap, 0 width") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.PlainText"; + QTest::newRow("plain_wrap, elide") << "The quick red fox jumped over the lazy brown dog" << "50" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("plain_wrap, 0 width, elide") << "The quick red fox jumped over the lazy brown dog" << "0" << "Text.Wrap" << "Text.ElideRight" << "Text.PlainText"; + QTest::newRow("richtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.RichText"; + QTest::newRow("styledtext_wrap, 0 width") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "0" << "Text.Wrap" << "Text.ElideNone" << "Text.StyledText"; } void tst_qquicktext::implicitSize() { QFETCH(QString, text); QFETCH(QString, width); + QFETCH(QString, format); QFETCH(QString, wrap); QFETCH(QString, elide); QString componentStr = "import QtQuick 2.0\nText { " "text: \"" + text + "\"; " "width: " + width + "; " + "textFormat: " + format + "; " "wrapMode: " + wrap + "; " "elide: " + elide + "; " "maximumLineCount: 1 }"; @@ -1631,6 +1640,35 @@ void tst_qquicktext::contentSize() QCOMPARE(spy.count(), ++spyCount); } +void tst_qquicktext::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktext::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }"; + + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickText *textObject = qobject_cast<QQuickText *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktext::lineLaidOut() { QQuickView *canvas = createView(testFile("lineLayout.qml")); diff --git a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml index 7c7cb0b6fc..b7a15962f4 100644 --- a/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml +++ b/tests/auto/quick/qquicktextedit/data/mouseselection_true.qml @@ -2,6 +2,6 @@ import QtQuick 2.0 TextEdit { focus: true - text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + text: "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" selectByMouse: true } diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp index a90b23dfd7..83e7e78866 100644 --- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp +++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp @@ -69,6 +69,7 @@ Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode) +Q_DECLARE_METATYPE(Qt::Key) DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) @@ -151,6 +152,8 @@ private slots: void implicitSize_data(); void implicitSize(); void contentSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); void preeditCursorRectangle(); void inputMethodComposing(); @@ -185,7 +188,7 @@ private: void simulateKeys(QWindow *window, const QList<Key> &keys); void simulateKeys(QWindow *window, const QKeySequence &sequence); - void simulateKey(QQuickView *, int key, Qt::KeyboardModifiers modifiers = 0); + void simulateKey(QWindow *, int key, Qt::KeyboardModifiers modifiers = 0); QStringList standard; QStringList richText; @@ -1012,23 +1015,88 @@ void tst_qquicktextedit::persistentSelection() void tst_qquicktextedit::focusOnPress() { - { - QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: true; text: \"Hello World\" }"; - QQmlComponent texteditComponent(&engine); - texteditComponent.setData(componentStr.toLatin1(), QUrl()); - QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); - QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->focusOnPress(), true); - } + QString componentStr = + "import QtQuick 2.0\n" + "TextEdit {\n" + "property bool selectOnFocus: false\n" + "width: 100; height: 50\n" + "activeFocusOnPress: true\n" + "text: \"Hello World\"\n" + "onFocusChanged: { if (focus && selectOnFocus) selectAll() }" + " }"; + QQmlComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); + QVERIFY(textEditObject != 0); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(textEditObject->hasFocus(), false); - { - QString componentStr = "import QtQuick 2.0\nTextEdit { activeFocusOnPress: false; text: \"Hello World\" }"; - QQmlComponent texteditComponent(&engine); - texteditComponent.setData(componentStr.toLatin1(), QUrl()); - QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create()); - QVERIFY(textEditObject != 0); - QCOMPARE(textEditObject->focusOnPress(), false); - } + QSignalSpy focusSpy(textEditObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusSpy(textEditObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusOnPressSpy(textEditObject, SIGNAL(activeFocusOnPressChanged(bool))); + + textEditObject->setFocusOnPress(true); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 0); + + QQuickCanvas canvas; + canvas.resize(100, 50); + textEditObject->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + + QPoint centerPoint(canvas.width()/2, canvas.height()/2); + Qt::KeyboardModifiers noModifiers = 0; + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), true); + QCOMPARE(textEditObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(textEditObject->selectedText(), QString()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textEditObject->setFocusOnPress(false); + QCOMPARE(textEditObject->focusOnPress(), false); + QCOMPARE(activeFocusOnPressSpy.count(), 1); + + textEditObject->setFocus(false); + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + + // Wait for double click timeout to expire before clicking again. + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), false); + QCOMPARE(textEditObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textEditObject->setFocusOnPress(true); + QCOMPARE(textEditObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 2); + + // Test a selection made in the on(Active)FocusChanged handler isn't overwritten. + textEditObject->setProperty("selectOnFocus", true); + + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textEditObject->hasFocus(), true); + QCOMPARE(textEditObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 3); + QCOMPARE(activeFocusSpy.count(), 3); + QCOMPARE(textEditObject->selectedText(), textEditObject->text()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); } void tst_qquicktextedit::selection() @@ -1562,21 +1630,41 @@ void tst_qquicktextedit::mouseSelection_data() QTest::addColumn<int>("from"); QTest::addColumn<int>("to"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<bool>("focus"); + QTest::addColumn<bool>("focusOnPress"); + QTest::addColumn<bool>("doubleClick"); // import installed - QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678"; - QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString(); - QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString(); - QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString(); - QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789"; - QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false; + QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false; + QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false; + + QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false; + QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false; + + QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false; + QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false; + + QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false; + + QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true; + QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; + QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true; } void tst_qquicktextedit::mouseSelection() @@ -1585,6 +1673,9 @@ void tst_qquicktextedit::mouseSelection() QFETCH(int, from); QFETCH(int, to); QFETCH(QString, selectedText); + QFETCH(bool, focus); + QFETCH(bool, focusOnPress); + QFETCH(bool, doubleClick); QQuickView canvas(QUrl::fromLocalFile(qmlfile)); @@ -1597,9 +1688,14 @@ void tst_qquicktextedit::mouseSelection() QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject()); QVERIFY(textEditObject != 0); + textEditObject->setFocus(focus); + textEditObject->setFocusOnPress(focusOnPress); + // press-and-drag-and-release from x1 to x2 QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint(); QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint(); + if (doubleClick) + QTest::mouseClick(&canvas, Qt::LeftButton, 0, p1); QTest::mousePress(&canvas, Qt::LeftButton, 0, p1); QTest::mouseMove(&canvas, p2); QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2); @@ -1608,7 +1704,10 @@ void tst_qquicktextedit::mouseSelection() // Clicking and shift to clicking between the same points should select the same text. textEditObject->setCursorPosition(0); - QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1); + if (doubleClick) + QTest::mouseDClick(&canvas, Qt::LeftButton, 0, p1); + else + QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1); QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2); QTest::qWait(50); QTRY_COMPARE(textEditObject->selectedText(), selectedText); @@ -2155,7 +2254,7 @@ void tst_qquicktextedit::readOnly() QCOMPARE(edit->cursorPosition(), edit->text().length()); } -void tst_qquicktextedit::simulateKey(QQuickView *view, int key, Qt::KeyboardModifiers modifiers) +void tst_qquicktextedit::simulateKey(QWindow *view, int key, Qt::KeyboardModifiers modifiers) { QKeyEvent press(QKeyEvent::KeyPress, key, modifiers); QKeyEvent release(QKeyEvent::KeyRelease, key, modifiers); @@ -2415,17 +2514,19 @@ void tst_qquicktextedit::implicitSize_data() { QTest::addColumn<QString>("text"); QTest::addColumn<QString>("wrap"); - QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap"; - QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap"; - QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap"; - QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap"; + QTest::addColumn<QString>("format"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap" << "TextEdit.PlainText"; + QTest::newRow("richtext") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.NoWrap" << "TextEdit.RichText"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap" << "TextEdit.PlainText"; + QTest::newRow("richtext_wrap") << "<b>The quick red fox jumped over the lazy brown dog</b>" << "TextEdit.Wrap" << "TextEdit.RichText"; } void tst_qquicktextedit::implicitSize() { QFETCH(QString, text); QFETCH(QString, wrap); - QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + "; textFormat: " + format + " }"; QQmlComponent textComponent(&engine); textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit*>(textComponent.create()); @@ -2466,6 +2567,34 @@ void tst_qquicktextedit::contentSize() QCOMPARE(spy.count(), 3); } +void tst_qquicktextedit::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktextedit::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QFETCH(QString, format); + QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktextedit::preeditCursorRectangle() { QString preeditText = "super"; @@ -3255,63 +3384,118 @@ void tst_qquicktextedit::keySequence_data() QTest::addColumn<int>("cursorPosition"); QTest::addColumn<QString>("expectedText"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<Qt::Key>("layoutDirection"); // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog" QTest::newRow("select all") << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0 - << 44 << standard.at(0) << standard.at(0); + << 44 << standard.at(0) << standard.at(0) + << Qt::Key_Direction_L; + QTest::newRow("select start of line") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << Qt::Key_Direction_L; + QTest::newRow("select start of block") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << Qt::Key_Direction_L; QTest::newRow("select end of line") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5 - << 44 << standard.at(0) << standard.at(0).mid(5); + << 44 << standard.at(0) << standard.at(0).mid(5) + << Qt::Key_Direction_L; QTest::newRow("select end of document") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3 - << 44 << standard.at(0) << standard.at(0).mid(3); + << 44 << standard.at(0) << standard.at(0).mid(3) + << Qt::Key_Direction_L; QTest::newRow("select end of block") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18 - << 44 << standard.at(0) << standard.at(0).mid(18); + << 44 << standard.at(0) << standard.at(0).mid(18) + << Qt::Key_Direction_L; QTest::newRow("delete end of line") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24 - << 24 << standard.at(0).mid(0, 24) << QString(); + << 24 << standard.at(0).mid(0, 24) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to start of line") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to start of block") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << Qt::Key_Direction_L; QTest::newRow("move to next char") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12 - << 13 << standard.at(0) << QString(); - QTest::newRow("move to previous char") + << 13 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous char (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 - << 2 << standard.at(0) << QString(); - QTest::newRow("select next char") + << 2 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous char (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("move to previous char with selection") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7 + << 3 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("select next char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 + << 24 << standard.at(0) << standard.at(0).mid(23, 1) + << Qt::Key_Direction_L; + QTest::newRow("select next char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 - << 24 << standard.at(0) << standard.at(0).mid(23, 1); - QTest::newRow("select previous char") + << 22 << standard.at(0) << standard.at(0).mid(22, 1) + << Qt::Key_Direction_R; + QTest::newRow("select previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 + << 18 << standard.at(0) << standard.at(0).mid(18, 1) + << Qt::Key_Direction_L; + QTest::newRow("select previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 - << 18 << standard.at(0) << standard.at(0).mid(18, 1); - QTest::newRow("move to next word") + << 20 << standard.at(0) << standard.at(0).mid(19, 1) + << Qt::Key_Direction_R; + QTest::newRow("move to next word (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 - << 10 << standard.at(0) << QString(); - QTest::newRow("move to previous word") + << 10 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to next word (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("move to previous word (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << Qt::Key_Direction_L; + QTest::newRow("move to previous word (rlt)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 - << 4 << standard.at(0) << QString(); + << 10 << standard.at(0) << QString() + << Qt::Key_Direction_R; + QTest::newRow("select next word") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11 + << 16 << standard.at(0) << standard.at(0).mid(11, 5) + << Qt::Key_Direction_L; QTest::newRow("select previous word") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11 - << 10 << standard.at(0) << standard.at(0).mid(10, 1); + << 10 << standard.at(0) << standard.at(0).mid(10, 1) + << Qt::Key_Direction_L; QTest::newRow("delete (selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15 - << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString(); + << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete (no selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15 - << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString(); + << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete end of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24 - << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString(); + << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString() + << Qt::Key_Direction_L; QTest::newRow("delete start of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7 - << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString(); + << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString() + << Qt::Key_Direction_L; } void tst_qquicktextedit::keySequence() @@ -3323,6 +3507,7 @@ void tst_qquicktextedit::keySequence() QFETCH(int, cursorPosition); QFETCH(QString, expectedText); QFETCH(QString, selectedText); + QFETCH(Qt::Key, layoutDirection); if (sequence.isEmpty()) { QSKIP("Key sequence is undefined"); @@ -3341,6 +3526,8 @@ void tst_qquicktextedit::keySequence() QTest::qWaitForWindowShown(&canvas); QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + simulateKey(&canvas, layoutDirection); + textEdit->select(selectionStart, selectionEnd); simulateKeys(&canvas, sequence); @@ -3466,7 +3653,7 @@ void tst_qquicktextedit::undo_data() insertString << " unique instance."; expectedString << "Ensuring a unique instance."; - expectedString << "Ensuring a "; // ### Not present in TextInput. + expectedString << "Ensuring a "; // ### Not present in TextEdit. expectedString << "Ensuring an instan"; expectedString << "Ensuring instan"; expectedString << ""; @@ -3754,7 +3941,7 @@ void tst_qquicktextedit::undo_keypressevents_data() << "ABC"; expectedString << "ABC"; - // ### One operation in TextInput. + // ### One operation in TextEdit. expectedString << "A"; expectedString << "123"; diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp index c5db92af45..afe102aa4c 100644 --- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp +++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp @@ -63,6 +63,9 @@ #include "../../shared/platforminputcontext.h" Q_DECLARE_METATYPE(QQuickTextInput::SelectionMode) +Q_DECLARE_METATYPE(QQuickTextInput::EchoMode) +Q_DECLARE_METATYPE(Qt::Key) + DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) @@ -90,6 +93,8 @@ template <typename T> static T evaluate(QObject *scope, const QString &expressio return result; } +template<typename T, int N> int lengthOf(const T (&)[N]) { return N; } + typedef QPair<int, QChar> Key; class tst_qquicktextinput : public QQmlDataTest @@ -137,6 +142,7 @@ private slots: void cursorDelegate_data(); void cursorDelegate(); void cursorVisible(); + void cursorRectangle_data(); void cursorRectangle(); void navigation(); void navigation_RTL(); @@ -145,6 +151,7 @@ private slots: void canPasteEmpty(); void canPaste(); void readOnly(); + void focusOnPress(); void openInputPanel(); void setHAlignClearCache(); @@ -185,10 +192,28 @@ private slots: void QTBUG_19956_data(); void QTBUG_19956_regexp(); + void implicitSize_data(); + void implicitSize(); + void implicitSizeBinding_data(); + void implicitSizeBinding(); + void negativeDimensions(); + + void setInputMask_data(); + void setInputMask(); + void inputMask_data(); + void inputMask(); + void clearInputMask(); + void keypress_inputMask_data(); + void keypress_inputMask(); + void hasAcceptableInputMask_data(); + void hasAcceptableInputMask(); + void maskCharacter_data(); + void maskCharacter(); + private: - void simulateKey(QQuickView *, int key); + void simulateKey(QWindow *, int key); void simulateKeys(QWindow *window, const QList<Key> &keys); void simulateKeys(QWindow *window, const QKeySequence &sequence); @@ -1184,17 +1209,27 @@ void tst_qquicktextinput::mouseSelectionMode_data() { QTest::addColumn<QString>("qmlfile"); QTest::addColumn<bool>("selectWords"); + QTest::addColumn<bool>("focus"); + QTest::addColumn<bool>("focusOnPress"); // import installed - QTest::newRow("SelectWords") << testFile("mouseselectionmode_words.qml") << true; - QTest::newRow("SelectCharacters") << testFile("mouseselectionmode_characters.qml") << false; - QTest::newRow("default") << testFile("mouseselectionmode_default.qml") << false; + QTest::newRow("SelectWords focused") << testFile("mouseselectionmode_words.qml") << true << true << true; + QTest::newRow("SelectCharacters focused") << testFile("mouseselectionmode_characters.qml") << false << true << true; + QTest::newRow("default focused") << testFile("mouseselectionmode_default.qml") << false << true << true; + QTest::newRow("SelectWords unfocused") << testFile("mouseselectionmode_words.qml") << true << false << false; + QTest::newRow("SelectCharacters unfocused") << testFile("mouseselectionmode_characters.qml") << false << false << false; + QTest::newRow("default unfocused") << testFile("mouseselectionmode_default.qml") << false << true << false; + QTest::newRow("SelectWords focuss on press") << testFile("mouseselectionmode_words.qml") << true << false << true; + QTest::newRow("SelectCharacters focus on press") << testFile("mouseselectionmode_characters.qml") << false << false << true; + QTest::newRow("default focus on press") << testFile("mouseselectionmode_default.qml") << false << false << true; } void tst_qquicktextinput::mouseSelectionMode() { QFETCH(QString, qmlfile); QFETCH(bool, selectWords); + QFETCH(bool, focus); + QFETCH(bool, focusOnPress); QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -1209,6 +1244,9 @@ void tst_qquicktextinput::mouseSelectionMode() QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(canvas.rootObject()); QVERIFY(textInputObject != 0); + textInputObject->setFocus(focus); + textInputObject->setFocusOnPress(focusOnPress); + // press-and-drag-and-release from x1 to x2 int x1 = 10; int x2 = 70; @@ -2126,7 +2164,7 @@ void tst_qquicktextinput::copyAndPaste() { // copy and paste QCOMPARE(textInput->text().length(), 12); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); textInput->copy(); QCOMPARE(textInput->selectedText(), QString("Hello world!")); QCOMPARE(textInput->selectedText().length(), 12); @@ -2169,7 +2207,7 @@ void tst_qquicktextinput::copyAndPaste() { QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index); textInput->setEchoMode(echoMode); textInput->setText("My password"); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); textInput->copy(); if (echoMode == QQuickTextInput::Normal) { QVERIFY(!clipboard->text().isEmpty()); @@ -2246,7 +2284,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence() { QQuickTextInput::EchoMode echoMode = QQuickTextInput::EchoMode(index); textInput->setEchoMode(echoMode); textInput->setText("My password"); - textInput->select(0, textInput->text().length());; + textInput->select(0, textInput->text().length()); simulateKeys(&canvas, QKeySequence::Copy); if (echoMode == QQuickTextInput::Normal) { QVERIFY(!clipboard->text().isEmpty()); @@ -2402,10 +2440,34 @@ void tst_qquicktextinput::cursorVisible() QCOMPARE(spy.count(), 7); } +void tst_qquicktextinput::cursorRectangle_data() +{ + const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647}; + + QTest::addColumn<QString>("text"); + QTest::addColumn<int>("positionAtWidth"); + QTest::addColumn<int>("wrapPosition"); + QTest::addColumn<QString>("shortText"); + QTest::addColumn<bool>("leftToRight"); + + QTest::newRow("left to right") + << "Hello World!" << 5 << 11 + << "Hi" + << true; + QTest::newRow("right to left") + << QString::fromUtf16(arabic_str, lengthOf(arabic_str)) << 5 << 11 + << QString::fromUtf16(arabic_str, 3) + << false; +} + void tst_qquicktextinput::cursorRectangle() { - QString text = "Hello World!"; + QFETCH(QString, text); + QFETCH(int, positionAtWidth); + QFETCH(int, wrapPosition); + QFETCH(QString, shortText); + QFETCH(bool, leftToRight); QQuickTextInput input; input.setText(text); @@ -2422,33 +2484,30 @@ void tst_qquicktextinput::cursorRectangle() QTextLine line = layout.createLine(); layout.endLayout(); - input.setWidth(line.cursorToX(5, QTextLine::Leading)); + qreal offset = 0; + if (leftToRight) { + input.setWidth(line.cursorToX(positionAtWidth, QTextLine::Leading)); + } else { + input.setWidth(line.horizontalAdvance() - line.cursorToX(positionAtWidth, QTextLine::Leading)); + offset = line.horizontalAdvance() - input.width(); + } input.setHeight(qCeil(line.height() * 3 / 2)); QRectF r; - // some tolerance for different fonts. -#ifdef Q_OS_LINUX - const int error = 2; -#else - const int error = 5; -#endif - - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i <= positionAtWidth; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } // Check the cursor rectangle remains within the input bounding rect when auto scrolling. - QVERIFY(r.left() < input.width() + error); - QVERIFY(r.right() >= input.width() - error); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); - for (int i = 6; i < text.length(); ++i) { + for (int i = positionAtWidth + 1; i < text.length(); ++i) { input.setCursorPosition(i); QCOMPARE(r, input.cursorRectangle()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); @@ -2459,7 +2518,11 @@ void tst_qquicktextinput::cursorRectangle() input.setCursorPosition(i); r = input.cursorRectangle(); QCOMPARE(r.top(), 0.); - QVERIFY(r.right() >= 0); + if (leftToRight) { + QVERIFY(r.right() >= 0); + } else { + QVERIFY(r.left() <= input.width()); + } QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } @@ -2467,69 +2530,102 @@ void tst_qquicktextinput::cursorRectangle() // Check position with word wrap. input.setWrapMode(QQuickTextInput::WordWrap); input.setAutoScroll(false); - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i < wrapPosition; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + if (i > positionAtWidth) + QEXPECT_FAIL("right to left", "QTBUG-24801", Continue); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(r.top(), 0.); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - input.setCursorPosition(6); + input.setCursorPosition(wrapPosition); r = input.cursorRectangle(); - QCOMPARE(r.left(), 0.); - QVERIFY(r.top() > line.height() - error); + if (leftToRight) { + QCOMPARE(r.left(), 0.); + } else { + QCOMPARE(r.left(), input.width()); + } + QVERIFY(r.top() >= line.height() - 1); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); - QCOMPARE(input.positionToRectangle(6), r); + QCOMPARE(input.positionToRectangle(11), r); - for (int i = 7; i < text.length(); ++i) { + for (int i = wrapPosition + 1; i < text.length(); ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.top() > line.height() - error); + QVERIFY(r.top() >= line.height() - 1); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } // Check vertical scrolling with word wrap. input.setAutoScroll(true); - for (int i = 0; i <= 5; ++i) { + for (int i = 0; i <= positionAtWidth; ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing))); - QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading))); + QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset); QCOMPARE(r.top(), 0.); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - input.setCursorPosition(6); + // Whitespace doesn't wrap, so scroll horizontally until the until the cursor + // reaches the next non-whitespace character. + QCOMPARE(r.left(), leftToRight ? input.width() : 0); + for (int i = positionAtWidth + 1; i < wrapPosition && leftToRight; ++i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(i), r); + } + + input.setCursorPosition(wrapPosition); r = input.cursorRectangle(); - QCOMPARE(r.left(), 0.); - QVERIFY(r.bottom() >= input.height() - error); + if (leftToRight) { + QCOMPARE(r.left(), 0.); + } else { + QCOMPARE(r.left(), input.width()); + } + QVERIFY(r.bottom() >= input.height()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); - QCOMPARE(input.positionToRectangle(6), r); + QCOMPARE(input.positionToRectangle(11), r); - for (int i = 7; i < text.length(); ++i) { + for (int i = wrapPosition + 1; i < text.length(); ++i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.bottom() >= input.height() - error); + QVERIFY(r.bottom() >= input.height()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - for (int i = text.length() - 2; i >= 6; --i) { + for (int i = text.length() - 2; i >= wrapPosition; --i) { input.setCursorPosition(i); r = input.cursorRectangle(); - QVERIFY(r.bottom() >= input.height() - error); + QVERIFY(r.bottom() >= input.height()); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(i), r); + } + + input.setCursorPosition(wrapPosition - 1); + r = input.cursorRectangle(); + QCOMPARE(r.top(), 0.); + QEXPECT_FAIL("right to left", "QTBUG-24801", Continue); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); + QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); + QCOMPARE(input.positionToRectangle(10), r); + + for (int i = wrapPosition - 2; i >= positionAtWidth + 1; --i) { + input.setCursorPosition(i); + QCOMPARE(r, input.cursorRectangle()); QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r); QCOMPARE(input.positionToRectangle(i), r); } - for (int i = 5; i >= 0; --i) { + for (int i = positionAtWidth; i >= 0; --i) { input.setCursorPosition(i); r = input.cursorRectangle(); QCOMPARE(r.top(), 0.); @@ -2537,11 +2633,10 @@ void tst_qquicktextinput::cursorRectangle() QCOMPARE(input.positionToRectangle(i), r); } - input.setText("Hi!"); - input.setHAlign(QQuickTextInput::AlignRight); + input.setText(shortText); + input.setHAlign(leftToRight ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft); r = input.cursorRectangle(); - QVERIFY(r.left() < input.width() + error); - QVERIFY(r.right() >= input.width() - error); + QCOMPARE(r.left(), leftToRight ? input.width() : 0); } void tst_qquicktextinput::readOnly() @@ -2702,7 +2797,7 @@ void tst_qquicktextinput::passwordEchoDelay() #endif -void tst_qquicktextinput::simulateKey(QQuickView *view, int key) +void tst_qquicktextinput::simulateKey(QWindow *view, int key) { QKeyEvent press(QKeyEvent::KeyPress, key, 0); QKeyEvent release(QKeyEvent::KeyRelease, key, 0); @@ -2712,6 +2807,92 @@ void tst_qquicktextinput::simulateKey(QQuickView *view, int key) } +void tst_qquicktextinput::focusOnPress() +{ + QString componentStr = + "import QtQuick 2.0\n" + "TextInput {\n" + "property bool selectOnFocus: false\n" + "width: 100; height: 50\n" + "activeFocusOnPress: true\n" + "text: \"Hello World\"\n" + "onFocusChanged: { if (focus && selectOnFocus) selectAll() }" + " }"; + QQmlComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput*>(texteditComponent.create()); + QVERIFY(textInputObject != 0); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(textInputObject->hasFocus(), false); + + QSignalSpy focusSpy(textInputObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusSpy(textInputObject, SIGNAL(focusChanged(bool))); + QSignalSpy activeFocusOnPressSpy(textInputObject, SIGNAL(activeFocusOnPressChanged(bool))); + + textInputObject->setFocusOnPress(true); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 0); + + QQuickCanvas canvas; + canvas.resize(100, 50); + textInputObject->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + + QPoint centerPoint(canvas.width()/2, canvas.height()/2); + Qt::KeyboardModifiers noModifiers = 0; + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), true); + QCOMPARE(textInputObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 1); + QCOMPARE(activeFocusSpy.count(), 1); + QCOMPARE(textInputObject->selectedText(), QString()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textInputObject->setFocusOnPress(false); + QCOMPARE(textInputObject->focusOnPress(), false); + QCOMPARE(activeFocusOnPressSpy.count(), 1); + + textInputObject->setFocus(false); + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + + // Wait for double click timeout to expire before clicking again. + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), false); + QCOMPARE(textInputObject->hasActiveFocus(), false); + QCOMPARE(focusSpy.count(), 2); + QCOMPARE(activeFocusSpy.count(), 2); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); + + textInputObject->setFocusOnPress(true); + QCOMPARE(textInputObject->focusOnPress(), true); + QCOMPARE(activeFocusOnPressSpy.count(), 2); + + // Test a selection made in the on(Active)FocusChanged handler isn't overwritten. + textInputObject->setProperty("selectOnFocus", true); + + QTest::qWait(400); + QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint); + QGuiApplication::processEvents(); + QCOMPARE(textInputObject->hasFocus(), true); + QCOMPARE(textInputObject->hasActiveFocus(), true); + QCOMPARE(focusSpy.count(), 3); + QCOMPARE(activeFocusSpy.count(), 3); + QCOMPARE(textInputObject->selectedText(), textInputObject->text()); + QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint); +} + void tst_qquicktextinput::openInputPanel() { PlatformInputContext platformInputContext; @@ -2888,6 +3069,13 @@ void tst_qquicktextinput::contentSize() QVERIFY(textObject->contentWidth() > textObject->width()); QVERIFY(textObject->contentHeight() > textObject->height()); QCOMPARE(spy.count(), 3); + + textObject->setText("The quick red fox jumped over the lazy brown dog"); + for (int w = 60; w < 120; ++w) { + textObject->setWidth(w); + QVERIFY(textObject->contentWidth() <= textObject->width()); + QVERIFY(textObject->contentHeight() > textObject->height()); + } } static void sendPreeditText(const QString &text, int cursor) @@ -4084,63 +4272,135 @@ void tst_qquicktextinput::keySequence_data() QTest::addColumn<int>("cursorPosition"); QTest::addColumn<QString>("expectedText"); QTest::addColumn<QString>("selectedText"); + QTest::addColumn<QQuickTextInput::EchoMode>("echoMode"); + QTest::addColumn<Qt::Key>("layoutDirection"); // standard[0] == "the [4]quick [10]brown [16]fox [20]jumped [27]over [32]the [36]lazy [41]dog" QTest::newRow("select all") << standard.at(0) << QKeySequence(QKeySequence::SelectAll) << 0 << 0 - << 44 << standard.at(0) << standard.at(0); + << 44 << standard.at(0) << standard.at(0) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select start of line") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfLine) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select start of block") + << standard.at(0) << QKeySequence(QKeySequence::SelectStartOfBlock) << 5 << 5 + << 0 << standard.at(0) << standard.at(0).mid(0, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of line") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfLine) << 5 << 5 - << 44 << standard.at(0) << standard.at(0).mid(5); + << 44 << standard.at(0) << standard.at(0).mid(5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of document") // ### Not handled. << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfDocument) << 3 << 3 - << 3 << standard.at(0) << QString(); + << 3 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select end of block") << standard.at(0) << QKeySequence(QKeySequence::SelectEndOfBlock) << 18 << 18 - << 44 << standard.at(0) << standard.at(0).mid(18); + << 44 << standard.at(0) << standard.at(0).mid(18) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete end of line") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfLine) << 24 << 24 - << 24 << standard.at(0).mid(0, 24) << QString(); + << 24 << standard.at(0).mid(0, 24) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to start of line") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfLine) << 31 << 31 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to start of block") << standard.at(0) << QKeySequence(QKeySequence::MoveToStartOfBlock) << 25 << 25 - << 0 << standard.at(0) << QString(); + << 0 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("move to next char") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextChar) << 12 << 12 - << 13 << standard.at(0) << QString(); - QTest::newRow("move to previous char") + << 13 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 + << 2 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 3 - << 2 << standard.at(0) << QString(); - QTest::newRow("select next char") + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to previous char with selection") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousChar) << 3 << 7 + << 3 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select next char (ltr)") << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 - << 24 << standard.at(0) << standard.at(0).mid(23, 1); - QTest::newRow("select previous char") + << 24 << standard.at(0) << standard.at(0).mid(23, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select next char (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextChar) << 23 << 23 + << 22 << standard.at(0) << standard.at(0).mid(22, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("select previous char (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 + << 18 << standard.at(0) << standard.at(0).mid(18, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("select previous char (rtl)") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousChar) << 19 << 19 - << 18 << standard.at(0) << standard.at(0).mid(18, 1); - QTest::newRow("move to next word") + << 20 << standard.at(0) << standard.at(0).mid(19, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to next word (ltr)") << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 - << 10 << standard.at(0) << QString(); - QTest::newRow("move to previous word") + << 10 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to next word (rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to next word (password,ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 44 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_L; + QTest::newRow("move to next word (password,rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToNextWord) << 7 << 7 + << 0 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_R; + QTest::newRow("move to previous word (ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 4 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; + QTest::newRow("move to previous word (rlt)") << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 - << 4 << standard.at(0) << QString(); + << 10 << standard.at(0) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_R; + QTest::newRow("move to previous word (password,ltr)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 0 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_L; + QTest::newRow("move to previous word (password,rtl)") + << standard.at(0) << QKeySequence(QKeySequence::MoveToPreviousWord) << 7 << 7 + << 44 << standard.at(0) << QString() + << QQuickTextInput::Password << Qt::Key_Direction_R; + QTest::newRow("select next word") + << standard.at(0) << QKeySequence(QKeySequence::SelectNextWord) << 11 << 11 + << 16 << standard.at(0) << standard.at(0).mid(11, 5) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("select previous word") << standard.at(0) << QKeySequence(QKeySequence::SelectPreviousWord) << 11 << 11 - << 10 << standard.at(0) << standard.at(0).mid(10, 1); + << 10 << standard.at(0) << standard.at(0).mid(10, 1) + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete (selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 12 << 15 - << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString(); + << 12 << (standard.at(0).mid(0, 12) + standard.at(0).mid(15)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete (no selection)") << standard.at(0) << QKeySequence(QKeySequence::Delete) << 15 << 15 - << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString(); + << 15 << (standard.at(0).mid(0, 15) + standard.at(0).mid(16)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete end of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteEndOfWord) << 24 << 24 - << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString(); + << 24 << (standard.at(0).mid(0, 24) + standard.at(0).mid(27)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; QTest::newRow("delete start of word") << standard.at(0) << QKeySequence(QKeySequence::DeleteStartOfWord) << 7 << 7 - << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString(); + << 4 << (standard.at(0).mid(0, 4) + standard.at(0).mid(7)) << QString() + << QQuickTextInput::Normal << Qt::Key_Direction_L; } void tst_qquicktextinput::keySequence() @@ -4152,6 +4412,8 @@ void tst_qquicktextinput::keySequence() QFETCH(int, cursorPosition); QFETCH(QString, expectedText); QFETCH(QString, selectedText); + QFETCH(QQuickTextInput::EchoMode, echoMode); + QFETCH(Qt::Key, layoutDirection); if (sequence.isEmpty()) { QSKIP("Key sequence is undefined"); @@ -4162,6 +4424,7 @@ void tst_qquicktextinput::keySequence() textInputComponent.setData(componentStr.toLatin1(), QUrl()); QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); QVERIFY(textInput != 0); + textInput->setEchoMode(echoMode); QQuickCanvas canvas; textInput->setParentItem(canvas.rootItem()); @@ -4170,6 +4433,8 @@ void tst_qquicktextinput::keySequence() QTest::qWaitForWindowShown(&canvas); QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + simulateKey(&canvas, layoutDirection); + textInput->select(selectionStart, selectionEnd); simulateKeys(&canvas, sequence); @@ -4507,9 +4772,6 @@ void tst_qquicktextinput::undo_keypressevents_data() << Qt::Key_Delete << QKeySequence::Undo << Qt::Key_Right -#ifdef Q_OS_WIN //Mac(?) has a specialcase to handle jumping to the end of a selection - << Qt::Key_Left -#endif << (Qt::Key_Right | Qt::ShiftModifier) << (Qt::Key_Right | Qt::ShiftModifier) << Qt::Key_Delete; @@ -4586,6 +4848,19 @@ void tst_qquicktextinput::undo_keypressevents_data() expectedString << "123"; QTest::newRow("Inserts,moving,selection and overwriting") << keys << expectedString; + } { + KeyList keys; + QStringList expectedString; + + // inserting '123' + keys << "123" + << QKeySequence::Undo + << QKeySequence::Redo; + + expectedString << "123"; + expectedString << QString(); + + QTest::newRow("Insert,undo,redo") << keys << expectedString; } } @@ -4683,6 +4958,58 @@ void tst_qquicktextinput::QTBUG_19956_regexp() QVERIFY(canvas.rootObject()->property("acceptableInput").toBool()); } +void tst_qquicktextinput::implicitSize_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextInput.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextInput.Wrap"; +} + +void tst_qquicktextinput::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + +void tst_qquicktextinput::implicitSizeBinding_data() +{ + implicitSize_data(); +} + +void tst_qquicktextinput::implicitSizeBinding() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QScopedPointer<QObject> object(textComponent.create()); + QQuickTextInput *textObject = qobject_cast<QQuickTextInput *>(object.data()); + + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetWidth(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); + + textObject->resetHeight(); + QCOMPARE(textObject->width(), textObject->implicitWidth()); + QCOMPARE(textObject->height(), textObject->implicitHeight()); +} + void tst_qquicktextinput::negativeDimensions() { @@ -4696,6 +5023,482 @@ void tst_qquicktextinput::negativeDimensions() QCOMPARE(input->height(), qreal(-1)); } + +void tst_qquicktextinput::setInputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<QString>("expectedDisplay"); + QTest::addColumn<bool>("insert_text"); + + // both keyboard and insert() + for (int i=0; i<2; i++) { + bool insert_text = i==0 ? false : true; + QString insert_mode = "keys "; + if (insert_text) + insert_mode = "insert "; + + QTest::newRow(QString(insert_mode + "ip_localhost").toLatin1()) + << QString("000.000.000.000") + << QString("127.0.0.1") + << QString("127.0.0.1") + << QString("127.0 .0 .1 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "mac").toLatin1()) + << QString("HH:HH:HH:HH:HH:HH;#") + << QString("00:E0:81:21:9E:8E") + << QString("00:E0:81:21:9E:8E") + << QString("00:E0:81:21:9E:8E") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "mac2").toLatin1()) + << QString("<HH:>HH:!HH:HH:HH:HH;#") + << QString("AAe081219E8E") + << QString("aa:E0:81:21:9E:8E") + << QString("aa:E0:81:21:9E:8E") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "byte").toLatin1()) + << QString("BBBBBBBB;0") + << QString("11011001") + << QString("11111") + << QString("11011001") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "halfbytes").toLatin1()) + << QString("bbbb.bbbb;-") + << QString("110. 0001") + << QString("110.0001") + << QString("110-.0001") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "blank char same type as content").toLatin1()) + << QString("000.000.000.000;0") + << QString("127.0.0.1") + << QString("127...1") + << QString("127.000.000.100") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "parts of ip_localhost").toLatin1()) + << QString("000.000.000.000") + << QString(".0.0.1") + << QString(".0.0.1") + << QString(" .0 .0 .1 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_null").toLatin1()) + << QString("000.000.000.000") + << QString() + << QString("...") + << QString(" . . . ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_null_hash").toLatin1()) + << QString("000.000.000.000;#") + << QString() + << QString("...") + << QString("###.###.###.###") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "ip_overflow").toLatin1()) + << QString("000.000.000.000") + << QString("1234123412341234") + << QString("123.412.341.234") + << QString("123.412.341.234") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "uppercase").toLatin1()) + << QString(">AAAA") + << QString("AbCd") + << QString("ABCD") + << QString("ABCD") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "lowercase").toLatin1()) + << QString("<AAAA") + << QString("AbCd") + << QString("abcd") + << QString("abcd") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "nocase").toLatin1()) + << QString("!AAAA") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "nocase1").toLatin1()) + << QString("!A!A!A!A") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "nocase2").toLatin1()) + << QString("AAAA") + << QString("AbCd") + << QString("AbCd") + << QString("AbCd") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "reserved").toLatin1()) + << QString("{n}[0]") + << QString("A9") + << QString("A9") + << QString("A9") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape01").toLatin1()) + << QString("\\\\N\\\\n00") + << QString("9") + << QString("Nn9") + << QString("Nn9 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape02").toLatin1()) + << QString("\\\\\\\\00") + << QString("0") + << QString("\\0") + << QString("\\0 ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "escape03").toLatin1()) + << QString("\\\\(00\\\\)") + << QString("0") + << QString("(0)") + << QString("(0 )") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "upper_lower_nocase1").toLatin1()) + << QString(">AAAA<AAAA!AAAA") + << QString("AbCdEfGhIjKl") + << QString("ABCDefghIjKl") + << QString("ABCDefghIjKl") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "upper_lower_nocase2").toLatin1()) + << QString(">aaaa<aaaa!aaaa") + << QString("AbCdEfGhIjKl") + << QString("ABCDefghIjKl") + << QString("ABCDefghIjKl") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "exact_case1").toLatin1()) + << QString(">A<A<A>A>A<A!A!A") + << QString("AbCdEFGH") + << QString("AbcDEfGH") + << QString("AbcDEfGH") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case2").toLatin1()) + << QString(">A<A<A>A>A<A!A!A") + << QString("aBcDefgh") + << QString("AbcDEfgh") + << QString("AbcDEfgh") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case3").toLatin1()) + << QString(">a<a<a>a>a<a!a!a") + << QString("AbCdEFGH") + << QString("AbcDEfGH") + << QString("AbcDEfGH") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case4").toLatin1()) + << QString(">a<a<a>a>a<a!a!a") + << QString("aBcDefgh") + << QString("AbcDEfgh") + << QString("AbcDEfgh") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case5").toLatin1()) + << QString(">H<H<H>H>H<H!H!H") + << QString("aBcDef01") + << QString("AbcDEf01") + << QString("AbcDEf01") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "exact_case6").toLatin1()) + << QString(">h<h<h>h>h<h!h!h") + << QString("aBcDef92") + << QString("AbcDEf92") + << QString("AbcDEf92") + << bool(insert_text); + + QTest::newRow(QString(insert_mode + "illegal_keys1").toLatin1()) + << QString("AAAAAAAA") + << QString("A2#a;.0!") + << QString("Aa") + << QString("Aa ") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "illegal_keys2").toLatin1()) + << QString("AAAA") + << QString("f4f4f4f4") + << QString("ffff") + << QString("ffff") + << bool(insert_text); + QTest::newRow(QString(insert_mode + "blank=input").toLatin1()) + << QString("9999;0") + << QString("2004") + << QString("2004") + << QString("2004") + << bool(insert_text); + } +} + +void tst_qquicktextinput::setInputMask() +{ + QFETCH(QString, mask); + QFETCH(QString, input); + QFETCH(QString, expectedText); + QFETCH(QString, expectedDisplay); + QFETCH(bool, insert_text); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + // then either insert using insert() or keyboard + if (insert_text) { + textInput->insert(0, input); + } else { + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + simulateKey(&canvas, Qt::Key_Home); + for (int i = 0; i < input.length(); i++) + QTest::keyClick(&canvas, input.at(i).toLatin1()); + } + + QEXPECT_FAIL( "keys blank=input", "To eat blanks or not? Known issue. Task 43172", Abort); + QEXPECT_FAIL( "insert blank=input", "To eat blanks or not? Known issue. Task 43172", Abort); + + QCOMPARE(textInput->text(), expectedText); + QCOMPARE(textInput->displayText(), expectedDisplay); +} + +void tst_qquicktextinput::inputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("expectedMask"); + + // if no mask is set a nul string should be returned + QTest::newRow("nul 1") << QString("") << QString(); + QTest::newRow("nul 2") << QString() << QString(); + + // try different masks + QTest::newRow("mask 1") << QString("000.000.000.000") << QString("000.000.000.000; "); + QTest::newRow("mask 2") << QString("000.000.000.000;#") << QString("000.000.000.000;#"); + QTest::newRow("mask 3") << QString("AAA.aa.999.###;") << QString("AAA.aa.999.###; "); + QTest::newRow("mask 4") << QString(">abcdef<GHIJK") << QString(">abcdef<GHIJK; "); + + // set an invalid input mask... + // the current behaviour is that this exact (faulty) string is returned. + QTest::newRow("invalid") << QString("ABCDEFGHIKLMNOP;") << QString("ABCDEFGHIKLMNOP; "); + + // verify that we can unset the mask again + QTest::newRow("unset") << QString("") << QString(); +} + +void tst_qquicktextinput::inputMask() +{ + QFETCH(QString, mask); + QFETCH(QString, expectedMask); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QCOMPARE(textInput->inputMask(), expectedMask); +} + +void tst_qquicktextinput::clearInputMask() +{ + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"000.000.000.000\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QVERIFY(textInput->inputMask() != QString()); + textInput->setInputMask(QString()); + QCOMPARE(textInput->inputMask(), QString()); +} + +void tst_qquicktextinput::keypress_inputMask_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<KeyList>("keys"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<QString>("expectedDisplayText"); + + { + KeyList keys; + // inserting 'A1.2B' + keys << Qt::Key_Home << "A1.2B"; + QTest::newRow("jumping on period(separator)") << QString("000.000;_") << keys << QString("1.2") << QString("1__.2__"); + } + { + KeyList keys; + // inserting '0!P3' + keys << Qt::Key_Home << "0!P3"; + QTest::newRow("jumping on input") << QString("D0.AA.XX.AA.00;_") << keys << QString("0..!P..3") << QString("_0.__.!P.__.3_"); + } + { + KeyList keys; + // pressing delete + keys << Qt::Key_Home + << Qt::Key_Delete; + QTest::newRow("delete") << QString("000.000;_") << keys << QString(".") << QString("___.___"); + } + { + KeyList keys; + // selecting all and delete + keys << Qt::Key_Home + << Key(Qt::ShiftModifier, Qt::Key_End) + << Qt::Key_Delete; + QTest::newRow("deleting all") << QString("000.000;_") << keys << QString(".") << QString("___.___"); + } + { + KeyList keys; + // inserting '12.12' then two backspaces + keys << Qt::Key_Home << "12.12" << Qt::Key_Backspace << Qt::Key_Backspace; + QTest::newRow("backspace") << QString("000.000;_") << keys << QString("12.") << QString("12_.___"); + } + { + KeyList keys; + // inserting '12ab' + keys << Qt::Key_Home << "12ab"; + QTest::newRow("uppercase") << QString("9999 >AA;_") << keys << QString("12 AB") << QString("12__ AB"); + } +} + +void tst_qquicktextinput::keypress_inputMask() +{ + QFETCH(QString, mask); + QFETCH(KeyList, keys); + QFETCH(QString, expectedText); + QFETCH(QString, expectedDisplayText); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + simulateKeys(&canvas, keys); + + QCOMPARE(textInput->text(), expectedText); + QCOMPARE(textInput->displayText(), expectedDisplayText); +} + + +void tst_qquicktextinput::hasAcceptableInputMask_data() +{ + QTest::addColumn<QString>("optionalMask"); + QTest::addColumn<QString>("requiredMask"); + QTest::addColumn<QString>("invalid"); + QTest::addColumn<QString>("valid"); + + QTest::newRow("Alphabetic optional and required") + << QString("aaaa") << QString("AAAA") << QString("ab") << QString("abcd"); + QTest::newRow("Alphanumeric optional and require") + << QString("nnnn") << QString("NNNN") << QString("R2") << QString("R2D2"); + QTest::newRow("Any optional and required") + << QString("xxxx") << QString("XXXX") << QString("+-") << QString("+-*/"); + QTest::newRow("Numeric (0-9) required") + << QString("0000") << QString("9999") << QString("11") << QString("1138"); + QTest::newRow("Numeric (1-9) optional and required") + << QString("dddd") << QString("DDDD") << QString("12") << QString("1234"); +} + +void tst_qquicktextinput::hasAcceptableInputMask() +{ + QFETCH(QString, optionalMask); + QFETCH(QString, requiredMask); + QFETCH(QString, invalid); + QFETCH(QString, valid); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + optionalMask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + // test that invalid input (for required) work for optionalMask + 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()); + + textInput->setText(valid); + QVERIFY(textInput->hasAcceptableInput()); +} + +void tst_qquicktextinput::maskCharacter_data() +{ + QTest::addColumn<QString>("mask"); + QTest::addColumn<QString>("input"); + QTest::addColumn<bool>("expectedValid"); + + QTest::newRow("Hex") << QString("H") + << QString("0123456789abcdefABCDEF") << true; + QTest::newRow("hex") << QString("h") + << QString("0123456789abcdefABCDEF") << true; + QTest::newRow("HexInvalid") << QString("H") + << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ") + << false; + QTest::newRow("hexInvalid") << QString("h") + << QString("ghijklmnopqrstuvwxyzGHIJKLMNOPQRSTUVWXYZ") + << false; + QTest::newRow("Bin") << QString("B") + << QString("01") << true; + QTest::newRow("bin") << QString("b") + << QString("01") << true; + QTest::newRow("BinInvalid") << QString("B") + << QString("23456789qwertyuiopasdfghjklzxcvbnm") + << false; + QTest::newRow("binInvalid") << QString("b") + << QString("23456789qwertyuiopasdfghjklzxcvbnm") + << false; +} + +void tst_qquicktextinput::maskCharacter() +{ + QFETCH(QString, mask); + QFETCH(QString, input); + QFETCH(bool, expectedValid); + + QString componentStr = "import QtQuick 2.0\nTextInput { focus: true; inputMask: \"" + mask + "\" }"; + QQmlComponent textInputComponent(&engine); + textInputComponent.setData(componentStr.toLatin1(), QUrl()); + QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create()); + QVERIFY(textInput != 0); + + QQuickCanvas canvas; + textInput->setParentItem(canvas.rootItem()); + canvas.show(); + canvas.requestActivateWindow(); + QTest::qWaitForWindowShown(&canvas); + QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas); + + for (int i = 0; i < input.size(); ++i) { + QString in = QString(input.at(i)); + QString expected = expectedValid ? in : QString(); + textInput->setText(QString(input.at(i))); + QCOMPARE(textInput->text(), expected); + } +} + QTEST_MAIN(tst_qquicktextinput) #include "tst_qquicktextinput.moc" |