Related to QTBUG-18919, but that was not reproduceable.
Rewrites a fair bit of the autotest to no longer rely on repositionings
happening immediately.
Change-Id: I80683d6e03a5543fc838cdd55b2d53e49a8a68bd
Reviewed-on: http://codereview.qt.nokia.com/3690
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
for the child items. Depending on the chosen type, only x or y changes will be applied.
Note that the subclass is responsible for adding the spacing in between items.
+
+ Positioning is usually delayed until before a frame is rendered, to batch multiple repositioning
+ changes into one calculation.
*/
QSGBasePositioner::QSGBasePositioner(QSGBasePositionerPrivate &dd, PositionerType at, QSGItem *parent)
positionedItems.clear();
}
+void QSGBasePositioner::updatePolish()
+{
+ Q_D(QSGBasePositioner);
+ if (d->positioningDirty)
+ prePositioning();
+}
+
int QSGBasePositioner::spacing() const
{
Q_D(const QSGBasePositioner);
if (s==d->spacing)
return;
d->spacing = s;
- prePositioning();
+ d->setPositioningDirty();
emit spacingChanged();
}
{
Q_D(QSGBasePositioner);
if (change == ItemChildAddedChange){
- prePositioning();
+ d->setPositioningDirty();
} else if (change == ItemChildRemovedChange) {
QSGItem *child = value.item;
QSGBasePositioner::PositionedItem posItem(child);
d->unwatchChanges(child);
positionedItems.remove(idx);
}
- prePositioning();
+ d->setPositioningDirty();
}
QSGItem::itemChange(change, value);
if (d->doingPositioning)
return;
- d->queuedPositioning = false;
+ d->positioningDirty = false;
d->doingPositioning = true;
//Need to order children by creation order modified by stacking order
QList<QSGItem *> children = childItems();
Items with a width or height of 0 will not be positioned.
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
\sa Row, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
Items with a width or height of 0 will not be positioned.
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
\sa Column, Grid, Flow, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
Items with a width or height of 0 will not be positioned.
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
\sa Flow, Row, Column, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
Items with a width or height of 0 will not be positioned.
+ Positioning is batched and syncronized with painting to reduce the number of
+ calculations needed. This means that positioners may not reposition items immediately
+ when changes occur, but it will have moved by the next frame.
+
\sa Column, Row, Grid, Positioner, {declarative/positioners}{Positioners example}
*/
/*!
virtual void itemChange(ItemChange, const ItemChangeData &);
void finishApplyTransitions();
+ virtual void updatePolish();
+
Q_SIGNALS:
void spacingChanged();
void moveChanged();
public:
QSGBasePositionerPrivate()
: spacing(0), type(QSGBasePositioner::None)
- , moveTransition(0), addTransition(0), queuedPositioning(false)
+ , moveTransition(0), addTransition(0), positioningDirty(false)
, doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
{
}
void watchChanges(QSGItem *other);
void unwatchChanges(QSGItem* other);
- bool queuedPositioning : 1;
+ void setPositioningDirty() {
+ Q_Q(QSGBasePositioner);
+ if (!positioningDirty) {
+ positioningDirty = true;
+ q->polish();
+ }
+ }
+
+ bool positioningDirty : 1;
bool doingPositioning : 1;
bool anchorConflict : 1;
Qt::LayoutDirection layoutDirection;
- void schedulePositioning()
- {
- Q_Q(QSGBasePositioner);
- if(!queuedPositioning){
- QTimer::singleShot(0,q,SLOT(prePositioning()));
- queuedPositioning = true;
- }
- }
-
void mirrorChange() {
- Q_Q(QSGBasePositioner);
if (type != QSGBasePositioner::Vertical)
- q->prePositioning();
+ setPositioningDirty();
}
bool isLeftToRight() const {
if (type == QSGBasePositioner::Vertical)
virtual void itemSiblingOrderChanged(QSGItem* other)
{
Q_UNUSED(other);
- //Delay is due to many children often being reordered at once
- //And we only want to reposition them all once
- schedulePositioning();
+ setPositioningDirty();
}
void itemGeometryChanged(QSGItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
{
- Q_Q(QSGBasePositioner);
if (newGeometry.size() != oldGeometry.size())
- q->prePositioning();
+ setPositioningDirty();
}
virtual void itemVisibilityChanged(QSGItem *)
{
- schedulePositioning();
- }
- virtual void itemOpacityChanged(QSGItem *)
- {
- Q_Q(QSGBasePositioner);
- q->prePositioning();
+ setPositioningDirty();
}
void itemDestroyed(QSGItem *item)
QSGView *canvas = createView();
canvas->show();
+ QTest::qWaitForWindowShown(canvas);
TestModel model;
model.addItem("Item 0", "a");
// Change the width of the row and check that items stay to the right
row->setWidth(200);
- QCOMPARE(one->x(), 150.0);
+ QTRY_COMPARE(one->x(), 150.0);
QCOMPARE(one->y(), 0.0);
QCOMPARE(two->x(), 130.0);
QCOMPARE(two->y(), 0.0);
// Change the width of the grid and check that items stay to the right
grid->setWidth(200);
- QCOMPARE(one->x(), 150.0);
+ QTRY_COMPARE(one->x(), 150.0);
QCOMPARE(one->y(), 0.0);
QCOMPARE(two->x(), 130.0);
QCOMPARE(two->y(), 0.0);
QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
QVERIFY(five != 0);
- QCOMPARE(one->x(), 0.0);
- QCOMPARE(one->y(), 0.0);
- QCOMPARE(two->x(), 50.0);
- QCOMPARE(two->y(), 0.0);
- QCOMPARE(three->x(), 70.0);
- QCOMPARE(three->y(), 0.0);
- QCOMPARE(four->x(), 0.0);
- QCOMPARE(four->y(), 50.0);
- QCOMPARE(five->x(), 50.0);
- QCOMPARE(five->y(), 50.0);
+ QTRY_COMPARE(one->x(), 0.0);
+ QTRY_COMPARE(one->y(), 0.0);
+ QTRY_COMPARE(two->x(), 50.0);
+ QTRY_COMPARE(two->y(), 0.0);
+ QTRY_COMPARE(three->x(), 70.0);
+ QTRY_COMPARE(three->y(), 0.0);
+ QTRY_COMPARE(four->x(), 0.0);
+ QTRY_COMPARE(four->y(), 50.0);
+ QTRY_COMPARE(five->x(), 50.0);
+ QTRY_COMPARE(five->y(), 50.0);
delete canvas;
}
root->setProperty("testRightToLeft", true);
QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
- QVERIFY(one != 0);
+ QTRY_VERIFY(one != 0);
QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
QVERIFY(two != 0);
QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
break;
QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
- QVERIFY(itemA->x() != itemB->x());
+ QTRY_VERIFY(itemA->x() != itemB->x());
}
QSGItemPrivate* rootPrivateB = QSGItemPrivate::get(rootB);
break;
QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
- QCOMPARE(itemA->x(), itemB->x());
+ QTRY_COMPARE(itemA->x(), itemB->x());
}
rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
break;
QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
- QCOMPARE(itemA->x(), itemB->x());
+ QTRY_COMPARE(itemA->x(), itemB->x());
}
delete canvasA;
delete canvasB;
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);
+ QTRY_VERIFY(rect1->property("index").toInt() == 1);
+ QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
+ QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
QSGRectangle *rect2 = canvas->rootObject()->findChild<QSGRectangle *>("rect2");
QVERIFY(rect2 != 0);
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);
+ QTRY_VERIFY(rect1->property("index").toInt() == 1);
+ QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
+ QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
delete canvas;
}
QSGView *canvas = new QSGView(0);
canvas->setSource(QUrl::fromLocalFile(filename));
+ canvas->show();
+ QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
return canvas;
}