summaryrefslogtreecommitdiffstats
path: root/src/widgets/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/graphicsview')
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp43
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.h3
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h15
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp88
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h5
-rw-r--r--src/widgets/graphicsview/qgraphicsscene_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp24
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.cpp58
-rw-r--r--src/widgets/graphicsview/qgraphicssceneevent.h6
-rw-r--r--src/widgets/graphicsview/qgraphicssceneindex.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicsscenelinearindex_p.h45
-rw-r--r--src/widgets/graphicsview/qgraphicsview.cpp10
12 files changed, 261 insertions, 41 deletions
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index e327a8737a..551f229611 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -332,6 +332,8 @@
this flag is disabled; children can draw anywhere. This behavior is
enforced by QGraphicsView::drawItems() or
QGraphicsScene::drawItems(). This flag was introduced in Qt 4.3.
+ \note This flag is similar to ItemContainsChildrenInShape but in addition
+ enforces the containment by clipping the children.
\value ItemIgnoresTransformations The item ignores inherited
transformations (i.e., its position is still anchored to its parent, but
@@ -423,6 +425,19 @@
ItemStopsClickFocusPropagation, but also suppresses focus-out. This flag
allows you to completely take over focus handling.
This flag was introduced in Qt 4.7. \endomit
+
+ \value ItemContainsChildrenInShape This flag indicates that all of the
+ item's direct or indirect children only draw within the item's shape.
+ Unlike ItemClipsChildrenToShape, this restriction is not enforced. Set
+ ItemContainsChildrenInShape when you manually assure that drawing
+ is bound to the item's shape and want to avoid the cost associated with
+ enforcing the clip. Setting this flag enables more efficient drawing and
+ collision detection. The flag is disabled by default.
+ \note If both this flag and ItemClipsChildrenToShape are set, the clip
+ will be enforced. This is equivalent to just setting
+ ItemClipsChildrenToShape.
+ .
+ This flag was introduced in Qt 5.4.
*/
/*!
@@ -836,6 +851,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
flag = AncestorIgnoresTransformations;
enabled = flags & QGraphicsItem::ItemIgnoresTransformations;
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ flag = AncestorContainsChildren;
+ enabled = flags & QGraphicsItem::ItemContainsChildrenInShape;
+ break;
default:
return;
}
@@ -895,6 +914,8 @@ void QGraphicsItemPrivate::updateAncestorFlags()
flags |= AncestorClipsChildren;
if (pd->flags & QGraphicsItem::ItemIgnoresTransformations)
flags |= AncestorIgnoresTransformations;
+ if (pd->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ flags |= AncestorContainsChildren;
}
if (ancestorFlags == flags)
@@ -1831,6 +1852,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->markParentDirty(true);
}
+ if ((flags & ItemContainsChildrenInShape) != (oldFlags & ItemContainsChildrenInShape)) {
+ // Item children containtment changes. Propagate the ancestor flag to all children.
+ d_ptr->updateAncestorFlag(ItemContainsChildrenInShape);
+ }
+
if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
// Item children clipping changes. Propagate the ancestor flag to
// all children.
@@ -2322,7 +2348,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
}
// Update children with explicitly = false.
- const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape)
+ const bool updateChildren = update && !((flags & QGraphicsItem::ItemClipsChildrenToShape
+ || flags & QGraphicsItem::ItemContainsChildrenInShape)
&& !(flags & QGraphicsItem::ItemHasNoContents));
foreach (QGraphicsItem *child, children) {
if (!newVisible || !child->d_ptr->explicitlyHidden)
@@ -2835,7 +2862,9 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
#ifndef QT_NO_GRAPHICSEFFECT
Q_Q(const QGraphicsItem);
QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
- if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
+ if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
+ || topMostEffectItem == q)
return brect;
const QGraphicsItem *effectParent = parent;
@@ -2847,6 +2876,7 @@ QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectI
brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
}
if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren
|| topMostEffectItem == effectParent) {
return brect;
}
@@ -7442,7 +7472,8 @@ QVariant QGraphicsItem::extension(const QVariant &variant) const
*/
void QGraphicsItem::addToIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### add to child index only if applicable
return;
}
@@ -7459,7 +7490,8 @@ void QGraphicsItem::addToIndex()
*/
void QGraphicsItem::removeFromIndex()
{
- if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren) {
// ### remove from child index only if applicable
return;
}
@@ -11451,6 +11483,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStopsFocusHandling:
str = "ItemStopsFocusHandling";
break;
+ case QGraphicsItem::ItemContainsChildrenInShape:
+ str = "ItemContainsChildrenInShape";
+ break;
}
debug << str;
return debug;
diff --git a/src/widgets/graphicsview/qgraphicsitem.h b/src/widgets/graphicsview/qgraphicsitem.h
index 4283deb5b8..dfc06fdaea 100644
--- a/src/widgets/graphicsview/qgraphicsitem.h
+++ b/src/widgets/graphicsview/qgraphicsitem.h
@@ -105,7 +105,8 @@ public:
ItemIsFocusScope = 0x8000, // internal
ItemSendsScenePositionChanges = 0x10000,
ItemStopsClickFocusPropagation = 0x20000,
- ItemStopsFocusHandling = 0x40000
+ ItemStopsFocusHandling = 0x40000,
+ ItemContainsChildrenInShape = 0x80000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index 3968d89a13..4d1835f178 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -172,7 +172,8 @@ public:
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
AncestorIgnoresTransformations = 0x4,
- AncestorFiltersChildEvents = 0x8
+ AncestorFiltersChildEvents = 0x8,
+ AncestorContainsChildren = 0x10
};
inline QGraphicsItemPrivate()
@@ -213,7 +214,6 @@ public:
needSortChildren(0),
allChildrenDirty(0),
fullUpdatePending(0),
- dirtyChildrenBoundingRect(1),
flags(0),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -239,6 +239,7 @@ public:
mayHaveChildWithGraphicsEffect(0),
isDeclarativeItem(0),
sendParentChangeNotification(0),
+ dirtyChildrenBoundingRect(1),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -544,7 +545,7 @@ public:
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 4;
+ quint32 ancestorFlags : 5;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
@@ -555,10 +556,9 @@ public:
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
quint32 fullUpdatePending : 1;
- quint32 dirtyChildrenBoundingRect : 1;
// Packed 32 bits
- quint32 flags : 19;
+ quint32 flags : 20;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
@@ -571,9 +571,9 @@ public:
quint32 filtersDescendantEvents : 1;
quint32 sceneTransformTranslateOnly : 1;
quint32 notifyBoundingRectChanged : 1;
- quint32 notifyInvalidated : 1;
// New 32 bits
+ quint32 notifyInvalidated : 1;
quint32 mouseSetsFocus : 1;
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
@@ -585,7 +585,8 @@ public:
quint32 mayHaveChildWithGraphicsEffect : 1;
quint32 isDeclarativeItem : 1;
quint32 sendParentChangeNotification : 1;
- quint32 padding : 21;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 padding : 19;
// Optional stacking order
int globalStackingOrder;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index bccdb1fbaa..1cd162e6bb 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -299,6 +299,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
painterStateProtection(true),
sortCacheEnabled(false),
allItemsIgnoreTouchEvents(true),
+ minimumRenderSize(0.0),
selectionChanging(0),
rectAdjust(2),
focusItem(0),
@@ -4716,19 +4717,40 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
wasDirtyParentSceneTransform = true;
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool drawItem = itemHasContents && !itemIsFullyTransparent;
- if (drawItem) {
+ if (drawItem || minimumRenderSize > 0.0) {
const QRectF brect = adjustedItemEffectiveBoundingRect(item);
ENSURE_TRANSFORM_PTR
- QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
- : transformPtr->mapRect(brect).toAlignedRect();
- viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
- if (widget)
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
- drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
- : !viewBoundingRect.normalized().isEmpty();
- if (!drawItem) {
+ QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
+ : transformPtr->mapRect(brect);
+
+ bool itemIsTooSmallToRender = false;
+ if (minimumRenderSize > 0.0
+ && (preciseViewBoundingRect.width() < minimumRenderSize
+ || preciseViewBoundingRect.height() < minimumRenderSize)) {
+ itemIsTooSmallToRender = true;
+ drawItem = false;
+ }
+
+ bool itemIsOutsideVisibleRect = false;
+ if (drawItem) {
+ QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
+ viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
+ if (widget)
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
+ : !viewBoundingRect.normalized().isEmpty();
+ itemIsOutsideVisibleRect = !drawItem;
+ }
+
+ if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
+ // We cannot simply use !drawItem here. If we did it is possible
+ // to enter the outter if statement with drawItem == false and minimumRenderSize > 0
+ // and finally end up inside this inner if, even though none of the above two
+ // conditions are met. In that case we should not return from this function
+ // but call draw() instead.
if (!itemHasChildren)
return;
if (itemClipsChildrenToShape) {
@@ -5200,7 +5222,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
// Process children.
if (itemHasChildren && item->d_ptr->dirtyChildren) {
- const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
// Items with no content are threated as 'dummy' items which means they are never drawn and
// 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
// such an item changes geometry, its children have to take care of the update regardless
@@ -5729,6 +5752,49 @@ bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
return d->sendEvent(item, event);
}
+/*!
+ \property QGraphicsScene::minimumRenderSize
+ \since 5.4
+ \brief the minimal view-transformed size an item must have to be drawn
+
+ When the scene is rendered, any item whose width or height, transformed
+ to the target view, is smaller that minimumRenderSize(), will not be
+ rendered. If an item is not rendered and it clips its children items
+ they will also not be rendered. Set this value to speed up rendering
+ of scenes with many objects rendered on a zoomed out view.
+
+ The default value is 0. If unset, or if set to 0 or a negative value,
+ all items will always be rendered.
+
+ For example, setting this property can be especially useful if a scene
+ is rendered by multiple views, one of which serves as an overview which
+ always displays all items. In scenes with many items, such a view will
+ use a high scaling factor so that all items can be shown. Due to the
+ scaling, smaller items will only make an insignificant contribution to
+ the final rendered scene. To avoid drawing these items and reduce the
+ time necessary to render the scene, you can call setMinimumRenderSize()
+ with a non-negative value.
+
+ \note Items that are not drawn as a result of being too small, are still
+ returned by methods such as items() and itemAt(), and participate in
+ collision detection and interactions. It is recommended that you set
+ minimumRenderSize() to a value less than or equal to 1 in order to
+ avoid large unrendered items that are interactive.
+
+ \sa QStyleOptionGraphicsItem::levelOfDetailFromTransform()
+*/
+qreal QGraphicsScene::minimumRenderSize() const
+{
+ Q_D(const QGraphicsScene);
+ return d->minimumRenderSize;
+}
+void QGraphicsScene::setMinimumRenderSize(qreal minSize)
+{
+ Q_D(QGraphicsScene);
+ d->minimumRenderSize = minSize;
+ update();
+}
+
void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
views << view;
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index cde0eda125..d95237baef 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -107,6 +107,7 @@ class Q_WIDGETS_EXPORT QGraphicsScene : public QObject
Q_PROPERTY(QFont font READ font WRITE setFont)
Q_PROPERTY(bool sortCacheEnabled READ isSortCacheEnabled WRITE setSortCacheEnabled)
Q_PROPERTY(bool stickyFocus READ stickyFocus WRITE setStickyFocus)
+ Q_PROPERTY(qreal minimumRenderSize READ minimumRenderSize WRITE setMinimumRenderSize)
public:
enum ItemIndexMethod {
@@ -249,6 +250,9 @@ public:
bool sendEvent(QGraphicsItem *item, QEvent *event);
+ qreal minimumRenderSize() const;
+ void setMinimumRenderSize(qreal minSize);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
@@ -309,6 +313,7 @@ private:
friend class QGraphicsEffect;
friend class QGraphicsSceneIndex;
friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneLinearIndex;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h
index 9e5bcec488..9f50dcfea7 100644
--- a/src/widgets/graphicsview/qgraphicsscene_p.h
+++ b/src/widgets/graphicsview/qgraphicsscene_p.h
@@ -117,6 +117,8 @@ public:
quint32 allItemsIgnoreTouchEvents : 1;
quint32 padding : 15;
+ qreal minimumRenderSize;
+
QRectF growingItemsBoundingRect;
void _q_emitUpdated();
diff --git a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
index 7598163f2d..50f17ab73f 100644
--- a/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
+++ b/src/widgets/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -169,7 +169,8 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex()
untransformableItems << item;
continue;
}
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)
continue;
bsp.insertItem(item, item->d_ptr->sceneEffectiveBoundingRect());
@@ -351,7 +352,8 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec
// Avoid virtual function calls from the destructor.
purgePending = true;
removedItems << item;
- } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
bsp.removeItem(item, item->d_ptr->sceneEffectiveBoundingRect());
}
} else {
@@ -510,7 +512,8 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *
return;
if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
- || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren)) {
return; // Item is not in BSP tree; nothing to do.
}
@@ -641,8 +644,10 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
QGraphicsItem::GraphicsItemFlags newFlags = *static_cast<const QGraphicsItem::GraphicsItemFlags *>(value);
bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
bool willIgnoreTransform = newFlags & QGraphicsItem::ItemIgnoresTransformations;
- bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
- bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
+ bool willClipChildren = newFlags & QGraphicsItem::ItemClipsChildrenToShape
+ || newFlags & QGraphicsItem::ItemContainsChildrenInShape;
if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
@@ -663,10 +668,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics
bool ignoredTransform = item->d_ptr->itemIsUntransformable();
bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations)
|| (newParent && newParent->d_ptr->itemIsUntransformable());
- bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren;
+ bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren;
bool ancestorWillClipChildren = newParent
- && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
+ && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || newParent->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape)
+ || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
+ || newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorContainsChildren));
if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) {
QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
// Remove item and its descendants from the index and append
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.cpp b/src/widgets/graphicsview/qgraphicssceneevent.cpp
index 631aa7bf19..be91c63fad 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneevent.cpp
@@ -348,7 +348,7 @@ class QGraphicsSceneMouseEventPrivate : public QGraphicsSceneEventPrivate
public:
inline QGraphicsSceneMouseEventPrivate()
: button(Qt::NoButton),
- buttons(0), modifiers(0)
+ buttons(0), modifiers(0), source(Qt::MouseEventNotSynthesized), flags(0)
{ }
QPointF pos;
@@ -363,6 +363,8 @@ public:
Qt::MouseButton button;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers modifiers;
+ Qt::MouseEventSource source;
+ Qt::MouseEventFlags flags;
};
/*!
@@ -626,6 +628,60 @@ Qt::KeyboardModifiers QGraphicsSceneMouseEvent::modifiers() const
}
/*!
+ \since 5.4
+
+ Returns information about the mouse event source.
+
+ The mouse event source can be used to distinguish between genuine
+ and artificial mouse events. The latter are events that are
+ synthesized from touch events by the operating system or Qt itself.
+
+ \sa Qt::MouseEventSource
+ \sa QMouseEvent::source()
+ */
+Qt::MouseEventSource QGraphicsSceneMouseEvent::source() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->source;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setSource(Qt::MouseEventSource source)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->source = source;
+}
+
+/*!
+ \since 5.4
+
+ Returns the mouse event flags.
+
+ The mouse event flags provide additional information about a mouse event.
+
+ \sa Qt::MouseEventFlag
+ \sa QMouseEvent::flags()
+ */
+Qt::MouseEventFlags QGraphicsSceneMouseEvent::flags() const
+{
+ Q_D(const QGraphicsSceneMouseEvent);
+ return d->flags;
+}
+
+/*!
+ \since 5.4
+ \internal
+ */
+void QGraphicsSceneMouseEvent::setFlags(Qt::MouseEventFlags flags)
+{
+ Q_D(QGraphicsSceneMouseEvent);
+ d->flags = flags;
+}
+
+/*!
\internal
*/
void QGraphicsSceneMouseEvent::setModifiers(Qt::KeyboardModifiers modifiers)
diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h
index e744d08edf..2c9c1f3f50 100644
--- a/src/widgets/graphicsview/qgraphicssceneevent.h
+++ b/src/widgets/graphicsview/qgraphicssceneevent.h
@@ -121,6 +121,12 @@ public:
Qt::KeyboardModifiers modifiers() const;
void setModifiers(Qt::KeyboardModifiers modifiers);
+ Qt::MouseEventSource source() const;
+ void setSource(Qt::MouseEventSource source);
+
+ Qt::MouseEventFlags flags() const;
+ void setFlags(Qt::MouseEventFlags);
+
private:
Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent)
Q_DISABLE_COPY(QGraphicsSceneMouseEvent)
diff --git a/src/widgets/graphicsview/qgraphicssceneindex.cpp b/src/widgets/graphicsview/qgraphicssceneindex.cpp
index 40f63937f4..d06c5523ca 100644
--- a/src/widgets/graphicsview/qgraphicssceneindex.cpp
+++ b/src/widgets/graphicsview/qgraphicssceneindex.cpp
@@ -278,7 +278,8 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
Q_ASSERT(!item->d_ptr->dirtySceneTransform);
}
- const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
+ || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
bool processItem = !itemIsFullyTransparent;
if (processItem) {
processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
diff --git a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
index 7debcfb501..baf3de3755 100644
--- a/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
+++ b/src/widgets/graphicsview/qgraphicsscenelinearindex_p.h
@@ -70,31 +70,62 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
Q_OBJECT
public:
- QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene)
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene), m_itemsIsValid(true)
{ }
QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const
- { Q_UNUSED(order); return m_items; }
+ {
+ Q_UNUSED(order);
+ return validList();
+ }
virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const
{
Q_UNUSED(rect);
Q_UNUSED(order);
- return m_items;
+ return validList();
}
protected :
virtual void clear()
- { m_items.clear(); }
+ {
+ m_items.clear();
+ m_itemsIsValid = true;
+ }
virtual void addItem(QGraphicsItem *item)
- { m_items << item; }
+ {
+ if (m_itemsIsValid)
+ m_items << item;
+ }
virtual void removeItem(QGraphicsItem *item)
- { m_items.removeOne(item); }
+ {
+ Q_UNUSED(item);
+ m_itemsIsValid = false;
+ }
private:
- QList<QGraphicsItem*> m_items;
+ mutable QList<QGraphicsItem*> m_items;
+ mutable bool m_itemsIsValid;
+
+ QList<QGraphicsItem*>& validList() const
+ {
+ if (!m_itemsIsValid)
+ {
+ m_items.clear();
+
+ QList<QGraphicsItem*> stack = scene()->d_func()->topLevelItems;
+ m_items << stack;
+ while (!stack.isEmpty())
+ {
+ m_items << stack.last()->childItems();
+ stack << stack.takeLast()->childItems();
+ }
+ m_itemsIsValid = true;
+ }
+ return m_items;
+ }
};
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp
index 5bcf52b6a3..7bdfae5fec 100644
--- a/src/widgets/graphicsview/qgraphicsview.cpp
+++ b/src/widgets/graphicsview/qgraphicsview.cpp
@@ -655,6 +655,8 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
lastMouseMoveScenePoint = mouseEvent.scenePos();
lastMouseMoveScreenPoint = mouseEvent.screenPos();
mouseEvent.setAccepted(false);
@@ -2760,7 +2762,7 @@ void QGraphicsView::setupViewport(QWidget *widget)
return;
}
- const bool isGLWidget = widget->inherits("QGLWidget");
+ const bool isGLWidget = widget->inherits("QGLWidget") || widget->inherits("QOpenGLWidget");
d->accelerateScrolling = !(isGLWidget);
@@ -3217,6 +3219,8 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
mouseEvent.setAccepted(false);
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
else
@@ -3265,6 +3269,8 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);
@@ -3392,6 +3398,8 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
mouseEvent.setButtons(event->buttons());
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
+ mouseEvent.setSource(event->source());
+ mouseEvent.setFlags(event->flags());
mouseEvent.setAccepted(false);
if (event->spontaneous())
qt_sendSpontaneousEvent(d->scene, &mouseEvent);