summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan-Arve Sæther <jan-arve.saether@nokia.com>2009-08-12 07:33:37 (GMT)
committerJan-Arve Sæther <jan-arve.saether@nokia.com>2009-08-12 08:55:48 (GMT)
commitd67b7829e7d5d8fbd57b701f4268dc1c6d77f1b0 (patch)
treed036ef35cf109fb171c6998aebb5ca6f515d66d8
parent1d3de98158b9409fa63e2e7cf8d3ca8b77f26285 (diff)
downloadQt-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.cpp97
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h4
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,