diff options
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.cpp | 3 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 508 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsanchorlayout_p.h | 66 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 13 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitemanimation.cpp | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 25 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicssceneindex.cpp | 4 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview_p.h | 7 |
10 files changed, 235 insertions, 395 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.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index 01c3a86..063639e 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 struct 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 594a205..a6f5992 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -55,14 +55,13 @@ 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) { } QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() { - // ### - layoutPrivate->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Orientation(data->orientation)); layoutPrivate->removeAnchor(data->from, data->to); } @@ -76,31 +75,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; } @@ -139,22 +167,22 @@ 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; 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; maxSize = QWIDGETSIZE_MAX; if (isCenterAnchor) maxSize /= 2; - return true; + return; } else { if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) { policy = item->sizePolicy().horizontalPolicy(); @@ -175,14 +203,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); @@ -214,8 +244,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } void ParallelAnchorData::updateChildrenSizes() @@ -224,8 +252,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; @@ -239,26 +272,21 @@ void ParallelAnchorData::updateChildrenSizes() secondEdge->updateChildrenSizes(); } -bool ParallelAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) -{ - return refreshSizeHints_helper(styleInfo); -} - -bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, - bool refreshChildren) +bool ParallelAnchorData::calculateSizeHints() { - 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 // 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); @@ -386,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; @@ -400,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; @@ -414,8 +431,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } #ifdef QT_DEBUG @@ -490,7 +505,6 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() interpolationProgress[i] = -1; spacings[i] = -1; - graphSimplified[i] = false; graphHasConflicts[i] = false; layoutFirstVertex[i] = 0; @@ -591,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; } @@ -652,7 +666,7 @@ static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph, sequence->from = before; sequence->to = after; - sequence->refreshSizeHints_helper(0, false); + sequence->calculateSizeHints(); return sequence; } @@ -696,16 +710,18 @@ static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *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 @@ -723,13 +739,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; } @@ -1134,10 +1153,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"); @@ -1257,7 +1272,6 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() addAnchor_helper(layout, Qt::AnchorLeft, layout, Qt::AnchorRight, data); data->maxSize = QWIDGETSIZE_MAX; - data->skipInPreferred = 1; // Save a reference to layout vertices layoutFirstVertex[Horizontal] = internalVertex(layout, Qt::AnchorLeft); @@ -1269,7 +1283,6 @@ void QGraphicsAnchorLayoutPrivate::createLayoutEdges() addAnchor_helper(layout, Qt::AnchorTop, layout, Qt::AnchorBottom, data); data->maxSize = QWIDGETSIZE_MAX; - data->skipInPreferred = 1; // Save a reference to layout vertices layoutFirstVertex[Vertical] = internalVertex(layout, Qt::AnchorTop); @@ -1292,19 +1305,17 @@ 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 // 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(); } /*! @@ -1336,8 +1347,6 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Check if vertex already exists if (internalVertex(item, centerEdge)) return; @@ -1366,14 +1375,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); @@ -1404,8 +1413,6 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Orientation code Qt::AnchorPoint firstEdge; Qt::AnchorPoint lastEdge; @@ -1442,7 +1449,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); @@ -1473,8 +1480,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 @@ -1505,15 +1510,21 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * /*! * \internal + * Implements the high level "addAnchor" feature. Called by the public API + * addAnchor method. + * + * 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). * - * 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. + * 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)) { @@ -1534,10 +1545,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 @@ -1547,12 +1554,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); } @@ -1565,7 +1570,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,45 +1589,39 @@ 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; } +/* + \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); 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); - - // 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); } @@ -1647,15 +1652,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; @@ -1740,12 +1743,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) @@ -1753,67 +1753,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<QGraphicsAnchorLayoutPrivate *>(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) { @@ -1879,8 +1818,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); @@ -1983,20 +1920,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; } @@ -2044,26 +1969,13 @@ 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); - - // 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. - if (!refreshAllSizeHints(orientation)) { - qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); - graphHasConflicts[orientation] = true; - return; - } + static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); + + // Reset the nominal sizes of each anchor based on the current item sizes + refreshAllSizeHints(orientation); // Simplify the graph - if (!simplifyGraph(orientation)) { + if (simplificationEnabled && !simplifyGraph(orientation)) { qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); graphHasConflicts[orientation] = true; return; @@ -2127,6 +2039,9 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( qDeleteAll(constraints[orientation]); constraints[orientation].clear(); graphPaths[orientation].clear(); // ### + + if (simplificationEnabled) + restoreSimplifiedGraph(orientation); } /*! @@ -2226,29 +2141,19 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra /*! \internal - Traverse the graph refreshing the size hints. Complex anchors will call the - refresh method of their children anchors. Simple anchors, if are internal - anchors, will query the associated item for their size hints. - - Returns false if some unfeasibility was found in the graph regarding the - complex anchors. + Traverse the graph refreshing the size hints. Edges will query their associated + item or graphicsAnchor for their size hints. */ -bool QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) +void QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) { Graph<AnchorVertex, AnchorData> &g = graph[orientation]; QList<QPair<AnchorVertex *, AnchorVertex *> > 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; } /*! @@ -2364,13 +2269,21 @@ QList<QSimplexConstraint *> QGraphicsAnchorLayoutPrivate::constraintsFromSizeHin layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutCentralVertex[orient]); } else { layoutEdge = graph[orient].edgeData(layoutFirstVertex[orient], layoutLastVertex[orient]); + } - // If maxSize is less then "infinite", that means there are other anchors - // grouped together with this one. We can't ignore its maximum value so we - // set back the variable to NULL to prevent the continue condition from being - // satisfied in the loop below. - if (layoutEdge->maxSize < QWIDGETSIZE_MAX) - layoutEdge = 0; + // If maxSize is less then "infinite", that means there are other anchors + // grouped together with this one. We can't ignore its maximum value so we + // set back the variable to NULL to prevent the continue condition from being + // satisfied in the loop below. + const qreal expectedMax = layoutCentralVertex[orient] ? QWIDGETSIZE_MAX / 2 : QWIDGETSIZE_MAX; + qreal actualMax; + if (layoutEdge->from == layoutFirstVertex[orient]) { + actualMax = layoutEdge->maxSize; + } else { + actualMax = -layoutEdge->minSize; + } + if (actualMax != expectedMax) { + layoutEdge = 0; } // For each variable, create constraints based on size hints @@ -2621,21 +2534,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<AnchorVertexPair *>(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 @@ -2650,7 +2548,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 @@ -2661,16 +2559,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<AnchorVertex *, AnchorVertex *> 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); @@ -2710,24 +2604,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); @@ -2741,64 +2631,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); + edge->from->distance = base->distance - edgeDistance; } - - // Process child anchors - if (edge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast<SequentialAnchorData *>(edge)); - else if (edge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(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<SequentialAnchorData *>(data->firstEdge)); - else if (data->firstEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(data->firstEdge)); - - // Second edge - if (data->secondEdge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast<SequentialAnchorData *>(data->secondEdge)); - else if (data->secondEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(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; - } - - // 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<QSimplexConstraint *> &constraints, @@ -2870,7 +2706,9 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(const QList<QSimplexConstraint // for (int i = 0; i < variables.size(); ++i) { AnchorData *ad = variables.at(i); - if (ad->skipInPreferred) + + // The layout original structure anchors are not relevant in preferred size calculation + if (ad->isLayoutAnchor) continue; QSimplexVariable *grower = new QSimplexVariable; diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 5f50c85..8529e2e 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -121,17 +121,16 @@ 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), - graphicsAnchor(0), skipInPreferred(0), - type(Normal), hasSize(true), isLayoutAnchor(false), + sizeAtMaximum(0), item(0), graphicsAnchor(0), + type(Normal), isLayoutAnchor(false), isCenterAnchor(false), orientation(0), dependency(Independent) {} virtual void updateChildrenSizes() {} - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); + void refreshSizeHints(const QLayoutStyleInfo *styleInfo = 0); virtual ~AnchorData() {} @@ -141,43 +140,35 @@ struct AnchorData : public QSimplexVariable { QString name; #endif - inline void setPreferredSize(qreal size) - { - prefSize = size; - hasSize = true; - } - - inline void unsetSize() - { - 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; 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; @@ -204,9 +195,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<AnchorVertex*> m_children; // list of vertices in the sequence QVector<AnchorData*> m_edges; // keep the list of edges too. @@ -233,9 +222,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; @@ -350,7 +337,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 }; @@ -445,11 +438,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); @@ -489,7 +477,7 @@ public: const QList<AnchorData *> &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); @@ -528,8 +516,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<QSimplexConstraint *> &constraints, @@ -576,8 +562,6 @@ public: Interval interpolationInterval[2]; qreal interpolationProgress[2]; - // ### - bool graphSimplified[2]; bool graphHasConflicts[2]; QSet<QGraphicsLayoutItem *> m_floatItems[2]; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 4e5e5c8..94a37a0 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -52,7 +52,7 @@ painting implementation and item interaction through its event handlers. QGraphicsItem is part of \l{The Graphics View Framework} - \img graphicsview-items.png + \image graphicsview-items.png For convenience, Qt provides a set of standard graphics items for the most common shapes. These are: @@ -378,14 +378,14 @@ it's parent if it's z-value is negative. This flag enables setZValue() to toggle ItemStacksBehindParent. - \value ItemIsPanel. The item is a panel. A panel provides activation and + \value ItemIsPanel The item is a panel. A panel provides activation and contained focus handling. Only one panel can be active at a time (see QGraphicsItem::isActive()). When no panel is active, QGraphicsScene activates all non-panel items. Window items (i.e., QGraphicsItem::isWindow() returns true) are panels. This flag was introduced in Qt 4.6. - \omitvalue ItemIsFocusScope Internal only (for now). + \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit \value ItemSendsScenePositionChanges The item enables itemChange() notifications for ItemScenePositionHasChanged. For performance reasons, @@ -1240,7 +1240,7 @@ void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, con const QTransform reverseMap = worldTransform.inverted(); const QVector<QRect> exposedRects(exposedRegion.rects()); for (int i = 0; i < exposedRects.size(); ++i) { - option->exposedRect |= reverseMap.mapRect(exposedRects.at(i)); + option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i))); if (option->exposedRect.contains(brect)) break; } @@ -10178,9 +10178,10 @@ bool QGraphicsTextItemPrivate::_q_mouseOnEdge(QGraphicsSceneMouseEvent *event) void QGraphicsTextItem::setTextInteractionFlags(Qt::TextInteractionFlags flags) { if (flags == Qt::NoTextInteraction) - setFlags(this->flags() & ~QGraphicsItem::ItemIsFocusable); + setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod)); else - setFlags(this->flags() | QGraphicsItem::ItemIsFocusable); + setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod); + dd->textControl()->setTextInteractionFlags(flags); } diff --git a/src/gui/graphicsview/qgraphicsitemanimation.cpp b/src/gui/graphicsview/qgraphicsitemanimation.cpp index be2f300..b67ee2e 100644 --- a/src/gui/graphicsview/qgraphicsitemanimation.cpp +++ b/src/gui/graphicsview/qgraphicsitemanimation.cpp @@ -45,6 +45,7 @@ support for QGraphicsItem. \since 4.2 \ingroup graphicsview-api + \deprecated The QGraphicsItemAnimation class animates a QGraphicsItem. You can schedule changes to the item's transformation matrix at diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 13f31b8..10d251d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2556,11 +2556,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) item->d_ptr->resolveFont(d->font.resolve()); item->d_ptr->resolvePalette(d->palette.resolve()); - if (!item->d_ptr->explicitlyHidden) { - if (d->unpolishedItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); - d->unpolishedItems.insert(item); - } + if (d->unpolishedItems.isEmpty()) + QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); + d->unpolishedItems.insert(item); // Reenable selectionChanged() for individual items --d->selectionChanging; @@ -4422,9 +4420,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte bool allowPartialCacheExposure = !viewRect.contains(deviceRect); #else // Only if deviceRect is 20% taller or wider than the desktop. - QRect desktopRect = QApplication::desktop()->availableGeometry(widget); - bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() - || desktopRect.height() * 1.2 < deviceRect.height()); + bool allowPartialCacheExposure = false; + if (widget) { + QRect desktopRect = QApplication::desktop()->availableGeometry(widget); + allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() + || desktopRect.height() * 1.2 < deviceRect.height()); + } #endif QRegion scrollExposure; if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) { @@ -4551,6 +4552,10 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget) { + // Make sure we don't have unpolished items before we draw. + if (!unpolishedItems.isEmpty()) + _q_polishItems(); + QRectF exposedSceneRect; if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); @@ -5077,6 +5082,10 @@ void QGraphicsScene::drawItems(QPainter *painter, const QStyleOptionGraphicsItem options[], QWidget *widget) { Q_D(QGraphicsScene); + // Make sure we don't have unpolished items before we draw. + if (!d->unpolishedItems.isEmpty()) + d->_q_polishItems(); + QTransform viewTransform = painter->worldTransform(); Q_UNUSED(options); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index f0404fd..70ecd49 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -354,8 +354,8 @@ void QGraphicsSceneIndexPrivate::init() if (!scene) return; - QObject::connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), - q_func(), SLOT(updateSceneRect(const QRectF&))); + QObject::connect(scene, SIGNAL(sceneRectChanged(QRectF)), + q_func(), SLOT(updateSceneRect(QRectF))); } /*! diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 3ef311c..3f9f443 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1517,6 +1517,8 @@ void QGraphicsView::setScene(QGraphicsScene *scene) QEvent windowDeactivate(QEvent::WindowDeactivate); QApplication::sendEvent(d->scene, &windowDeactivate); } + if(hasFocus()) + d->scene->clearFocus(); } // Assign the new scene and update the contents (scrollbars, etc.)). diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 762cad1..cd161ad 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -172,10 +172,17 @@ public: inline void dispatchPendingUpdateRequests() { +#ifndef Q_WS_MAC + // QWidget::update() works slightly different on the Mac; it's not part of + // our backing store so it needs special threatment. if (qt_widget_private(viewport)->paintOnScreen()) QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest); else QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest); +#else + QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::ExcludeSocketNotifiers + | QEventLoop::ExcludeUserInputEvents); +#endif } bool updateRect(const QRect &rect); |