From aeac9840e4c46786e84ab7eb16a89db22d4ff81a Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 29 Jun 2012 17:06:38 +1000 Subject: [PATCH] Allow all explicit margins to override margins. Task-number: QTBUG-24515 Change-Id: Ibfc657dec9fd0c8e71cf3686a04ea7b00ad72c11 Reviewed-by: Michael Brasser --- src/quick/items/qquickanchors.cpp | 105 +++++++++++++++++++-- src/quick/items/qquickanchors_p.h | 12 ++- src/quick/items/qquickanchors_p_p.h | 10 +- src/quick/items/qquickitem.cpp | 2 + .../quick/qquickanchors/data/individualMargins.qml | 16 ++++ .../auto/quick/qquickanchors/tst_qquickanchors.cpp | 95 +++++++++++++++++-- 6 files changed, 218 insertions(+), 22 deletions(-) create mode 100644 tests/auto/quick/qquickanchors/data/individualMargins.qml diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index 0626c66..9097cc4 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -985,6 +985,7 @@ qreal QQuickAnchors::leftMargin() const void QQuickAnchors::setLeftMargin(qreal offset) { Q_D(QQuickAnchors); + d->leftMarginExplicit = true; if (d->leftMargin == offset) return; d->leftMargin = offset; @@ -995,6 +996,20 @@ void QQuickAnchors::setLeftMargin(qreal offset) emit leftMarginChanged(); } +void QQuickAnchors::resetLeftMargin() +{ + Q_D(QQuickAnchors); + d->leftMarginExplicit = false; + if (d->leftMargin == d->margins) + return; + d->leftMargin = d->margins; + if (d->fill) + d->fillChanged(); + else + d->updateHorizontalAnchors(); + emit leftMarginChanged(); +} + qreal QQuickAnchors::rightMargin() const { Q_D(const QQuickAnchors); @@ -1004,6 +1019,7 @@ qreal QQuickAnchors::rightMargin() const void QQuickAnchors::setRightMargin(qreal offset) { Q_D(QQuickAnchors); + d->rightMarginExplicit = true; if (d->rightMargin == offset) return; d->rightMargin = offset; @@ -1014,6 +1030,20 @@ void QQuickAnchors::setRightMargin(qreal offset) emit rightMarginChanged(); } +void QQuickAnchors::resetRightMargin() +{ + Q_D(QQuickAnchors); + d->rightMarginExplicit = false; + if (d->rightMargin == d->margins) + return; + d->rightMargin = d->margins; + if (d->fill) + d->fillChanged(); + else + d->updateHorizontalAnchors(); + emit rightMarginChanged(); +} + qreal QQuickAnchors::margins() const { Q_D(const QQuickAnchors); @@ -1025,18 +1055,43 @@ void QQuickAnchors::setMargins(qreal offset) Q_D(QQuickAnchors); if (d->margins == offset) return; - //###Is it significantly faster to set them directly so we can call fillChanged only once? - if (!d->rightMargin || d->rightMargin == d->margins) - setRightMargin(offset); - if (!d->leftMargin || d->leftMargin == d->margins) - setLeftMargin(offset); - if (!d->topMargin || d->topMargin == d->margins) - setTopMargin(offset); - if (!d->bottomMargin || d->bottomMargin == d->margins) - setBottomMargin(offset); d->margins = offset; - emit marginsChanged(); + bool updateHorizontal = false; + bool updateVertical = false; + + if (!d->rightMarginExplicit && d->rightMargin != offset) { + d->rightMargin = offset; + updateHorizontal = true; + emit rightMarginChanged(); + } + if (!d->leftMarginExplicit && d->leftMargin != offset) { + d->leftMargin = offset; + updateHorizontal = true; + emit leftMarginChanged(); + } + if (!d->topMarginExplicit && d->topMargin != offset) { + d->topMargin = offset; + updateVertical = true; + emit topMarginChanged(); + } + if (!d->bottomMarginExplicit && d->bottomMargin != offset) { + d->bottomMargin = offset; + updateVertical = true; + emit bottomMarginChanged(); + } + + if (d->fill) { + if (updateHorizontal || updateVertical) + d->fillChanged(); + } else { + if (updateHorizontal) + d->updateHorizontalAnchors(); + if (updateVertical) + d->updateVerticalAnchors(); + } + + emit marginsChanged(); } qreal QQuickAnchors::horizontalCenterOffset() const @@ -1067,6 +1122,7 @@ qreal QQuickAnchors::topMargin() const void QQuickAnchors::setTopMargin(qreal offset) { Q_D(QQuickAnchors); + d->topMarginExplicit = true; if (d->topMargin == offset) return; d->topMargin = offset; @@ -1077,6 +1133,20 @@ void QQuickAnchors::setTopMargin(qreal offset) emit topMarginChanged(); } +void QQuickAnchors::resetTopMargin() +{ + Q_D(QQuickAnchors); + d->topMarginExplicit = false; + if (d->topMargin == d->margins) + return; + d->topMargin = d->margins; + if (d->fill) + d->fillChanged(); + else + d->updateVerticalAnchors(); + emit topMarginChanged(); +} + qreal QQuickAnchors::bottomMargin() const { Q_D(const QQuickAnchors); @@ -1086,6 +1156,7 @@ qreal QQuickAnchors::bottomMargin() const void QQuickAnchors::setBottomMargin(qreal offset) { Q_D(QQuickAnchors); + d->bottomMarginExplicit = true; if (d->bottomMargin == offset) return; d->bottomMargin = offset; @@ -1096,6 +1167,20 @@ void QQuickAnchors::setBottomMargin(qreal offset) emit bottomMarginChanged(); } +void QQuickAnchors::resetBottomMargin() +{ + Q_D(QQuickAnchors); + d->bottomMarginExplicit = false; + if (d->bottomMargin == d->margins) + return; + d->bottomMargin = d->margins; + if (d->fill) + d->fillChanged(); + else + d->updateVerticalAnchors(); + emit bottomMarginChanged(); +} + qreal QQuickAnchors::verticalCenterOffset() const { Q_D(const QQuickAnchors); diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h index 3fb3a7b..8890d23 100644 --- a/src/quick/items/qquickanchors_p.h +++ b/src/quick/items/qquickanchors_p.h @@ -67,11 +67,11 @@ class Q_QUICK_PRIVATE_EXPORT QQuickAnchors : public QObject Q_PROPERTY(QQuickAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter NOTIFY verticalCenterChanged) Q_PROPERTY(QQuickAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline NOTIFY baselineChanged) Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged) - Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged) - Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged) + Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin RESET resetLeftMargin NOTIFY leftMarginChanged) + Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin RESET resetRightMargin NOTIFY rightMarginChanged) Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged) - Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged) - Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged) + Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin RESET resetTopMargin NOTIFY topMarginChanged) + Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin RESET resetBottomMargin NOTIFY bottomMarginChanged) Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged) Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged) Q_PROPERTY(QQuickItem *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged) @@ -125,18 +125,22 @@ public: qreal leftMargin() const; void setLeftMargin(qreal); + void resetLeftMargin(); qreal rightMargin() const; void setRightMargin(qreal); + void resetRightMargin(); qreal horizontalCenterOffset() const; void setHorizontalCenterOffset(qreal); qreal topMargin() const; void setTopMargin(qreal); + void resetTopMargin(); qreal bottomMargin() const; void setBottomMargin(qreal); + void resetBottomMargin(); qreal margins() const; void setMargins(qreal); diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h index 0fdcd15..c641745 100644 --- a/src/quick/items/qquickanchors_p_p.h +++ b/src/quick/items/qquickanchors_p_p.h @@ -92,10 +92,13 @@ class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListe Q_DECLARE_PUBLIC(QQuickAnchors) public: QQuickAnchorsPrivate(QQuickItem *i) - : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true), updatingHorizontalAnchor(0), + : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true), + leftMarginExplicit(false), rightMarginExplicit(false), topMarginExplicit(false), + bottomMarginExplicit(false), updatingHorizontalAnchor(0), updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0), centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0) + { } @@ -110,6 +113,10 @@ public: bool updatingMe:1; bool inDestructor:1; bool centerAligned:1; + bool leftMarginExplicit : 1; + bool rightMarginExplicit : 1; + bool topMarginExplicit : 1; + bool bottomMarginExplicit : 1; uint updatingHorizontalAnchor:2; uint updatingVerticalAnchor:2; uint updatingFill:2; @@ -165,6 +172,7 @@ public: qreal hCenterOffset; qreal baselineOffset; + static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) { return static_cast(QObjectPrivate::get(o)); } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 9c43645..d3c8973 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2872,6 +2872,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty *prop) Margins apply to top, bottom, left, right, and fill anchors. The \c anchors.margins property can be used to set all of the various margins at once, to the same value. + It will not override a specific margin that has been previously set; to clear an explicit margin + set it's value to \c undefined. Note that margins are anchor-specific and are not applied if an item does not use anchors. diff --git a/tests/auto/quick/qquickanchors/data/individualMargins.qml b/tests/auto/quick/qquickanchors/data/individualMargins.qml new file mode 100644 index 0000000..ce2899a --- /dev/null +++ b/tests/auto/quick/qquickanchors/data/individualMargins.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Rectangle { + width: 200; height: 200 + Rectangle { + objectName: "filler" + width: 50; height: 50; color: "blue" + anchors.left: parent.left; + anchors.top: parent.top + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 10 + anchors.leftMargin: 5 + anchors.topMargin: 6 + } +} diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp index 45c00e0..b8c3d5b 100644 --- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp +++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp @@ -81,7 +81,9 @@ private slots: void hvCenterRTL(); void fill(); void fillRTL(); + void margins_data(); void margins(); + void marginsRTL_data() { margins_data(); } void marginsRTL(); void stretch(); void baselineOffset(); @@ -635,9 +637,19 @@ void tst_qquickanchors::hvCenterRTL() delete view; } + +void tst_qquickanchors::margins_data() +{ + QTest::addColumn("source"); + + QTest::newRow("fill") << testFileUrl("margins.qml"); + QTest::newRow("individual") << testFileUrl("individualMargins.qml"); +} + void tst_qquickanchors::margins() { - QQuickView *view = new QQuickView(testFileUrl("margins.qml")); + QFETCH(QUrl, source); + QQuickView *view = new QQuickView(source); qApp->processEvents(); QQuickRectangle* rect = findItem(view->rootObject(), QLatin1String("filler")); @@ -656,22 +668,91 @@ void tst_qquickanchors::margins() rectPrivate->anchors()->setMargins(20.0); QCOMPARE(rectPrivate->anchors()->margins(), 20.0); - QEXPECT_FAIL("","QTBUG-24515", Continue); QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0); QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0); QCOMPARE(rectPrivate->anchors()->bottomMargin(), 20.0); QCOMPARE(rectPrivate->anchors()->rightMargin(), 20.0); QCOMPARE(rect->x(), 5.0); - QCOMPARE(rect->y(), 20.0); + QCOMPARE(rect->y(), 0.0); QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0); - QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 20.0); + + rectPrivate->anchors()->setRightMargin(0.0); + rectPrivate->anchors()->setBottomMargin(0.0); + QCOMPARE(rectPrivate->anchors()->margins(), 20.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0); + QCOMPARE(rect->x(), 5.0); + QCOMPARE(rect->y(), 0.0); + QCOMPARE(rect->width(), 200.0 - 5.0 - 0.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 0.0); + + // Test setting margins doesn't have any effect on individual margins with explicit values. + rectPrivate->anchors()->setMargins(50.0); + QCOMPARE(rectPrivate->anchors()->margins(), 50.0); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0); + QCOMPARE(rect->x(), 0.0 + 5.0); + QCOMPARE(rect->y(), 0.0 + 0.0); + QCOMPARE(rect->width(), 200.0 - 5.0 - 0.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 0.0); + + // Test that individual margins that are reset have the same value as margins. + rectPrivate->anchors()->resetLeftMargin(); + rectPrivate->anchors()->resetBottomMargin(); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 50.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 50.0); + QCOMPARE(rect->x(), 0.0 + 50.0); + QCOMPARE(rect->y(), 0.0 + 0.0); + QCOMPARE(rect->width(), 200.0 - 50.0 - 0.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 50.0); + + rectPrivate->anchors()->setMargins(30.0); + QCOMPARE(rectPrivate->anchors()->margins(), 30.0); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 30.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 30.0); + QCOMPARE(rect->x(), 0.0 + 30.0); + QCOMPARE(rect->y(), 0.0 + 0.0); + QCOMPARE(rect->width(), 200.0 - 30.0 - 0.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 30.0); + + rectPrivate->anchors()->resetTopMargin(); + rectPrivate->anchors()->resetRightMargin(); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 30.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 30.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 30.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 30.0); + QCOMPARE(rect->x(), 0.0 + 30.0); + QCOMPARE(rect->y(), 0.0 + 30.0); + QCOMPARE(rect->width(), 200.0 - 30.0 - 30.0); + QCOMPARE(rect->height(), 200.0 - 30.0 - 30.0); + + rectPrivate->anchors()->setMargins(25.0); + QCOMPARE(rectPrivate->anchors()->margins(), 25.0); + QCOMPARE(rectPrivate->anchors()->leftMargin(), 25.0); + QCOMPARE(rectPrivate->anchors()->topMargin(), 25.0); + QCOMPARE(rectPrivate->anchors()->rightMargin(), 25.0); + QCOMPARE(rectPrivate->anchors()->bottomMargin(), 25.0); + QCOMPARE(rect->x(), 0.0 + 25.0); + QCOMPARE(rect->y(), 0.0 + 25.0); + QCOMPARE(rect->width(), 200.0 - 25.0 - 25.0); + QCOMPARE(rect->height(), 200.0 - 25.0 - 25.0); delete view; } void tst_qquickanchors::marginsRTL() { - QQuickView *view = new QQuickView(testFileUrl("margins.qml")); + QFETCH(QUrl, source); + QQuickView *view = new QQuickView(source); QQuickRectangle* rect = findItem(view->rootObject(), QLatin1String("filler")); QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect); @@ -686,9 +767,9 @@ void tst_qquickanchors::marginsRTL() rectPrivate->anchors()->setMargins(20.0); QCOMPARE(rect->x(), 20.0); - QCOMPARE(rect->y(), 20.0); + QCOMPARE(rect->y(), 0.0); QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0); - QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0); + QCOMPARE(rect->height(), 200.0 - 0.0 - 20.0); delete view; } -- 2.7.4