From e7689dbab0e9a491d0ac6ead5b9412bf6ff86be0 Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Wed, 11 Nov 2009 19:22:42 -0300 Subject: QGAL (Test): Fix order of parameters in QCOMPARE The order is relevant when the test fails and QTest prints the failure message refering to the values as the expected and actual ones. Signed-off-by: Eduardo M. Fleury Reviewed-by: Caio Marcelo de Oliveira Filho --- tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp index 0fbd069..bca59c3 100644 --- a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp +++ b/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp @@ -1722,7 +1722,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() QRectF expected = truncate(item.rect); QRectF actual = truncate(widgets[item.index]->geometry()); - QCOMPARE(expected, actual); + QCOMPARE(actual, expected); } // Test mirrored mode @@ -1739,7 +1739,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() QRectF expected = truncate(mirroredRect); QRectF actual = truncate(widgets[item.index]->geometry()); - QCOMPARE(expected, actual); + QCOMPARE(actual, expected); delete widgets[item.index]; } -- cgit v0.12 From 0f5a0ec164b3a5bc1f2a48ae56688a984b990bbd Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Tue, 10 Nov 2009 13:00:44 -0300 Subject: QGAL (Test): Add test to ensure persistency of user-defined spacing Currently the user-defined spacing is saved inside "AnchorData->prefSize". However this value may be modified if spacing is negative or if the anchor's policy is "QSizePolicy::Ignored". Signed-off-by: Eduardo M. Fleury Reviewed-by: Caio Marcelo de Oliveira Filho --- .../tst_qgraphicsanchorlayout.cpp | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index c7ed309..2ad024f 100644 --- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -85,6 +85,7 @@ private slots: void simplificationVsOrder(); void parallelSimplificationOfCenter(); void simplificationVsRedundance(); + void spacingPersistency(); }; class RectWidget : public QGraphicsWidget @@ -1866,5 +1867,30 @@ void tst_QGraphicsAnchorLayout::simplificationVsRedundance() QCOMPARE(usedSimplex(l, Qt::Vertical), false); } +/* + Avoid regression where the saved prefSize would be lost. This was + solved by saving the original spacing in the QGraphicsAnchorPrivate class +*/ +void tst_QGraphicsAnchorLayout::spacingPersistency() +{ + QGraphicsWidget w; + QGraphicsWidget *a = createItem(); + QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w); + + l->addAnchors(l, a, Qt::Horizontal); + QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); + + anchor->setSpacing(-30); + QCOMPARE(anchor->spacing(), -30.0); + + anchor->setSpacing(30); + QCOMPARE(anchor->spacing(), 30.0); + + anchor->setSizePolicy(QSizePolicy::Ignored); + w.effectiveSizeHint(Qt::PreferredSize); + + QCOMPARE(anchor->spacing(), 30.0); +} + QTEST_MAIN(tst_QGraphicsAnchorLayout) #include "tst_qgraphicsanchorlayout.moc" -- cgit v0.12 From bf0e30ce2987a9e93369fe01ab0f01eeb1d3afdb Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Tue, 10 Nov 2009 15:51:53 -0300 Subject: QGAL: Update header documentation in QGALPrivate As part of the refactoring of the setSpacing logic, we are encoraging the analogy between the references to QGraphicsLayoutItem and to QGraphicsAnchor, from the AnchorData point of view. It happens that leaf anchors (ie, those that were not created by the simplification) either represent an item or an user-created anchor. This means that they should fetch their size information either from a QGraphicsLayoutItem (member AnchorData->item) or from a QGraphicsAnchor (member AnchorData->graphicsAnchor). Thus, I'm organizing the header to make it more consistent to the new concept. Signed-off-by: Eduardo M. Fleury Reviewed-by: Caio Marcelo de Oliveira Filho --- src/gui/graphicsview/qgraphicsanchorlayout_p.h | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 5f50c85..26df109 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -121,10 +121,10 @@ struct AnchorData : public QSimplexVariable { }; AnchorData() - : QSimplexVariable(), item(0), from(0), to(0), + : QSimplexVariable(), from(0), to(0), minSize(0), prefSize(0), maxSize(0), sizeAtMinimum(0), sizeAtPreferred(0), - sizeAtMaximum(0), + sizeAtMaximum(0), item(0), graphicsAnchor(0), skipInPreferred(0), type(Normal), hasSize(true), isLayoutAnchor(false), isCenterAnchor(false), orientation(0), @@ -152,27 +152,32 @@ struct AnchorData : public QSimplexVariable { hasSize = false; } - // Internal anchors have associated items - QGraphicsLayoutItem *item; - // Anchor is semantically directed AnchorVertex *from; AnchorVertex *to; - // Size restrictions of this edge. For anchors internal to items, these - // values are derived from the respective item size hints. For anchors - // that were added by users, these values are equal to the specified anchor - // size. + // Nominal sizes + // These are the intrinsic size restrictions for a given item. They are + // used as input for the calculation of the actual sizes. + // These values are filled by the refreshSizeHints method, based on the + // anchor size policy, the size hints of the item it (possibly) represents + // and the layout spacing information. qreal minSize; qreal prefSize; qreal maxSize; + // Calculated sizes // These attributes define which sizes should that anchor be in when the // layout is at its minimum, preferred or maximum sizes. Values are // calculated by the Simplex solver based on the current layout setup. qreal sizeAtMinimum; qreal sizeAtPreferred; qreal sizeAtMaximum; + + // References to the classes that represent this anchor in the public world + // An anchor may represent a LayoutItem, it may also be acessible externally + // through a GraphicsAnchor "handler". + QGraphicsLayoutItem *item; QGraphicsAnchor *graphicsAnchor; uint skipInPreferred : 1; -- cgit v0.12 From 6cc1703af1f403168b7251616a7685aa83de8caa Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Tue, 10 Nov 2009 16:55:43 -0300 Subject: QGAL: Move size information from AnchorData to QGraphicsAnchorPrivate To solve the spacing persistency bug, this commit saves the preferredSize (spacing) information inside QGraphicsAnchorPrivate. The problem started when we could not rely on "AnchorData->prefSize" to keep the spacing information for user-defined anchors. This happens because that member can be overriden if the spacing is negative (anchor is inverted) or its sizePolicy is of type "Ignored" (it is overriden by minSize). Then, to decide where to store it, we aimed to make something similar to what happens with item-internal anchors. Those can rely on their items to get fresh information regarding their size, so we decided that user-anchors (that don't have items, but do have QGraphicsAnchors) could read such information from there. This refactory also reduced the deep indirection that existed in the "QGraphicsAnchor->setSpacing" call. Previously it would call internal layout methods to do some black magic, that's now gone. As the spacing information is now stored in the anchor itself, it can do pretty much all the work and, after that, just invalidate the layout. Also, moved information like "AnchorData->hasSize" to QGAnchor as its pretty much related to the preferredSize information itself. Signed-off-by: Eduardo M. Fleury Reviewed-by: Caio Marcelo de Oliveira Filho --- src/gui/graphicsview/qgraphicsanchorlayout.h | 1 + src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 148 +++++++++-------------- src/gui/graphicsview/qgraphicsanchorlayout_p.h | 25 ++-- 3 files changed, 66 insertions(+), 108 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index 01c3a86..1a0c458 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -76,6 +76,7 @@ private: Q_DECLARE_PRIVATE(QGraphicsAnchor) friend class QGraphicsAnchorLayoutPrivate; + friend class AnchorData; }; class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 182594e..872fecb 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -55,7 +55,8 @@ QT_BEGIN_NAMESPACE QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) : QObjectPrivate(version), layoutPrivate(0), data(0), - sizePolicy(QSizePolicy::Fixed) + sizePolicy(QSizePolicy::Fixed), preferredSize(0), + hasSize(true), reversed(false) { } @@ -76,31 +77,60 @@ void QGraphicsAnchorPrivate::setSizePolicy(QSizePolicy::Policy policy) void QGraphicsAnchorPrivate::setSpacing(qreal value) { - if (data) { - layoutPrivate->setAnchorSize(data, &value); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return; } + + const qreal rawValue = reversed ? -preferredSize : preferredSize; + if (hasSize && (rawValue == value)) + return; + + // The anchor has an user-defined size + hasSize = true; + + // The simplex solver cannot handle negative sizes. To workaround that, + // if value is less than zero, we reverse the anchor and set the absolute + // value; + if (value >= 0) { + preferredSize = value; + if (reversed) + qSwap(data->from, data->to); + reversed = false; + } else { + preferredSize = -value; + if (!reversed) + qSwap(data->from, data->to); + reversed = true; + } + + layoutPrivate->q_func()->invalidate(); } void QGraphicsAnchorPrivate::unsetSpacing() { - if (data) { - layoutPrivate->setAnchorSize(data, 0); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return; } + + // Return to standard direction + hasSize = false; + if (reversed) + qSwap(data->from, data->to); + reversed = false; + + layoutPrivate->q_func()->invalidate(); } qreal QGraphicsAnchorPrivate::spacing() const { - qreal size = 0; - if (data) { - layoutPrivate->anchorSize(data, 0, &size, 0); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return 0; } - return size; + + return reversed ? -preferredSize : preferredSize; } @@ -146,8 +176,8 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) qreal prefSizeHint; qreal maxSizeHint; - // It is an internal anchor if (item) { + // It is an internal anchor, fetch size information from the item if (isLayoutAnchor) { minSize = 0; prefSize = 0; @@ -175,14 +205,16 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) } } } else { + // It is a user-created anchor, fetch size information from the associated QGraphicsAnchor Q_ASSERT(graphicsAnchor); - policy = graphicsAnchor->sizePolicy(); + QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func(); + policy = anchorPrivate->sizePolicy; minSizeHint = 0; - if (hasSize) { + if (anchorPrivate->hasSize) { // One can only configure the preferred size of a normal anchor. Their minimum and // maximum "size hints" are always 0 and QWIDGETSIZE_MAX, correspondingly. However, // their effective size hints might be narrowed down due to their size policies. - prefSizeHint = prefSize; + prefSizeHint = anchorPrivate->preferredSize; } else { const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1); qreal s = styleInfo->defaultSpacing(orient); @@ -1565,7 +1597,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); AnchorData *data = new AnchorData; - if (!spacing) { + QGraphicsAnchor *graphicsAnchor = acquireGraphicsAnchor(data); + + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); + + if (spacing) { + graphicsAnchor->setSpacing(*spacing); + } else { // If firstItem or secondItem is the layout itself, the spacing will default to 0. // Otherwise, the following matrix is used (questionmark means that the spacing // is queried from the style): @@ -1578,22 +1616,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi || secondItem == q || pickEdge(firstEdge, Horizontal) == Qt::AnchorHorizontalCenter || oppositeEdge(firstEdge) != secondEdge) { - data->setPreferredSize(0); + graphicsAnchor->setSpacing(0); } else { - data->unsetSize(); + graphicsAnchor->unsetSpacing(); } - addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); - - } else if (*spacing >= 0) { - data->setPreferredSize(*spacing); - addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); - - } else { - data->setPreferredSize(-*spacing); - addAnchor_helper(secondItem, secondEdge, firstItem, firstEdge, data); } - return acquireGraphicsAnchor(data); + return graphicsAnchor; } void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, @@ -1753,67 +1782,6 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorV removeInternalVertex(v2->m_item, v2->m_edge); } -/*! - \internal - Only called from outside. (calls invalidate()) -*/ -void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal *anchorSize) -{ - Q_Q(QGraphicsAnchorLayout); - // ### we can avoid restoration if we really want to, but we would have to - // search recursively through all composite anchors - Q_ASSERT(data); - restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); - - QGraphicsLayoutItem *firstItem = data->from->m_item; - QGraphicsLayoutItem *secondItem = data->to->m_item; - Qt::AnchorPoint firstEdge = data->from->m_edge; - Qt::AnchorPoint secondEdge = data->to->m_edge; - - // Use heuristics to find out what the user meant with this anchor. - correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); - if (data->from->m_item != firstItem) - qSwap(data->from, data->to); - - if (anchorSize) { - // ### The current implementation makes "setAnchorSize" behavior - // dependent on the argument order for cases where we have - // no heuristic. Ie. two widgets, same anchor point. - - // We cannot have negative sizes inside the graph. This would cause - // the simplex solver to fail because all simplex variables are - // positive by definition. - // "negative spacing" is handled by inverting the standard item order. - if (*anchorSize >= 0) { - data->setPreferredSize(*anchorSize); - } else { - data->setPreferredSize(-*anchorSize); - qSwap(data->from, data->to); - } - } else { - data->unsetSize(); - } - q->invalidate(); -} - -void QGraphicsAnchorLayoutPrivate::anchorSize(const AnchorData *data, - qreal *minSize, - qreal *prefSize, - qreal *maxSize) const -{ - Q_ASSERT(minSize || prefSize || maxSize); - Q_ASSERT(data); - QGraphicsAnchorLayoutPrivate *that = const_cast(this); - that->restoreSimplifiedGraph(Orientation(data->orientation)); - - if (minSize) - *minSize = data->minSize; - if (prefSize) - *prefSize = data->prefSize; - if (maxSize) - *maxSize = data->maxSize; -} - AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) { diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 26df109..cb8c4dd 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -126,7 +126,7 @@ struct AnchorData : public QSimplexVariable { sizeAtMinimum(0), sizeAtPreferred(0), sizeAtMaximum(0), item(0), graphicsAnchor(0), skipInPreferred(0), - type(Normal), hasSize(true), isLayoutAnchor(false), + type(Normal), isLayoutAnchor(false), isCenterAnchor(false), orientation(0), dependency(Independent) {} @@ -141,17 +141,6 @@ struct AnchorData : public QSimplexVariable { QString name; #endif - inline void setPreferredSize(qreal size) - { - prefSize = size; - hasSize = true; - } - - inline void unsetSize() - { - hasSize = false; - } - // Anchor is semantically directed AnchorVertex *from; AnchorVertex *to; @@ -182,7 +171,6 @@ struct AnchorData : public QSimplexVariable { uint skipInPreferred : 1; uint type : 2; // either Normal, Sequential or Parallel - uint hasSize : 1; // if false, get size from style. uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor uint isCenterAnchor : 1; uint orientation : 1; @@ -355,7 +343,13 @@ public: QGraphicsAnchorLayoutPrivate *layoutPrivate; AnchorData *data; + + // Size information for user controlled anchor QSizePolicy::Policy sizePolicy; + qreal preferredSize; + + uint hasSize : 1; // if false, get size from style. + uint reversed : 1; // if true, the anchor was inverted to keep its value positive }; @@ -450,11 +444,6 @@ public: void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); - void setAnchorSize(AnchorData *data, const qreal *anchorSize); - void anchorSize(const AnchorData *data, - qreal *minSize = 0, - qreal *prefSize = 0, - qreal *maxSize = 0) const; void removeAnchors(QGraphicsLayoutItem *item); -- cgit v0.12 From 604b6d9d00e36de7ed516e4fa5c277946216f1e9 Mon Sep 17 00:00:00 2001 From: "Eduardo M. Fleury" Date: Thu, 12 Nov 2009 13:48:54 -0300 Subject: QGAL: Update code documentation Signed-off-by: Eduardo M. Fleury Reviewed-by: Caio Marcelo de Oliveira Filho --- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 39 ++++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 872fecb..a15e473 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -1537,15 +1537,21 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * /*! * \internal + * Implements the high level "addAnchor" feature. Called by the public API + * addAnchor method. * - * Helper function that is called from the anchor functions in the public API. - * If \a spacing is 0, it will pick up the spacing defined by the style. + * The optional \a spacing argument defines the size of the anchor. If not provided, + * the anchor size is either 0 or not-set, depending on type of anchor created (see + * matrix below). + * + * All anchors that remain with size not-set will assume the standard spacing, + * set either by the layout style or through the "setSpacing" layout API. */ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing) + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing) { Q_Q(QGraphicsAnchorLayout); if ((firstItem == 0) || (secondItem == 0)) { @@ -1625,11 +1631,20 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi return graphicsAnchor; } +/* + \internal + + This method adds an AnchorData to the internal graph. It is responsible for doing + the boilerplate part of such task. + + If another AnchorData exists between the mentioned vertices, it is deleted and + the new one is inserted. +*/ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - AnchorData *data) + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + AnchorData *data) { Q_Q(QGraphicsAnchorLayout); @@ -1639,13 +1654,11 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt // anchor manipulation always happen in the full graph restoreSimplifiedGraph(orientation); - // Is the Vertex (firstItem, firstEdge) already represented in our - // internal structure? + // Create or increase the reference count for the related vertices. AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge); AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge); // Remove previous anchor - // ### Could we update the existing edgeData rather than creating a new one? if (graph[orientation].edgeData(v1, v2)) { removeAnchor_helper(v1, v2); } -- cgit v0.12 From 41cc464ec332033127b88433ffa0a2a990fec83d Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Wed, 11 Nov 2009 22:09:11 -0300 Subject: QGAL: fix update size hints logic in parallel anchors When filling sizeAt* values for parallel anchors, we have to identify the case when the second anchor in the parallel doesn't have the same direction as the parallel itself. However, relying on the parallel group vertices to identify this case is not safe, because after a parallel group a new vertex simplification can happen. So, the comparing the 'from' with the first edge is the correct way to verify whether the second is backwards. Code was fixed to follow that. Note that, without negative spacing the case "out-of-order" for parallels is only the trivial case (size == 0). Signed-off-by: Caio Marcelo de Oliveira Filho Reviewed-by: Eduardo M. Fleury --- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index a15e473..8520ebd 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -256,8 +256,13 @@ void ParallelAnchorData::updateChildrenSizes() firstEdge->sizeAtPreferred = sizeAtPreferred; firstEdge->sizeAtMaximum = sizeAtMaximum; - const bool secondFwd = (secondEdge->from == from); - if (secondFwd) { + // We have the convention that the first children will define the direction of the + // pararell group. So we can check whether the second edge is "forward" in relation + // to the group if it have the same direction as the first edge. Note that we don't + // use 'this->from' because it might be changed by vertex simplification. + const bool secondForward = (firstEdge->from == secondEdge->from); + + if (secondForward) { secondEdge->sizeAtMinimum = sizeAtMinimum; secondEdge->sizeAtPreferred = sizeAtPreferred; secondEdge->sizeAtMaximum = sizeAtMaximum; @@ -287,10 +292,12 @@ bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleIn // Account for parallel anchors where the second edge is backwards. // We rely on the fact that a forward anchor of sizes min, pref, max is equivalent // to a backwards anchor of size (-max, -pref, -min) - const bool secondFwd = (secondEdge->from == from); - const qreal secondMin = secondFwd ? secondEdge->minSize : -secondEdge->maxSize; - const qreal secondPref = secondFwd ? secondEdge->prefSize : -secondEdge->prefSize; - const qreal secondMax = secondFwd ? secondEdge->maxSize : -secondEdge->minSize; + + // Also see comments in updateChildrenSizes(). + const bool secondForward = (firstEdge->from == secondEdge->from); + const qreal secondMin = secondForward ? secondEdge->minSize : -secondEdge->maxSize; + const qreal secondPref = secondForward ? secondEdge->prefSize : -secondEdge->prefSize; + const qreal secondMax = secondForward ? secondEdge->maxSize : -secondEdge->minSize; minSize = qMax(firstEdge->minSize, secondMin); maxSize = qMin(firstEdge->maxSize, secondMax); -- cgit v0.12 From 7a11b8ca00f49e22cfd3706b59606775d6792e29 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Wed, 11 Nov 2009 16:37:53 -0300 Subject: QGAL: remove the caching of simplified graph After discussion with Jan-Arve, we decided to remove for good the caching of simplified graph. This avoided recalculating the simplification (but not the simplex) in some situations. Since vertex simplification, this was temporarily disabled already. To know whether if we could the cached version or not, we needed to track individual anchors to see whether they reached size 0 or they were 0 and changed the size. This is because the vertex simplification depend on that fact. Now the simplified version of the graph exists only during the execution of calculateGraphs() function. This and next commits clear up the code to take advantage of that fact. Signed-off-by: Caio Marcelo de Oliveira Filho Reviewed-by: Eduardo M. Fleury --- src/gui/graphicsview/qgraphicsanchorlayout.cpp | 3 - src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 89 ++++++------------------ src/gui/graphicsview/qgraphicsanchorlayout_p.h | 2 - 3 files changed, 22 insertions(+), 72 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 872ec3c..7e5929e 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -477,9 +477,6 @@ void QGraphicsAnchorLayout::removeAt(int index) return; // Removing an item affects both horizontal and vertical graphs - d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Horizontal); - d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Vertical); - d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal); d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical); d->removeAnchors(item); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 8520ebd..5b1e36c 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -62,8 +62,6 @@ QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() { - // ### - layoutPrivate->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Orientation(data->orientation)); layoutPrivate->removeAnchor(data->from, data->to); } @@ -529,7 +527,6 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() interpolationProgress[i] = -1; spacings[i] = -1; - graphSimplified[i] = false; graphHasConflicts[i] = false; layoutFirstVertex[i] = 0; @@ -735,16 +732,18 @@ static AnchorData *createSequence(Graph *graph, */ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) { - static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - if (noSimplification || items.isEmpty()) + if (items.isEmpty()) return true; - if (graphSimplified[orientation]) - return true; - -#if 0 +#if defined(QT_DEBUG) && 0 qDebug("Simplifying Graph for %s", orientation == Horizontal ? "Horizontal" : "Vertical"); + + static int count = 0; + if (orientation == Horizontal) { + count++; + dumpGraph(QString::fromAscii("%1-full").arg(count)); + } #endif // Vertex simplification @@ -762,13 +761,16 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) // Note that if we are not feasible, we fallback and make sure that the graph is fully restored if (!feasible) { - graphSimplified[orientation] = true; restoreSimplifiedGraph(orientation); restoreVertices(orientation); return false; } - graphSimplified[orientation] = true; +#if defined(QT_DEBUG) && 0 + dumpGraph(QString::fromAscii("%1-simplified-%2").arg(count).arg( + QString::fromAscii(orientation == Horizontal ? "Horizontal" : "Vertical"))); +#endif + return true; } @@ -1173,10 +1175,6 @@ void QGraphicsAnchorLayoutPrivate::restoreSimplifiedConstraints(ParallelAnchorDa void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation) { - if (!graphSimplified[orientation]) - return; - graphSimplified[orientation] = false; - #if 0 qDebug("Restoring Simplified Graph for %s", orientation == Horizontal ? "Horizontal" : "Vertical"); @@ -1331,8 +1329,6 @@ void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) { - Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); - items.append(item); // Create horizontal and vertical internal anchors for the item and @@ -1375,8 +1371,6 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Check if vertex already exists if (internalVertex(item, centerEdge)) return; @@ -1443,8 +1437,6 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Orientation code Qt::AnchorPoint firstEdge; Qt::AnchorPoint lastEdge; @@ -1512,8 +1504,6 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation) { - Q_ASSERT(!graphSimplified[orientation]); - // Remove the item center constraints associated to this item // ### This is a temporary solution. We should probably use a better // data structure to hold items and/or their associated constraints @@ -1579,10 +1569,6 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi return 0; } - // Guarantee that the graph is no simplified when adding this anchor, - // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(edgeOrientation(firstEdge)); - // In QGraphicsAnchorLayout, items are represented in its internal // graph as four anchors that connect: // - Left -> HCenter @@ -1592,12 +1578,10 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi // Ensure that the internal anchors have been created for both items. if (firstItem != q && !items.contains(firstItem)) { - restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); createItemEdges(firstItem); addChildLayoutItem(firstItem); } if (secondItem != q && !items.contains(secondItem)) { - restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); createItemEdges(secondItem); addChildLayoutItem(secondItem); } @@ -1657,10 +1641,6 @@ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstIt const Orientation orientation = edgeOrientation(firstEdge); - // Guarantee that the graph is no simplified when adding this anchor, - // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(orientation); - // Create or increase the reference count for the related vertices. AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge); AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge); @@ -1696,15 +1676,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *fi QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { - Orientation orient = edgeOrientation(firstEdge); - restoreSimplifiedGraph(orient); - + const Orientation orientation = edgeOrientation(firstEdge); AnchorVertex *v1 = internalVertex(firstItem, firstEdge); AnchorVertex *v2 = internalVertex(secondItem, secondEdge); QGraphicsAnchor *graphicsAnchor = 0; - AnchorData *data = graph[orient].edgeData(v1, v2); + AnchorData *data = graph[orientation].edgeData(v1, v2); if (data) graphicsAnchor = acquireGraphicsAnchor(data); return graphicsAnchor; @@ -1789,12 +1767,9 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex, void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2) { Q_ASSERT(v1 && v2); - // Guarantee that the graph is no simplified when removing this anchor, - // anchor manipulation always happen in the full graph - Orientation o = edgeOrientation(v1->m_edge); - restoreSimplifiedGraph(o); // Remove edge from graph + const Orientation o = edgeOrientation(v1->m_edge); graph[o].removeEdge(v1, v2); // Decrease vertices reference count (may trigger a deletion) @@ -1867,8 +1842,6 @@ void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::A void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) { - Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); - // remove the center anchor first!! removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false); removeVertex(item, Qt::AnchorLeft); @@ -1971,20 +1944,8 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs() { if (!calculateGraphCacheDirty) return; - -#if defined(QT_DEBUG) && 0 - static int count = 0; - count++; - dumpGraph(QString::fromAscii("%1-before").arg(count)); -#endif - calculateGraphs(Horizontal); calculateGraphs(Vertical); - -#if defined(QT_DEBUG) && 0 - dumpGraph(QString::fromAscii("%1-after").arg(count)); -#endif - calculateGraphCacheDirty = false; } @@ -2032,18 +1993,9 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( lastCalculationUsedSimplex[orientation] = false; #endif - // ### This is necessary because now we do vertex simplification, we still don't know - // differentiate between invalidate()s that doesn't need resimplification and those which - // need. For example, when size hint of an item changes, this may cause an anchor to reach 0 or to - // leave 0 and get a size. In both cases we need resimplify. - // - // ### one possible solution would be tracking all the 0-sized anchors, if this set change, we need - // resimplify. - restoreSimplifiedGraph(orientation); + static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - // Reset the nominal sizes of each anchor based on the current item sizes. This function - // works with both simplified and non-simplified graphs, so it'll work when the - // simplification is going to be reused. + // Reset the nominal sizes of each anchor based on the current item sizes. if (!refreshAllSizeHints(orientation)) { qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); graphHasConflicts[orientation] = true; @@ -2051,7 +2003,7 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( } // Simplify the graph - if (!simplifyGraph(orientation)) { + if (simplificationEnabled && !simplifyGraph(orientation)) { qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); graphHasConflicts[orientation] = true; return; @@ -2115,6 +2067,9 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( qDeleteAll(constraints[orientation]); constraints[orientation].clear(); graphPaths[orientation].clear(); // ### + + if (simplificationEnabled) + restoreSimplifiedGraph(orientation); } /*! diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index cb8c4dd..7e2e00e 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -570,8 +570,6 @@ public: Interval interpolationInterval[2]; qreal interpolationProgress[2]; - // ### - bool graphSimplified[2]; bool graphHasConflicts[2]; QSet m_floatItems[2]; -- cgit v0.12 From e52ce79b8eee44742d71bf945e806aa2db06818b Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Thu, 12 Nov 2009 10:30:15 -0300 Subject: QGAL: clean up interpolation code Now the interpolation doesn't need to know how to traverse complex anchors, since when it runs, the graph is not simplified anymore. This commit removes unnecessary code for dealing with that. Signed-off-by: Caio Marcelo de Oliveira Filho Reviewed-by: Eduardo M. Fleury --- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 109 ++++------------------- src/gui/graphicsview/qgraphicsanchorlayout_p.h | 2 - 2 files changed, 16 insertions(+), 95 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 5b1e36c..7646d4c 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -2564,21 +2564,6 @@ void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom) } /*! - \internal - - Fill the distance in the vertex and in the sub-vertices if its a combined vertex. -*/ -static void setVertexDistance(AnchorVertex *v, qreal distance) -{ - v->distance = distance; - if (v->m_type == AnchorVertex::Pair) { - AnchorVertexPair *pair = static_cast(v); - setVertexDistance(pair->m_first, distance); - setVertexDistance(pair->m_second, distance); - } -} - -/*! \internal Calculate the position of each vertex based on the paths to each of @@ -2593,7 +2578,7 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( // Get root vertex AnchorVertex *root = layoutFirstVertex[orientation]; - setVertexDistance(root, 0); + root->distance = 0; visited.insert(root); // Add initial edges to the queue @@ -2604,16 +2589,12 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( // Do initial calculation required by "interpolateEdge()" setupEdgesInterpolation(orientation); - // Traverse the graph and calculate vertex positions, we need to - // visit all pairs since each of them could have a sequential - // anchor inside, which hides more vertices. + // Traverse the graph and calculate vertex positions while (!queue.isEmpty()) { QPair pair = queue.dequeue(); AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); - // Both vertices were interpolated, and the anchor itself can't have other - // anchors inside (it's not a complex anchor). - if (edge->type == AnchorData::Normal && visited.contains(pair.second)) + if (visited.contains(pair.second)) continue; visited.insert(pair.second); @@ -2653,24 +2634,20 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( } /*! - \internal - - Calculate the current Edge size based on the current Layout size and the - size the edge is supposed to have when the layout is at its: + \internal - - minimum size, - - preferred size, - - maximum size. + Calculate the current Edge size based on the current Layout size and the + size the edge is supposed to have when the layout is at its: - These three key values are calculated in advance using linear - programming (more expensive) or the simplification algorithm, then - subsequential resizes of the parent layout require a simple - interpolation. + - minimum size, + - preferred size, + - maximum size. - If the edge is sequential or parallel, it's possible to have more - vertices to be initalized, so it calls specialized functions that - will recurse back to interpolateEdge(). - */ + These three key values are calculated in advance using linear + programming (more expensive) or the simplification algorithm, then + subsequential resizes of the parent layout require a simple + interpolation. +*/ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorData *edge) { const Orientation orientation = Orientation(edge->orientation); @@ -2684,64 +2661,10 @@ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorDat // Calculate the distance for the vertex opposite to the base if (edge->from == base) { - setVertexDistance(edge->to, base->distance + edgeDistance); + edge->to->distance = base->distance + edgeDistance; } else { - setVertexDistance(edge->from, base->distance - edgeDistance); - } - - // Process child anchors - if (edge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast(edge)); - else if (edge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast(edge)); -} - -void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(ParallelAnchorData *data) -{ - // In parallels the boundary vertices are already calculate, we - // just need to look for sequential groups inside, because only - // them may have new vertices associated. - - // First edge - if (data->firstEdge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast(data->firstEdge)); - else if (data->firstEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast(data->firstEdge)); - - // Second edge - if (data->secondEdge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast(data->secondEdge)); - else if (data->secondEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast(data->secondEdge)); -} - -void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(SequentialAnchorData *data) -{ - // This method is supposed to handle any sequential anchor, even out-of-order - // ones. However, in the current QGAL implementation we should get only the - // well behaved ones. - Q_ASSERT(data->m_edges.first()->from == data->from); - Q_ASSERT(data->m_edges.last()->to == data->to); - - // At this point, the two outter vertices already have their distance - // calculated. - // We use the first as the base to calculate the internal ones - - AnchorVertex *prev = data->from; - - for (int i = 0; i < data->m_edges.count() - 1; ++i) { - AnchorData *edge = data->m_edges.at(i); - interpolateEdge(prev, edge); - - // Use the recently calculated vertex as the base for the next one - const bool edgeIsForward = (edge->from == prev); - prev = edgeIsForward ? edge->to : edge->from; + edge->from->distance = base->distance - edgeDistance; } - - // Treat the last specially, since we already calculated it's end - // vertex, so it's only interesting if it's a complex one - if (data->m_edges.last()->type != AnchorData::Normal) - interpolateEdge(prev, data->m_edges.last()); } bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList &constraints, diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 7e2e00e..fd82dd9 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -522,8 +522,6 @@ public: void calculateVertexPositions(Orientation orientation); void setupEdgesInterpolation(Orientation orientation); void interpolateEdge(AnchorVertex *base, AnchorData *edge); - void interpolateSequentialEdges(SequentialAnchorData *edge); - void interpolateParallelEdges(ParallelAnchorData *edge); // Linear Programming solver methods bool solveMinMax(const QList &constraints, -- cgit v0.12 From 3dcc9d6bc6385e2c4f4d7d7366c84b6dcc74508c Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Thu, 12 Nov 2009 12:21:51 -0300 Subject: QGAL: clean up size hint refresh code The code for refreshing size hints of items / user-created anchors now happens with a graph in full (not simplified). So we don't need to now how to refresh size hints for complex anchors. The code for refreshing complex anchors was used also to initialize the complex anchors (the '_helper' functions). Those were changed to calculateSizeHints() and refreshSizeHints() doesn't need to be virtual anymore. Signed-off-by: Caio Marcelo de Oliveira Filho Reviewed-by: Eduardo M. Fleury --- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 78 +++++++----------------- src/gui/graphicsview/qgraphicsanchorlayout_p.h | 12 ++-- 2 files changed, 25 insertions(+), 65 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 7646d4c..2e80857 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -167,7 +167,7 @@ static void internalSizeHints(QSizePolicy::Policy policy, *prefSize = prefSizeHint; } -bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) +void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) { QSizePolicy::Policy policy; qreal minSizeHint; @@ -182,7 +182,7 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) maxSize = QWIDGETSIZE_MAX; if (isCenterAnchor) maxSize /= 2; - return true; + return; } else { if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) { policy = item->sizePolicy().horizontalPolicy(); @@ -244,8 +244,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } void ParallelAnchorData::updateChildrenSizes() @@ -274,18 +272,11 @@ void ParallelAnchorData::updateChildrenSizes() secondEdge->updateChildrenSizes(); } -bool ParallelAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) +bool ParallelAnchorData::calculateSizeHints() { - return refreshSizeHints_helper(styleInfo); -} - -bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, - bool refreshChildren) -{ - if (refreshChildren && (!firstEdge->refreshSizeHints(styleInfo) - || !secondEdge->refreshSizeHints(styleInfo))) { - return false; - } + // Note that parallel groups can lead to unfeasibility, so during calculation, we can + // find out one unfeasibility. Because of that this method return boolean. This can't + // happen in sequential, so there the method is void. // Account for parallel anchors where the second edge is backwards. // We rely on the fact that a forward anchor of sizes min, pref, max is equivalent @@ -423,13 +414,7 @@ void SequentialAnchorData::updateChildrenSizes() } } -bool SequentialAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) -{ - return refreshSizeHints_helper(styleInfo); -} - -bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, - bool refreshChildren) +void SequentialAnchorData::calculateSizeHints() { minSize = 0; prefSize = 0; @@ -437,11 +422,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style for (int i = 0; i < m_edges.count(); ++i) { AnchorData *edge = m_edges.at(i); - - // If it's the case refresh children information first - if (refreshChildren && !edge->refreshSizeHints(styleInfo)) - return false; - minSize += edge->minSize; prefSize += edge->prefSize; maxSize += edge->maxSize; @@ -451,8 +431,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } #ifdef QT_DEBUG @@ -627,7 +605,7 @@ AnchorData *QGraphicsAnchorLayoutPrivate::addAnchorMaybeParallel(AnchorData *new // At this point we can identify that the parallel anchor is not feasible, e.g. one // anchor minimum size is bigger than the other anchor maximum size. - *feasible = parallel->refreshSizeHints_helper(0, false); + *feasible = parallel->calculateSizeHints(); newAnchor = parallel; } @@ -688,7 +666,7 @@ static AnchorData *createSequence(Graph *graph, sequence->from = before; sequence->to = after; - sequence->refreshSizeHints_helper(0, false); + sequence->calculateSizeHints(); return sequence; } @@ -1335,11 +1313,11 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) // refresh its size hint / policy values. AnchorData *data = new AnchorData; addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data); - data->refreshSizeHints(0); // 0 = effectiveSpacing, will not be used + data->refreshSizeHints(); data = new AnchorData; addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data); - data->refreshSizeHints(0); // 0 = effectiveSpacing, will not be used + data->refreshSizeHints(); } /*! @@ -1399,14 +1377,14 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( addAnchor_helper(item, firstEdge, item, centerEdge, data); data->isCenterAnchor = true; data->dependency = AnchorData::Master; - data->refreshSizeHints(0); + data->refreshSizeHints(); data = new AnchorData; c->variables.insert(data, -1.0); addAnchor_helper(item, centerEdge, item, lastEdge, data); data->isCenterAnchor = true; data->dependency = AnchorData::Slave; - data->refreshSizeHints(0); + data->refreshSizeHints(); itemCenterConstraints[orientation].append(c); @@ -1473,7 +1451,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( // Create the new anchor that should substitute the left-center-right anchors. AnchorData *data = new AnchorData; addAnchor_helper(item, firstEdge, item, lastEdge, data); - data->refreshSizeHints(0); + data->refreshSizeHints(); // Remove old anchors removeAnchor_helper(first, center); @@ -1995,12 +1973,8 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - // Reset the nominal sizes of each anchor based on the current item sizes. - if (!refreshAllSizeHints(orientation)) { - qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); - graphHasConflicts[orientation] = true; - return; - } + // Reset the nominal sizes of each anchor based on the current item sizes + refreshAllSizeHints(orientation); // Simplify the graph if (simplificationEnabled && !simplifyGraph(orientation)) { @@ -2169,29 +2143,19 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList &g = graph[orientation]; QList > vertices = g.connections(); QLayoutStyleInfo styleInf = styleInfo(); for (int i = 0; i < vertices.count(); ++i) { - AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);; - Q_ASSERT(data->from && data->to); - - // During the traversal we check the feasibility of the complex anchors. - if (!data->refreshSizeHints(&styleInf)) - return false; + AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second); + data->refreshSizeHints(&styleInf); } - - return true; } /*! diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index fd82dd9..2b365fb 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -131,7 +131,7 @@ struct AnchorData : public QSimplexVariable { dependency(Independent) {} virtual void updateChildrenSizes() {} - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); + void refreshSizeHints(const QLayoutStyleInfo *styleInfo = 0); virtual ~AnchorData() {} @@ -197,9 +197,7 @@ struct SequentialAnchorData : public AnchorData } virtual void updateChildrenSizes(); - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - - bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); + void calculateSizeHints(); QVector m_children; // list of vertices in the sequence QVector m_edges; // keep the list of edges too. @@ -226,9 +224,7 @@ struct ParallelAnchorData : public AnchorData } virtual void updateChildrenSizes(); - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - - bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); + bool calculateSizeHints(); AnchorData* firstEdge; AnchorData* secondEdge; @@ -483,7 +479,7 @@ public: const QList &variables); // Support functions for calculateGraph() - bool refreshAllSizeHints(Orientation orientation); + void refreshAllSizeHints(Orientation orientation); void findPaths(Orientation orientation); void constraintsFromPaths(Orientation orientation); void updateAnchorSizes(Orientation orientation); -- cgit v0.12