aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick')
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp99
-rw-r--r--tests/auto/quick/qquickboundaryrule/data/dragHandler.qml1
-rw-r--r--tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro2
-rw-r--r--tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp24
-rw-r--r--tests/auto/quick/qquickflickable/data/resize.qml1
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp7
-rw-r--r--tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml47
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml77
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp100
-rw-r--r--tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml8
-rw-r--r--tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml20
-rw-r--r--tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml20
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp10
-rw-r--r--tests/auto/quick/qquickmousearea/data/dragreset.qml1
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp6
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml59
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml64
-rw-r--r--tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml53
-rw-r--r--tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml52
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp37
-rw-r--r--tests/auto/quick/qquickpositioners/data/transitions-padding.qml10
-rw-r--r--tests/auto/quick/qquickpositioners/data/transitions.qml10
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp63
-rw-r--r--tests/auto/quick/qquickrepeater/data/objlist_required.qml23
-rw-r--r--tests/auto/quick/qquickrepeater/data/requiredProperty.qml16
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp25
-rw-r--r--tests/auto/quick/qquicktableview/data/delegateWithRequired.qml70
-rw-r--r--tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml71
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp45
29 files changed, 969 insertions, 52 deletions
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 66314f88a2..65c5ac9ef4 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -53,9 +53,12 @@ private slots:
void initTestCase();
void defaultPropertyValues();
+ void touchDrag_data();
void touchDrag();
void mouseDrag_data();
void mouseDrag();
+ void mouseDragThreshold_data();
+ void mouseDragThreshold();
void dragFromMargin();
void snapMode_data();
void snapMode();
@@ -131,9 +134,18 @@ void tst_DragHandler::defaultPropertyValues()
QCOMPARE(dragHandler->centroid().sceneGrabPosition(), QPointF());
}
+void tst_DragHandler::touchDrag_data()
+{
+ QTest::addColumn<int>("dragThreshold");
+ QTest::newRow("threshold zero") << 0;
+ QTest::newRow("threshold one") << 1;
+ QTest::newRow("threshold 20") << 20;
+ QTest::newRow("threshold default") << -1;
+}
+
void tst_DragHandler::touchDrag()
{
- const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QFETCH(int, dragThreshold);
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "draggables.qml");
QQuickView * window = windowPtr.data();
@@ -142,6 +154,12 @@ void tst_DragHandler::touchDrag()
QVERIFY(ball);
QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler);
+ if (dragThreshold < 0) {
+ dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QCOMPARE(dragHandler->dragThreshold(), dragThreshold);
+ } else {
+ dragHandler->setDragThreshold(dragThreshold);
+ }
QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
@@ -161,7 +179,9 @@ void tst_DragHandler::touchDrag()
p1 += QPoint(dragThreshold, 0);
QTest::touchEvent(window, touchDevice).move(1, p1, window);
QQuickTouchUtils::flush(window);
- QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ qCDebug(lcPointerTests) << "velocity after drag" << dragHandler->centroid().velocity();
+ if (dragThreshold > 0)
+ QTRY_VERIFY(!qFuzzyIsNull(dragHandler->centroid().velocity().x()));
QCOMPARE(centroidChangedSpy.count(), 2);
QVERIFY(!dragHandler->active());
p1 += QPoint(1, 0);
@@ -282,6 +302,81 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0);
}
+void tst_DragHandler::mouseDragThreshold_data()
+{
+ QTest::addColumn<int>("dragThreshold");
+ QTest::newRow("threshold zero") << 0;
+ QTest::newRow("threshold one") << 1;
+ QTest::newRow("threshold 20") << 20;
+ QTest::newRow("threshold default") << -1;
+}
+
+void tst_DragHandler::mouseDragThreshold()
+{
+ QFETCH(int, dragThreshold);
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "draggables.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *ball = window->rootObject()->childItems().first();
+ QVERIFY(ball);
+ QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+ if (dragThreshold < 0) {
+ dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QCOMPARE(dragHandler->dragThreshold(), dragThreshold);
+ } else {
+ dragHandler->setDragThreshold(dragThreshold);
+ }
+
+ QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
+ QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
+
+ QPointF ballCenter = ball->clipRect().center();
+ QPointF scenePressPos = ball->mapToScene(ballCenter);
+ QPoint p1 = scenePressPos.toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(centroidChangedSpy.count(), 1);
+ p1 += QPoint(dragThreshold, 0);
+ QTest::mouseMove(window, p1);
+ if (dragThreshold > 0)
+ QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(!dragHandler->active());
+ p1 += QPoint(1, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(translationChangedSpy.count(), 0);
+ QCOMPARE(centroidChangedSpy.count(), 3);
+ QCOMPARE(dragHandler->translation().x(), 0.0);
+ QPointF sceneGrabPos = p1;
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ p1 += QPoint(19, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 4);
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
+ QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
+ QCOMPARE(translationChangedSpy.count(), 1);
+ QCOMPARE(centroidChangedSpy.count(), 5);
+}
+
void tst_DragHandler::dragFromMargin() // QTBUG-74966
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
diff --git a/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml b/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
index c66fd76ff1..769a5b2c7d 100644
--- a/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
+++ b/tests/auto/quick/qquickboundaryrule/data/dragHandler.qml
@@ -14,6 +14,7 @@ Rectangle {
}
BoundaryRule on x {
+ objectName: "boundaryRule"
id: xbr
minimum: -50
maximum: 100
diff --git a/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro b/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
index ef43f4526a..c41f798d33 100644
--- a/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
+++ b/tests/auto/quick/qquickboundaryrule/qquickboundaryrule.pro
@@ -9,4 +9,4 @@ include (../shared/util.pri)
TESTDATA = data/*
-QT += core-private gui-private qml-private quick-private testlib
+QT += quick-private qml testlib
diff --git a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
index 44f1c9a2f9..75639dba49 100644
--- a/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
+++ b/tests/auto/quick/qquickboundaryrule/tst_qquickboundaryrule.cpp
@@ -30,7 +30,6 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/qquickview.h>
-#include <QtQuick/private/qquickboundaryrule_p.h>
#include <QtQuick/private/qquickdraghandler_p.h>
#include "../../shared/util.h"
#include "../shared/viewtestutil.h"
@@ -57,7 +56,7 @@ void tst_qquickboundaryrule::dragHandler()
QVERIFY(target);
QQuickDragHandler *dragHandler = target->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler);
- QQuickBoundaryRule *boundaryRule = target->findChild<QQuickBoundaryRule*>();
+ QObject *boundaryRule = target->findChild<QObject *>(QLatin1String("boundaryRule"));
QVERIFY(boundaryRule);
QSignalSpy overshootChangedSpy(boundaryRule, SIGNAL(currentOvershootChanged()));
@@ -68,29 +67,34 @@ void tst_qquickboundaryrule::dragHandler()
QTest::mouseMove(&window, p1);
QTRY_VERIFY(dragHandler->active());
QCOMPARE(target->position().x(), 100);
- QCOMPARE(boundaryRule->currentOvershoot(), 0);
- QCOMPARE(boundaryRule->peakOvershoot(), 0);
+ bool ok = false;
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
QCOMPARE(overshootChangedSpy.count(), 0);
// restricted drag: halfway into overshoot
p1 += QPoint(20, 0);
QTest::mouseMove(&window, p1);
QCOMPARE(target->position().x(), 117.5);
- QCOMPARE(boundaryRule->currentOvershoot(), 20);
- QCOMPARE(boundaryRule->peakOvershoot(), 20);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(), 20);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(), 20);
QCOMPARE(overshootChangedSpy.count(), 1);
// restricted drag: maximum overshoot
p1 += QPoint(80, 0);
QTest::mouseMove(&window, p1);
QCOMPARE(target->position().x(), 140);
- QCOMPARE(boundaryRule->currentOvershoot(), 100);
- QCOMPARE(boundaryRule->peakOvershoot(), 100);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(), 100);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(), 100);
QCOMPARE(overshootChangedSpy.count(), 2);
// release and let it return to bounds
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_COMPARE(dragHandler->active(), false);
QTRY_COMPARE(overshootChangedSpy.count(), 3);
- QCOMPARE(boundaryRule->currentOvershoot(), 0);
- QCOMPARE(boundaryRule->peakOvershoot(), 0);
+ QCOMPARE(boundaryRule->property("currentOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
+ QCOMPARE(boundaryRule->property("peakOvershoot").toReal(&ok), 0);
+ QVERIFY(ok);
QCOMPARE(target->position().x(), 100);
}
diff --git a/tests/auto/quick/qquickflickable/data/resize.qml b/tests/auto/quick/qquickflickable/data/resize.qml
index 2f7ae7b8bb..131691d012 100644
--- a/tests/auto/quick/qquickflickable/data/resize.qml
+++ b/tests/auto/quick/qquickflickable/data/resize.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Rectangle {
+ required property bool setRebound
function resizeContent() {
flick.resizeContent(600, 600, Qt.point(100, 100))
}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index c104eecbcd..5364530ca8 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -226,7 +226,7 @@ void tst_qquickflickable::create()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("flickable01.qml"));
- QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.create());
+ QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(c.createWithInitialProperties({{"setRebound", false}}));
QVERIFY(obj != nullptr);
QCOMPARE(obj->isAtXBeginning(), true);
@@ -782,9 +782,8 @@ void tst_qquickflickable::flickableDirection()
void tst_qquickflickable::resizeContent()
{
QQmlEngine engine;
- engine.rootContext()->setContextProperty("setRebound", QVariant::fromValue(false));
QQmlComponent c(&engine, testFileUrl("resize.qml"));
- QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.createWithInitialProperties({{"setRebound", false}}));
QQuickFlickable *obj = findItem<QQuickFlickable>(root, "flick");
QVERIFY(obj != nullptr);
@@ -816,7 +815,7 @@ void tst_qquickflickable::returnToBounds()
QScopedPointer<QQuickView> window(new QQuickView);
- window->rootContext()->setContextProperty("setRebound", setRebound);
+ window->setInitialProperties({{"setRebound", setRebound}});
window->setSource(testFileUrl("resize.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowActive(window.data()));
diff --git a/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml b/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml
new file mode 100644
index 0000000000..f354517678
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/delegatesWithRequiredProperties.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.12
+import Qt.fruit 1.0
+
+Rectangle {
+ id: root
+ required property bool useCpp
+ width: 200; height: 200
+
+
+ ListModel {
+ id: fruitModel
+
+ ListElement {
+ name: "Apple"
+ cost: 2
+ }
+ ListElement {
+ name: "Orange"
+ cost: 3
+ }
+ ListElement {
+ name: "Banana"
+ cost: 1
+ }
+ }
+
+
+ Component {
+ id: fruitDelegate
+ Row {
+ id: row
+ spacing: 10
+ required property string name
+ required property int cost
+ Text { text: row.name }
+ Text { text: '$' + row.cost }
+ Component.onCompleted: () => { console.debug(row.name+row.cost) };
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: root.useCpp ? FruitModelCpp : fruitModel
+ delegate: fruitDelegate
+ }
+
+}
diff --git a/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml b/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml
new file mode 100644
index 0000000000..18ce406e3f
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/listview-sections_delegate_required.qml
@@ -0,0 +1,77 @@
+import QtQuick 2.0
+
+Rectangle {
+ property string sectionProperty: "number"
+ property int sectionPositioning: ViewSection.InlineLabels
+ width: 240
+ height: 320
+ color: "#ffffff"
+ resources: [
+ Component {
+ id: myDelegate
+ Item {
+ id: wrapper
+ objectName: "wrapper"
+ property string section: ListView.section
+ property string nextSection: ListView.nextSection
+ property string prevSection: ListView.previousSection
+ height: 20;
+ width: 240
+ Rectangle {
+ height: 20
+ width: parent.width
+ color: wrapper.ListView.isCurrentItem ? "lightsteelblue" : "white"
+ Text {
+ text: index
+ }
+ Text {
+ x: 30
+ id: textName
+ objectName: "textName"
+ text: name
+ }
+ Text {
+ x: 100
+ id: textNumber
+ objectName: "textNumber"
+ text: number
+ }
+ Text {
+ objectName: "nextSection"
+ x: 150
+ text: wrapper.ListView.nextSection
+ }
+ Text {
+ x: 200
+ text: wrapper.y
+ }
+ }
+ ListView.onRemove: SequentialAnimation {
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+ NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 100; easing.type: Easing.InOutQuad }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+ ]
+ ListView {
+ id: list
+ objectName: "list"
+ width: 240
+ height: 320
+ cacheBuffer: 60
+ model: testModel
+ delegate: myDelegate
+ section.property: sectionProperty
+ section.delegate: Rectangle {
+ id: myDelegate
+ required property string section
+ objectName: "sect_" + section
+ color: "#99bb99"
+ height: 20
+ width: list.width
+ Text { text: myDelegate.section + ", " + parent.y + ", " + parent.objectName }
+ }
+ section.labelPositioning: sectionPositioning
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index ca438a9cd5..fb5ae168e8 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -127,6 +127,7 @@ private slots:
void qAbstractItemModel_package_sections();
void qAbstractItemModel_sections();
void sectionsPositioning();
+ void sectionsDelegate_data();
void sectionsDelegate();
void sectionsDragOutsideBounds_data();
void sectionsDragOutsideBounds();
@@ -280,6 +281,8 @@ private slots:
void touchCancel();
void resizeAfterComponentComplete();
+ void delegateWithRequiredProperties();
+
private:
template <class T> void items(const QUrl &source);
template <class T> void changed(const QUrl &source);
@@ -389,7 +392,7 @@ void tst_QQuickListView::init()
m_view = nullptr;
}
#endif
- qmlRegisterType<QAbstractItemModel>();
+ qmlRegisterAnonymousType<QAbstractItemModel>("Proxy", 1);
qmlRegisterType<ProxyTestInnerModel>("Proxy", 1, 0, "ProxyTestInnerModel");
qmlRegisterType<QSortFilterProxyModel>("Proxy", 1, 0, "QSortFilterProxyModel");
}
@@ -2183,8 +2186,17 @@ void tst_QQuickListView::sections(const QUrl &source)
QTRY_COMPARE(item->height(), 40.0);
}
+void tst_QQuickListView::sectionsDelegate_data()
+{
+ QTest::addColumn<QUrl>("path");
+ QTest::addRow("implicit") << testFileUrl("listview-sections_delegate.qml");
+ QTest::addRow("required") << testFileUrl("listview-sections_delegate_required.qml");
+}
+
void tst_QQuickListView::sectionsDelegate()
{
+ QFETCH(QUrl, path);
+
QScopedPointer<QQuickView> window(createView());
QaimModel model;
@@ -2194,7 +2206,7 @@ void tst_QQuickListView::sectionsDelegate()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);
- window->setSource(testFileUrl("listview-sections_delegate.qml"));
+ window->setSource(path);
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -9062,6 +9074,90 @@ void tst_QQuickListView::resizeAfterComponentComplete() // QTBUG-76487
QTRY_COMPARE(lastItem->property("y").toInt(), 9 * lastItem->property("height").toInt());
}
+class Animal
+{
+public:
+ Animal(const int cost, const QString &name) {m_name = name; m_cost = cost;}
+
+ int cost() const {return m_cost;}
+ QString name() const {return m_name;}
+
+ QString m_name;
+ int m_cost;
+};
+
+class FruitModel : public QAbstractListModel
+{
+ Q_OBJECT
+public:
+ enum AnimalRoles {
+ NameRole = Qt::UserRole + 1,
+ CostRole
+ };
+
+ FruitModel(QObject* = nullptr) {
+ m_animals.push_back(Animal {4, QLatin1String("Melon")});
+ m_animals.push_back(Animal {5, QLatin1String("Cherry")});
+ }
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override {return m_animals.count();}
+
+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override {
+ if (!checkIndex(index))
+ return {};
+ const Animal &animal = m_animals[index.row()];
+ if (role == CostRole)
+ return animal.cost();
+ else if (role == NameRole)
+ return animal.name();
+ return QVariant();
+ }
+
+protected:
+ QHash<int, QByteArray> roleNames() const override {
+ QHash<int, QByteArray> roles;
+ roles[CostRole] = "cost";
+ roles[NameRole] = "name";
+ return roles;
+ }
+private:
+ QList<Animal> m_animals;
+};
+
+void tst_QQuickListView::delegateWithRequiredProperties()
+{
+ FruitModel myModel;
+ qmlRegisterSingletonInstance("Qt.fruit", 1, 0, "FruitModelCpp", &myModel);
+ {
+ // ListModel
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Apple2");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Orange3");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Banana1");
+ QScopedPointer<QQuickView> window(createView());
+ window->setInitialProperties({{QLatin1String("useCpp"), false}});
+ window->setSource(testFileUrl("delegatesWithRequiredProperties.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *listView = window->rootObject();
+ QVERIFY(listView);
+ }
+ {
+ // C++ model
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Melon4");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, "Cherry5");
+ QScopedPointer<QQuickView> window(createView());
+ window->setInitialProperties({{QLatin1String("useCpp"), true}});
+ window->setSource(testFileUrl("delegatesWithRequiredProperties.qml"));
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *listView = window->rootObject();
+ QVERIFY(listView);
+ }
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml b/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml
new file mode 100644
index 0000000000..7bb21e8b93
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/RequiredPropertyValuesComponent.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Item {
+ id: behaviorCounter
+ required property int i
+ required property string s
+
+}
diff --git a/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml b/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml
new file mode 100644
index 0000000000..4728346ca1
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/initialPropertyValues.10.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property int i: 0
+ property string s: ""
+
+ Loader {
+ id: loader
+ objectName: "loader"
+ onLoaded: {
+ root.i = loader.item.i; // should be 42
+ root.s = loader.item.s; // should be 11
+ }
+ }
+
+ Component.onCompleted: {
+ loader.setSource("RequiredPropertyValuesComponent.qml", {"i": 42});
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml b/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml
new file mode 100644
index 0000000000..5d6e3171a0
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/initialPropertyValues.9.qml
@@ -0,0 +1,20 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property int i: 0
+ property string s: ""
+
+ Loader {
+ id: loader
+ objectName: "loader"
+ onLoaded: {
+ root.i = loader.item.i; // should be 42
+ root.s = loader.item.s; // should be 11
+ }
+ }
+
+ Component.onCompleted: {
+ loader.setSource("RequiredPropertyValuesComponent.qml", {"i": 42, "s": "hello world"});
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index fbdd87905b..da923d4d41 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -681,6 +681,16 @@ void tst_QQuickLoader::initialPropertyValues_data()
<< QStringList()
<< (QStringList() << "initialValue")
<< (QVariantList() << 6);
+
+ QTest::newRow("ensure required properties are set correctly") << testFileUrl("initialPropertyValues.9.qml")
+ << QStringList()
+ << (QStringList() << "i" << "s")
+ << (QVariantList() << 42 << QLatin1String("hello world"));
+
+ QTest::newRow("required properties only partially set =") << testFileUrl("initialPropertyValues.10.qml")
+ << (QStringList() << QString(testFileUrl("RequiredPropertyValuesComponent.qml").toString() + QLatin1String(":6:5: Required property s was not initialized")))
+ << (QStringList() << "i" << "s")
+ << (QVariantList() << 0 << QLatin1String(""));
}
void tst_QQuickLoader::initialPropertyValues()
diff --git a/tests/auto/quick/qquickmousearea/data/dragreset.qml b/tests/auto/quick/qquickmousearea/data/dragreset.qml
index 10039f1fcb..bbe0160080 100644
--- a/tests/auto/quick/qquickmousearea/data/dragreset.qml
+++ b/tests/auto/quick/qquickmousearea/data/dragreset.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Rectangle {
id: whiteRect
+ required property bool haveTarget
width: 200
height: 200
color: "white"
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 17553ee6c4..54a29dbc7f 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -307,7 +307,7 @@ void tst_QQuickMouseArea::resetDrag()
{
QQuickView window;
QByteArray errorMessage;
- window.rootContext()->setContextProperty("haveTarget", QVariant(true));
+ window.setInitialProperties({{"haveTarget", true}});
QVERIFY2(QQuickTest::initView(window, testFileUrl("dragreset.qml"), true, &errorMessage), errorMessage.constData());
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
@@ -326,7 +326,9 @@ void tst_QQuickMouseArea::resetDrag()
QVERIFY(rootItem != nullptr);
QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
QVERIFY(drag->target() != nullptr);
- window.rootContext()->setContextProperty("haveTarget", QVariant(false));
+ auto root = window.rootObject();
+ QQmlProperty haveTarget {root, "haveTarget"};
+ haveTarget.write(false);
QCOMPARE(targetSpy.count(),1);
QVERIFY(!drag->target());
}
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml
new file mode 100644
index 0000000000..ae8ca784bc
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.2.qml
@@ -0,0 +1,59 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ width: 800
+ height: 600
+ property bool working: false
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ height: 50
+ width: 50
+ required property string name
+ required property int index
+ onNameChanged: () => {if (myDelegate.name === "You-know-who") root.working = true}
+ Text {
+ text: myDelegate.name
+ font.pointSize: 10
+ anchors.fill: myDelegate
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 80; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 140; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+ Timer {
+ interval: 1
+ running: true
+ repeat: false
+ onTriggered: () => { myModel.setProperty(1, "name", "You-know-who"); }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml
new file mode 100644
index 0000000000..2996ba18fd
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.3.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.14
+
+Item {
+ id: root
+ width: 800
+ height: 600
+ property bool working: false
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ height: 50
+ width: 50
+ required property string name
+ required property int index
+ onNameChanged: () => {if (myDelegate.name === "You-know-who") root.working = false}
+ Text {
+ text: myDelegate.name
+ font.pointSize: 10
+ anchors.fill: myDelegate
+ }
+ Component.onCompleted: () => {myDelegate.name = "break binding"}
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 80; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 140; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+ Timer {
+ interval: 1
+ running: true
+ repeat: false
+ onTriggered: () => {
+ myModel.setProperty(1, "name", "You-know-who")
+ myModel.setProperty(2, "name", "You-know-who")
+ root.working = true
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml
new file mode 100644
index 0000000000..5d721fd0c4
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegateWithRequiredProperties.qml
@@ -0,0 +1,53 @@
+import QtQuick 2.14
+
+Item {
+ width: 400
+ height: 200
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ required property int index
+ required property string name
+ required property string place
+ height: 100
+ width: 100
+ Text {
+ text: myDelegate.name + " lives in " + myDelegate.place + myDelegate.index
+ font.pointSize: 16
+ anchors.fill: myDelegate
+
+ Component.onCompleted: () => {console.info(myDelegate.name+myDelegate.place+myDelegate.index)}
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml b/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml
new file mode 100644
index 0000000000..bf130a2d73
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/delegatewithUnrelatedRequiredPreventsAccessToModel.qml
@@ -0,0 +1,52 @@
+import QtQuick 2.14
+
+Item {
+ width: 400
+ height: 200
+
+ ListModel {
+ id: myModel
+ ListElement {
+ name: "Bill Jones"
+ place: "Berlin"
+ }
+ ListElement {
+ name: "Jane Doe"
+ place: "Oslo"
+ }
+ ListElement {
+ name: "John Smith"
+ place: "Oulo"
+ }
+ }
+
+ Component {
+ id: delegateComponent
+ Rectangle {
+ id: myDelegate
+ required property int set
+ set: 42
+ height: 100
+ width: 100
+ Text {
+ text: "Test"
+ font.pointSize: 16
+ anchors.fill: myDelegate
+
+ Component.onCompleted: () => { try {index; console.log(index); console.log(name)} catch(ex) {console.info(ex.name)} }
+ }
+ }
+ }
+
+ PathView {
+ anchors.fill: parent
+ model: myModel
+ delegate: delegateComponent
+ path: Path {
+ startX: 120; startY: 100
+ PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
+ PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 4498548d45..a8e847a5c7 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -150,6 +150,8 @@ private slots:
void movementDirection();
void removePath();
void objectModelMove();
+ void requiredPropertiesInDelegate();
+ void requiredPropertiesInDelegatePreventUnrelated();
};
class TestObject : public QObject
@@ -2724,6 +2726,41 @@ void tst_QQuickPathView::objectModelMove()
}
}
+void tst_QQuickPathView::requiredPropertiesInDelegate()
+{
+ {
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "Bill JonesBerlin0");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "Jane DoeOslo1");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "John SmithOulo2");
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegateWithRequiredProperties.qml"));
+ window->show();
+ }
+ {
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegateWithRequiredProperties.2.qml"));
+ window->show();
+ QTRY_VERIFY(window->rootObject()->property("working").toBool());
+ }
+ {
+ QScopedPointer<QQuickView> window(createView());
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression("Writing to \"name\" broke the binding to the underlying model"));
+ window->setSource(testFileUrl("delegateWithRequiredProperties.3.qml"));
+ window->show();
+ QTRY_VERIFY(window->rootObject()->property("working").toBool());
+ }
+}
+
+void tst_QQuickPathView::requiredPropertiesInDelegatePreventUnrelated()
+{
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "ReferenceError");
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegatewithUnrelatedRequiredPreventsAccessToModel.qml"));
+ window->show();
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickpositioners/data/transitions-padding.qml b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
index e3175c480c..eda9ce628e 100644
--- a/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
+++ b/tests/auto/quick/qquickpositioners/data/transitions-padding.qml
@@ -5,6 +5,16 @@ Rectangle {
width: 500
height: 500
+ required property bool usePopulateTransition
+ required property bool enableAddTransition
+ required property bool dynamicallyPopulate
+ required property var testModel
+ required property var model_targetItems_transitionFrom
+ required property var model_displacedItems_transitionVia
+ required property point targetItems_transitionFrom
+ required property point displacedItems_transitionVia
+ required property string testedPositioner
+
property int duration: 50
property real incrementalSize: 5
diff --git a/tests/auto/quick/qquickpositioners/data/transitions.qml b/tests/auto/quick/qquickpositioners/data/transitions.qml
index a1f27bb06e..988a01e373 100644
--- a/tests/auto/quick/qquickpositioners/data/transitions.qml
+++ b/tests/auto/quick/qquickpositioners/data/transitions.qml
@@ -5,6 +5,16 @@ Rectangle {
width: 500
height: 500
+ required property bool usePopulateTransition
+ required property bool enableAddTransition
+ required property bool dynamicallyPopulate
+ required property var testModel
+ required property var model_targetItems_transitionFrom
+ required property var model_displacedItems_transitionVia
+ required property point targetItems_transitionFrom
+ required property point displacedItems_transitionVia
+ required property string testedPositioner
+
property int duration: 50
property real incrementalSize: 5
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index d3c0f345b9..e6bbd8c215 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -1025,16 +1025,17 @@ void tst_qquickpositioners::populateTransitions(const QString &positionerObjectN
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", usePopulateTransition);
- ctxt->setContextProperty("enableAddTransition", true);
- ctxt->setContextProperty("dynamicallyPopulate", dynamicallyPopulate);
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", positionerObjectName);
+ window->setInitialProperties({
+ {"usePopulateTransition", usePopulateTransition},
+ {"enableAddTransition", true},
+ {"dynamicallyPopulate", dynamicallyPopulate},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", positionerObjectName}
+ });
window->setSource(testFileUrl(qmlFile));
QQuickItem *positioner = window->rootObject()->findChild<QQuickItem*>(positionerObjectName);
@@ -1111,16 +1112,17 @@ void tst_qquickpositioners::addTransitions(const QString &positionerObjectName)
QaimModel model_displacedItems_transitionVia;
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", QVariant(false));
- ctxt->setContextProperty("enableAddTransition", QVariant(true));
- ctxt->setContextProperty("dynamicallyPopulate", QVariant(false));
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", QString());
+ window->setInitialProperties({
+ {"usePopulateTransition", QVariant(false)},
+ {"enableAddTransition", QVariant(true)},
+ {"dynamicallyPopulate", QVariant(false)},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", QString()}
+ });
window->setSource(testFileUrl(qmlFile));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
@@ -1234,16 +1236,17 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
QaimModel model_displacedItems_transitionVia;
QScopedPointer<QQuickView> window(QQuickViewTestUtil::createView());
- QQmlContext *ctxt = window->rootContext();
- ctxt->setContextProperty("usePopulateTransition", QVariant(false));
- ctxt->setContextProperty("enableAddTransition", QVariant(false));
- ctxt->setContextProperty("dynamicallyPopulate", QVariant(false));
- ctxt->setContextProperty("testModel", &model);
- ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
- ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
- ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
- ctxt->setContextProperty("displacedItems_transitionVia", displacedItems_transitionVia);
- ctxt->setContextProperty("testedPositioner", QString());
+ window->setInitialProperties({
+ {"usePopulateTransition", QVariant(false)},
+ {"enableAddTransition", QVariant(false)},
+ {"dynamicallyPopulate", QVariant(false)},
+ {"testModel", QVariant::fromValue(&model)},
+ {"model_targetItems_transitionFrom", QVariant::fromValue(&model_targetItems_transitionFrom)},
+ {"model_displacedItems_transitionVia", QVariant::fromValue(&model_displacedItems_transitionVia)},
+ {"targetItems_transitionFrom", targetItems_transitionFrom},
+ {"displacedItems_transitionVia", displacedItems_transitionVia},
+ {"testedPositioner", QString()}
+ });
window->setSource(testFileUrl(qmlFile));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window.data()));
diff --git a/tests/auto/quick/qquickrepeater/data/objlist_required.qml b/tests/auto/quick/qquickrepeater/data/objlist_required.qml
new file mode 100644
index 0000000000..cc9dd9566c
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/objlist_required.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: container
+ objectName: "container"
+ width: 240
+ height: 320
+ color: "white"
+ Repeater {
+ id: repeater
+ objectName: "repeater"
+ model: testData
+ property int errors: 0
+ property int instantiated: 0
+ Component {
+ Item{
+ required property int index
+ required property int idx
+ Component.onCompleted: {if (index != idx) repeater.errors += 1; repeater.instantiated++}
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/data/requiredProperty.qml b/tests/auto/quick/qquickrepeater/data/requiredProperty.qml
new file mode 100644
index 0000000000..80eb3c28ee
--- /dev/null
+++ b/tests/auto/quick/qquickrepeater/data/requiredProperty.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.14
+
+Item {
+ Column {
+ Repeater {
+ model: ["apples", "oranges", "pears"]
+ Text {
+ id: txt
+ required property string modelData
+ required property int index
+ text: modelData + index
+ Component.onCompleted: () => {console.info(txt.text)}
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 65e7d29595..ccfef63902 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -55,6 +55,7 @@ public:
private slots:
void numberModel();
+ void objectList_data();
void objectList();
void stringList();
void dataModel_adding();
@@ -79,6 +80,7 @@ private slots:
void QTBUG54859_asynchronousMove();
void package();
void ownership();
+ void requiredProperties();
};
class TestObject : public QObject
@@ -143,6 +145,14 @@ void tst_QQuickRepeater::numberModel()
delete window;
}
+void tst_QQuickRepeater::objectList_data()
+{
+ QTest::addColumn<QUrl>("filename");
+
+ QTest::newRow("normal") << testFileUrl("objlist.qml");
+ QTest::newRow("required") << testFileUrl("objlist_required.qml");
+}
+
class MyObject : public QObject
{
Q_OBJECT
@@ -157,6 +167,7 @@ public:
void tst_QQuickRepeater::objectList()
{
+ QFETCH(QUrl, filename);
QQuickView *window = createView();
QObjectList data;
for (int i=0; i<100; i++)
@@ -165,7 +176,7 @@ void tst_QQuickRepeater::objectList()
QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testData", QVariant::fromValue(data));
- window->setSource(testFileUrl("objlist.qml"));
+ window->setSource(filename);
qApp->processEvents();
QQuickRepeater *repeater = findItem<QQuickRepeater>(window->rootObject(), "repeater");
@@ -1108,6 +1119,18 @@ void tst_QQuickRepeater::ownership()
QVERIFY(!modelGuard);
}
+void tst_QQuickRepeater::requiredProperties()
+{
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "apples0");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "oranges1");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "pears2");
+ QQmlEngine engine;
+
+ QQmlComponent component(&engine, testFileUrl("requiredProperty.qml"));
+ QScopedPointer<QObject> o {component.create()};
+ QVERIFY(o);
+}
+
QTEST_MAIN(tst_QQuickRepeater)
#include "tst_qquickrepeater.moc"
diff --git a/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
new file mode 100644
index 0000000000..bebfd86931
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/delegateWithRequired.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ id: rect
+ required property string position
+ required property bool hasModelChildren
+ required property QtObject model
+ Text {text: rect.position}
+ implicitWidth: 100
+ implicitHeight: 100
+ Component.onCompleted: () => {if (rect.position === "R1:C1" && rect.model.hasModelChildren == rect.hasModelChildren) console.info("success")}
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
new file mode 100644
index 0000000000..0c685cd49e
--- /dev/null
+++ b/tests/auto/quick/qquicktableview/data/delegatewithRequiredUnset.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Window 2.3
+
+Item {
+ width: 640
+ height: 450
+
+ property alias tableView: tableView
+
+ TableView {
+ id: tableView
+ width: 600
+ height: 400
+ delegate: tableViewDelegate
+ }
+
+ Component {
+ id: tableViewDelegate
+ Rectangle {
+ id: rect
+ required property string position
+ required property bool unset
+ required property bool hasModelChildren
+ required property QtObject model
+ Text {text: rect.position}
+ implicitWidth: 100
+ implicitHeight: 100
+ Component.onCompleted: () => {if (rect.position === "R1:C1" && rect.model.hasModelChildren == rect.hasModelChildren) console.info("success")}
+ }
+ }
+
+}
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 889175a228..230dcc9446 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -173,6 +173,7 @@ private slots:
void checkSyncView_differentSizedModels();
void checkSyncView_connect_late_data();
void checkSyncView_connect_late();
+ void delegateWithRequiredProperties();
};
tst_QQuickTableView::tst_QQuickTableView()
@@ -2619,6 +2620,50 @@ void tst_QQuickTableView::checkSyncView_connect_late()
}
+void tst_QQuickTableView::delegateWithRequiredProperties()
+{
+ constexpr static int PositionRole = Qt::UserRole+1;
+ struct MyTable : QAbstractTableModel {
+
+
+ using QAbstractTableModel::QAbstractTableModel;
+
+ int rowCount(const QModelIndex& = QModelIndex()) const override {
+ return 3;
+ }
+
+ int columnCount(const QModelIndex& = QModelIndex()) const override {
+ return 3;
+ }
+
+ QVariant data(const QModelIndex &index, int = Qt::DisplayRole) const override {
+ return QVariant::fromValue(QString::asprintf("R%d:C%d", index.row(), index.column()));
+ }
+
+ QHash<int, QByteArray> roleNames() const override {
+ return QHash<int, QByteArray> { {PositionRole, "position"} };
+ }
+ };
+
+ auto model = QVariant::fromValue(QSharedPointer<MyTable>(new MyTable));
+ {
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "success");
+ LOAD_TABLEVIEW("delegateWithRequired.qml")
+ QVERIFY(tableView);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QVERIFY(view->errors().empty());
+ }
+ {
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(R"|(TableView: failed loading index: \d)|"));
+ LOAD_TABLEVIEW("delegatewithRequiredUnset.qml")
+ QVERIFY(tableView);
+ tableView->setModel(model);
+ WAIT_UNTIL_POLISHED;
+ QTRY_VERIFY(view->errors().empty());
+ }
+}
+
QTEST_MAIN(tst_QQuickTableView)
#include "tst_qquicktableview.moc"