summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/fx/qfxanchors.cpp192
-rw-r--r--src/declarative/fx/qfxanchors_p.h6
-rw-r--r--tests/auto/declarative/anchors/anchors.pro5
-rw-r--r--tests/auto/declarative/anchors/data/loop1.qml6
-rw-r--r--tests/auto/declarative/anchors/data/loop2.qml18
-rw-r--r--tests/auto/declarative/anchors/tst_anchors.cpp52
6 files changed, 206 insertions, 73 deletions
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
index 540e1cb..f570663 100644
--- a/src/declarative/fx/qfxanchors.cpp
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -424,23 +424,31 @@ void QFxAnchors::updateTopAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasTopAnchor) {
- //Handle stretching
- bool invalid = true;
- int height = 0;
- if (d->usedAnchors & HasBottomAnchor) {
- invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height);
- } else if (d->usedAnchors & HasVCenterAnchor) {
- invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height);
- height *= 2;
- }
- if (!invalid)
- d->item->setHeight(height);
+ if (!d->updatingVerticalAnchor) {
+ d->updatingVerticalAnchor = true;
- //Handle top
- if (d->top.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin);
- } else if (d->top.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin);
+ //Handle stretching
+ bool invalid = true;
+ int height = 0;
+ if (d->usedAnchors & HasBottomAnchor) {
+ invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height);
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height);
+ height *= 2;
+ }
+ if (!invalid)
+ d->item->setHeight(height);
+
+ //Handle top
+ if (d->top.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin);
+ } else if (d->top.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin);
+ }
+
+ d->updatingVerticalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on vertical anchor.";
}
}
}
@@ -449,20 +457,28 @@ void QFxAnchors::updateBottomAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasBottomAnchor) {
- //Handle stretching (top + bottom case is handled in updateLeftAnchor)
- if (d->usedAnchors & HasVCenterAnchor) {
- int height = 0;
- bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
- QFxAnchorLine::Top, height);
- if (!invalid)
- d->item->setHeight(height*2);
- }
-
- //Handle bottom
- if (d->bottom.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
- } else if (d->bottom.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ if (!d->updatingVerticalAnchor) {
+ d->updatingVerticalAnchor = true;
+
+ //Handle stretching (top + bottom case is handled in updateLeftAnchor)
+ if (d->usedAnchors & HasVCenterAnchor) {
+ int height = 0;
+ bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
+ QFxAnchorLine::Top, height);
+ if (!invalid)
+ d->item->setHeight(height*2);
+ }
+
+ //Handle bottom
+ if (d->bottom.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ } else if (d->bottom.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin);
+ }
+
+ d->updatingVerticalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on vertical anchor.";
}
}
}
@@ -471,14 +487,22 @@ void QFxAnchors::updateVCenterAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasVCenterAnchor) {
- //(stetching handled in other update functions)
+ if (!d->updatingVerticalAnchor) {
+ d->updatingVerticalAnchor = true;
- //Handle vCenter
- if (d->vCenter.item == d->item->itemParent()) {
- d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine)
- - d->item->height()/2 + d->vCenterOffset);
- } else if (d->vCenter.item->itemParent() == d->item->itemParent()) {
- d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset);
+ //(stetching handled in other update functions)
+
+ //Handle vCenter
+ if (d->vCenter.item == d->item->itemParent()) {
+ d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine)
+ - d->item->height()/2 + d->vCenterOffset);
+ } else if (d->vCenter.item->itemParent() == d->item->itemParent()) {
+ d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset);
+ }
+
+ d->updatingVerticalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on vertical anchor.";
}
}
}
@@ -487,23 +511,31 @@ void QFxAnchors::updateLeftAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasLeftAnchor) {
- //Handle stretching
- bool invalid = true;
- int width = 0;
- if (d->usedAnchors & HasRightAnchor) {
- invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width);
- } else if (d->usedAnchors & HasHCenterAnchor) {
- invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width);
- width *= 2;
- }
- if (!invalid)
- d->item->setWidth(width);
+ if (!d->updatingHorizontalAnchor) {
+ d->updatingHorizontalAnchor = true;
- //Handle left
- if (d->left.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
- } else if (d->left.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
+ //Handle stretching
+ bool invalid = true;
+ int width = 0;
+ if (d->usedAnchors & HasRightAnchor) {
+ invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width);
+ } else if (d->usedAnchors & HasHCenterAnchor) {
+ invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width);
+ width *= 2;
+ }
+ if (!invalid)
+ d->item->setWidth(width);
+
+ //Handle left
+ if (d->left.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin);
+ } else if (d->left.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin);
+ }
+
+ d->updatingHorizontalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
}
}
}
@@ -512,20 +544,28 @@ void QFxAnchors::updateRightAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasRightAnchor) {
- //Handle stretching (left + right case is handled in updateLeftAnchor)
- if (d->usedAnchors & HasHCenterAnchor) {
- int width = 0;
- bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
- QFxAnchorLine::Left, width);
- if (!invalid)
- d->item->setWidth(width*2);
- }
-
- //Handle right
- if (d->right.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
- } else if (d->right.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ if (!d->updatingHorizontalAnchor) {
+ d->updatingHorizontalAnchor = true;
+
+ //Handle stretching (left + right case is handled in updateLeftAnchor)
+ if (d->usedAnchors & HasHCenterAnchor) {
+ int width = 0;
+ bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
+ QFxAnchorLine::Left, width);
+ if (!invalid)
+ d->item->setWidth(width*2);
+ }
+
+ //Handle right
+ if (d->right.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ } else if (d->right.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin);
+ }
+
+ d->updatingHorizontalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
}
}
}
@@ -534,11 +574,19 @@ void QFxAnchors::updateHCenterAnchor()
{
Q_D(QFxAnchors);
if (d->usedAnchors & HasHCenterAnchor) {
- //Handle hCenter
- if (d->hCenter.item == d->item->itemParent()) {
- d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
- } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
- d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ if (!d->updatingHorizontalAnchor) {
+ d->updatingHorizontalAnchor = true;
+
+ //Handle hCenter
+ if (d->hCenter.item == d->item->itemParent()) {
+ d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ } else if (d->hCenter.item->itemParent() == d->item->itemParent()) {
+ d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset);
+ }
+
+ d->updatingHorizontalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
}
}
}
diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h
index 3a5d1c7..76f83a8 100644
--- a/src/declarative/fx/qfxanchors_p.h
+++ b/src/declarative/fx/qfxanchors_p.h
@@ -64,7 +64,8 @@ class QFxAnchorsPrivate : public QObjectPrivate
public:
QFxAnchorsPrivate()
: item(0), usedAnchors(0), fill(0), centeredIn(0), leftMargin(0), rightMargin(0),
- topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0)
+ topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0),
+ updatingHorizontalAnchor(false), updatingVerticalAnchor(false)
{
}
@@ -99,6 +100,9 @@ public:
int bottomMargin;
int vCenterOffset;
int hCenterOffset;
+
+ bool updatingHorizontalAnchor;
+ bool updatingVerticalAnchor;
};
QT_END_NAMESPACE
diff --git a/tests/auto/declarative/anchors/anchors.pro b/tests/auto/declarative/anchors/anchors.pro
new file mode 100644
index 0000000..7b22cfb
--- /dev/null
+++ b/tests/auto/declarative/anchors/anchors.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative
+SOURCES += tst_anchors.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/anchors/data/loop1.qml b/tests/auto/declarative/anchors/data/loop1.qml
new file mode 100644
index 0000000..a4de1bf
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/loop1.qml
@@ -0,0 +1,6 @@
+Rect {
+ id: rect
+ width: 120; height: 200; color: "white"
+ Text { id: Text1; anchors.right: Text2.right; text: "Hello" }
+ Text { id: Text2; anchors.right: Text1.right; anchors.rightMargin: 10; text: "World" }
+}
diff --git a/tests/auto/declarative/anchors/data/loop2.qml b/tests/auto/declarative/anchors/data/loop2.qml
new file mode 100644
index 0000000..4b2c74e
--- /dev/null
+++ b/tests/auto/declarative/anchors/data/loop2.qml
@@ -0,0 +1,18 @@
+Rect {
+ id: container;
+ width: 600;
+ height: 600;
+
+ Image {
+ id: Image1
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/3311388091_ac2a257feb.jpg"
+ anchors.right: Image2.left
+ }
+
+ Image {
+ id: Image2
+ source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/oslo_groupphoto.jpg"
+ anchors.left: Image1.right
+ anchors.leftMargin: 20
+ }
+}
diff --git a/tests/auto/declarative/anchors/tst_anchors.cpp b/tests/auto/declarative/anchors/tst_anchors.cpp
new file mode 100644
index 0000000..7d920af
--- /dev/null
+++ b/tests/auto/declarative/anchors/tst_anchors.cpp
@@ -0,0 +1,52 @@
+#include <qtest.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxview.h>
+#include <QtDeclarative/qfximage.h>
+#include <QtDeclarative/qfxtext.h>
+
+class tst_anchors : public QObject
+{
+ Q_OBJECT
+public:
+ tst_anchors() {}
+
+private slots:
+ void loops();
+};
+
+// mostly testing that we don't crash
+void tst_anchors::loops()
+{
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/loop1.qml"));
+
+ //### ignoreMessage doesn't seem to work
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor.");
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+
+ {
+ QFxView *view = new QFxView;
+
+ view->setUrl(QUrl("file://" SRCDIR "/data/loop2.qml"));
+
+ //### ignoreMessage doesn't seem to work
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor.");
+ //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor.");
+ view->execute();
+ qApp->processEvents();
+
+ delete view;
+ }
+}
+
+QTEST_MAIN(tst_anchors)
+
+#include "tst_anchors.moc"