summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h26
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp112
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h5
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp61
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h4
5 files changed, 135 insertions, 73 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 688130b..a0d061b 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -56,6 +56,7 @@
#include "qgraphicsitem.h"
#include "qset.h"
#include "qpixmapcache.h"
+#include "qgraphicsview_p.h"
#include <QtCore/qpoint.h>
@@ -158,6 +159,8 @@ public:
geometryChanged(0),
inDestructor(0),
isObject(0),
+ ignoreVisible(0),
+ ignoreOpacity(0),
acceptTouchEvents(0),
acceptedTouchBeginEvent(0),
globalStackingOrder(-1),
@@ -181,7 +184,7 @@ public:
void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
-
+
// ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
static bool movableAncestorIsSelected(const QGraphicsItem *item);
@@ -250,7 +253,7 @@ public:
}
}
}
-
+
struct ExtraStruct {
ExtraStruct(Extra type, QVariant value)
: type(type), value(value)
@@ -262,7 +265,7 @@ public:
bool operator<(Extra extra) const
{ return type < extra; }
};
-
+
QList<ExtraStruct> extras;
QGraphicsItemCache *maybeExtraItemCache() const;
@@ -337,6 +340,15 @@ public:
return calcEffectiveOpacity();
}
+ inline qreal combineOpacityFromParent(qreal parentOpacity) const
+ {
+ if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity)
+ && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ return parentOpacity * opacity;
+ }
+ return opacity;
+ }
+
inline bool childrenCombineOpacity() const
{
if (!children.size())
@@ -423,8 +435,8 @@ public:
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
- quint32 dirty : 1;
- quint32 dirtyChildren : 1;
+ quint32 dirty : 1;
+ quint32 dirtyChildren : 1;
quint32 localCollisionHack : 1;
quint32 dirtyClipPath : 1;
quint32 emptyClipPath : 1;
@@ -441,9 +453,11 @@ public:
quint32 geometryChanged : 1;
quint32 inDestructor : 1;
quint32 isObject : 1;
+ quint32 ignoreVisible : 1;
+ quint32 ignoreOpacity : 1;
quint32 acceptTouchEvents : 1;
quint32 acceptedTouchBeginEvent : 1;
- quint32 unused : 12; // feel free to use
+ quint32 unused : 10; // feel free to use
// Optional stacking order
int globalStackingOrder;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 13b1b5a..7428d79 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5180,14 +5180,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (item) {
if (!item->d_ptr->visible)
return;
- QGraphicsItem *p = item->d_ptr->parent;
- bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
- bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
- if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) {
- opacity = parentOpacity * item->opacity();
- } else {
- opacity = item->d_ptr->opacity;
- }
+ opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity();
if (!invisibleButChildIgnoresParentOpacity)
@@ -5337,7 +5330,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
if (clipsToShape)
painter->setClipPath(item->shape(), Qt::IntersectClip);
painter->setOpacity(opacity);
- drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+
+ if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
+ item->paint(painter, &styleOptionTmp, widget);
+ else
+ drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
if (savePainter)
painter->restore();
@@ -5421,6 +5418,11 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
item->d_ptr->dirtyChildren = 1;
}
+ if (force)
+ item->d_ptr->ignoreVisible = 1;
+ if (ignoreOpacity)
+ item->d_ptr->ignoreOpacity = 1;
+
QGraphicsItem *p = item->d_ptr->parent;
while (p && !p->d_ptr->dirtyChildren) {
p->d_ptr->dirtyChildren = 1;
@@ -5428,34 +5430,58 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
}
}
-void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren)
+static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
+ const QRectF &rect, const QTransform &xform)
+{
+ Q_ASSERT(view);
+ Q_ASSERT(item);
+ if (item->hasBoundingRegionGranularity)
+ return view->updateRegion(xform.map(QRegion(rect.toRect())));
+ return view->updateRect(xform.mapRect(rect).toRect());
+}
+
+void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
+ qreal parentOpacity)
{
Q_Q(QGraphicsScene);
- // Calculate the full scene transform for this item.
+ bool wasDirtyParentViewBoundingRects = false;
bool wasDirtyParentSceneTransform = false;
- if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) {
- item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
- : QTransform();
- item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
- item->d_ptr->dirtySceneTransform = 0;
- wasDirtyParentSceneTransform = true;
+ qreal opacity = parentOpacity;
+
+ if (item) {
+ wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
+ opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
+ const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
+ const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity == 0.0;
+
+ if (item->d_ptr->dirtySceneTransform && !itemIsHidden && !item->d_ptr->itemIsUntransformable()
+ && !(itemIsFullyTransparent && item->d_ptr->childrenCombineOpacity())) {
+ // Calculate the full scene transform for this item.
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+
+ if (itemIsHidden || itemIsFullyTransparent || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) {
+ // Make sure we don't process invisible items or items with no content.
+ item->d_ptr->dirty = 0;
+ item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ }
}
// Process item.
- bool wasDirtyParentViewBoundingRects = false;
if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) {
const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask);
const bool untransformableItem = item->d_ptr->itemIsUntransformable();
- const QRectF itemBoundingRect = item->boundingRect();
+ const QRectF itemBoundingRect = adjustedItemBoundingRect(item);
if (item->d_ptr->geometryChanged) {
// Update growingItemsBoundingRect.
- if (!hasSceneRect) {
- QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
- _q_adjustRect(&itemSceneBoundingRect);
- growingItemsBoundingRect |= itemSceneBoundingRect;
- }
+ if (!hasSceneRect)
+ growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
item->d_ptr->geometryChanged = 0;
}
@@ -5484,11 +5510,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
break;
}
+ QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
wasDirtyParentViewBoundingRects = true;
- QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
- rect.translate(viewPrivate->dirtyScrollOffset);
- viewPrivate->updateRect(rect);
+ paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
+ if (!viewPrivate->updateRect(paintedViewBoundingRect))
+ paintedViewBoundingRect = QRect();
}
if (!item->d_ptr->dirty)
@@ -5496,7 +5523,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
if (uninitializedDirtyRect) {
dirtyRect = itemBoundingRect;
- _q_adjustRect(&dirtyRect);
if (!item->d_ptr->fullUpdatePending) {
_q_adjustRect(&item->d_ptr->needsRepaint);
dirtyRect &= item->d_ptr->needsRepaint;
@@ -5507,17 +5533,19 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
if (dirtyRect.isEmpty())
continue; // Discard updates outside the bounding rect.
- QTransform deviceTransform = item->d_ptr->sceneTransform;
- if (view->isTransformed()) {
- if (!untransformableItem)
- deviceTransform *= view->viewportTransform();
- else
- deviceTransform = item->deviceTransform(view->viewportTransform());
+ bool valid = false;
+ if (untransformableItem) {
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect,
+ item->deviceTransform(view->viewportTransform()));
+ } else if (!view->isTransformed()) {
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform);
+ } else {
+ QTransform deviceTransform = item->d_ptr->sceneTransform;
+ deviceTransform *= view->viewportTransform();
+ valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform);
}
- if (item->d_ptr->hasBoundingRegionGranularity)
- viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect())));
- else
- viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect());
+ if (!valid)
+ paintedViewBoundingRect = QRect();
}
}
}
@@ -5530,12 +5558,18 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending
&& (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
}
+ const bool parentIgnoresVisible = item && item->d_ptr->ignoreVisible;
+ const bool parentIgnoresOpacity = item && item->d_ptr->ignoreOpacity;
for (int i = 0; i < children->size(); ++i) {
QGraphicsItem *child = children->at(i);
if (wasDirtyParentSceneTransform)
child->d_ptr->dirtySceneTransform = 1;
if (wasDirtyParentViewBoundingRects)
child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+ if (parentIgnoresVisible)
+ child->d_ptr->ignoreVisible = 1;
+ if (parentIgnoresOpacity)
+ child->d_ptr->ignoreOpacity = 1;
if (allChildrenDirty) {
child->d_ptr->dirty = 1;
@@ -5558,7 +5592,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
}
- processDirtyItemsRecursive(child, dirtyAncestorContainsChildren);
+ processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
}
} else if (wasDirtyParentSceneTransform) {
item->d_ptr->invalidateChildrenSceneTransform();
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index b3f168c..983486f 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -271,7 +271,8 @@ public:
void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
bool removingItemFromScene = false);
- void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false);
+ void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false,
+ qreal parentOpacity = qreal(1.0));
inline void resetDirtyItem(QGraphicsItem *item)
{
@@ -283,6 +284,8 @@ public:
item->d_ptr->needsRepaint = QRectF();
item->d_ptr->allChildrenDirty = 0;
item->d_ptr->fullUpdatePending = 0;
+ item->d_ptr->ignoreVisible = 0;
+ item->d_ptr->ignoreOpacity = 0;
}
QStyle *style;
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 47a492b..6ac2914 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -846,19 +846,22 @@ void QGraphicsViewPrivate::processPendingUpdates()
dirtyRegion = QRegion();
}
-void QGraphicsViewPrivate::updateRegion(const QRegion &r)
+bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
- if (r.isEmpty() || fullUpdatePending)
- return;
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
+ return false;
+
+ const QRect boundingRect = r.boundingRect();
+ if (!boundingRect.intersects(viewport->rect()))
+ return false; // Update region outside viewport.
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
+ dirtyBoundingRect |= boundingRect;
if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
viewport->update();
@@ -876,18 +879,20 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r)
}
break;
}
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ default:
break;
}
+
+ return true;
}
-void QGraphicsViewPrivate::updateRect(const QRect &r)
+bool QGraphicsViewPrivate::updateRect(const QRect &r)
{
- if (r.isEmpty() || fullUpdatePending)
- return;
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
+ || !r.intersects(viewport->rect())) {
+ return false;
+ }
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
@@ -907,10 +912,11 @@ void QGraphicsViewPrivate::updateRect(const QRect &r)
else
dirtyRegion += r.adjusted(-2, -2, 2, 2);
break;
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ default:
break;
}
+
+ return true;
}
QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems)
@@ -3288,10 +3294,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Determine the exposed region
d->exposedRegion = event->region();
- if (!d->accelerateScrolling)
- d->exposedRegion = viewport()->rect();
- else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
- d->exposedRegion = event->rect();
QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
@@ -3305,8 +3307,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.setRenderHints(d->renderHints, true);
// Set up viewport transform
- const QTransform viewTransform = viewportTransform();
- painter.setWorldTransform(viewTransform);
+ const bool viewTransformed = isTransformed();
+ if (viewTransformed)
+ painter.setWorldTransform(viewportTransform());
+ const QTransform viewTransform = painter.worldTransform();
// Draw background
if ((d->cacheMode & CacheBackground)
@@ -3331,16 +3335,21 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
if (!d->backgroundPixmapExposed.isEmpty()) {
QPainter backgroundPainter(&d->backgroundPixmap);
backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
- backgroundPainter.setTransform(viewportTransform());
+ if (viewTransformed)
+ backgroundPainter.setTransform(viewTransform);
backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
drawBackground(&backgroundPainter, exposedSceneRect);
d->backgroundPixmapExposed = QRegion();
}
// Blit the background from the background pixmap
- painter.setWorldTransform(QTransform());
- painter.drawPixmap(QPoint(), d->backgroundPixmap);
- painter.setWorldTransform(viewTransform);
+ if (viewTransformed) {
+ painter.setWorldTransform(QTransform());
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ painter.setWorldTransform(viewTransform);
+ } else {
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ }
} else {
if (!(d->optimizationFlags & DontSavePainterState))
painter.save();
@@ -3363,8 +3372,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
const int numItems = itemList.size();
QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- for (int i = 0; i < numItems; ++i)
- itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
+ for (int i = 0; i < numItems; ++i) {
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform,
+ d->exposedRegion, allItems);
+ }
// Draw the items.
drawItems(&painter, numItems, itemArray, styleOptionArray);
d->freeStyleOptionsArray(styleOptionArray);
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index 903ca2b..5682138 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -171,8 +171,8 @@ public:
dirtyBoundingRect = QRect();
dirtyRegion = QRegion();
}
- void updateRect(const QRect &rect);
- void updateRegion(const QRegion &region);
+ bool updateRect(const QRect &rect);
+ bool updateRegion(const QRegion &region);
bool updateSceneSlotReimplementedChecked;
QRegion exposedRegion;