aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Watson <glenn.watson@nokia.com>2011-08-16 11:48:14 +1000
committerQt by Nokia <qt-info@nokia.com>2011-08-18 00:24:09 +0200
commit74f3a67fe80fecf7ba2fd76e1758b6c0f68ce918 (patch)
tree1f50ac2696414113387da29de3213c9ed494ec68
parentdc5644758a2cdbe67111e3471488b89b1ddddd8c (diff)
Add attached properties to the positioners.
Added an attached property type to the base positioner class. This allows items within a positioner (Row, Column, Grid, Flow) to determine their index inside the positioner, as well as whether they are the first or last items. Non-visible items are ignored, as in the positioner layout objects themselves. It may be useful to expand this in the future to contain more information specific to the positioner, for example row/column for Grid. Task-number: QTBUG-19211 Change-Id: I10a8c9ca5528dd12811125cae8a9b4d2e3747972 Reviewed-on: http://codereview.qt.nokia.com/2983 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
-rw-r--r--doc/src/declarative/whatsnew.qdoc3
-rw-r--r--examples/declarative/positioners/positioners-attachedproperties.qml66
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp1
-rw-r--r--src/declarative/items/qsgpositioners.cpp122
-rw-r--r--src/declarative/items/qsgpositioners_p.h39
-rw-r--r--tests/auto/declarative/qsgpositioners/data/attachedproperties-column.qml50
-rw-r--r--tests/auto/declarative/qsgpositioners/data/attachedproperties-dynamic.qml44
-rw-r--r--tests/auto/declarative/qsgpositioners/data/attachedproperties-flow.qml50
-rw-r--r--tests/auto/declarative/qsgpositioners/data/attachedproperties-grid.qml50
-rw-r--r--tests/auto/declarative/qsgpositioners/data/attachedproperties-row.qml50
-rw-r--r--tests/auto/declarative/qsgpositioners/data/rectangleComponent.qml11
-rw-r--r--tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp114
12 files changed, 596 insertions, 4 deletions
diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc
index 3707d41cd9..9bac55efe9 100644
--- a/doc/src/declarative/whatsnew.qdoc
+++ b/doc/src/declarative/whatsnew.qdoc
@@ -54,6 +54,9 @@ of the properties was changed.
Grid now has rowSpacing and columnSpacing properties.
+Positioner now has an attached property that can be used to determine a subitem's location within a
+container such as Column or Row.
+
\section2 QtQuick 1 is now a separate library and module
Writing C++ applications using QtQuick 1 specific API, i.e. QDeclarativeView or QDeclarativeItem
diff --git a/examples/declarative/positioners/positioners-attachedproperties.qml b/examples/declarative/positioners/positioners-attachedproperties.qml
new file mode 100644
index 0000000000..49638683e4
--- /dev/null
+++ b/examples/declarative/positioners/positioners-attachedproperties.qml
@@ -0,0 +1,66 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 400
+ height: 100
+
+ // Create row with four rectangles, the fourth one is hidden
+ Row {
+ id: row
+
+ Rectangle {
+ id: red
+ color: "red"
+ width: 100
+ height: 100
+
+ // When mouse is clicked, display the values of the positioner
+ MouseArea {
+ anchors.fill: parent
+ onClicked: row.showInfo(red.Positioner)
+ }
+ }
+
+ Rectangle {
+ id: green
+ color: "green"
+ width: 100
+ height: 100
+
+ // When mouse is clicked, display the values of the positioner
+ MouseArea {
+ anchors.fill: parent
+ onClicked: row.showInfo(green.Positioner)
+ }
+ }
+
+ Rectangle {
+ id: blue
+ color: "blue"
+ width: 100
+ height: 100
+
+ // When mouse is clicked, display the values of the positioner
+ MouseArea {
+ anchors.fill: parent
+ onClicked: row.showInfo(blue.Positioner)
+ }
+ }
+
+ // This rectangle is not visible, so it doesn't have a positioner value
+ Rectangle {
+ color: "black"
+ width: 100
+ height: 100
+ visible: false
+ }
+
+ // Print the index of the child item in the positioner and convenience
+ // properties showing if it's the first or last item.
+ function showInfo(positioner) {
+ console.log("Item Index = " + positioner.index)
+ console.log(" isFirstItem = " + positioner.isFirstItem)
+ console.log(" isLastItem = " + positioner.isLastItem)
+ }
+ }
+}
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 62a4bd06cb..9359906f25 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -126,6 +126,7 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
qmlRegisterType<QSGPathView>(uri,major,minor,"PathView");
+ qmlRegisterUncreatableType<QSGBasePositioner>(uri,major,minor,"Positioner","Positioner is an abstract type that is only available as an attached property.");
#ifndef QT_NO_VALIDATOR
qmlRegisterType<QIntValidator>(uri,major,minor,"IntValidator");
qmlRegisterType<QDoubleValidator>(uri,major,minor,"DoubleValidator");
diff --git a/src/declarative/items/qsgpositioners.cpp b/src/declarative/items/qsgpositioners.cpp
index d500afd81c..df3450e4d7 100644
--- a/src/declarative/items/qsgpositioners.cpp
+++ b/src/declarative/items/qsgpositioners.cpp
@@ -230,6 +230,7 @@ void QSGBasePositioner::prePositioning()
}
QSizeF contentSize(0,0);
doPositioning(&contentSize);
+ updateAttachedProperties();
if (!d->addActions.isEmpty() || !d->moveActions.isEmpty())
finishApplyTransitions();
d->doingPositioning = false;
@@ -285,6 +286,119 @@ void QSGBasePositioner::finishApplyTransitions()
d->moveActions.clear();
}
+QSGPositionerAttached *QSGBasePositioner::qmlAttachedProperties(QObject *obj)
+{
+ return new QSGPositionerAttached(obj);
+}
+
+void QSGBasePositioner::updateAttachedProperties(QSGPositionerAttached *specificProperty, QSGItem *specificPropertyOwner) const
+{
+ // If this function is deemed too expensive or shows up in profiles, it could
+ // be changed to run only when there are attached properties present. This
+ // could be a flag in the positioner that is set by the attached property
+ // constructor.
+ QSGPositionerAttached *prevLastProperty = 0;
+ QSGPositionerAttached *lastProperty = 0;
+
+ int visibleItemIndex = 0;
+ for (int ii = 0; ii < positionedItems.count(); ++ii) {
+ const PositionedItem &child = positionedItems.at(ii);
+ if (!child.item)
+ continue;
+
+ QSGPositionerAttached *property = 0;
+
+ if (specificProperty) {
+ if (specificPropertyOwner == child.item) {
+ property = specificProperty;
+ }
+ } else {
+ property = static_cast<QSGPositionerAttached *>(qmlAttachedPropertiesObject<QSGBasePositioner>(child.item, false));
+ }
+
+ if (child.isVisible) {
+ if (property) {
+ property->setIndex(visibleItemIndex);
+ property->setIsFirstItem(visibleItemIndex == 0);
+
+ if (property->isLastItem())
+ prevLastProperty = property;
+ }
+
+ lastProperty = property;
+ ++visibleItemIndex;
+ } else if (property) {
+ property->setIndex(-1);
+ property->setIsFirstItem(false);
+ property->setIsLastItem(false);
+ }
+ }
+
+ if (prevLastProperty && prevLastProperty != lastProperty)
+ prevLastProperty->setIsLastItem(false);
+ if (lastProperty)
+ lastProperty->setIsLastItem(true);
+}
+
+/*!
+ \qmlclass Positioner QSGPositionerAttached
+ \inqmlmodule QtQuick 2
+ \ingroup qml-positioning-elements
+ \brief The Positioner type provides attached properties that contain details on where an item exists in a positioner.
+
+ Positioner items (such as Column, Row, Flow and Grid) provide automatic layout
+ for child items. Attaching this property allows a child item to determine
+ where it exists within the positioner.
+*/
+
+QSGPositionerAttached::QSGPositionerAttached(QObject *parent) : QObject(parent), m_index(-1), m_isFirstItem(false), m_isLastItem(false)
+{
+ QSGItem *attachedItem = qobject_cast<QSGItem *>(parent);
+ if (attachedItem) {
+ QSGBasePositioner *positioner = qobject_cast<QSGBasePositioner *>(attachedItem->parent());
+ if (positioner) {
+ positioner->updateAttachedProperties(this, attachedItem);
+ }
+ }
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::index
+
+ This property allows the item to determine
+ its index within the positioner.
+*/
+void QSGPositionerAttached::setIndex(int index)
+{
+ if (m_index == index)
+ return;
+ m_index = index;
+ emit indexChanged();
+}
+
+/*!
+ \qmlattachedproperty Item QtQuick2::Positioner::isFirstItem
+ \qmlattachedproperty Item QtQuick2::Positioner::isLastItem
+
+ These properties allow the item to determine if it
+ is the first or last item in the positioner, respectively.
+*/
+void QSGPositionerAttached::setIsFirstItem(bool isFirstItem)
+{
+ if (m_isFirstItem == isFirstItem)
+ return;
+ m_isFirstItem = isFirstItem;
+ emit isFirstItemChanged();
+}
+
+void QSGPositionerAttached::setIsLastItem(bool isLastItem)
+{
+ if (m_isLastItem == isLastItem)
+ return;
+ m_isLastItem = isLastItem;
+ emit isLastItemChanged();
+}
+
/*!
\qmlclass Column QSGColumn
\inqmlmodule QtQuick 2
@@ -349,7 +463,7 @@ void QSGBasePositioner::finishApplyTransitions()
Items with a width or height of 0 will not be positioned.
- \sa Row, Grid, Flow, {declarative/positioners}{Positioners example}
+ \sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
\qmlproperty Transition QtQuick2::Column::add
@@ -492,7 +606,7 @@ void QSGColumn::reportConflictingAnchors()
Items with a width or height of 0 will not be positioned.
- \sa Column, Grid, Flow, {declarative/positioners}{Positioners example}
+ \sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
\qmlproperty Transition QtQuick2::Row::add
@@ -722,7 +836,7 @@ void QSGRow::reportConflictingAnchors()
Items with a width or height of 0 will not be positioned.
- \sa Flow, Row, Column, {declarative/positioners}{Positioners example}
+ \sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
\qmlproperty Transition QtQuick2::Grid::add
@@ -1149,7 +1263,7 @@ void QSGGrid::reportConflictingAnchors()
Items with a width or height of 0 will not be positioned.
- \sa Column, Row, Grid, {declarative/positioners}{Positioners example}
+ \sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
\qmlproperty Transition QtQuick2::Flow::add
diff --git a/src/declarative/items/qsgpositioners_p.h b/src/declarative/items/qsgpositioners_p.h
index 8f9d3eb310..7200b6da8d 100644
--- a/src/declarative/items/qsgpositioners_p.h
+++ b/src/declarative/items/qsgpositioners_p.h
@@ -59,6 +59,37 @@ QT_MODULE(Declarative)
class QSGBasePositionerPrivate;
+class QSGPositionerAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QSGPositionerAttached(QObject *parent);
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ Q_PROPERTY(bool isFirstItem READ isFirstItem NOTIFY isFirstItemChanged)
+ Q_PROPERTY(bool isLastItem READ isLastItem NOTIFY isLastItemChanged)
+
+ int index() const { return m_index; }
+ void setIndex(int index);
+
+ bool isFirstItem() const { return m_isFirstItem; }
+ void setIsFirstItem(bool isFirstItem);
+
+ bool isLastItem() const { return m_isLastItem; }
+ void setIsLastItem(bool isLastItem);
+
+Q_SIGNALS:
+ void indexChanged();
+ void isFirstItemChanged();
+ void isLastItemChanged();
+
+private:
+ int m_index;
+ bool m_isFirstItem;
+ bool m_isLastItem;
+};
+
class Q_DECLARATIVE_PRIVATE_EXPORT QSGBasePositioner : public QSGImplicitSizeItem
{
Q_OBJECT
@@ -80,6 +111,10 @@ public:
QDeclarativeTransition *add() const;
void setAdd(QDeclarativeTransition *);
+ static QSGPositionerAttached *qmlAttachedProperties(QObject *obj);
+
+ void updateAttachedProperties(QSGPositionerAttached *specificProperty = 0, QSGItem *specificPropertyOwner = 0) const;
+
protected:
QSGBasePositioner(QSGBasePositionerPrivate &dd, PositionerType at, QSGItem *parent);
virtual void componentComplete();
@@ -120,6 +155,7 @@ class Q_AUTOTEST_EXPORT QSGColumn : public QSGBasePositioner
Q_OBJECT
public:
QSGColumn(QSGItem *parent=0);
+
protected:
virtual void doPositioning(QSizeF *contentSize);
virtual void reportConflictingAnchors();
@@ -249,6 +285,9 @@ QML_DECLARE_TYPE(QSGRow)
QML_DECLARE_TYPE(QSGGrid)
QML_DECLARE_TYPE(QSGFlow)
+QML_DECLARE_TYPE(QSGBasePositioner)
+QML_DECLARE_TYPEINFO(QSGBasePositioner, QML_HAS_ATTACHED_PROPERTIES)
+
QT_END_HEADER
#endif // QSGPOSITIONERS_P_H
diff --git a/tests/auto/declarative/qsgpositioners/data/attachedproperties-column.qml b/tests/auto/declarative/qsgpositioners/data/attachedproperties-column.qml
new file mode 100644
index 0000000000..4c667aa205
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/attachedproperties-column.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 100
+ height: 200
+
+ Column {
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'red'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "greenRect"
+ width: 100
+ height: 100
+ color: 'green'
+ property int posIndex: Positioner.index
+ property bool isFirstItem: Positioner.isFirstItem
+ property bool isLastItem: Positioner.isLastItem
+ }
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'blue'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "yellowRect"
+ width: 100
+ height: 100
+ color: 'yellow'
+
+ property int posIndex: -1
+ property bool isFirstItem: false
+ property bool isLastItem: false
+
+ function onDemandPositioner() {
+ posIndex = Positioner.index;
+ isFirstItem = Positioner.isFirstItem
+ isLastItem = Positioner.isLastItem
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgpositioners/data/attachedproperties-dynamic.qml b/tests/auto/declarative/qsgpositioners/data/attachedproperties-dynamic.qml
new file mode 100644
index 0000000000..894749dc16
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/attachedproperties-dynamic.qml
@@ -0,0 +1,44 @@
+import QtQuick 2.0
+
+Rectangle
+{
+ width: 300
+ height: 100
+
+ Row {
+ id: pos
+ objectName: "pos"
+ anchors.fill: parent
+
+ Rectangle {
+ objectName: "rect0"
+ width: 100
+ height: 100
+ color: 'red'
+ property int index: Positioner.index
+ property bool firstItem: Positioner.isFirstItem
+ property bool lastItem: Positioner.isLastItem
+ }
+
+ Rectangle {
+ objectName: "rect1"
+ width: 100
+ height: 100
+ color: 'green'
+ property int index: Positioner.index
+ property bool firstItem: Positioner.isFirstItem
+ property bool lastItem: Positioner.isLastItem
+ }
+
+ property QtObject subRect;
+
+ function createSubRect() {
+ var component = Qt.createComponent("rectangleComponent.qml");
+ subRect = component.createObject(pos, {});
+ }
+
+ function destroySubRect() {
+ subRect.destroy();
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgpositioners/data/attachedproperties-flow.qml b/tests/auto/declarative/qsgpositioners/data/attachedproperties-flow.qml
new file mode 100644
index 0000000000..e7f9a63e2a
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/attachedproperties-flow.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 100
+
+ Flow {
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'red'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "greenRect"
+ width: 100
+ height: 100
+ color: 'green'
+ property int posIndex: Positioner.index
+ property bool isFirstItem: Positioner.isFirstItem
+ property bool isLastItem: Positioner.isLastItem
+ }
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'blue'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "yellowRect"
+ width: 100
+ height: 100
+ color: 'yellow'
+
+ property int posIndex: -1
+ property bool isFirstItem: false
+ property bool isLastItem: false
+
+ function onDemandPositioner() {
+ posIndex = Positioner.index;
+ isFirstItem = Positioner.isFirstItem
+ isLastItem = Positioner.isLastItem
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgpositioners/data/attachedproperties-grid.qml b/tests/auto/declarative/qsgpositioners/data/attachedproperties-grid.qml
new file mode 100644
index 0000000000..2094309b9f
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/attachedproperties-grid.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 100
+
+ Grid {
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'red'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "greenRect"
+ width: 100
+ height: 100
+ color: 'green'
+ property int posIndex: Positioner.index
+ property bool isFirstItem: Positioner.isFirstItem
+ property bool isLastItem: Positioner.isLastItem
+ }
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'blue'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "yellowRect"
+ width: 100
+ height: 100
+ color: 'yellow'
+
+ property int posIndex: -1
+ property bool isFirstItem: false
+ property bool isLastItem: false
+
+ function onDemandPositioner() {
+ posIndex = Positioner.index;
+ isFirstItem = Positioner.isFirstItem
+ isLastItem = Positioner.isLastItem
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgpositioners/data/attachedproperties-row.qml b/tests/auto/declarative/qsgpositioners/data/attachedproperties-row.qml
new file mode 100644
index 0000000000..212a26b431
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/attachedproperties-row.qml
@@ -0,0 +1,50 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 200
+ height: 100
+
+ Row {
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'red'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "greenRect"
+ width: 100
+ height: 100
+ color: 'green'
+ property int posIndex: Positioner.index
+ property bool isFirstItem: Positioner.isFirstItem
+ property bool isLastItem: Positioner.isLastItem
+ }
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: 'blue'
+ visible: false
+ }
+
+ Rectangle {
+ objectName: "yellowRect"
+ width: 100
+ height: 100
+ color: 'yellow'
+
+ property int posIndex: -1
+ property bool isFirstItem: false
+ property bool isLastItem: false
+
+ function onDemandPositioner() {
+ posIndex = Positioner.index;
+ isFirstItem = Positioner.isFirstItem
+ isLastItem = Positioner.isLastItem
+ }
+ }
+ }
+}
diff --git a/tests/auto/declarative/qsgpositioners/data/rectangleComponent.qml b/tests/auto/declarative/qsgpositioners/data/rectangleComponent.qml
new file mode 100644
index 0000000000..de1bb99593
--- /dev/null
+++ b/tests/auto/declarative/qsgpositioners/data/rectangleComponent.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0;
+
+Rectangle {
+ objectName: "rect2"
+ color: "blue"
+ width: 100
+ height: 100
+ property int index: Positioner.index
+ property bool firstItem: Positioner.isFirstItem
+ property bool lastItem: Positioner.isLastItem
+}
diff --git a/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp b/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp
index 497f511335..137e6acd77 100644
--- a/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp
+++ b/tests/auto/declarative/qsgpositioners/tst_qsgpositioners.cpp
@@ -91,6 +91,10 @@ private slots:
void test_conflictinganchors();
void test_mirroring();
void test_allInvisible();
+ void test_attachedproperties();
+ void test_attachedproperties_data();
+ void test_attachedproperties_dynamic();
+
private:
QSGView *createView(const QString &filename);
};
@@ -1345,6 +1349,116 @@ void tst_qsgpositioners::test_allInvisible()
QVERIFY(column->height() == 0);
}
+void tst_qsgpositioners::test_attachedproperties()
+{
+ QFETCH(QString, filename);
+
+ QSGView *canvas = createView(filename);
+ QVERIFY(canvas->rootObject() != 0);
+
+ QSGRectangle *greenRect = canvas->rootObject()->findChild<QSGRectangle *>("greenRect");
+ QVERIFY(greenRect != 0);
+
+ int posIndex = greenRect->property("posIndex").toInt();
+ QVERIFY(posIndex == 0);
+ bool isFirst = greenRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == true);
+ bool isLast = greenRect->property("isLastItem").toBool();
+ QVERIFY(isLast == false);
+
+ QSGRectangle *yellowRect = canvas->rootObject()->findChild<QSGRectangle *>("yellowRect");
+ QVERIFY(yellowRect != 0);
+
+ posIndex = yellowRect->property("posIndex").toInt();
+ QVERIFY(posIndex == -1);
+ isFirst = yellowRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = yellowRect->property("isLastItem").toBool();
+ QVERIFY(isLast == false);
+
+ yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
+
+ posIndex = yellowRect->property("posIndex").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = yellowRect->property("isFirstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = yellowRect->property("isLastItem").toBool();
+ QVERIFY(isLast == true);
+
+ delete canvas;
+}
+
+void tst_qsgpositioners::test_attachedproperties_data()
+{
+ QTest::addColumn<QString>("filename");
+
+ QTest::newRow("column") << SRCDIR "/data/attachedproperties-column.qml";
+ QTest::newRow("row") << SRCDIR "/data/attachedproperties-row.qml";
+ QTest::newRow("grid") << SRCDIR "/data/attachedproperties-grid.qml";
+ QTest::newRow("flow") << SRCDIR "/data/attachedproperties-flow.qml";
+}
+
+void tst_qsgpositioners::test_attachedproperties_dynamic()
+{
+ QSGView *canvas = createView(SRCDIR "/data/attachedproperties-dynamic.qml");
+ QVERIFY(canvas->rootObject() != 0);
+
+ QSGRow *row = canvas->rootObject()->findChild<QSGRow *>("pos");
+ QVERIFY(row != 0);
+
+ QSGRectangle *rect0 = canvas->rootObject()->findChild<QSGRectangle *>("rect0");
+ QVERIFY(rect0 != 0);
+
+ int posIndex = rect0->property("index").toInt();
+ QVERIFY(posIndex == 0);
+ bool isFirst = rect0->property("firstItem").toBool();
+ QVERIFY(isFirst == true);
+ bool isLast = rect0->property("lastItem").toBool();
+ QVERIFY(isLast == false);
+
+ QSGRectangle *rect1 = canvas->rootObject()->findChild<QSGRectangle *>("rect1");
+ QVERIFY(rect1 != 0);
+
+ posIndex = rect1->property("index").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = rect1->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect1->property("lastItem").toBool();
+ QVERIFY(isLast == true);
+
+ row->metaObject()->invokeMethod(row, "createSubRect");
+
+ posIndex = rect1->property("index").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = rect1->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect1->property("lastItem").toBool();
+ QVERIFY(isLast == false);
+
+ QSGRectangle *rect2 = canvas->rootObject()->findChild<QSGRectangle *>("rect2");
+ QVERIFY(rect2 != 0);
+
+ posIndex = rect2->property("index").toInt();
+ QVERIFY(posIndex == 2);
+ isFirst = rect2->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect2->property("lastItem").toBool();
+ QVERIFY(isLast == true);
+
+ row->metaObject()->invokeMethod(row, "destroySubRect");
+
+ qApp->processEvents(QEventLoop::DeferredDeletion);
+
+ posIndex = rect1->property("index").toInt();
+ QVERIFY(posIndex == 1);
+ isFirst = rect1->property("firstItem").toBool();
+ QVERIFY(isFirst == false);
+ isLast = rect1->property("lastItem").toBool();
+ QVERIFY(isLast == true);
+
+ delete canvas;
+}
+
QSGView *tst_qsgpositioners::createView(const QString &filename)
{
QSGView *canvas = new QSGView(0);