diff options
author | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-09-17 12:10:29 (GMT) |
---|---|---|
committer | Jan-Arve Sæther <jan-arve.saether@nokia.com> | 2009-09-17 12:10:29 (GMT) |
commit | 53dfbd5708cdf64bfd3139cd4b0afc3aef8e186f (patch) | |
tree | ec9160f5ba39dd63144fcdd332166e2a6c54dbe7 /src | |
parent | 0644e3dce532b1df00a77d3a30c61d6b75d3ff30 (diff) | |
parent | c2443b9d2cadb220012d37e4ed6a5973a6cc6abe (diff) | |
download | Qt-53dfbd5708cdf64bfd3139cd4b0afc3aef8e186f.zip Qt-53dfbd5708cdf64bfd3139cd4b0afc3aef8e186f.tar.gz Qt-53dfbd5708cdf64bfd3139cd4b0afc3aef8e186f.tar.bz2 |
Merge branch 'orbit-fixes' into 4.6
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.cpp | 6 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 200 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.h | 14 |
3 files changed, 148 insertions, 72 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 5897ae4..efad259 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -194,7 +194,7 @@ QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { Q_D(QGraphicsAnchorLayout); - QGraphicsAnchor *a = d->anchor(firstItem, firstEdge, secondItem, secondEdge); + QGraphicsAnchor *a = d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); invalidate(); return a; } @@ -246,12 +246,12 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, // Horizontal anchor Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft); - d->anchor(firstItem, firstEdge, secondItem, secondEdge); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); // Vertical anchor firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop); - d->anchor(firstItem, firstEdge, secondItem, secondEdge); + d->addAnchor(firstItem, firstEdge, secondItem, secondEdge); invalidate(); } diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index a37ec96..b02adf4 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -59,7 +59,7 @@ QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() { - layoutPrivate->deleteAnchorData(data); + layoutPrivate->removeAnchor(data->from, data->to); } void QGraphicsAnchorPrivate::setSpacing(qreal value) @@ -790,7 +790,7 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() // Horizontal AnchorData *data = new AnchorData(0, 0, QWIDGETSIZE_MAX); - addAnchor(layout, Qt::AnchorLeft, layout, + addAnchor_helper(layout, Qt::AnchorLeft, layout, Qt::AnchorRight, data); data->skipInPreferred = 1; @@ -800,7 +800,7 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() // Vertical data = new AnchorData(0, 0, QWIDGETSIZE_MAX); - addAnchor(layout, Qt::AnchorTop, layout, + addAnchor_helper(layout, Qt::AnchorTop, layout, Qt::AnchorBottom, data); data->skipInPreferred = 1; @@ -816,8 +816,10 @@ void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() Q_ASSERT(internalVertex(q, Qt::AnchorHorizontalCenter) == NULL); Q_ASSERT(internalVertex(q, Qt::AnchorVerticalCenter) == NULL); - removeAnchor(q, Qt::AnchorLeft, q, Qt::AnchorRight); - removeAnchor(q, Qt::AnchorTop, q, Qt::AnchorBottom); + removeAnchor_helper(internalVertex(q, Qt::AnchorLeft), + internalVertex(q, Qt::AnchorRight)); + removeAnchor_helper(internalVertex(q, Qt::AnchorTop), + internalVertex(q, Qt::AnchorBottom)); } void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) @@ -832,7 +834,7 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) int maximumSize = item->maximumWidth(); AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, Qt::AnchorLeft, item, + addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data); // Vertical @@ -841,7 +843,7 @@ void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) maximumSize = item->maximumHeight(); data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, Qt::AnchorTop, item, + addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data); } @@ -904,16 +906,16 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( QSimplexConstraint *c = new QSimplexConstraint; AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); c->variables.insert(data, 1.0); - addAnchor(item, firstEdge, item, centerEdge, data); + addAnchor_helper(item, firstEdge, item, centerEdge, data); data = new AnchorData(minimumSize, preferredSize, maximumSize); c->variables.insert(data, -1.0); - addAnchor(item, centerEdge, item, lastEdge, data); + addAnchor_helper(item, centerEdge, item, lastEdge, data); itemCenterConstraints[orientation].append(c); // Remove old one - removeAnchor(item, firstEdge, item, lastEdge); + removeAnchor_helper(first, last); } void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( @@ -976,11 +978,11 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( int maximumSize = oldData->maxSize * 2; AnchorData *data = new AnchorData(minimumSize, preferredSize, maximumSize); - addAnchor(item, firstEdge, item, lastEdge, data); + addAnchor_helper(item, firstEdge, item, lastEdge, data); // Remove old anchors - removeAnchor(item, firstEdge, item, centerEdge); - removeAnchor(item, centerEdge, item, lastEdge); + removeAnchor_helper(first, center); + removeAnchor_helper(center, internalVertex(item, lastEdge)); } else { // this is only called from removeAnchors() @@ -989,13 +991,13 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( 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); + removeAnchor_helper(center, internalVertex(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); + removeAnchor_helper(first, internalVertex(item, lastEdge)); } } @@ -1039,7 +1041,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * * 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. */ -QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, +QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -1112,18 +1114,18 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *first } else { data = new AnchorData(0); // spacing should be 0 } - addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); } else if (*spacing >= 0) { data = new AnchorData(*spacing); - addAnchor(firstItem, firstEdge, secondItem, secondEdge, data); + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); } else { data = new AnchorData(-*spacing); - addAnchor(secondItem, secondEdge, firstItem, firstEdge, data); + addAnchor_helper(secondItem, secondEdge, firstItem, firstEdge, data); } return acquireGraphicsAnchor(data); } -void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, +void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -1142,8 +1144,9 @@ void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, // Remove previous anchor // ### Could we update the existing edgeData rather than creating a new one? - if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) - removeAnchor(firstItem, firstEdge, secondItem, secondEdge); + if (graph[edgeOrientation(firstEdge)].edgeData(v1, v2)) { + removeAnchor_helper(v1, v2); + } // Create a bi-directional edge in the sense it can be transversed both // from v1 or v2. "data" however is shared between the two references @@ -1178,15 +1181,82 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *fi return graphicsAnchor; } -void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge) +/*! + * \internal + * + * Implements the high level "removeAnchor" feature. Called by + * the QAnchorData destructor. + */ +void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex, + AnchorVertex *secondVertex) { - removeAnchor_helper(internalVertex(firstItem, firstEdge), - internalVertex(secondItem, secondEdge)); + Q_Q(QGraphicsAnchorLayout); + + // Actually delete the anchor + removeAnchor_helper(firstVertex, secondVertex); + + QGraphicsLayoutItem *firstItem = firstVertex->m_item; + QGraphicsLayoutItem *secondItem = secondVertex->m_item; + + // Checking if the item stays in the layout or not + bool keepFirstItem = false; + bool keepSecondItem = false; + + QPair<AnchorVertex *, int> v; + int refcount = -1; + + if (firstItem != q) { + for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { + v = m_vertexList.value(qMakePair(firstItem, static_cast<Qt::AnchorPoint>(i))); + if (v.first) { + if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) + refcount = 2; + else + refcount = 1; + + if (v.second > refcount) { + keepFirstItem = true; + break; + } + } + } + } else + keepFirstItem = true; + + if (secondItem != q) { + for (int i = Qt::AnchorLeft; i <= Qt::AnchorBottom; ++i) { + v = m_vertexList.value(qMakePair(secondItem, static_cast<Qt::AnchorPoint>(i))); + if (v.first) { + if (i == Qt::AnchorHorizontalCenter || i == Qt::AnchorVerticalCenter) + refcount = 2; + else + refcount = 1; + + if (v.second > refcount) { + keepSecondItem = true; + break; + } + } + } + } else + keepSecondItem = true; + + if (!keepFirstItem) + q->removeAt(items.indexOf(firstItem)); + + if (!keepSecondItem) + q->removeAt(items.indexOf(secondItem)); + + // Removing anchors invalidates the layout + q->invalidate(); } +/* + \internal + + Implements the low level "removeAnchor" feature. Called by + private methods. +*/ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2) { Q_ASSERT(v1 && v2); @@ -1207,17 +1277,6 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorV \internal Only called from outside. (calls invalidate()) */ -void QGraphicsAnchorLayoutPrivate::deleteAnchorData(AnchorData *data) -{ - Q_Q(QGraphicsAnchorLayout); - removeAnchor_helper(data->from, data->to); - q->invalidate(); -} - -/*! - \internal - Only called from outside. (calls invalidate()) -*/ void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal *anchorSize) { Q_Q(QGraphicsAnchorLayout); @@ -1225,12 +1284,35 @@ void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal * // 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) { - data->setFixedSize(*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->setFixedSize(*anchorSize); + } else { + data->setFixedSize(-*anchorSize); + qSwap(data->from, data->to); + } } else { data->unsetSize(); } - q->invalidate(); } @@ -1360,25 +1442,23 @@ void QGraphicsAnchorLayoutPrivate::correctEdgeDirection(QGraphicsLayoutItem *&fi { Q_Q(QGraphicsAnchorLayout); - Qt::AnchorPoint effectiveFirst = firstEdge; - Qt::AnchorPoint effectiveSecond = secondEdge; - - if (firstItem == q) - effectiveFirst = QGraphicsAnchorLayoutPrivate::oppositeEdge(firstEdge); - if (secondItem == q) - effectiveSecond = QGraphicsAnchorLayoutPrivate::oppositeEdge(secondEdge); - - if (effectiveFirst < effectiveSecond) { - - // ### DEBUG - /* printf("Swapping Anchor from %s %d --to--> %s %d\n", - firstItem->isLayout() ? "<layout>" : - qPrintable(static_cast<QGraphicsWidget *>(firstItem)->data(0).toString()), - firstEdge, - secondItem->isLayout() ? "<layout>" : - qPrintable(static_cast<QGraphicsWidget *>(secondItem)->data(0).toString()), - secondEdge); - */ + if ((firstItem != q) && (secondItem != q)) { + // If connection is between widgets (not the layout itself) + // Ensure that "right-edges" sit to the left of "left-edges". + if (firstEdge < secondEdge) { + qSwap(firstItem, secondItem); + qSwap(firstEdge, secondEdge); + } + } else if (firstItem == q) { + // If connection involves the right or bottom of a layout, ensure + // the layout is the second item. + if ((firstEdge == Qt::AnchorRight) || (firstEdge == Qt::AnchorBottom)) { + qSwap(firstItem, secondItem); + qSwap(firstEdge, secondEdge); + } + } else if ((secondEdge != Qt::AnchorRight) && (secondEdge != Qt::AnchorBottom)) { + // If connection involves the left, center or top of layout, ensure + // the layout is the first item. qSwap(firstItem, secondItem); qSwap(firstEdge, secondEdge); } diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index f701c3f..4d746bf 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -403,15 +403,15 @@ public: return data->graphicsAnchor; } - // helper function used by the 4 API functions - QGraphicsAnchor *anchor(QGraphicsLayoutItem *firstItem, + // function used by the 4 API functions + QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, qreal *spacing = 0); - // Anchor Manipulation methods - void addAnchor(QGraphicsLayoutItem *firstItem, + // Helper for Anchor Manipulation methods + void addAnchor_helper(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, @@ -420,12 +420,8 @@ public: QGraphicsAnchor *getAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - void removeAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge); + void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); - void deleteAnchorData(AnchorData *data); void setAnchorSize(AnchorData *data, const qreal *anchorSize); void anchorSize(const AnchorData *data, qreal *minSize = 0, |