diff options
Diffstat (limited to 'src/widgets/graphicsview/qgraphicsscene.cpp')
-rw-r--r-- | src/widgets/graphicsview/qgraphicsscene.cpp | 88 |
1 files changed, 77 insertions, 11 deletions
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; |