diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-08-12 07:33:37 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-08-12 08:55:48 (GMT) |
commit | d67b7829e7d5d8fbd57b701f4268dc1c6d77f1b0 (patch) | |
tree | d036ef35cf109fb171c6998aebb5ca6f515d66d8 | |
parent | 1d3de98158b9409fa63e2e7cf8d3ca8b77f26285 (diff) | |
download | Qt-d67b7829e7d5d8fbd57b701f4268dc1c6d77f1b0.zip Qt-d67b7829e7d5d8fbd57b701f4268dc1c6d77f1b0.tar.gz Qt-d67b7829e7d5d8fbd57b701f4268dc1c6d77f1b0.tar.bz2 |
Fix a bug in removeAnchors and reorder how anchors are removed.
The problem was that if an item had a center anchor and we removed the
left-center anchor before we called removeCenterAnchors().
Suppose the center vertex had 3 edges, (refcount was 3)
removeAnchor would then *first* remove the left-center edge, causing the
internalVertex refcount to go to 2. That would cause removeInternalVertex()
to try to "merge" the two center anchors by calling removeCenterAnchors().
Of course, calling removeCenterAnchors at that point did not work since
removeCenterAnchors() assumed that the only two edges connected to the center
vertex was its internal left-center and center-right anchors. This was not
the case, and the assertion
Q_ASSERT(first && center && last);
was triggered, since first (or last) was removed at that point.
Of course it was not enough to simply call removeCenterAnchors first,
because that function assumed that the only two anchors connected to the
center vertex was "internal center anchors".
removeAnchors is a bit special since we are not really interested in
first converting the "internal center anchors" to a single internal anchor
because the ultimate goal of that function is to remove *all* anchors.
The solution was the additional argument "substitute" to indicate
that we really just want to substitute with a simpler anchor (normal
behaviour). If not, we really just want to delete the center anchors (don't
even try to merge them into a simple internal anchor).
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 97 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.h | 4 |
2 files changed, 66 insertions, 35 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index e44b59a..6b7a12c 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -592,7 +592,8 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( } void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( - QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge centerEdge) + QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge centerEdge, + bool substitute) { Orientation orientation; switch (centerEdge) { @@ -619,22 +620,20 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( lastEdge = QGraphicsAnchorLayout::Bottom; } - AnchorVertex *first = internalVertex(item, firstEdge); AnchorVertex *center = internalVertex(item, centerEdge); + if (!center) + return; + AnchorVertex *first = internalVertex(item, firstEdge); AnchorVertex *last = internalVertex(item, lastEdge); - Q_ASSERT(first && center && last); - Q_ASSERT(graph[orientation].adjacentVertices(center).count() == 2); - // Create new anchor - AnchorData *oldData = graph[orientation].edgeData(first, center); + Q_ASSERT(first); + Q_ASSERT(center); + Q_ASSERT(last); - int minimumSize = oldData->minSize * 2; - int preferredSize = oldData->prefSize * 2; - int maximumSize = oldData->maxSize * 2; + Graph<AnchorVertex, AnchorData> &g = graph[orientation]; - AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, firstEdge, item, lastEdge, data); + AnchorData *oldData = g.edgeData(first, center); // Remove center constraint for (int i = itemCenterConstraints[orientation].count() - 1; i >= 0; --i) { if (itemCenterConstraints[orientation][i]->variables.contains(oldData)) { @@ -643,9 +642,36 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( } } - // Remove old anchors - removeAnchor(item, firstEdge, item, centerEdge); - removeAnchor(item, centerEdge, item, lastEdge); + if (substitute) { + // Create the new anchor that should substitute the left-center-right anchors. + AnchorData *oldData = g.edgeData(first, center); + + int minimumSize = oldData->minSize * 2; + int preferredSize = oldData->prefSize * 2; + int maximumSize = oldData->maxSize * 2; + + AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); + addAnchor(item, firstEdge, item, lastEdge, data); + + // Remove old anchors + removeAnchor(item, firstEdge, item, centerEdge); + removeAnchor(item, centerEdge, item, lastEdge); + + } else { + // this is only called from removeAnchors() + // first, remove all non-internal anchors + QList<AnchorVertex*> adjacents = g.adjacentVertices(center); + for (int i = 0; i < adjacents.count(); ++i) { + AnchorVertex *v = adjacents.at(i); + if (v->m_item != item) { + removeAnchor(item, centerEdge, v->m_item, v->m_edge); + } + } + // when all non-internal anchors is removed it will automatically merge the + // center anchor into a left-right (or top-bottom) anchor. We must also delete that. + // by this time, the center vertex is deleted and merged into a non-centered internal anchor + removeAnchor(item, firstEdge, item, lastEdge); + } } @@ -832,7 +858,7 @@ void QGraphicsAnchorLayoutPrivate::removeInternalVertex(QGraphicsLayoutItem *ite if ((v.second == 2) && ((edge == QGraphicsAnchorLayout::HCenter) || (edge == QGraphicsAnchorLayout::VCenter))) { - removeCenterAnchors(item, edge); + removeCenterAnchors(item, edge, true); } } } @@ -856,30 +882,33 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem, removeInternalVertex(secondItem, secondEdge); } -void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) +void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge edge) { - AnchorVertex *v1 = 0; - AnchorVertex *v2 = 0; - QList<AnchorVertex *> allVertex; - int edge; - - for (edge = QGraphicsAnchorLayout::Left; edge <= QGraphicsAnchorLayout::Bottom; ++edge) { - // Remove all vertex for all edges - QGraphicsAnchorLayout::Edge e = static_cast<QGraphicsAnchorLayout::Edge>(edge); - - if ((v1 = internalVertex(item, e))) { - // Remove all edges - allVertex = graph[edgeOrientation(e)].adjacentVertices(v1); - - foreach (v2, allVertex) { - graph[edgeOrientation(e)].removeEdge(v1, v2); - removeInternalVertex(item, e); - removeInternalVertex(v2->m_item, v2->m_edge); - } + if (AnchorVertex *v = internalVertex(item, edge)) { + Graph<AnchorVertex, AnchorData> &g = graph[edgeOrientation(edge)]; + const QList<AnchorVertex *> allVertices = graph[edgeOrientation(edge)].adjacentVertices(v); + AnchorVertex *v2; + foreach (v2, allVertices) { + g.removeEdge(v, v2); + removeInternalVertex(item, edge); + removeInternalVertex(v2->m_item, v2->m_edge); } } } +void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) +{ + // remove the center anchor first!! + removeCenterAnchors(item, QGraphicsAnchorLayout::HCenter, false); + removeVertex(item, QGraphicsAnchorLayout::Left); + removeVertex(item, QGraphicsAnchorLayout::Right); + + removeCenterAnchors(item, QGraphicsAnchorLayout::VCenter, false); + removeVertex(item, QGraphicsAnchorLayout::Top); + removeVertex(item, QGraphicsAnchorLayout::Bottom); + +} + /*! \internal diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 1c0f737..131d7c3 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -300,7 +300,7 @@ public: void deleteLayoutEdges(); void createItemEdges(QGraphicsLayoutItem *item); void createCenterAnchors(QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge centerEdge); - void removeCenterAnchors(QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge centerEdge); + void removeCenterAnchors(QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge centerEdge, bool substitute = true); void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation); // helper function used by the 4 API functions @@ -324,6 +324,8 @@ public: void removeAnchors(QGraphicsLayoutItem *item); + void removeVertex(QGraphicsLayoutItem *item, QGraphicsAnchorLayout::Edge edge); + void correctEdgeDirection(QGraphicsLayoutItem *&firstItem, QGraphicsAnchorLayout::Edge &firstEdge, QGraphicsLayoutItem *&secondItem, |