Allow all explicit margins to override margins.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Fri, 29 Jun 2012 07:06:38 +0000 (17:06 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 6 Jul 2012 03:24:45 +0000 (05:24 +0200)
Task-number: QTBUG-24515
Change-Id: Ibfc657dec9fd0c8e71cf3686a04ea7b00ad72c11
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
src/quick/items/qquickanchors.cpp
src/quick/items/qquickanchors_p.h
src/quick/items/qquickanchors_p_p.h
src/quick/items/qquickitem.cpp
tests/auto/quick/qquickanchors/data/individualMargins.qml [new file with mode: 0644]
tests/auto/quick/qquickanchors/tst_qquickanchors.cpp

index 0626c66..9097cc4 100644 (file)
@@ -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);
index 3fb3a7b..8890d23 100644 (file)
@@ -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);
index 0fdcd15..c641745 100644 (file)
@@ -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<QQuickAnchorsPrivate *>(QObjectPrivate::get(o));
     }
index 9c43645..d3c8973 100644 (file)
@@ -2872,6 +2872,8 @@ void QQuickItemPrivate::transform_clear(QQmlListProperty<QQuickTransform> *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 (file)
index 0000000..ce2899a
--- /dev/null
@@ -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
+    }
+}
index 45c00e0..b8c3d5b 100644 (file)
@@ -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<QUrl>("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<QQuickRectangle>(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<QQuickRectangle>(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;
 }