9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
108
109
110
111
112
113
114
115
116
117
118
119
120
121
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
199
200
201
202
203
204
205
206
207
208
209
210
211
212
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
234
235
236
237
238
239
240
241
242
243
244
257#include <QtCore/qdatetime.h>
258#include <QtCore/qdebug.h>
259#include <QtCore/qmath.h>
260#include <QtCore/qscopedvaluerollback.h>
261#include <QtWidgets/qapplication.h>
262#include <QtGui/qevent.h>
263#include <QtWidgets/qlayout.h>
264#include <QtGui/qtransform.h>
265#include <QtGui/qpainter.h>
266#include <QtGui/qpainterpath.h>
267#include <QtWidgets/qscrollbar.h>
268#include <QtWidgets/qstyleoption.h>
270#include <private/qevent_p.h>
271#include <QtGui/private/qeventpoint_p.h>
279 if (d <= (qreal) INT_MIN)
281 else if (d >= (qreal) INT_MAX)
283 return d >= 0.0 ?
int(d + 0.5) :
int(d -
int(d-1) + 0.5) +
int(d-1);
286void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
288 for (
int i = 0; i < touchEvent->pointCount(); ++i) {
289 auto &pt = touchEvent->point(i);
292 QMutableEventPoint::setScenePosition(pt, d->mapToScene(pt.position()));
298
299
300QGraphicsViewPrivate::QGraphicsViewPrivate()
301 : renderHints(QPainter::TextAntialiasing),
302 dragMode(QGraphicsView::NoDrag),
303 sceneInteractionAllowed(
true), hasSceneRect(
false),
304 connectedToScene(
false),
305 useLastMouseEvent(
false),
306 identityMatrix(
true),
308 accelerateScrolling(
true),
309 keepLastCenterPoint(
true),
311 handScrolling(
false),
312 mustAllocateStyleOptions(
false),
313 mustResizeBackgroundPixmap(
true),
314 fullUpdatePending(
true),
315 hasUpdateClip(
false),
316 mousePressButton(Qt::NoButton),
317 leftIndent(0), topIndent(0),
318 alignment(Qt::AlignCenter),
319 transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor),
320 viewportUpdateMode(QGraphicsView::MinimalViewportUpdate),
322#if QT_CONFIG(rubberband)
323 rubberBanding(
false),
324 rubberBandSelectionMode(Qt::IntersectsItemShape),
325 rubberBandSelectionOperation(Qt::ReplaceSelection),
327 handScrollMotions(0),
329 hasStoredOriginalCursor(
false),
331 lastDragDropEvent(
nullptr),
332 updateSceneSlotReimplementedChecked(
false)
334 styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
337QGraphicsViewPrivate::~QGraphicsViewPrivate()
342
343
344void QGraphicsViewPrivate::recalculateContentSize()
348 const QSize maxSize = q->maximumViewportSize();
349 int width = maxSize.width();
350 int height = maxSize.height();
351 const QRectF viewRect = matrix.mapRect(q->sceneRect());
353 bool frameOnlyAround = (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents,
nullptr, q));
354 if (frameOnlyAround) {
355 if (hbarpolicy == Qt::ScrollBarAlwaysOn)
356 height -= frameWidth * 2;
357 if (vbarpolicy == Qt::ScrollBarAlwaysOn)
358 width -= frameWidth * 2;
363 const int scrollBarExtent = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent,
nullptr, q)
364 + (frameOnlyAround ? frameWidth * 2 : 0);
368 bool useHorizontalScrollBar = (viewRect.width() > width) && hbarpolicy == Qt::ScrollBarAsNeeded;
369 bool useVerticalScrollBar = (viewRect.height() > height) && vbarpolicy == Qt::ScrollBarAsNeeded;
370 if (useHorizontalScrollBar && vbarpolicy == Qt::ScrollBarAsNeeded) {
371 if (viewRect.height() > height - scrollBarExtent)
372 useVerticalScrollBar =
true;
374 if (useVerticalScrollBar && hbarpolicy == Qt::ScrollBarAsNeeded) {
375 if (viewRect.width() > width - scrollBarExtent)
376 useHorizontalScrollBar =
true;
378 if (useHorizontalScrollBar)
379 height -= scrollBarExtent;
380 if (useVerticalScrollBar)
381 width -= scrollBarExtent;
386 const QPointF savedLastCenterPoint = lastCenterPoint;
389 const qreal oldLeftIndent = leftIndent;
390 const qreal oldTopIndent = topIndent;
394 const int left = q_round_bound(viewRect.left());
395 const int right = q_round_bound(viewRect.right() - width);
397 switch (alignment & Qt::AlignHorizontal_Mask) {
399 leftIndent = -viewRect.left();
402 leftIndent = maxSize.width() - viewRect.width() - viewRect.left() - 1;
404 case Qt::AlignHCenter:
406 leftIndent = maxSize.width() / 2 - (viewRect.left() + viewRect.right()) / 2;
410 hbar->setRange(0, 0);
414 hbar->setRange(left, right);
415 hbar->setPageStep(width);
416 hbar->setSingleStep(width / 20);
418 if (oldLeftIndent != 0)
419 hbar->setValue(-oldLeftIndent);
424 const int top = q_round_bound(viewRect.top());
425 const int bottom = q_round_bound(viewRect.bottom() - height);
427 switch (alignment & Qt::AlignVertical_Mask) {
429 topIndent = -viewRect.top();
431 case Qt::AlignBottom:
432 topIndent = maxSize.height() - viewRect.height() - viewRect.top() - 1;
434 case Qt::AlignVCenter:
436 topIndent = maxSize.height() / 2 - (viewRect.top() + viewRect.bottom()) / 2;
440 vbar->setRange(0, 0);
444 vbar->setRange(top, bottom);
445 vbar->setPageStep(height);
446 vbar->setSingleStep(height / 20);
448 if (oldTopIndent != 0)
449 vbar->setValue(-oldTopIndent);
453 lastCenterPoint = savedLastCenterPoint;
458 if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
461 }
else if (q->isRightToLeft() && !leftIndent) {
469 if (cacheMode & QGraphicsView::CacheBackground) {
471 mustResizeBackgroundPixmap =
true;
476
477
478void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
482 case QGraphicsView::AnchorUnderMouse: {
483 if (q->underMouse()) {
486 QPointF transformationDiff = mapToScene(viewport->rect().toRectF().center())
487 - mapToScene(viewport->mapFromGlobal(QCursor::pos().toPointF()));
488 q->centerOn(lastMouseMoveScenePoint + transformationDiff);
490 q->centerOn(lastCenterPoint);
494 case QGraphicsView::AnchorViewCenter:
495 q->centerOn(lastCenterPoint);
497 case QGraphicsView::NoAnchor:
503
504
505void QGraphicsViewPrivate::updateLastCenterPoint()
507 lastCenterPoint = mapToScene(viewport->rect().toRectF().center());
511
512
513
514
515
516qint64 QGraphicsViewPrivate::horizontalScroll()
const
519 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
524
525
526
527
528
529qint64 QGraphicsViewPrivate::verticalScroll()
const
532 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
537
538
539
540
541QRectF QGraphicsViewPrivate::mapRectToScene(
const QRect &rect)
const
544 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
545 QRectF scrolled = QRectF(rect.translated(scrollX, scrollY));
546 return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled);
551
552
553
554
555QRectF QGraphicsViewPrivate::mapRectFromScene(
const QRectF &rect)
const
558 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
559 return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY);
563
564
565void QGraphicsViewPrivate::updateScroll()
568 scrollX = qint64(-leftIndent);
569 if (q->isRightToLeft()) {
571 scrollX += hbar->minimum();
572 scrollX += hbar->maximum();
573 scrollX -= hbar->value();
576 scrollX += hbar->value();
579 scrollY = qint64(vbar->value() - topIndent);
585
586
587
588
589
590bool QGraphicsViewPrivate::canStartScrollingAt(
const QPoint &startPos)
const
592 Q_Q(
const QGraphicsView);
593 if (q->dragMode() != QGraphicsView::NoDrag)
596 const QGraphicsItem *childItem = q->itemAt(startPos);
598 if (!startPos.isNull() && childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
601 return QAbstractScrollAreaPrivate::canStartScrollingAt(startPos);
605
606
607void QGraphicsViewPrivate::replayLastMouseEvent()
609 if (!useLastMouseEvent || !scene)
611 QSinglePointEvent *spe =
static_cast<QSinglePointEvent *>(&lastMouseEvent);
612 mouseMoveEventHandler(
static_cast<QMouseEvent *>(spe));
616
617
618void QGraphicsViewPrivate::storeMouseEvent(QMouseEvent *event)
620 useLastMouseEvent =
true;
621 lastMouseEvent = *event;
624void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
628#if QT_CONFIG(rubberband)
629 updateRubberBand(event);
632 storeMouseEvent(event);
633 lastMouseEvent.setAccepted(
false);
635 if (!sceneInteractionAllowed)
642 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
643 mouseEvent.setWidget(viewport);
644 mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
645 mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
646 mouseEvent.setScenePos(q->mapToScene(event->position().toPoint()));
647 mouseEvent.setScreenPos(event->globalPosition().toPoint());
648 mouseEvent.setLastScenePos(lastMouseMoveScenePoint);
649 mouseEvent.setLastScreenPos(lastMouseMoveScreenPoint);
650 mouseEvent.setButtons(event->buttons());
651 mouseEvent.setButton(event->button());
652 mouseEvent.setModifiers(event->modifiers());
653 mouseEvent.setSource(event->source());
654 mouseEvent.setFlags(event->flags());
655 mouseEvent.setTimestamp(event->timestamp());
656 lastMouseMoveScenePoint = mouseEvent.scenePos();
657 lastMouseMoveScreenPoint = mouseEvent.screenPos();
658 mouseEvent.setAccepted(
false);
659 if (event->spontaneous())
660 qt_sendSpontaneousEvent(scene, &mouseEvent);
662 QCoreApplication::sendEvent(scene, &mouseEvent);
665 lastMouseEvent.setAccepted(mouseEvent.isAccepted());
667 if (mouseEvent.isAccepted() && mouseEvent.buttons() != 0) {
678 if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
679 && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
680 scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
681 mouseEvent.scenePos(),
682 mouseEvent.widget());
685 for (QGraphicsItem *item : std::as_const(scene->d_func()->cachedItemsUnderMouse)) {
686 if (item->isEnabled() && item->hasCursor()) {
687 _q_setViewportCursor(item->cursor());
693 if (hasStoredOriginalCursor) {
695 hasStoredOriginalCursor =
false;
696 viewport->setCursor(originalCursor);
702
703
704#if QT_CONFIG(rubberband)
705QRegion QGraphicsViewPrivate::rubberBandRegion(
const QWidget *widget,
const QRect &rect)
const
707 QStyleHintReturnMask mask;
708 QStyleOptionRubberBand option;
709 option.initFrom(widget);
711 option.opaque =
false;
712 option.shape = QRubberBand::Rectangle;
715 tmp += rect.adjusted(-1, -1, 1, 1);
716 if (widget->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, widget, &mask))
721void QGraphicsViewPrivate::updateRubberBand(
const QMouseEvent *event)
724 if (dragMode != QGraphicsView::RubberBandDrag || !sceneInteractionAllowed || !rubberBanding)
727 if ((mousePressViewPoint - event->position().toPoint()).manhattanLength() < QApplication::startDragDistance())
731 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate && !rubberBandRect.isEmpty()) {
732 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
733 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
740 if (!event->buttons()) {
741 rubberBanding =
false;
742 rubberBandSelectionOperation = Qt::ReplaceSelection;
743 if (!rubberBandRect.isNull()) {
744 rubberBandRect = QRect();
745 emit q->rubberBandChanged(rubberBandRect, QPointF(), QPointF());
750 QRect oldRubberband = rubberBandRect;
753 const QPoint mp = q->mapFromScene(mousePressScenePoint);
754 const QPoint ep = event->position().toPoint();
755 rubberBandRect = QRect(qMin(mp.x(), ep.x()), qMin(mp.y(), ep.y()),
756 qAbs(mp.x() - ep.x()) + 1, qAbs(mp.y() - ep.y()) + 1);
758 if (rubberBandRect != oldRubberband || lastRubberbandScenePoint != lastMouseMoveScenePoint) {
759 lastRubberbandScenePoint = lastMouseMoveScenePoint;
760 oldRubberband = rubberBandRect;
761 emit q->rubberBandChanged(rubberBandRect, mousePressScenePoint, lastRubberbandScenePoint);
765 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
766 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
767 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
772 QPainterPath selectionArea;
773 selectionArea.addPolygon(q->mapToScene(rubberBandRect));
774 selectionArea.closeSubpath();
776 scene->setSelectionArea(selectionArea, rubberBandSelectionOperation, rubberBandSelectionMode, q->viewportTransform());
779void QGraphicsViewPrivate::clearRubberBand()
782 if (dragMode != QGraphicsView::RubberBandDrag || !sceneInteractionAllowed || !rubberBanding)
785 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
786 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
787 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
792 rubberBanding =
false;
793 rubberBandSelectionOperation = Qt::ReplaceSelection;
794 if (!rubberBandRect.isNull()) {
795 rubberBandRect = QRect();
796 emit q->rubberBandChanged(rubberBandRect, QPointF(), QPointF());
802
803
805void QGraphicsViewPrivate::_q_setViewportCursor(
const QCursor &cursor)
807 if (!hasStoredOriginalCursor) {
808 hasStoredOriginalCursor =
true;
809 originalCursor = viewport->cursor();
811 viewport->setCursor(cursor);
816
817
819void QGraphicsViewPrivate::_q_unsetViewportCursor()
822 const auto items = q->items(lastMouseEvent.position().toPoint());
823 for (QGraphicsItem *item : items) {
824 if (item->isEnabled() && item->hasCursor()) {
825 _q_setViewportCursor(item->cursor());
831 if (hasStoredOriginalCursor) {
832 hasStoredOriginalCursor =
false;
833 if (dragMode == QGraphicsView::ScrollHandDrag)
834 viewport->setCursor(Qt::OpenHandCursor);
836 viewport->setCursor(originalCursor);
842
843
844void QGraphicsViewPrivate::storeDragDropEvent(
const QGraphicsSceneDragDropEvent *event)
846 delete lastDragDropEvent;
847 lastDragDropEvent =
new QGraphicsSceneDragDropEvent(event->type());
848 lastDragDropEvent->setScenePos(event->scenePos());
849 lastDragDropEvent->setScreenPos(event->screenPos());
850 lastDragDropEvent->setButtons(event->buttons());
851 lastDragDropEvent->setModifiers(event->modifiers());
852 lastDragDropEvent->setPossibleActions(event->possibleActions());
853 lastDragDropEvent->setProposedAction(event->proposedAction());
854 lastDragDropEvent->setDropAction(event->dropAction());
855 lastDragDropEvent->setMimeData(event->mimeData());
856 lastDragDropEvent->setWidget(event->widget());
857 lastDragDropEvent->setSource(event->source());
858 lastDragDropEvent->setTimestamp(event->timestamp());
862
863
864void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
867#if QT_CONFIG(draganddrop)
869 dest->setScenePos(q->mapToScene(source->position().toPoint()));
870 dest->setScreenPos(q->mapToGlobal(source->position().toPoint()));
871 dest->setButtons(source->buttons());
872 dest->setModifiers(source->modifiers());
873 dest->setPossibleActions(source->possibleActions());
874 dest->setProposedAction(source->proposedAction());
875 dest->setDropAction(source->dropAction());
876 dest->setMimeData(source->mimeData());
877 dest->setWidget(viewport);
878 dest->setSource(qobject_cast<QWidget *>(source->source()));
886
887
888QTransform QGraphicsViewPrivate::mapToViewTransform(
const QGraphicsItem *item)
const
890 Q_Q(
const QGraphicsView);
892 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
894 if (item->d_ptr->itemIsUntransformable())
895 return item->deviceTransform(q->viewportTransform());
900 const QGraphicsItem *parentItem = item;
901 const QGraphicsItemPrivate *itemd;
903 itemd = parentItem->d_ptr.data();
904 if (itemd->transformData)
906 offset += itemd->pos;
907 }
while ((parentItem = itemd->parent));
909 QTransform move = QTransform::fromTranslate(offset.x(), offset.y());
911 move.translate(-scrollX, -scrollY);
912 return identityMatrix ? move : matrix * move;
914 QTransform tr = parentItem->sceneTransform();
917 return move * tr * QTransform::fromTranslate(-scrollX, -scrollY);
920QRect QGraphicsViewPrivate::mapToViewRect(
const QGraphicsItem *item,
const QRectF &rect)
const
922 return mapToViewTransform(item).mapRect(rect).toAlignedRect();
926
927
928QRegion QGraphicsViewPrivate::mapToViewRegion(
const QGraphicsItem *item,
const QRectF &rect)
const
930 Q_Q(
const QGraphicsView);
932 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
935 QTransform itv = item->deviceTransform(q->viewportTransform());
936 return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
940
941
942void QGraphicsViewPrivate::processPendingUpdates()
947 if (fullUpdatePending) {
949 }
else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
950 viewport->update(dirtyBoundingRect);
952 viewport->update(dirtyRegion);
955 dirtyBoundingRect = QRect();
956 dirtyRegion = QRegion();
960{
return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
963{
return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
967 if (rect->isEmpty()) {
970 rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
971 qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
976
977
978
979
980void QGraphicsViewPrivate::setUpdateClip(QGraphicsItem *item)
985 if (!item || viewportUpdateMode == QGraphicsView::NoViewportUpdate
986 || viewportUpdateMode == QGraphicsView::FullViewportUpdate) {
987 hasUpdateClip =
false;
996 if (item->d_ptr->itemIsUntransformable()) {
997 QTransform xform = item->deviceTransform(q->viewportTransform());
998 clip = xform.mapRect(item->boundingRect()).toAlignedRect();
999 }
else if (item->d_ptr->sceneTransformTranslateOnly && identityMatrix) {
1000 QRectF r(item->boundingRect());
1001 r.translate(item->d_ptr->sceneTransform.dx() - horizontalScroll(),
1002 item->d_ptr->sceneTransform.dy() - verticalScroll());
1003 clip = r.toAlignedRect();
1004 }
else if (!q->isTransformed()) {
1005 clip = item->d_ptr->sceneTransform.mapRect(item->boundingRect()).toAlignedRect();
1007 QTransform xform = item->d_ptr->sceneTransform;
1008 xform *= q->viewportTransform();
1009 clip = xform.mapRect(item->boundingRect()).toAlignedRect();
1012 if (hasUpdateClip) {
1017 hasUpdateClip =
true;
1021bool QGraphicsViewPrivate::updateRegion(
const QRectF &rect,
const QTransform &xform)
1026 if (viewportUpdateMode != QGraphicsView::MinimalViewportUpdate
1027 && viewportUpdateMode != QGraphicsView::SmartViewportUpdate) {
1029 return updateRectF(xform.mapRect(rect));
1034 const QRegion region = xform.map(QRegion(rect.toAlignedRect()));
1035 QRect viewRect = region.boundingRect();
1036 const bool dontAdjustForAntialiasing = optimizationFlags & QGraphicsView::DontAdjustForAntialiasing;
1037 if (dontAdjustForAntialiasing)
1038 viewRect.adjust(-1, -1, 1, 1);
1040 viewRect.adjust(-2, -2, 2, 2);
1041 if (!intersectsViewport(viewRect, viewport->width(), viewport->height()))
1044 for (QRect viewRect : region) {
1045 if (dontAdjustForAntialiasing)
1046 viewRect.adjust(-1, -1, 1, 1);
1048 viewRect.adjust(-2, -2, 2, 2);
1050 viewRect &= updateClip;
1051 dirtyRegion += viewRect;
1059bool QGraphicsViewPrivate::updateRect(
const QRect &r)
1061 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
1062 || !intersectsViewport(r, viewport->width(), viewport->height())) {
1066 switch (viewportUpdateMode) {
1067 case QGraphicsView::FullViewportUpdate:
1068 fullUpdatePending =
true;
1071 case QGraphicsView::BoundingRectViewportUpdate:
1073 QRect_unite(&dirtyBoundingRect, r & updateClip);
1075 QRect_unite(&dirtyBoundingRect, r);
1076 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
1077 fullUpdatePending =
true;
1081 case QGraphicsView::SmartViewportUpdate:
1082 case QGraphicsView::MinimalViewportUpdate:
1084 dirtyRegion += r & updateClip;
1095QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(
int numItems)
1097 if (mustAllocateStyleOptions || (numItems > styleOptions.capacity()))
1099 return new QStyleOptionGraphicsItem[numItems];
1102 if (numItems > styleOptions.size())
1103 styleOptions.resize(numItems);
1105 mustAllocateStyleOptions =
true;
1106 return styleOptions.data();
1109void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array)
1111 mustAllocateStyleOptions =
false;
1112 if (array != styleOptions.data())
1119
1120
1121
1122
1123
1124
1125
1126
1127QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(
const QRegion &exposedRegion,
bool *allItems,
1128 const QTransform &viewTransform)
const
1130 Q_Q(
const QGraphicsView);
1135 const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
1137 if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
1142 return scene->items(Qt::AscendingOrder);
1148 bool simpleRectLookup = exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale;
1149 if (simpleRectLookup) {
1150 return scene->items(exposedRegionSceneBounds,
1151 Qt::IntersectsItemBoundingRect,
1152 Qt::AscendingOrder, viewTransform);
1158 QRegion adjustedRegion;
1159 for (
const QRect &r : exposedRegion)
1160 adjustedRegion += r.adjusted(-1, -1, 1, 1);
1162 const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
1163 return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
1164 Qt::AscendingOrder, viewTransform);
1168
1169
1170
1171
1172
1173
1174void QGraphicsViewPrivate::updateInputMethodSensitivity()
1177 QGraphicsItem *focusItem =
nullptr;
1178 bool enabled = scene && (focusItem = scene->focusItem())
1179 && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod);
1180 q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
1181 q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
1184 q->setInputMethodHints({ });
1188 QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget()
1189 ?
static_cast<QGraphicsProxyWidget *>(focusItem) :
nullptr;
1191 q->setInputMethodHints(focusItem->inputMethodHints());
1192 }
else if (QWidget *widget = proxy->widget()) {
1193 if (QWidget *fw = widget->focusWidget())
1195 q->setInputMethodHints(widget->inputMethodHints());
1197 q->setInputMethodHints({ });
1202
1203
1204QGraphicsView::QGraphicsView(QWidget *parent)
1205 : QAbstractScrollArea(*
new QGraphicsViewPrivate, parent)
1207 setViewport(
nullptr);
1208 setAcceptDrops(
true);
1209 setBackgroundRole(QPalette::Base);
1211 setAttribute(Qt::WA_InputMethodEnabled);
1212 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1216
1217
1218
1219QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent)
1220 : QAbstractScrollArea(*
new QGraphicsViewPrivate, parent)
1223 setViewport(
nullptr);
1224 setAcceptDrops(
true);
1225 setBackgroundRole(QPalette::Base);
1227 setAttribute(Qt::WA_InputMethodEnabled);
1228 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1232
1233
1234QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent)
1235 : QAbstractScrollArea(dd, parent)
1237 setViewport(
nullptr);
1238 setAcceptDrops(
true);
1239 setBackgroundRole(QPalette::Base);
1241 setAttribute(Qt::WA_InputMethodEnabled);
1242 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1246
1247
1248QGraphicsView::~QGraphicsView()
1252 d->scene->d_func()->views.removeAll(
this);
1253 delete d->lastDragDropEvent;
1257
1258
1259QSize QGraphicsView::sizeHint()
const
1261 Q_D(
const QGraphicsView);
1263 QSizeF baseSize = d->matrix.mapRect(sceneRect()).size();
1264 baseSize += QSizeF(d->frameWidth * 2, d->frameWidth * 2);
1265 return baseSize.boundedTo((3 * QGuiApplication::primaryScreen()->virtualSize()) / 4).toSize();
1267 return QAbstractScrollArea::sizeHint();
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285QPainter::RenderHints QGraphicsView::renderHints()
const
1287 Q_D(
const QGraphicsView);
1288 return d->renderHints;
1290void QGraphicsView::setRenderHints(QPainter::RenderHints hints)
1293 if (hints == d->renderHints)
1295 d->renderHints = hints;
1300
1301
1302
1303
1304
1305void QGraphicsView::setRenderHint(QPainter::RenderHint hint,
bool enabled)
1308 QPainter::RenderHints oldHints = d->renderHints;
1309 d->renderHints.setFlag(hint, enabled);
1310 if (oldHints != d->renderHints)
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326Qt::Alignment QGraphicsView::alignment()
const
1328 Q_D(
const QGraphicsView);
1329 return d->alignment;
1331void QGraphicsView::setAlignment(Qt::Alignment alignment)
1334 if (d->alignment != alignment) {
1335 d->alignment = alignment;
1336 d->recalculateContentSize();
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358QGraphicsView::ViewportAnchor QGraphicsView::transformationAnchor()
const
1360 Q_D(
const QGraphicsView);
1361 return d->transformationAnchor;
1363void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor)
1366 d->transformationAnchor = anchor;
1370 if (d->transformationAnchor == AnchorUnderMouse)
1371 d->viewport->setMouseTracking(
true);
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390QGraphicsView::ViewportAnchor QGraphicsView::resizeAnchor()
const
1392 Q_D(
const QGraphicsView);
1393 return d->resizeAnchor;
1395void QGraphicsView::setResizeAnchor(ViewportAnchor anchor)
1398 d->resizeAnchor = anchor;
1402 if (d->resizeAnchor == AnchorUnderMouse)
1403 d->viewport->setMouseTracking(
true);
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424QGraphicsView::ViewportUpdateMode QGraphicsView::viewportUpdateMode()
const
1426 Q_D(
const QGraphicsView);
1427 return d->viewportUpdateMode;
1429void QGraphicsView::setViewportUpdateMode(ViewportUpdateMode mode)
1432 d->viewportUpdateMode = mode;
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453QGraphicsView::OptimizationFlags QGraphicsView::optimizationFlags()
const
1455 Q_D(
const QGraphicsView);
1456 return d->optimizationFlags;
1458void QGraphicsView::setOptimizationFlags(OptimizationFlags flags)
1461 d->optimizationFlags = flags;
1465
1466
1467
1468
1469void QGraphicsView::setOptimizationFlag(OptimizationFlag flag,
bool enabled)
1472 d->optimizationFlags.setFlag(flag, enabled);
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489QGraphicsView::DragMode QGraphicsView::dragMode()
const
1491 Q_D(
const QGraphicsView);
1494void QGraphicsView::setDragMode(DragMode mode)
1497 if (d->dragMode == mode)
1500#if QT_CONFIG(rubberband)
1501 d->clearRubberBand();
1505 if (d->dragMode == ScrollHandDrag)
1506 viewport()->unsetCursor();
1513 if (d->dragMode == ScrollHandDrag && mode == NoDrag && d->handScrolling)
1514 d->handScrolling =
false;
1519 if (d->dragMode == ScrollHandDrag) {
1521 d->hasStoredOriginalCursor =
false;
1522 viewport()->setCursor(Qt::OpenHandCursor);
1527#if QT_CONFIG(rubberband)
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541Qt::ItemSelectionMode QGraphicsView::rubberBandSelectionMode()
const
1543 Q_D(
const QGraphicsView);
1544 return d->rubberBandSelectionMode;
1546void QGraphicsView::setRubberBandSelectionMode(Qt::ItemSelectionMode mode)
1549 d->rubberBandSelectionMode = mode;
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1564QRect QGraphicsView::rubberBandRect()
const
1566 Q_D(
const QGraphicsView);
1567 if (d->dragMode != QGraphicsView::RubberBandDrag || !d->sceneInteractionAllowed || !d->rubberBanding)
1570 return d->rubberBandRect;
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594QGraphicsView::CacheMode QGraphicsView::cacheMode()
const
1596 Q_D(
const QGraphicsView);
1597 return d->cacheMode;
1599void QGraphicsView::setCacheMode(CacheMode mode)
1602 if (mode == d->cacheMode)
1604 d->cacheMode = mode;
1605 resetCachedContent();
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621void QGraphicsView::resetCachedContent()
1624 if (d->cacheMode == CacheNone)
1627 if (d->cacheMode & CacheBackground) {
1629 d->mustResizeBackgroundPixmap =
true;
1631 }
else if (d->mustResizeBackgroundPixmap) {
1634 d->mustResizeBackgroundPixmap =
false;
1635 d->backgroundPixmap = QPixmap();
1636 d->backgroundPixmapExposed = QRegion();
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656void QGraphicsView::invalidateScene(
const QRectF &rect, QGraphicsScene::SceneLayers layers)
1659 if ((layers & QGraphicsScene::BackgroundLayer) && !d->mustResizeBackgroundPixmap) {
1660 QRect viewRect = mapFromScene(rect).boundingRect();
1661 if (viewport()->rect().intersects(viewRect)) {
1664 d->backgroundPixmapExposed += viewRect;
1666 d->scene->update(rect);
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681bool QGraphicsView::isInteractive()
const
1683 Q_D(
const QGraphicsView);
1684 return d->sceneInteractionAllowed;
1686void QGraphicsView::setInteractive(
bool allowed)
1689 d->sceneInteractionAllowed = allowed;
1693
1694
1695
1696
1697
1698QGraphicsScene *QGraphicsView::scene()
const
1700 Q_D(
const QGraphicsView);
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714void QGraphicsView::setScene(QGraphicsScene *scene)
1717 if (d->scene == scene)
1725 disconnect(d->scene, SIGNAL(changed(QList<QRectF>)),
1726 this, SLOT(updateScene(QList<QRectF>)));
1727 disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
1728 this, SLOT(updateSceneRect(QRectF)));
1729 d->scene->d_func()->removeView(
this);
1730 d->connectedToScene =
false;
1732 if (isActiveWindow() && isVisible()) {
1733 QEvent windowDeactivate(QEvent::WindowDeactivate);
1734 QCoreApplication::sendEvent(d->scene, &windowDeactivate);
1737 d->scene->clearFocus();
1741 if ((d->scene = scene)) {
1742 connect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
1743 this, SLOT(updateSceneRect(QRectF)));
1744 d->updateSceneSlotReimplementedChecked =
false;
1745 d->scene->d_func()->addView(
this);
1746 d->recalculateContentSize();
1747 d->lastCenterPoint = sceneRect().center();
1748 d->keepLastCenterPoint =
true;
1751 if (!d->scene->d_func()->allItemsIgnoreHoverEvents
1752 || !d->scene->d_func()->allItemsUseDefaultCursor) {
1753 d->viewport->setMouseTracking(
true);
1757 if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
1758 d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
1760 if (isActiveWindow() && isVisible()) {
1761 QEvent windowActivate(QEvent::WindowActivate);
1762 QCoreApplication::sendEvent(d->scene, &windowActivate);
1765 d->recalculateContentSize();
1768 d->updateInputMethodSensitivity();
1770 if (d->scene && hasFocus())
1771 d->scene->setFocus();
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797QRectF QGraphicsView::sceneRect()
const
1799 Q_D(
const QGraphicsView);
1800 if (d->hasSceneRect)
1801 return d->sceneRect;
1803 return d->scene->sceneRect();
1806void QGraphicsView::setSceneRect(
const QRectF &rect)
1809 d->hasSceneRect = !rect.isNull();
1810 d->sceneRect = rect;
1811 d->recalculateContentSize();
1815
1816
1817
1818
1819void QGraphicsView::rotate(qreal angle)
1822 QTransform matrix = d->matrix;
1823 matrix.rotate(angle);
1824 setTransform(matrix);
1828
1829
1830
1831
1832void QGraphicsView::scale(qreal sx, qreal sy)
1835 QTransform matrix = d->matrix;
1836 matrix.scale(sx, sy);
1837 setTransform(matrix);
1841
1842
1843
1844
1845void QGraphicsView::shear(qreal sh, qreal sv)
1848 QTransform matrix = d->matrix;
1849 matrix.shear(sh, sv);
1850 setTransform(matrix);
1854
1855
1856
1857
1858void QGraphicsView::translate(qreal dx, qreal dy)
1861 QTransform matrix = d->matrix;
1862 matrix.translate(dx, dy);
1863 setTransform(matrix);
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878void QGraphicsView::centerOn(
const QPointF &pos)
1881 qreal width = viewport()->width();
1882 qreal height = viewport()->height();
1883 QPointF viewPoint = d->matrix.map(pos);
1884 QPointF oldCenterPoint = pos;
1886 if (!d->leftIndent) {
1887 if (isRightToLeft()) {
1888 qint64 horizontal = 0;
1889 horizontal += horizontalScrollBar()->minimum();
1890 horizontal += horizontalScrollBar()->maximum();
1891 horizontal -= qRound(viewPoint.x() - width / 2.0);
1892 horizontalScrollBar()->setValue(horizontal);
1894 horizontalScrollBar()->setValue(qRound(viewPoint.x() - width / 2.0));
1898 verticalScrollBar()->setValue(qRound(viewPoint.y() - height / 2.0));
1899 d->lastCenterPoint = oldCenterPoint;
1903
1904
1905
1906
1907
1908
1911
1912
1913
1914
1915
1916
1917
1918void QGraphicsView::centerOn(
const QGraphicsItem *item)
1920 centerOn(item->sceneBoundingRect().center());
1924
1925
1926
1927
1928
1929
1930
1931
1932void QGraphicsView::ensureVisible(
const QRectF &rect,
int xmargin,
int ymargin)
1935 qreal width = viewport()->width();
1936 qreal height = viewport()->height();
1937 QRectF viewRect = d->matrix.mapRect(rect);
1939 qreal left = d->horizontalScroll();
1940 qreal right = left + width;
1941 qreal top = d->verticalScroll();
1942 qreal bottom = top + height;
1944 if (viewRect.left() <= left + xmargin) {
1947 horizontalScrollBar()->setValue(
int(viewRect.left() - xmargin - 0.5));
1949 if (viewRect.right() >= right - xmargin) {
1952 horizontalScrollBar()->setValue(
int(viewRect.right() - width + xmargin + 0.5));
1954 if (viewRect.top() <= top + ymargin) {
1957 verticalScrollBar()->setValue(
int(viewRect.top() - ymargin - 0.5));
1959 if (viewRect.bottom() >= bottom - ymargin) {
1962 verticalScrollBar()->setValue(
int(viewRect.bottom() - height + ymargin + 0.5));
1967
1968
1969
1970
1971
1972
1973
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985void QGraphicsView::ensureVisible(
const QGraphicsItem *item,
int xmargin,
int ymargin)
1987 ensureVisible(item->sceneBoundingRect(), xmargin, ymargin);
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014void QGraphicsView::fitInView(
const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
2017 if (!d->scene || rect.isNull())
2021 QRectF unity = d->matrix.mapRect(QRectF(0, 0, 1, 1));
2022 if (unity.isEmpty())
2024 scale(1 / unity.width(), 1 / unity.height());
2028 QRectF viewRect = viewport()->rect().adjusted(margin, margin, -margin, -margin);
2029 if (viewRect.isEmpty())
2031 QRectF sceneRect = d->matrix.mapRect(rect);
2032 if (sceneRect.isEmpty())
2034 qreal xratio = viewRect.width() / sceneRect.width();
2035 qreal yratio = viewRect.height() / sceneRect.height();
2038 switch (aspectRatioMode) {
2039 case Qt::KeepAspectRatio:
2040 xratio = yratio = qMin(xratio, yratio);
2042 case Qt::KeepAspectRatioByExpanding:
2043 xratio = yratio = qMax(xratio, yratio);
2045 case Qt::IgnoreAspectRatio:
2050 scale(xratio, yratio);
2051 centerOn(rect.center());
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2067
2068
2069
2070
2071
2072
2073
2074void QGraphicsView::fitInView(
const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode)
2076 QPainterPath path = item->isClipped() ? item->clipPath() : item->shape();
2077 if (item->d_ptr->hasTranslateOnlySceneTransform()) {
2078 path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy());
2079 fitInView(path.boundingRect(), aspectRatioMode);
2081 fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode);
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105void QGraphicsView::render(QPainter *painter,
const QRectF &target,
const QRect &source,
2106 Qt::AspectRatioMode aspectRatioMode)
2111 if (!d->scene || !(painter && painter->isActive()))
2115 QRect sourceRect = source;
2116 if (source.isNull())
2117 sourceRect = viewport()->rect();
2120 QRectF targetRect = target;
2121 if (target.isNull()) {
2122 if (painter->device()->devType() == QInternal::Picture)
2123 targetRect = sourceRect;
2125 targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
2129 qreal xratio = targetRect.width() / sourceRect.width();
2130 qreal yratio = targetRect.height() / sourceRect.height();
2133 switch (aspectRatioMode) {
2134 case Qt::KeepAspectRatio:
2135 xratio = yratio = qMin(xratio, yratio);
2137 case Qt::KeepAspectRatioByExpanding:
2138 xratio = yratio = qMax(xratio, yratio);
2140 case Qt::IgnoreAspectRatio:
2146 QPolygonF sourceScenePoly = mapToScene(sourceRect.adjusted(-1, -1, 1, 1));
2147 QList<QGraphicsItem *> itemList = d->scene->items(sourceScenePoly,
2148 Qt::IntersectsItemBoundingRect);
2149 QGraphicsItem **itemArray =
new QGraphicsItem *[itemList.size()];
2150 int numItems = itemList.size();
2151 for (
int i = 0; i < numItems; ++i)
2152 itemArray[numItems - i - 1] = itemList.at(i);
2156 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
2157 QTransform painterMatrix = d->matrix * moveMatrix;
2158 painterMatrix *= QTransform()
2159 .translate(targetRect.left(), targetRect.top())
2160 .scale(xratio, yratio)
2161 .translate(-sourceRect.left(), -sourceRect.top());
2164 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
2165 for (
int i = 0; i < numItems; ++i)
2166 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
2171 painter->setClipRect(targetRect);
2173 path.addPolygon(sourceScenePoly);
2174 path.closeSubpath();
2175 painter->setClipPath(painterMatrix.map(path), Qt::IntersectClip);
2178 painter->setTransform(painterMatrix,
true);
2181 QRectF sourceSceneRect = sourceScenePoly.boundingRect();
2182 drawBackground(painter, sourceSceneRect);
2183 drawItems(painter, numItems, itemArray, styleOptionArray);
2184 drawForeground(painter, sourceSceneRect);
2186 delete [] itemArray;
2187 d->freeStyleOptionsArray(styleOptionArray);
2193
2194
2195
2196
2197
2198
2199QList<QGraphicsItem *> QGraphicsView::items()
const
2201 Q_D(
const QGraphicsView);
2203 return QList<QGraphicsItem *>();
2204 return d->scene->items();
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221QList<QGraphicsItem *> QGraphicsView::items(
const QPoint &pos)
const
2223 Q_D(
const QGraphicsView);
2225 return QList<QGraphicsItem *>();
2229 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
2231 QTransform xinv = viewportTransform().inverted();
2232 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
2233 Qt::IntersectsItemShape,
2234 Qt::DescendingOrder,
2235 viewportTransform());
2238 return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
2239 Qt::IntersectsItemShape,
2240 Qt::DescendingOrder,
2241 viewportTransform());
2245
2246
2247
2248
2249
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266QList<QGraphicsItem *> QGraphicsView::items(
const QRect &rect, Qt::ItemSelectionMode mode)
const
2268 Q_D(
const QGraphicsView);
2270 return QList<QGraphicsItem *>();
2271 return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform());
2275
2276
2277
2278
2279
2280
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297QList<QGraphicsItem *> QGraphicsView::items(
const QPolygon &polygon, Qt::ItemSelectionMode mode)
const
2299 Q_D(
const QGraphicsView);
2301 return QList<QGraphicsItem *>();
2302 return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform());
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317QList<QGraphicsItem *> QGraphicsView::items(
const QPainterPath &path, Qt::ItemSelectionMode mode)
const
2319 Q_D(
const QGraphicsView);
2321 return QList<QGraphicsItem *>();
2322 return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform());
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336QGraphicsItem *QGraphicsView::itemAt(
const QPoint &pos)
const
2338 Q_D(
const QGraphicsView);
2341 const QList<QGraphicsItem *> itemsAtPos = items(pos);
2342 return itemsAtPos.isEmpty() ?
nullptr : itemsAtPos.first();
2346
2347
2348
2349
2350
2351
2354
2355
2356
2357
2358
2359
2360
2361
2362QPointF QGraphicsView::mapToScene(
const QPoint &point)
const
2364 Q_D(
const QGraphicsView);
2366 p.rx() += d->horizontalScroll();
2367 p.ry() += d->verticalScroll();
2368 return d->identityMatrix ? p : d->matrix.inverted().map(p);
2372
2373
2374
2375
2376
2379
2380
2381
2382
2383
2384QPolygonF QGraphicsView::mapToScene(
const QRect &rect)
const
2386 Q_D(
const QGraphicsView);
2387 if (!rect.isValid())
2390 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
2391 QRect r = rect.adjusted(0, 0, 1, 1);
2392 QPointF tl = scrollOffset + r.topLeft();
2393 QPointF tr = scrollOffset + r.topRight();
2394 QPointF br = scrollOffset + r.bottomRight();
2395 QPointF bl = scrollOffset + r.bottomLeft();
2398 if (!d->identityMatrix) {
2399 QTransform x = d->matrix.inverted();
2400 poly[0] = x.map(tl);
2401 poly[1] = x.map(tr);
2402 poly[2] = x.map(br);
2403 poly[3] = x.map(bl);
2414
2415
2416
2417
2418
2421
2422
2423
2424
2425
2426QPolygonF QGraphicsView::mapToScene(
const QPolygon &polygon)
const
2429 poly.reserve(polygon.size());
2430 for (
const QPoint &point : polygon)
2431 poly << mapToScene(point);
2436
2437
2438
2439
2440
2441QPainterPath QGraphicsView::mapToScene(
const QPainterPath &path)
const
2443 Q_D(
const QGraphicsView);
2444 QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
2445 matrix *= d->matrix.inverted();
2446 return matrix.map(path);
2450
2451
2452
2453
2454QPoint QGraphicsView::mapFromScene(
const QPointF &point)
const
2456 Q_D(
const QGraphicsView);
2457 QPointF p = d->identityMatrix ? point : d->matrix.map(point);
2458 p.rx() -= d->horizontalScroll();
2459 p.ry() -= d->verticalScroll();
2464
2465
2466
2467
2468
2471
2472
2473
2474
2475
2476QPolygon QGraphicsView::mapFromScene(
const QRectF &rect)
const
2478 Q_D(
const QGraphicsView);
2483 if (!d->identityMatrix) {
2484 const QTransform &x = d->matrix;
2485 tl = x.map(rect.topLeft());
2486 tr = x.map(rect.topRight());
2487 br = x.map(rect.bottomRight());
2488 bl = x.map(rect.bottomLeft());
2490 tl = rect.topLeft();
2491 tr = rect.topRight();
2492 br = rect.bottomRight();
2493 bl = rect.bottomLeft();
2495 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
2502 poly[0] = tl.toPoint();
2503 poly[1] = tr.toPoint();
2504 poly[2] = br.toPoint();
2505 poly[3] = bl.toPoint();
2510
2511
2512
2513
2514
2517
2518
2519
2520
2521
2522QPolygon QGraphicsView::mapFromScene(
const QPolygonF &polygon)
const
2525 poly.reserve(polygon.size());
2526 for (
const QPointF &point : polygon)
2527 poly << mapFromScene(point);
2532
2533
2534
2535
2536
2537QPainterPath QGraphicsView::mapFromScene(
const QPainterPath &path)
const
2539 Q_D(
const QGraphicsView);
2540 QTransform matrix = d->matrix;
2541 matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
2542 return matrix.map(path);
2546
2547
2548QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query)
const
2550 Q_D(
const QGraphicsView);
2554 QVariant value = d->scene->inputMethodQuery(query);
2555 if (value.userType() == QMetaType::QRectF)
2556 value = d->mapRectFromScene(value.toRectF());
2557 else if (value.userType() == QMetaType::QPointF)
2558 value = mapFromScene(value.toPointF());
2559 else if (value.userType() == QMetaType::QRect)
2560 value = d->mapRectFromScene(value.toRect()).toRect();
2561 else if (value.userType() == QMetaType::QPoint)
2562 value = mapFromScene(value.toPoint());
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579QBrush QGraphicsView::backgroundBrush()
const
2581 Q_D(
const QGraphicsView);
2582 return d->backgroundBrush;
2584void QGraphicsView::setBackgroundBrush(
const QBrush &brush)
2587 d->backgroundBrush = brush;
2590 if (d->cacheMode & CacheBackground) {
2592 d->mustResizeBackgroundPixmap =
true;
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609QBrush QGraphicsView::foregroundBrush()
const
2611 Q_D(
const QGraphicsView);
2612 return d->foregroundBrush;
2614void QGraphicsView::setForegroundBrush(
const QBrush &brush)
2617 d->foregroundBrush = brush;
2622
2623
2624
2625
2626void QGraphicsView::updateScene(
const QList<QRectF> &rects)
2634 if (d->fullUpdatePending || d->viewportUpdateMode == QGraphicsView::NoViewportUpdate)
2638 QList<QRect> dirtyViewportRects;
2639 dirtyViewportRects.reserve(d->dirtyRegion.rectCount() + rects.size());
2640 for (
const QRect &dirtyRect : d->dirtyRegion)
2641 dirtyViewportRects += dirtyRect;
2642 d->dirtyRegion = QRegion();
2643 d->dirtyBoundingRect = QRect();
2645 bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
2646 bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
2647 || (d->viewportUpdateMode == QGraphicsView::SmartViewportUpdate
2648 && ((dirtyViewportRects.size() + rects.size()) >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD));
2650 QRegion updateRegion;
2652 QRect viewportRect = viewport()->rect();
2653 bool redraw =
false;
2654 QTransform transform = viewportTransform();
2657 for (
const QRectF &rect : rects) {
2658 QRect xrect = transform.mapRect(rect).toAlignedRect();
2659 if (!(d->optimizationFlags & DontAdjustForAntialiasing))
2660 xrect.adjust(-2, -2, 2, 2);
2662 xrect.adjust(-1, -1, 1, 1);
2663 if (!viewportRect.intersects(xrect))
2665 dirtyViewportRects << xrect;
2668 for (
const QRect &rect : std::as_const(dirtyViewportRects)) {
2671 if (!boundingRectUpdate) {
2672 updateRegion += rect;
2674 boundingRect |= rect;
2688 viewport()->update();
2689 else if (boundingRectUpdate)
2690 viewport()->update(boundingRect);
2692 viewport()->update(updateRegion);
2696
2697
2698
2699
2700
2701
2702void QGraphicsView::updateSceneRect(
const QRectF &rect)
2705 if (!d->hasSceneRect) {
2706 d->sceneRect = rect;
2707 d->recalculateContentSize();
2712
2713
2714
2715
2716
2717
2718void QGraphicsView::setupViewport(QWidget *widget)
2723 qWarning(
"QGraphicsView::setupViewport: cannot initialize null widget");
2727 const bool isGLWidget = widget->inherits(
"QOpenGLWidget");
2729 d->accelerateScrolling = !(isGLWidget);
2731 widget->setFocusPolicy(Qt::StrongFocus);
2734 d->stereoEnabled = QWidgetPrivate::get(widget)->isStereoEnabled();
2738 widget->setAutoFillBackground(
true);
2744 if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
2745 || !d->scene->d_func()->allItemsUseDefaultCursor))
2746 || d->transformationAnchor == AnchorUnderMouse
2747 || d->resizeAnchor == AnchorUnderMouse) {
2748 widget->setMouseTracking(
true);
2752 if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
2753 widget->setAttribute(Qt::WA_AcceptTouchEvents);
2755#ifndef QT_NO_GESTURES
2757 const auto gestures = d->scene->d_func()->grabbedGestures.keys();
2758 for (Qt::GestureType gesture : gestures)
2759 widget->grabGesture(gesture);
2763 widget->setAcceptDrops(acceptDrops());
2767
2768
2769bool QGraphicsView::event(QEvent *event)
2773 if (d->sceneInteractionAllowed) {
2774 switch (event->type()) {
2775 case QEvent::ShortcutOverride:
2777 return QCoreApplication::sendEvent(d->scene, event);
2779 case QEvent::KeyPress:
2781 QKeyEvent *k =
static_cast<QKeyEvent *>(event);
2782 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
2789 QCoreApplication::sendEvent(d->scene, event);
2790 if (event->isAccepted())
2804 return QAbstractScrollArea::event(event);
2808
2809
2810bool QGraphicsView::viewportEvent(QEvent *event)
2814 return QAbstractScrollArea::viewportEvent(event);
2816 switch (event->type()) {
2818 QCoreApplication::sendEvent(d->scene, event);
2820 case QEvent::WindowActivate:
2821 QCoreApplication::sendEvent(d->scene, event);
2823 case QEvent::WindowDeactivate:
2828 if (!d->scene->d_func()->popupWidgets.isEmpty())
2829 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.constFirst());
2830 QCoreApplication::sendEvent(d->scene, event);
2833 if (d->scene && isActiveWindow()) {
2834 QEvent windowActivate(QEvent::WindowActivate);
2835 QCoreApplication::sendEvent(d->scene, &windowActivate);
2840 if (!event->spontaneous() && d->scene && isActiveWindow()) {
2841 QEvent windowDeactivate(QEvent::WindowDeactivate);
2842 QCoreApplication::sendEvent(d->scene, &windowDeactivate);
2845 case QEvent::Leave: {
2849 if ((QApplication::activePopupWidget() && QApplication::activePopupWidget() != window())
2850 || (QApplication::activeModalWidget() && QApplication::activeModalWidget() != window())
2851 || (QApplication::activeWindow() != window())) {
2852 if (!d->scene->d_func()->popupWidgets.isEmpty())
2853 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.constFirst());
2855 d->useLastMouseEvent =
false;
2856 QGraphicsSceneEvent leaveEvent(QEvent::GraphicsSceneLeave);
2857 leaveEvent.setWidget(viewport());
2858 QCoreApplication::sendEvent(d->scene, &leaveEvent);
2859 event->setAccepted(leaveEvent.isAccepted());
2862#if QT_CONFIG(tooltip)
2863 case QEvent::ToolTip: {
2864 QHelpEvent *toolTip =
static_cast<QHelpEvent *>(event);
2865 QGraphicsSceneHelpEvent helpEvent(QEvent::GraphicsSceneHelp);
2866 helpEvent.setWidget(viewport());
2867 helpEvent.setScreenPos(toolTip->globalPos());
2868 helpEvent.setScenePos(mapToScene(toolTip->pos()));
2869 QCoreApplication::sendEvent(d->scene, &helpEvent);
2870 toolTip->setAccepted(helpEvent.isAccepted());
2876 d->fullUpdatePending =
false;
2877 d->dirtyScrollOffset = QPoint();
2882 if (!d->updateSceneSlotReimplementedChecked) {
2883 d->updateSceneSlotReimplementedChecked =
true;
2884 const QMetaObject *mo = metaObject();
2885 if (mo != &QGraphicsView::staticMetaObject) {
2886 if (mo->indexOfSlot(
"updateScene(QList<QRectF>)")
2887 != QGraphicsView::staticMetaObject.indexOfSlot(
"updateScene(QList<QRectF>)")) {
2888 connect(d->scene, SIGNAL(changed(QList<QRectF>)),
2889 this, SLOT(updateScene(QList<QRectF>)));
2895 case QEvent::TouchBegin:
2896 case QEvent::TouchUpdate:
2897 case QEvent::TouchEnd:
2902 if (d->scene && d->sceneInteractionAllowed) {
2904 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
2905 QMutableTouchEvent::setTarget(touchEvent, viewport());
2906 QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
2907 QCoreApplication::sendEvent(d->scene, touchEvent);
2914#ifndef QT_NO_GESTURES
2915 case QEvent::Gesture:
2916 case QEvent::GestureOverride:
2921 if (d->scene && d->sceneInteractionAllowed) {
2922 QGestureEvent *gestureEvent =
static_cast<QGestureEvent *>(event);
2923 gestureEvent->setWidget(viewport());
2924 QCoreApplication::sendEvent(d->scene, gestureEvent);
2933 return QAbstractScrollArea::viewportEvent(event);
2936#ifndef QT_NO_CONTEXTMENU
2938
2939
2940void QGraphicsView::contextMenuEvent(QContextMenuEvent *event)
2943 if (!d->scene || !d->sceneInteractionAllowed)
2946 d->mousePressViewPoint = event->pos();
2947 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
2948 d->mousePressScreenPoint = event->globalPos();
2949 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
2950 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
2952 QGraphicsSceneContextMenuEvent contextEvent(QEvent::GraphicsSceneContextMenu);
2953 contextEvent.setWidget(viewport());
2954 contextEvent.setScenePos(d->mousePressScenePoint);
2955 contextEvent.setScreenPos(d->mousePressScreenPoint);
2956 contextEvent.setModifiers(event->modifiers());
2957 contextEvent.setReason((QGraphicsSceneContextMenuEvent::Reason)(event->reason()));
2958 contextEvent.setAccepted(event->isAccepted());
2959 contextEvent.setTimestamp(event->timestamp());
2960 QCoreApplication::sendEvent(d->scene, &contextEvent);
2961 event->setAccepted(contextEvent.isAccepted());
2965#if QT_CONFIG(draganddrop)
2967
2968
2969void QGraphicsView::dropEvent(QDropEvent *event)
2972 if (!d->scene || !d->sceneInteractionAllowed)
2976 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDrop);
2977 d->populateSceneDragDropEvent(&sceneEvent, event);
2980 QCoreApplication::sendEvent(d->scene, &sceneEvent);
2983 event->setAccepted(sceneEvent.isAccepted());
2984 if (sceneEvent.isAccepted())
2985 event->setDropAction(sceneEvent.dropAction());
2987 delete d->lastDragDropEvent;
2988 d->lastDragDropEvent =
nullptr;
2992
2993
2994void QGraphicsView::dragEnterEvent(QDragEnterEvent *event)
2997 if (!d->scene || !d->sceneInteractionAllowed)
3001 d->useLastMouseEvent =
false;
3004 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragEnter);
3005 d->populateSceneDragDropEvent(&sceneEvent, event);
3008 d->storeDragDropEvent(&sceneEvent);
3011 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3014 if (sceneEvent.isAccepted()) {
3015 event->setAccepted(
true);
3016 event->setDropAction(sceneEvent.dropAction());
3021
3022
3023void QGraphicsView::dragLeaveEvent(QDragLeaveEvent *event)
3026 if (!d->scene || !d->sceneInteractionAllowed)
3028 if (!d->lastDragDropEvent) {
3029 qWarning(
"QGraphicsView::dragLeaveEvent: drag leave received before drag enter");
3034 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragLeave);
3035 sceneEvent.setScenePos(d->lastDragDropEvent->scenePos());
3036 sceneEvent.setScreenPos(d->lastDragDropEvent->screenPos());
3037 sceneEvent.setButtons(d->lastDragDropEvent->buttons());
3038 sceneEvent.setModifiers(d->lastDragDropEvent->modifiers());
3039 sceneEvent.setPossibleActions(d->lastDragDropEvent->possibleActions());
3040 sceneEvent.setProposedAction(d->lastDragDropEvent->proposedAction());
3041 sceneEvent.setDropAction(d->lastDragDropEvent->dropAction());
3042 sceneEvent.setMimeData(d->lastDragDropEvent->mimeData());
3043 sceneEvent.setWidget(d->lastDragDropEvent->widget());
3044 sceneEvent.setSource(d->lastDragDropEvent->source());
3045 delete d->lastDragDropEvent;
3046 d->lastDragDropEvent =
nullptr;
3049 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3052 if (sceneEvent.isAccepted())
3053 event->setAccepted(
true);
3057
3058
3059void QGraphicsView::dragMoveEvent(QDragMoveEvent *event)
3062 if (!d->scene || !d->sceneInteractionAllowed)
3066 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragMove);
3067 d->populateSceneDragDropEvent(&sceneEvent, event);
3070 d->storeDragDropEvent(&sceneEvent);
3073 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3076 event->setAccepted(sceneEvent.isAccepted());
3077 if (sceneEvent.isAccepted())
3078 event->setDropAction(sceneEvent.dropAction());
3083
3084
3085void QGraphicsView::focusInEvent(QFocusEvent *event)
3088 d->updateInputMethodSensitivity();
3089 QAbstractScrollArea::focusInEvent(event);
3091 QCoreApplication::sendEvent(d->scene, event);
3093 if (!d->scene || !event->isAccepted())
3094 QAbstractScrollArea::focusInEvent(event);
3098
3099
3100bool QGraphicsView::focusNextPrevChild(
bool next)
3102 return QAbstractScrollArea::focusNextPrevChild(next);
3106
3107
3108void QGraphicsView::focusOutEvent(QFocusEvent *event)
3111 QAbstractScrollArea::focusOutEvent(event);
3113 QCoreApplication::sendEvent(d->scene, event);
3117
3118
3119void QGraphicsView::keyPressEvent(QKeyEvent *event)
3122 if (!d->scene || !d->sceneInteractionAllowed) {
3123 QAbstractScrollArea::keyPressEvent(event);
3126 QCoreApplication::sendEvent(d->scene, event);
3127 if (!event->isAccepted())
3128 QAbstractScrollArea::keyPressEvent(event);
3132
3133
3134void QGraphicsView::keyReleaseEvent(QKeyEvent *event)
3137 if (!d->scene || !d->sceneInteractionAllowed)
3139 QCoreApplication::sendEvent(d->scene, event);
3140 if (!event->isAccepted())
3141 QAbstractScrollArea::keyReleaseEvent(event);
3145
3146
3147void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
3150 if (!d->scene || !d->sceneInteractionAllowed)
3153 d->storeMouseEvent(event);
3154 d->mousePressViewPoint = event->position().toPoint();
3155 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
3156 d->mousePressScreenPoint = event->globalPosition().toPoint();
3157 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
3158 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
3159 d->mousePressButton = event->button();
3161 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
3162 mouseEvent.setWidget(viewport());
3163 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3164 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3165 mouseEvent.setScenePos(mapToScene(d->mousePressViewPoint));
3166 mouseEvent.setScreenPos(d->mousePressScreenPoint);
3167 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3168 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3169 mouseEvent.setButtons(event->buttons());
3170 mouseEvent.setAccepted(
false);
3171 mouseEvent.setButton(event->button());
3172 mouseEvent.setModifiers(event->modifiers());
3173 mouseEvent.setSource(event->source());
3174 mouseEvent.setFlags(event->flags());
3175 mouseEvent.setTimestamp(event->timestamp());
3176 if (event->spontaneous())
3177 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3179 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3182 const bool isAccepted = mouseEvent.isAccepted();
3183 event->setAccepted(isAccepted);
3186 d->lastMouseEvent.setAccepted(isAccepted);
3190
3191
3192void QGraphicsView::mousePressEvent(QMouseEvent *event)
3199 d->storeMouseEvent(event);
3200 d->lastMouseEvent.setAccepted(
false);
3202 if (d->sceneInteractionAllowed) {
3204 d->mousePressViewPoint = event->position().toPoint();
3205 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
3206 d->mousePressScreenPoint = event->globalPosition().toPoint();
3207 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
3208 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
3209 d->mousePressButton = event->button();
3213 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
3214 mouseEvent.setWidget(viewport());
3215 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3216 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3217 mouseEvent.setScenePos(d->mousePressScenePoint);
3218 mouseEvent.setScreenPos(d->mousePressScreenPoint);
3219 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3220 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3221 mouseEvent.setButtons(event->buttons());
3222 mouseEvent.setButton(event->button());
3223 mouseEvent.setModifiers(event->modifiers());
3224 mouseEvent.setSource(event->source());
3225 mouseEvent.setFlags(event->flags());
3226 mouseEvent.setAccepted(
false);
3227 mouseEvent.setTimestamp(event->timestamp());
3228 if (event->spontaneous())
3229 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3231 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3234 bool isAccepted = mouseEvent.isAccepted();
3235 event->setAccepted(isAccepted);
3238 d->lastMouseEvent.setAccepted(isAccepted);
3245#if QT_CONFIG(rubberband)
3246 if (d->dragMode == QGraphicsView::RubberBandDrag && !d->rubberBanding) {
3247 if (d->sceneInteractionAllowed) {
3250 d->rubberBanding =
true;
3251 d->rubberBandRect = QRect();
3253 bool extendSelection = (event->modifiers() & Qt::ControlModifier) != 0;
3255 if (extendSelection) {
3256 d->rubberBandSelectionOperation = Qt::AddToSelection;
3258 d->rubberBandSelectionOperation = Qt::ReplaceSelection;
3259 d->scene->clearSelection();
3265 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
3268 d->handScrolling =
true;
3269 d->handScrollMotions = 0;
3271 viewport()->setCursor(Qt::ClosedHandCursor);
3277
3278
3279void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
3283 if (d->dragMode == QGraphicsView::ScrollHandDrag) {
3284 if (d->handScrolling) {
3285 QScrollBar *hBar = horizontalScrollBar();
3286 QScrollBar *vBar = verticalScrollBar();
3287 QPoint delta = event->position().toPoint() - d->lastMouseEvent.position().toPoint();
3288 hBar->setValue(hBar->value() + (isRightToLeft() ? delta.x() : -delta.x()));
3289 vBar->setValue(vBar->value() - delta.y());
3293 ++d->handScrollMotions;
3297 d->mouseMoveEventHandler(event);
3301
3302
3303void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
3307#if QT_CONFIG(rubberband)
3308 if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed && !event->buttons()) {
3309 d->clearRubberBand();
3312 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
3317 viewport()->setCursor(Qt::OpenHandCursor);
3319 d->handScrolling =
false;
3321 if (d->scene && d->sceneInteractionAllowed && !d->lastMouseEvent.isAccepted() && d->handScrollMotions <= 6) {
3325 d->scene->clearSelection();
3329 d->storeMouseEvent(event);
3331 if (!d->sceneInteractionAllowed)
3337 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
3338 mouseEvent.setWidget(viewport());
3339 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3340 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3341 mouseEvent.setScenePos(mapToScene(event->position().toPoint()));
3342 mouseEvent.setScreenPos(event->globalPosition().toPoint());
3343 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3344 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3345 mouseEvent.setButtons(event->buttons());
3346 mouseEvent.setButton(event->button());
3347 mouseEvent.setModifiers(event->modifiers());
3348 mouseEvent.setSource(event->source());
3349 mouseEvent.setFlags(event->flags());
3350 mouseEvent.setAccepted(
false);
3351 mouseEvent.setTimestamp(event->timestamp());
3352 if (event->spontaneous())
3353 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3355 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3358 d->lastMouseEvent.setAccepted(mouseEvent.isAccepted());
3359 event->setAccepted(mouseEvent.isAccepted());
3362 if (mouseEvent.isAccepted() && mouseEvent.buttons() == 0 && viewport()->testAttribute(Qt::WA_SetCursor)) {
3364 d->_q_unsetViewportCursor();
3369#if QT_CONFIG(wheelevent)
3371
3372
3373void QGraphicsView::wheelEvent(QWheelEvent *event)
3376 if (!d->scene || !d->sceneInteractionAllowed) {
3377 QAbstractScrollArea::wheelEvent(event);
3383 QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel);
3384 wheelEvent.setWidget(viewport());
3385 wheelEvent.setScenePos(mapToScene(event->position().toPoint()));
3386 wheelEvent.setScreenPos(event->globalPosition().toPoint());
3387 wheelEvent.setButtons(event->buttons());
3388 wheelEvent.setModifiers(event->modifiers());
3389 const bool horizontal = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y());
3390 wheelEvent.setDelta(horizontal ? event->angleDelta().x() : event->angleDelta().y());
3391 wheelEvent.setPixelDelta(event->pixelDelta());
3392 wheelEvent.setPhase(event->phase());
3393 wheelEvent.setInverted(event->isInverted());
3394 wheelEvent.setOrientation(horizontal ? Qt::Horizontal : Qt::Vertical);
3395 wheelEvent.setAccepted(
false);
3396 wheelEvent.setTimestamp(event->timestamp());
3397 QCoreApplication::sendEvent(d->scene, &wheelEvent);
3398 event->setAccepted(wheelEvent.isAccepted());
3399 if (!event->isAccepted())
3400 QAbstractScrollArea::wheelEvent(event);
3405
3406
3407void QGraphicsView::paintEvent(QPaintEvent *event)
3411 QAbstractScrollArea::paintEvent(event);
3416 d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
3419 d->exposedRegion = event->region();
3420 QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
3423 QPainter painter(viewport());
3424#if QT_CONFIG(rubberband)
3425 if (d->rubberBanding && !d->rubberBandRect.isEmpty())
3429 painter.setRenderHints(painter.renderHints(),
false);
3430 painter.setRenderHints(d->renderHints,
true);
3433 const bool viewTransformed = isTransformed();
3434 if (viewTransformed)
3435 painter.setWorldTransform(viewportTransform());
3436 const QTransform viewTransform = painter.worldTransform();
3438 const auto actuallyDraw = [&]() {
3440 if (d->cacheMode & CacheBackground) {
3443 if (d->mustResizeBackgroundPixmap) {
3444 const qreal dpr = d->viewport->devicePixelRatio();
3445 d->backgroundPixmap = QPixmap(viewport()->size() * dpr);
3446 d->backgroundPixmap.setDevicePixelRatio(dpr);
3447 QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
3448 if (!bgBrush.isOpaque())
3449 d->backgroundPixmap.fill(Qt::transparent);
3450 QPainter p(&d->backgroundPixmap);
3451 p.fillRect(0, 0, d->backgroundPixmap.width(), d->backgroundPixmap.height(), bgBrush);
3452 d->backgroundPixmapExposed = QRegion(viewport()->rect());
3453 d->mustResizeBackgroundPixmap =
false;
3457 if (!d->backgroundPixmapExposed.isEmpty()) {
3458 QPainter backgroundPainter(&d->backgroundPixmap);
3459 backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
3460 if (viewTransformed)
3461 backgroundPainter.setTransform(viewTransform);
3462 QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect();
3463 drawBackground(&backgroundPainter, backgroundExposedSceneRect);
3464 d->backgroundPixmapExposed = QRegion();
3468 if (viewTransformed) {
3469 painter.setWorldTransform(QTransform());
3470 painter.drawPixmap(QPoint(), d->backgroundPixmap);
3471 painter.setWorldTransform(viewTransform);
3473 painter.drawPixmap(QPoint(), d->backgroundPixmap);
3476 if (!(d->optimizationFlags & DontSavePainterState))
3479 drawBackground(&painter, exposedSceneRect);
3480 if (!(d->optimizationFlags & DontSavePainterState))
3485 if (!(d->optimizationFlags & IndirectPainting)) {
3486 const quint32 oldRectAdjust = d->scene->d_func()->rectAdjust;
3487 if (d->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
3488 d->scene->d_func()->rectAdjust = 1;
3490 d->scene->d_func()->rectAdjust = 2;
3491 d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform :
nullptr,
3492 &d->exposedRegion, viewport());
3493 d->scene->d_func()->rectAdjust = oldRectAdjust;
3500 if (!d->scene->d_func()->painterStateProtection)
3501 painter.setOpacity(1.0);
3502 painter.setWorldTransform(viewTransform);
3505 if (!d->scene->d_func()->unpolishedItems.isEmpty())
3506 d->scene->d_func()->_q_polishItems();
3509 d->scene->d_func()->updateAll =
false;
3512 bool allItems =
false;
3513 QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
3514 if (!itemList.isEmpty()) {
3516 const int numItems = itemList.size();
3517 QGraphicsItem **itemArray = &itemList[0];
3518 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
3519 QTransform transform(Qt::Uninitialized);
3520 for (
int i = 0; i < numItems; ++i) {
3521 QGraphicsItem *item = itemArray[i];
3522 QGraphicsItemPrivate *itemd = item->d_ptr.data();
3523 itemd->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
3529 const QRectF brect = adjustedItemEffectiveBoundingRect(item);
3530 if (!itemd->itemIsUntransformable()) {
3531 transform = item->sceneTransform();
3532 if (viewTransformed)
3533 transform *= viewTransform;
3535 transform = item->deviceTransform(viewTransform);
3537 itemd->paintedViewBoundingRects.insert(d->viewport, transform.mapRect(brect).toRect());
3540 drawItems(&painter, numItems, itemArray, styleOptionArray);
3541 d->freeStyleOptionsArray(styleOptionArray);
3546 drawForeground(&painter, exposedSceneRect);
3548 #if QT_CONFIG(rubberband)
3550 if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
3552 QStyleOptionRubberBand option;
3553 option.initFrom(viewport());
3554 option.rect = d->rubberBandRect;
3555 option.shape = QRubberBand::Rectangle;
3557 QStyleHintReturnMask mask;
3558 if (viewport()->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, viewport(), &mask)) {
3560 painter.setClipRegion(mask.region, Qt::IntersectClip);
3563 viewport()->style()->drawControl(QStyle::CE_RubberBand, &option, &painter, viewport());
3571 if (d->stereoEnabled) {
3572 QWidgetPrivate* w = QWidgetPrivate::get(viewport());
3573 if (w->toggleStereoTargetBuffer()) {
3575 w->toggleStereoTargetBuffer();
3582 d->scene->d_func()->painterStateProtection =
true;
3586
3587
3588void QGraphicsView::resizeEvent(QResizeEvent *event)
3593 QPointF oldLastCenterPoint = d->lastCenterPoint;
3595 QAbstractScrollArea::resizeEvent(event);
3596 d->recalculateContentSize();
3599 if (d->resizeAnchor == NoAnchor && !d->keepLastCenterPoint) {
3600 d->updateLastCenterPoint();
3602 d->lastCenterPoint = oldLastCenterPoint;
3604 d->centerView(d->resizeAnchor);
3605 d->keepLastCenterPoint =
false;
3607 if (d->cacheMode & CacheBackground) {
3609 d->mustResizeBackgroundPixmap =
true;
3614
3615
3616void QGraphicsView::scrollContentsBy(
int dx,
int dy)
3619 d->dirtyScroll =
true;
3620 if (d->transforming)
3622 if (isRightToLeft())
3625 if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
3626 if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
3627 if (d->accelerateScrolling) {
3628#if QT_CONFIG(rubberband)
3630 if (!d->rubberBandRect.isEmpty()) {
3631 QRegion rubberBandRegion(d->rubberBandRegion(viewport(), d->rubberBandRect));
3632 rubberBandRegion += rubberBandRegion.translated(-dx, -dy);
3633 viewport()->update(rubberBandRegion);
3636 d->dirtyScrollOffset.rx() += dx;
3637 d->dirtyScrollOffset.ry() += dy;
3638 d->dirtyRegion.translate(dx, dy);
3639 viewport()->scroll(dx, dy);
3648 d->updateLastCenterPoint();
3650 if (d->cacheMode & CacheBackground) {
3653 const qreal dpr = d->backgroundPixmap.devicePixelRatio();
3654 const qreal inverseDpr = qreal(1) / dpr;
3658 if (!d->backgroundPixmap.isNull())
3659 d->backgroundPixmap.scroll(dx * dpr, dy * dpr, d->backgroundPixmap.rect(), &exposed);
3662 d->backgroundPixmapExposed.translate(dx, dy);
3663 const QRegion exposedScaled = QTransform::fromScale(inverseDpr, inverseDpr).map(exposed);
3664 d->backgroundPixmapExposed += exposedScaled;
3668 if (d->sceneInteractionAllowed)
3669 d->replayLastMouseEvent();
3673
3674
3675void QGraphicsView::showEvent(QShowEvent *event)
3678 d->recalculateContentSize();
3679 d->centerView(d->transformationAnchor);
3680 QAbstractScrollArea::showEvent(event);
3684
3685
3686void QGraphicsView::inputMethodEvent(QInputMethodEvent *event)
3690 QCoreApplication::sendEvent(d->scene, event);
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710void QGraphicsView::drawBackground(QPainter *painter,
const QRectF &rect)
3713 if (d->scene && d->backgroundBrush.style() == Qt::NoBrush) {
3714 d->scene->drawBackground(painter, rect);
3718 const bool wasAa = painter->testRenderHint(QPainter::Antialiasing);
3720 painter->setRenderHints(QPainter::Antialiasing,
false);
3721 painter->fillRect(rect, d->backgroundBrush);
3723 painter->setRenderHints(QPainter::Antialiasing,
true);
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743void QGraphicsView::drawForeground(QPainter *painter,
const QRectF &rect)
3746 if (d->scene && d->foregroundBrush.style() == Qt::NoBrush) {
3747 d->scene->drawForeground(painter, rect);
3751 painter->fillRect(rect, d->foregroundBrush);
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771void QGraphicsView::drawItems(QPainter *painter,
int numItems,
3772 QGraphicsItem *items[],
3773 const QStyleOptionGraphicsItem options[])
3777 QWidget *widget = painter->device() == viewport() ? viewport() :
nullptr;
3778 d->scene->drawItems(painter, numItems, items, options, widget);
3783
3784
3785
3786
3787
3788QTransform QGraphicsView::transform()
const
3790 Q_D(
const QGraphicsView);
3795
3796
3797
3798
3799QTransform QGraphicsView::viewportTransform()
const
3801 Q_D(
const QGraphicsView);
3802 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
3803 return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
3807
3808
3809
3810
3811
3812
3813
3814bool QGraphicsView::isTransformed()
const
3816 Q_D(
const QGraphicsView);
3817 return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846void QGraphicsView::setTransform(
const QTransform &matrix,
bool combine )
3849 QTransform oldMatrix = d->matrix;
3853 d->matrix = matrix * d->matrix;
3854 if (oldMatrix == d->matrix)
3857 d->identityMatrix = d->matrix.isIdentity();
3858 d->transforming =
true;
3860 d->recalculateContentSize();
3861 d->centerView(d->transformationAnchor);
3863 d->updateLastCenterPoint();
3866 if (d->sceneInteractionAllowed)
3867 d->replayLastMouseEvent();
3868 d->transforming =
false;
3875
3876
3877
3878
3879void QGraphicsView::resetTransform()
3881 setTransform(QTransform());
3884QPointF QGraphicsViewPrivate::mapToScene(
const QPointF &point)
const
3887 p.rx() += horizontalScroll();
3888 p.ry() += verticalScroll();
3889 return identityMatrix ? p : matrix.inverted().map(p);
3892QRectF QGraphicsViewPrivate::mapToScene(
const QRectF &rect)
const
3894 QPointF scrollOffset(horizontalScroll(), verticalScroll());
3895 QPointF tl = scrollOffset + rect.topLeft();
3896 QPointF tr = scrollOffset + rect.topRight();
3897 QPointF br = scrollOffset + rect.bottomRight();
3898 QPointF bl = scrollOffset + rect.bottomLeft();
3901 if (!identityMatrix) {
3902 QTransform x = matrix.inverted();
3903 poly[0] = x.map(tl);
3904 poly[1] = x.map(tr);
3905 poly[2] = x.map(br);
3906 poly[3] = x.map(bl);
3913 return poly.boundingRect();
3918#include "moc_qgraphicsview.cpp"
Combined button and popup list for selecting options.
static bool intersectsViewport(const QRect &r, int width, int height)
static bool containsViewport(const QRect &r, int width, int height)
static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD
static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS
static void QRect_unite(QRect *rect, const QRect &other)
int q_round_bound(qreal d)
QPainterPath qt_regionToPath(const QRegion ®ion)