diff options
-rw-r--r-- | src/declarative/fx/qfxanchors.cpp | 192 | ||||
-rw-r--r-- | src/declarative/fx/qfxanchors_p.h | 6 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/anchors.pro | 5 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/data/loop1.qml | 6 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/data/loop2.qml | 18 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/tst_anchors.cpp | 52 |
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" |