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
106
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
164
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
197
200
201
202
203
204
205
206
207
208
209
210
211
212
213
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
235
236
237
238
239
240
241
242
243
244
245
258#include <QtCore/qdatetime.h>
259#include <QtCore/qdebug.h>
260#include <QtCore/qmath.h>
261#include <QtCore/qscopedvaluerollback.h>
262#include <QtWidgets/qapplication.h>
263#include <QtGui/qevent.h>
264#include <QtWidgets/qlayout.h>
265#include <QtGui/qtransform.h>
266#include <QtGui/qpainter.h>
267#include <QtGui/qpainterpath.h>
268#include <QtWidgets/qscrollbar.h>
269#include <QtWidgets/qstyleoption.h>
271#include <private/qevent_p.h>
272#include <QtGui/private/qeventpoint_p.h>
280 if (d <= (qreal) INT_MIN)
282 else if (d >= (qreal) INT_MAX)
284 return d >= 0.0 ?
int(d + 0.5) :
int(d -
int(d-1) + 0.5) +
int(d-1);
287void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
289 for (
int i = 0; i < touchEvent->pointCount(); ++i) {
290 auto &pt = touchEvent->point(i);
293 QMutableEventPoint::setScenePosition(pt, d->mapToScene(pt.position()));
299
300
301QGraphicsViewPrivate::QGraphicsViewPrivate()
302 : renderHints(QPainter::TextAntialiasing),
303 dragMode(QGraphicsView::NoDrag),
304 sceneInteractionAllowed(
true), hasSceneRect(
false),
305 connectedToScene(
false),
306 useLastMouseEvent(
false),
307 identityMatrix(
true),
309 accelerateScrolling(
true),
310 keepLastCenterPoint(
true),
312 handScrolling(
false),
313 mustAllocateStyleOptions(
false),
314 mustResizeBackgroundPixmap(
true),
315 fullUpdatePending(
true),
316 hasUpdateClip(
false),
317 mousePressButton(Qt::NoButton),
318 leftIndent(0), topIndent(0),
319 alignment(Qt::AlignCenter),
320 transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor),
321 viewportUpdateMode(QGraphicsView::MinimalViewportUpdate),
323#if QT_CONFIG(rubberband)
324 rubberBanding(
false),
325 rubberBandSelectionMode(Qt::IntersectsItemShape),
326 rubberBandSelectionOperation(Qt::ReplaceSelection),
328 handScrollMotions(0),
330 hasStoredOriginalCursor(
false),
332 lastDragDropEvent(
nullptr),
333 updateSceneSlotReimplementedChecked(
false)
335 styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
338QGraphicsViewPrivate::~QGraphicsViewPrivate()
343
344
345void QGraphicsViewPrivate::recalculateContentSize()
349 const QSize maxSize = q->maximumViewportSize();
350 int width = maxSize.width();
351 int height = maxSize.height();
352 const QRectF viewRect = matrix.mapRect(q->sceneRect());
354 bool frameOnlyAround = (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents,
nullptr, q));
355 if (frameOnlyAround) {
356 if (hbarpolicy == Qt::ScrollBarAlwaysOn)
357 height -= frameWidth * 2;
358 if (vbarpolicy == Qt::ScrollBarAlwaysOn)
359 width -= frameWidth * 2;
364 const int scrollBarExtent = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent,
nullptr, q)
365 + (frameOnlyAround ? frameWidth * 2 : 0);
369 bool useHorizontalScrollBar = (viewRect.width() > width) && hbarpolicy == Qt::ScrollBarAsNeeded;
370 bool useVerticalScrollBar = (viewRect.height() > height) && vbarpolicy == Qt::ScrollBarAsNeeded;
371 if (useHorizontalScrollBar && vbarpolicy == Qt::ScrollBarAsNeeded) {
372 if (viewRect.height() > height - scrollBarExtent)
373 useVerticalScrollBar =
true;
375 if (useVerticalScrollBar && hbarpolicy == Qt::ScrollBarAsNeeded) {
376 if (viewRect.width() > width - scrollBarExtent)
377 useHorizontalScrollBar =
true;
379 if (useHorizontalScrollBar)
380 height -= scrollBarExtent;
381 if (useVerticalScrollBar)
382 width -= scrollBarExtent;
387 const QPointF savedLastCenterPoint = lastCenterPoint;
390 const qreal oldLeftIndent = leftIndent;
391 const qreal oldTopIndent = topIndent;
393 const auto singleStep = defaultSingleStep();
397 const int left = q_round_bound(viewRect.left());
398 const int right = q_round_bound(viewRect.right() - width);
400 switch (alignment & Qt::AlignHorizontal_Mask) {
402 leftIndent = -viewRect.left();
405 leftIndent = maxSize.width() - viewRect.width() - viewRect.left() - 1;
407 case Qt::AlignHCenter:
409 leftIndent = maxSize.width() / 2 - (viewRect.left() + viewRect.right()) / 2;
413 hbar->setRange(0, 0);
417 hbar->setRange(left, right);
418 hbar->setPageStep(width);
419 hbar->setSingleStep(width / singleStep);
421 if (oldLeftIndent != 0)
422 hbar->setValue(-oldLeftIndent);
427 const int top = q_round_bound(viewRect.top());
428 const int bottom = q_round_bound(viewRect.bottom() - height);
430 switch (alignment & Qt::AlignVertical_Mask) {
432 topIndent = -viewRect.top();
434 case Qt::AlignBottom:
435 topIndent = maxSize.height() - viewRect.height() - viewRect.top() - 1;
437 case Qt::AlignVCenter:
439 topIndent = maxSize.height() / 2 - (viewRect.top() + viewRect.bottom()) / 2;
443 vbar->setRange(0, 0);
447 vbar->setRange(top, bottom);
448 vbar->setPageStep(height);
449 vbar->setSingleStep(height / singleStep);
451 if (oldTopIndent != 0)
452 vbar->setValue(-oldTopIndent);
456 lastCenterPoint = savedLastCenterPoint;
461 if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
464 }
else if (q->isRightToLeft() && !leftIndent) {
472 if (cacheMode & QGraphicsView::CacheBackground) {
474 mustResizeBackgroundPixmap =
true;
479
480
481void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
485 case QGraphicsView::AnchorUnderMouse: {
486 if (q->underMouse()) {
489 QPointF transformationDiff = mapToScene(viewport->rect().toRectF().center())
490 - mapToScene(viewport->mapFromGlobal(QCursor::pos().toPointF()));
491 q->centerOn(lastMouseMoveScenePoint + transformationDiff);
493 q->centerOn(lastCenterPoint);
497 case QGraphicsView::AnchorViewCenter:
498 q->centerOn(lastCenterPoint);
500 case QGraphicsView::NoAnchor:
506
507
508void QGraphicsViewPrivate::updateLastCenterPoint()
510 lastCenterPoint = mapToScene(viewport->rect().toRectF().center());
514
515
516
517
518
519qint64 QGraphicsViewPrivate::horizontalScroll()
const
522 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
527
528
529
530
531
532qint64 QGraphicsViewPrivate::verticalScroll()
const
535 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
540
541
542
543
544QRectF QGraphicsViewPrivate::mapRectToScene(
const QRect &rect)
const
547 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
548 QRectF scrolled = QRectF(rect.translated(scrollX, scrollY));
549 return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled);
554
555
556
557
558QRectF QGraphicsViewPrivate::mapRectFromScene(
const QRectF &rect)
const
561 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
562 return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY);
566
567
568void QGraphicsViewPrivate::updateScroll()
571 scrollX = qint64(-leftIndent);
572 if (q->isRightToLeft()) {
574 scrollX += hbar->minimum();
575 scrollX += hbar->maximum();
576 scrollX -= hbar->value();
579 scrollX += hbar->value();
582 scrollY = qint64(vbar->value() - topIndent);
588
589
590
591
592
593bool QGraphicsViewPrivate::canStartScrollingAt(
const QPoint &startPos)
const
595 Q_Q(
const QGraphicsView);
596 if (q->dragMode() != QGraphicsView::NoDrag)
599 const QGraphicsItem *childItem = q->itemAt(startPos);
601 if (!startPos.isNull() && childItem && (childItem->flags() & QGraphicsItem::ItemIsMovable))
604 return QAbstractScrollAreaPrivate::canStartScrollingAt(startPos);
608
609
610void QGraphicsViewPrivate::replayLastMouseEvent()
612 if (!useLastMouseEvent || !scene)
614 mouseMoveEventHandler(&*lastMouseEvent);
618
619
620void QGraphicsViewPrivate::storeMouseEvent(QMouseEvent *event)
622 useLastMouseEvent =
true;
624 lastMouseEvent.storeUnlessAlias(*event);
627void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
631#if QT_CONFIG(rubberband)
632 updateRubberBand(event);
635 storeMouseEvent(event);
636 lastMouseEvent->setAccepted(
false);
638 if (!sceneInteractionAllowed)
645 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
646 mouseEvent.setWidget(viewport);
647 mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
648 mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
649 mouseEvent.setScenePos(q->mapToScene(event->position().toPoint()));
650 mouseEvent.setScreenPos(event->globalPosition().toPoint());
651 mouseEvent.setLastScenePos(lastMouseMoveScenePoint);
652 mouseEvent.setLastScreenPos(lastMouseMoveScreenPoint);
653 mouseEvent.setButtons(event->buttons());
654 mouseEvent.setButton(event->button());
655 mouseEvent.setModifiers(event->modifiers());
656 mouseEvent.setSource(event->source());
657 mouseEvent.setFlags(event->flags());
658 mouseEvent.setTimestamp(event->timestamp());
659 lastMouseMoveScenePoint = mouseEvent.scenePos();
660 lastMouseMoveScreenPoint = mouseEvent.screenPos();
661 mouseEvent.setAccepted(
false);
662 if (event->spontaneous())
663 qt_sendSpontaneousEvent(scene, &mouseEvent);
665 QCoreApplication::sendEvent(scene, &mouseEvent);
668 lastMouseEvent->setAccepted(mouseEvent.isAccepted());
670 if (mouseEvent.isAccepted() && mouseEvent.buttons() != 0) {
681 if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
682 && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
683 scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
684 mouseEvent.scenePos(),
685 mouseEvent.widget());
688 for (QGraphicsItem *item : std::as_const(scene->d_func()->cachedItemsUnderMouse)) {
689 if (item->isEnabled() && item->hasCursor()) {
690 _q_setViewportCursor(item->cursor());
696 if (hasStoredOriginalCursor) {
698 hasStoredOriginalCursor =
false;
699 viewport->setCursor(originalCursor);
705
706
707#if QT_CONFIG(rubberband)
708QRegion QGraphicsViewPrivate::rubberBandRegion(
const QWidget *widget,
const QRect &rect)
const
710 QStyleHintReturnMask mask;
711 QStyleOptionRubberBand option;
712 option.initFrom(widget);
714 option.opaque =
false;
715 option.shape = QRubberBand::Rectangle;
718 tmp += rect.adjusted(-1, -1, 1, 1);
719 if (widget->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, widget, &mask))
724void QGraphicsViewPrivate::updateRubberBand(
const QMouseEvent *event)
727 if (dragMode != QGraphicsView::RubberBandDrag || !sceneInteractionAllowed || !rubberBanding)
730 if ((mousePressViewPoint - event->position().toPoint()).manhattanLength() < QApplication::startDragDistance())
734 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate && !rubberBandRect.isEmpty()) {
735 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
736 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
743 if (!event->buttons()) {
744 rubberBanding =
false;
745 rubberBandSelectionOperation = Qt::ReplaceSelection;
746 if (!rubberBandRect.isNull()) {
747 rubberBandRect = QRect();
748 emit q->rubberBandChanged(rubberBandRect, QPointF(), QPointF());
753 QRect oldRubberband = rubberBandRect;
756 const QPoint mp = q->mapFromScene(mousePressScenePoint);
757 const QPoint ep = event->position().toPoint();
758 rubberBandRect = QRect(qMin(mp.x(), ep.x()), qMin(mp.y(), ep.y()),
759 qAbs(mp.x() - ep.x()) + 1, qAbs(mp.y() - ep.y()) + 1);
761 if (rubberBandRect != oldRubberband || lastRubberbandScenePoint != lastMouseMoveScenePoint) {
762 lastRubberbandScenePoint = lastMouseMoveScenePoint;
763 oldRubberband = rubberBandRect;
764 emit q->rubberBandChanged(rubberBandRect, mousePressScenePoint, lastRubberbandScenePoint);
768 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
769 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
770 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
775 QPainterPath selectionArea;
776 selectionArea.addPolygon(q->mapToScene(rubberBandRect));
777 selectionArea.closeSubpath();
779 scene->setSelectionArea(selectionArea, rubberBandSelectionOperation, rubberBandSelectionMode, q->viewportTransform());
782void QGraphicsViewPrivate::clearRubberBand()
785 if (dragMode != QGraphicsView::RubberBandDrag || !sceneInteractionAllowed || !rubberBanding)
788 if (viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
789 if (viewportUpdateMode != QGraphicsView::FullViewportUpdate)
790 q->viewport()->update(rubberBandRegion(q->viewport(), rubberBandRect));
795 rubberBanding =
false;
796 rubberBandSelectionOperation = Qt::ReplaceSelection;
797 if (!rubberBandRect.isNull()) {
798 rubberBandRect = QRect();
799 emit q->rubberBandChanged(rubberBandRect, QPointF(), QPointF());
805
806
808void QGraphicsViewPrivate::_q_setViewportCursor(
const QCursor &cursor)
810 if (!hasStoredOriginalCursor) {
811 hasStoredOriginalCursor =
true;
812 originalCursor = viewport->cursor();
814 viewport->setCursor(cursor);
819
820
822void QGraphicsViewPrivate::_q_unsetViewportCursor()
825 const auto items = q->items(lastMouseEvent->position().toPoint());
826 for (QGraphicsItem *item : items) {
827 if (item->isEnabled() && item->hasCursor()) {
828 _q_setViewportCursor(item->cursor());
834 if (hasStoredOriginalCursor) {
835 hasStoredOriginalCursor =
false;
836 if (dragMode == QGraphicsView::ScrollHandDrag)
837 viewport->setCursor(Qt::OpenHandCursor);
839 viewport->setCursor(originalCursor);
845
846
847void QGraphicsViewPrivate::storeDragDropEvent(
const QGraphicsSceneDragDropEvent *event)
849 delete lastDragDropEvent;
850 lastDragDropEvent =
new QGraphicsSceneDragDropEvent(event->type());
851 lastDragDropEvent->setScenePos(event->scenePos());
852 lastDragDropEvent->setScreenPos(event->screenPos());
853 lastDragDropEvent->setButtons(event->buttons());
854 lastDragDropEvent->setModifiers(event->modifiers());
855 lastDragDropEvent->setPossibleActions(event->possibleActions());
856 lastDragDropEvent->setProposedAction(event->proposedAction());
857 lastDragDropEvent->setDropAction(event->dropAction());
858 lastDragDropEvent->setMimeData(event->mimeData());
859 lastDragDropEvent->setWidget(event->widget());
860 lastDragDropEvent->setSource(event->source());
861 lastDragDropEvent->setTimestamp(event->timestamp());
865
866
867void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
870#if QT_CONFIG(draganddrop)
872 dest->setScenePos(q->mapToScene(source->position().toPoint()));
873 dest->setScreenPos(q->mapToGlobal(source->position().toPoint()));
874 dest->setButtons(source->buttons());
875 dest->setModifiers(source->modifiers());
876 dest->setPossibleActions(source->possibleActions());
877 dest->setProposedAction(source->proposedAction());
878 dest->setDropAction(source->dropAction());
879 dest->setMimeData(source->mimeData());
880 dest->setWidget(viewport);
881 dest->setSource(qobject_cast<QWidget *>(source->source()));
889
890
891QTransform QGraphicsViewPrivate::mapToViewTransform(
const QGraphicsItem *item)
const
893 Q_Q(
const QGraphicsView);
895 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
897 if (item->d_ptr->itemIsUntransformable())
898 return item->deviceTransform(q->viewportTransform());
903 const QGraphicsItem *parentItem = item;
904 const QGraphicsItemPrivate *itemd;
906 itemd = parentItem->d_ptr.data();
907 if (itemd->transformData)
909 offset += itemd->pos;
910 }
while ((parentItem = itemd->parent));
912 QTransform move = QTransform::fromTranslate(offset.x(), offset.y());
914 move.translate(-scrollX, -scrollY);
915 return identityMatrix ? move : matrix * move;
917 QTransform tr = parentItem->sceneTransform();
920 return move * tr * QTransform::fromTranslate(-scrollX, -scrollY);
923QRect QGraphicsViewPrivate::mapToViewRect(
const QGraphicsItem *item,
const QRectF &rect)
const
925 return mapToViewTransform(item).mapRect(rect).toAlignedRect();
929
930
931QRegion QGraphicsViewPrivate::mapToViewRegion(
const QGraphicsItem *item,
const QRectF &rect)
const
933 Q_Q(
const QGraphicsView);
935 const_cast<QGraphicsViewPrivate *>(
this)->updateScroll();
938 QTransform itv = item->deviceTransform(q->viewportTransform());
939 return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
943
944
945void QGraphicsViewPrivate::processPendingUpdates()
950 if (fullUpdatePending) {
952 }
else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
953 viewport->update(dirtyBoundingRect);
955 viewport->update(dirtyRegion);
958 dirtyBoundingRect = QRect();
959 dirtyRegion = QRegion();
963{
return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
966{
return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
970 if (rect->isEmpty()) {
973 rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
974 qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
979
980
981
982
983void QGraphicsViewPrivate::setUpdateClip(QGraphicsItem *item)
988 if (!item || viewportUpdateMode == QGraphicsView::NoViewportUpdate
989 || viewportUpdateMode == QGraphicsView::FullViewportUpdate) {
990 hasUpdateClip =
false;
999 if (item->d_ptr->itemIsUntransformable()) {
1000 QTransform xform = item->deviceTransform(q->viewportTransform());
1001 clip = xform.mapRect(item->boundingRect()).toAlignedRect();
1002 }
else if (item->d_ptr->sceneTransformTranslateOnly && identityMatrix) {
1003 QRectF r(item->boundingRect());
1004 r.translate(item->d_ptr->sceneTransform.dx() - horizontalScroll(),
1005 item->d_ptr->sceneTransform.dy() - verticalScroll());
1006 clip = r.toAlignedRect();
1007 }
else if (!q->isTransformed()) {
1008 clip = item->d_ptr->sceneTransform.mapRect(item->boundingRect()).toAlignedRect();
1010 QTransform xform = item->d_ptr->sceneTransform;
1011 xform *= q->viewportTransform();
1012 clip = xform.mapRect(item->boundingRect()).toAlignedRect();
1015 if (hasUpdateClip) {
1020 hasUpdateClip =
true;
1024bool QGraphicsViewPrivate::updateRegion(
const QRectF &rect,
const QTransform &xform)
1029 if (viewportUpdateMode != QGraphicsView::MinimalViewportUpdate
1030 && viewportUpdateMode != QGraphicsView::SmartViewportUpdate) {
1032 return updateRectF(xform.mapRect(rect));
1037 const QRegion region = xform.map(QRegion(rect.toAlignedRect()));
1038 QRect viewRect = region.boundingRect();
1039 const bool dontAdjustForAntialiasing = optimizationFlags & QGraphicsView::DontAdjustForAntialiasing;
1040 if (dontAdjustForAntialiasing)
1041 viewRect.adjust(-1, -1, 1, 1);
1043 viewRect.adjust(-2, -2, 2, 2);
1044 if (!intersectsViewport(viewRect, viewport->width(), viewport->height()))
1047 for (QRect viewRect : region) {
1048 if (dontAdjustForAntialiasing)
1049 viewRect.adjust(-1, -1, 1, 1);
1051 viewRect.adjust(-2, -2, 2, 2);
1053 viewRect &= updateClip;
1054 dirtyRegion += viewRect;
1062bool QGraphicsViewPrivate::updateRect(
const QRect &r)
1064 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
1065 || !intersectsViewport(r, viewport->width(), viewport->height())) {
1069 switch (viewportUpdateMode) {
1070 case QGraphicsView::FullViewportUpdate:
1071 fullUpdatePending =
true;
1074 case QGraphicsView::BoundingRectViewportUpdate:
1076 QRect_unite(&dirtyBoundingRect, r & updateClip);
1078 QRect_unite(&dirtyBoundingRect, r);
1079 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
1080 fullUpdatePending =
true;
1084 case QGraphicsView::SmartViewportUpdate:
1085 case QGraphicsView::MinimalViewportUpdate:
1087 dirtyRegion += r & updateClip;
1098QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(
int numItems)
1100 if (mustAllocateStyleOptions || (numItems > styleOptions.capacity()))
1102 return new QStyleOptionGraphicsItem[numItems];
1105 if (numItems > styleOptions.size())
1106 styleOptions.resize(numItems);
1108 mustAllocateStyleOptions =
true;
1109 return styleOptions.data();
1112void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array)
1114 mustAllocateStyleOptions =
false;
1115 if (array != styleOptions.data())
1119Q_GUI_EXPORT
extern QPainterPath qt_regionToPath(
const QRegion ®ion);
1122
1123
1124
1125
1126
1127
1128
1129
1130QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(
const QRegion &exposedRegion,
bool *allItems,
1131 const QTransform &viewTransform)
const
1133 Q_Q(
const QGraphicsView);
1138 const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
1140 if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
1145 return scene->items(Qt::AscendingOrder);
1151 bool simpleRectLookup = exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale;
1152 if (simpleRectLookup) {
1153 return scene->items(exposedRegionSceneBounds,
1154 Qt::IntersectsItemBoundingRect,
1155 Qt::AscendingOrder, viewTransform);
1161 QRegion adjustedRegion;
1162 for (
const QRect &r : exposedRegion)
1163 adjustedRegion += r.adjusted(-1, -1, 1, 1);
1165 const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
1166 return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
1167 Qt::AscendingOrder, viewTransform);
1171
1172
1173
1174
1175
1176
1177void QGraphicsViewPrivate::updateInputMethodSensitivity()
1180 QGraphicsItem *focusItem =
nullptr;
1181 bool enabled = scene && (focusItem = scene->focusItem())
1182 && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod);
1183 q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
1184 q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
1187 q->setInputMethodHints({ });
1191 QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget()
1192 ?
static_cast<QGraphicsProxyWidget *>(focusItem) :
nullptr;
1194 q->setInputMethodHints(focusItem->inputMethodHints());
1195 }
else if (QWidget *widget = proxy->widget()) {
1196 if (QWidget *fw = widget->focusWidget())
1198 q->setInputMethodHints(widget->inputMethodHints());
1200 q->setInputMethodHints({ });
1205
1206
1207QGraphicsView::QGraphicsView(QWidget *parent)
1208 : QAbstractScrollArea(*
new QGraphicsViewPrivate, parent)
1210 setViewport(
nullptr);
1211 setAcceptDrops(
true);
1212 setBackgroundRole(QPalette::Base);
1214 setAttribute(Qt::WA_InputMethodEnabled);
1215 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1219
1220
1221
1222QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent)
1223 : QAbstractScrollArea(*
new QGraphicsViewPrivate, parent)
1226 setViewport(
nullptr);
1227 setAcceptDrops(
true);
1228 setBackgroundRole(QPalette::Base);
1230 setAttribute(Qt::WA_InputMethodEnabled);
1231 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1235
1236
1237QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent)
1238 : QAbstractScrollArea(dd, parent)
1240 setViewport(
nullptr);
1241 setAcceptDrops(
true);
1242 setBackgroundRole(QPalette::Base);
1244 setAttribute(Qt::WA_InputMethodEnabled);
1245 viewport()->setAttribute(Qt::WA_InputMethodEnabled);
1249
1250
1251QGraphicsView::~QGraphicsView()
1255 d->scene->d_func()->views.removeAll(
this);
1256 delete d->lastDragDropEvent;
1260
1261
1262QSize QGraphicsView::sizeHint()
const
1264 Q_D(
const QGraphicsView);
1266 QSizeF baseSize = d->matrix.mapRect(sceneRect()).size();
1267 baseSize += QSizeF(d->frameWidth * 2, d->frameWidth * 2);
1268 return baseSize.boundedTo((3 * QGuiApplication::primaryScreen()->virtualSize()) / 4).toSize();
1270 return QAbstractScrollArea::sizeHint();
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288QPainter::RenderHints QGraphicsView::renderHints()
const
1290 Q_D(
const QGraphicsView);
1291 return d->renderHints;
1293void QGraphicsView::setRenderHints(QPainter::RenderHints hints)
1296 if (hints == d->renderHints)
1298 d->renderHints = hints;
1303
1304
1305
1306
1307
1308void QGraphicsView::setRenderHint(QPainter::RenderHint hint,
bool enabled)
1311 QPainter::RenderHints oldHints = d->renderHints;
1312 d->renderHints.setFlag(hint, enabled);
1313 if (oldHints != d->renderHints)
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329Qt::Alignment QGraphicsView::alignment()
const
1331 Q_D(
const QGraphicsView);
1332 return d->alignment;
1334void QGraphicsView::setAlignment(Qt::Alignment alignment)
1337 if (d->alignment != alignment) {
1338 d->alignment = alignment;
1339 d->recalculateContentSize();
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361QGraphicsView::ViewportAnchor QGraphicsView::transformationAnchor()
const
1363 Q_D(
const QGraphicsView);
1364 return d->transformationAnchor;
1366void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor)
1369 d->transformationAnchor = anchor;
1373 if (d->transformationAnchor == AnchorUnderMouse)
1374 d->viewport->setMouseTracking(
true);
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393QGraphicsView::ViewportAnchor QGraphicsView::resizeAnchor()
const
1395 Q_D(
const QGraphicsView);
1396 return d->resizeAnchor;
1398void QGraphicsView::setResizeAnchor(ViewportAnchor anchor)
1401 d->resizeAnchor = anchor;
1405 if (d->resizeAnchor == AnchorUnderMouse)
1406 d->viewport->setMouseTracking(
true);
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427QGraphicsView::ViewportUpdateMode QGraphicsView::viewportUpdateMode()
const
1429 Q_D(
const QGraphicsView);
1430 return d->viewportUpdateMode;
1432void QGraphicsView::setViewportUpdateMode(ViewportUpdateMode mode)
1435 d->viewportUpdateMode = mode;
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456QGraphicsView::OptimizationFlags QGraphicsView::optimizationFlags()
const
1458 Q_D(
const QGraphicsView);
1459 return d->optimizationFlags;
1461void QGraphicsView::setOptimizationFlags(OptimizationFlags flags)
1464 d->optimizationFlags = flags;
1468
1469
1470
1471
1472void QGraphicsView::setOptimizationFlag(OptimizationFlag flag,
bool enabled)
1475 d->optimizationFlags.setFlag(flag, enabled);
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492QGraphicsView::DragMode QGraphicsView::dragMode()
const
1494 Q_D(
const QGraphicsView);
1497void QGraphicsView::setDragMode(DragMode mode)
1500 if (d->dragMode == mode)
1503#if QT_CONFIG(rubberband)
1504 d->clearRubberBand();
1508 if (d->dragMode == ScrollHandDrag)
1509 viewport()->unsetCursor();
1516 if (d->dragMode == ScrollHandDrag && mode == NoDrag && d->handScrolling)
1517 d->handScrolling =
false;
1522 if (d->dragMode == ScrollHandDrag) {
1524 d->hasStoredOriginalCursor =
false;
1525 viewport()->setCursor(Qt::OpenHandCursor);
1530#if QT_CONFIG(rubberband)
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544Qt::ItemSelectionMode QGraphicsView::rubberBandSelectionMode()
const
1546 Q_D(
const QGraphicsView);
1547 return d->rubberBandSelectionMode;
1549void QGraphicsView::setRubberBandSelectionMode(Qt::ItemSelectionMode mode)
1552 d->rubberBandSelectionMode = mode;
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1567QRect QGraphicsView::rubberBandRect()
const
1569 Q_D(
const QGraphicsView);
1570 if (d->dragMode != QGraphicsView::RubberBandDrag || !d->sceneInteractionAllowed || !d->rubberBanding)
1573 return d->rubberBandRect;
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597QGraphicsView::CacheMode QGraphicsView::cacheMode()
const
1599 Q_D(
const QGraphicsView);
1600 return d->cacheMode;
1602void QGraphicsView::setCacheMode(CacheMode mode)
1605 if (mode == d->cacheMode)
1607 d->cacheMode = mode;
1608 resetCachedContent();
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624void QGraphicsView::resetCachedContent()
1627 if (d->cacheMode == CacheNone)
1630 if (d->cacheMode & CacheBackground) {
1632 d->mustResizeBackgroundPixmap =
true;
1634 }
else if (d->mustResizeBackgroundPixmap) {
1637 d->mustResizeBackgroundPixmap =
false;
1638 d->backgroundPixmap = QPixmap();
1639 d->backgroundPixmapExposed = QRegion();
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659void QGraphicsView::invalidateScene(
const QRectF &rect, QGraphicsScene::SceneLayers layers)
1662 if ((layers & QGraphicsScene::BackgroundLayer) && !d->mustResizeBackgroundPixmap) {
1663 QRect viewRect = mapFromScene(rect).boundingRect();
1664 if (viewport()->rect().intersects(viewRect)) {
1667 d->backgroundPixmapExposed += viewRect;
1669 d->scene->update(rect);
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684bool QGraphicsView::isInteractive()
const
1686 Q_D(
const QGraphicsView);
1687 return d->sceneInteractionAllowed;
1689void QGraphicsView::setInteractive(
bool allowed)
1692 d->sceneInteractionAllowed = allowed;
1696
1697
1698
1699
1700
1701QGraphicsScene *QGraphicsView::scene()
const
1703 Q_D(
const QGraphicsView);
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717void QGraphicsView::setScene(QGraphicsScene *scene)
1720 if (d->scene == scene)
1728 disconnect(d->scene, SIGNAL(changed(QList<QRectF>)),
1729 this, SLOT(updateScene(QList<QRectF>)));
1730 disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
1731 this, SLOT(updateSceneRect(QRectF)));
1732 d->scene->d_func()->removeView(
this);
1733 d->connectedToScene =
false;
1735 if (isActiveWindow() && isVisible()) {
1736 QEvent windowDeactivate(QEvent::WindowDeactivate);
1737 QCoreApplication::sendEvent(d->scene, &windowDeactivate);
1740 d->scene->clearFocus();
1744 if ((d->scene = scene)) {
1745 connect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
1746 this, SLOT(updateSceneRect(QRectF)));
1747 d->updateSceneSlotReimplementedChecked =
false;
1748 d->scene->d_func()->addView(
this);
1749 d->recalculateContentSize();
1750 d->lastCenterPoint = sceneRect().center();
1751 d->keepLastCenterPoint =
true;
1754 if (!d->scene->d_func()->allItemsIgnoreHoverEvents
1755 || !d->scene->d_func()->allItemsUseDefaultCursor) {
1756 d->viewport->setMouseTracking(
true);
1760 if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
1761 d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
1763 if (isActiveWindow() && isVisible()) {
1764 QEvent windowActivate(QEvent::WindowActivate);
1765 QCoreApplication::sendEvent(d->scene, &windowActivate);
1768 d->recalculateContentSize();
1771 d->updateInputMethodSensitivity();
1773 if (d->scene && hasFocus())
1774 d->scene->setFocus();
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800QRectF QGraphicsView::sceneRect()
const
1802 Q_D(
const QGraphicsView);
1803 if (d->hasSceneRect)
1804 return d->sceneRect;
1806 return d->scene->sceneRect();
1809void QGraphicsView::setSceneRect(
const QRectF &rect)
1812 d->hasSceneRect = !rect.isNull();
1813 d->sceneRect = rect;
1814 d->recalculateContentSize();
1818
1819
1820
1821
1822void QGraphicsView::rotate(qreal angle)
1825 QTransform matrix = d->matrix;
1826 matrix.rotate(angle);
1827 setTransform(matrix);
1831
1832
1833
1834
1835void QGraphicsView::scale(qreal sx, qreal sy)
1838 QTransform matrix = d->matrix;
1839 matrix.scale(sx, sy);
1840 setTransform(matrix);
1844
1845
1846
1847
1848void QGraphicsView::shear(qreal sh, qreal sv)
1851 QTransform matrix = d->matrix;
1852 matrix.shear(sh, sv);
1853 setTransform(matrix);
1857
1858
1859
1860
1861void QGraphicsView::translate(qreal dx, qreal dy)
1864 QTransform matrix = d->matrix;
1865 matrix.translate(dx, dy);
1866 setTransform(matrix);
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881void QGraphicsView::centerOn(
const QPointF &pos)
1884 qreal width = viewport()->width();
1885 qreal height = viewport()->height();
1886 QPointF viewPoint = d->matrix.map(pos);
1887 QPointF oldCenterPoint = pos;
1889 if (!d->leftIndent) {
1890 if (isRightToLeft()) {
1891 qint64 horizontal = 0;
1892 horizontal += horizontalScrollBar()->minimum();
1893 horizontal += horizontalScrollBar()->maximum();
1894 horizontal -= qRound(viewPoint.x() - width / 2.0);
1895 horizontalScrollBar()->setValue(horizontal);
1897 horizontalScrollBar()->setValue(qRound(viewPoint.x() - width / 2.0));
1901 verticalScrollBar()->setValue(qRound(viewPoint.y() - height / 2.0));
1902 d->lastCenterPoint = oldCenterPoint;
1906
1907
1908
1909
1910
1911
1914
1915
1916
1917
1918
1919
1920
1921void QGraphicsView::centerOn(
const QGraphicsItem *item)
1923 centerOn(item->sceneBoundingRect().center());
1927
1928
1929
1930
1931
1932
1933
1934
1935void QGraphicsView::ensureVisible(
const QRectF &rect,
int xmargin,
int ymargin)
1938 qreal width = viewport()->width();
1939 qreal height = viewport()->height();
1940 QRectF viewRect = d->matrix.mapRect(rect);
1942 qreal left = d->horizontalScroll();
1943 qreal right = left + width;
1944 qreal top = d->verticalScroll();
1945 qreal bottom = top + height;
1947 if (viewRect.left() <= left + xmargin) {
1950 horizontalScrollBar()->setValue(
int(viewRect.left() - xmargin - 0.5));
1952 if (viewRect.right() >= right - xmargin) {
1955 horizontalScrollBar()->setValue(
int(viewRect.right() - width + xmargin + 0.5));
1957 if (viewRect.top() <= top + ymargin) {
1960 verticalScrollBar()->setValue(
int(viewRect.top() - ymargin - 0.5));
1962 if (viewRect.bottom() >= bottom - ymargin) {
1965 verticalScrollBar()->setValue(
int(viewRect.bottom() - height + ymargin + 0.5));
1970
1971
1972
1973
1974
1975
1976
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988void QGraphicsView::ensureVisible(
const QGraphicsItem *item,
int xmargin,
int ymargin)
1990 ensureVisible(item->sceneBoundingRect(), xmargin, ymargin);
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017void QGraphicsView::fitInView(
const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
2020 if (!d->scene || rect.isNull())
2024 QRectF unity = d->matrix.mapRect(QRectF(0, 0, 1, 1));
2025 if (unity.isEmpty())
2027 scale(1 / unity.width(), 1 / unity.height());
2031 QRectF viewRect = viewport()->rect().adjusted(margin, margin, -margin, -margin);
2032 if (viewRect.isEmpty())
2034 QRectF sceneRect = d->matrix.mapRect(rect);
2035 if (sceneRect.isEmpty())
2037 qreal xratio = viewRect.width() / sceneRect.width();
2038 qreal yratio = viewRect.height() / sceneRect.height();
2041 switch (aspectRatioMode) {
2042 case Qt::KeepAspectRatio:
2043 xratio = yratio = qMin(xratio, yratio);
2045 case Qt::KeepAspectRatioByExpanding:
2046 xratio = yratio = qMax(xratio, yratio);
2048 case Qt::IgnoreAspectRatio:
2053 scale(xratio, yratio);
2054 centerOn(rect.center());
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2070
2071
2072
2073
2074
2075
2076
2077void QGraphicsView::fitInView(
const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode)
2079 QPainterPath path = item->isClipped() ? item->clipPath() : item->shape();
2080 if (item->d_ptr->hasTranslateOnlySceneTransform()) {
2081 path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy());
2082 fitInView(path.boundingRect(), aspectRatioMode);
2084 fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode);
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108void QGraphicsView::render(QPainter *painter,
const QRectF &target,
const QRect &source,
2109 Qt::AspectRatioMode aspectRatioMode)
2114 if (!d->scene || !(painter && painter->isActive()))
2118 QRect sourceRect = source;
2119 if (source.isNull())
2120 sourceRect = viewport()->rect();
2123 QRectF targetRect = target;
2124 if (target.isNull()) {
2125 if (painter->device()->devType() == QInternal::Picture)
2126 targetRect = sourceRect;
2128 targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
2132 qreal xratio = targetRect.width() / sourceRect.width();
2133 qreal yratio = targetRect.height() / sourceRect.height();
2136 switch (aspectRatioMode) {
2137 case Qt::KeepAspectRatio:
2138 xratio = yratio = qMin(xratio, yratio);
2140 case Qt::KeepAspectRatioByExpanding:
2141 xratio = yratio = qMax(xratio, yratio);
2143 case Qt::IgnoreAspectRatio:
2149 QPolygonF sourceScenePoly = mapToScene(sourceRect.adjusted(-1, -1, 1, 1));
2150 QList<QGraphicsItem *> itemList = d->scene->items(sourceScenePoly,
2151 Qt::IntersectsItemBoundingRect);
2152 QGraphicsItem **itemArray =
new QGraphicsItem *[itemList.size()];
2153 int numItems = itemList.size();
2154 for (
int i = 0; i < numItems; ++i)
2155 itemArray[numItems - i - 1] = itemList.at(i);
2159 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
2160 QTransform painterMatrix = d->matrix * moveMatrix;
2161 painterMatrix *= QTransform()
2162 .translate(targetRect.left(), targetRect.top())
2163 .scale(xratio, yratio)
2164 .translate(-sourceRect.left(), -sourceRect.top());
2167 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
2168 for (
int i = 0; i < numItems; ++i)
2169 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
2174 painter->setClipRect(targetRect);
2176 path.addPolygon(sourceScenePoly);
2177 path.closeSubpath();
2178 painter->setClipPath(painterMatrix.map(path), Qt::IntersectClip);
2181 painter->setTransform(painterMatrix,
true);
2184 QRectF sourceSceneRect = sourceScenePoly.boundingRect();
2185 drawBackground(painter, sourceSceneRect);
2186 drawItems(painter, numItems, itemArray, styleOptionArray);
2187 drawForeground(painter, sourceSceneRect);
2189 delete [] itemArray;
2190 d->freeStyleOptionsArray(styleOptionArray);
2196
2197
2198
2199
2200
2201
2202QList<QGraphicsItem *> QGraphicsView::items()
const
2204 Q_D(
const QGraphicsView);
2206 return QList<QGraphicsItem *>();
2207 return d->scene->items();
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224QList<QGraphicsItem *> QGraphicsView::items(
const QPoint &pos)
const
2226 Q_D(
const QGraphicsView);
2228 return QList<QGraphicsItem *>();
2232 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
2234 QTransform xinv = viewportTransform().inverted();
2235 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
2236 Qt::IntersectsItemShape,
2237 Qt::DescendingOrder,
2238 viewportTransform());
2241 return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
2242 Qt::IntersectsItemShape,
2243 Qt::DescendingOrder,
2244 viewportTransform());
2248
2249
2250
2251
2252
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269QList<QGraphicsItem *> QGraphicsView::items(
const QRect &rect, Qt::ItemSelectionMode mode)
const
2271 Q_D(
const QGraphicsView);
2273 return QList<QGraphicsItem *>();
2274 return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform());
2278
2279
2280
2281
2282
2283
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300QList<QGraphicsItem *> QGraphicsView::items(
const QPolygon &polygon, Qt::ItemSelectionMode mode)
const
2302 Q_D(
const QGraphicsView);
2304 return QList<QGraphicsItem *>();
2305 return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform());
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320QList<QGraphicsItem *> QGraphicsView::items(
const QPainterPath &path, Qt::ItemSelectionMode mode)
const
2322 Q_D(
const QGraphicsView);
2324 return QList<QGraphicsItem *>();
2325 return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform());
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339QGraphicsItem *QGraphicsView::itemAt(
const QPoint &pos)
const
2341 Q_D(
const QGraphicsView);
2344 const QList<QGraphicsItem *> itemsAtPos = items(pos);
2345 return itemsAtPos.isEmpty() ?
nullptr : itemsAtPos.first();
2349
2350
2351
2352
2353
2354
2357
2358
2359
2360
2361
2362
2363
2364
2365QPointF QGraphicsView::mapToScene(
const QPoint &point)
const
2367 Q_D(
const QGraphicsView);
2369 p.rx() += d->horizontalScroll();
2370 p.ry() += d->verticalScroll();
2371 return d->identityMatrix ? p : d->matrix.inverted().map(p);
2375
2376
2377
2378
2379
2382
2383
2384
2385
2386
2387QPolygonF QGraphicsView::mapToScene(
const QRect &rect)
const
2389 Q_D(
const QGraphicsView);
2390 if (!rect.isValid())
2393 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
2394 QRect r = rect.adjusted(0, 0, 1, 1);
2395 QPointF tl = scrollOffset + r.topLeft();
2396 QPointF tr = scrollOffset + r.topRight();
2397 QPointF br = scrollOffset + r.bottomRight();
2398 QPointF bl = scrollOffset + r.bottomLeft();
2401 if (!d->identityMatrix) {
2402 QTransform x = d->matrix.inverted();
2403 poly[0] = x.map(tl);
2404 poly[1] = x.map(tr);
2405 poly[2] = x.map(br);
2406 poly[3] = x.map(bl);
2417
2418
2419
2420
2421
2424
2425
2426
2427
2428
2429QPolygonF QGraphicsView::mapToScene(
const QPolygon &polygon)
const
2432 poly.reserve(polygon.size());
2433 for (
const QPoint &point : polygon)
2434 poly << mapToScene(point);
2439
2440
2441
2442
2443
2444QPainterPath QGraphicsView::mapToScene(
const QPainterPath &path)
const
2446 Q_D(
const QGraphicsView);
2447 QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
2448 matrix *= d->matrix.inverted();
2449 return matrix.map(path);
2453
2454
2455
2456
2457QPoint QGraphicsView::mapFromScene(
const QPointF &point)
const
2459 Q_D(
const QGraphicsView);
2460 QPointF p = d->identityMatrix ? point : d->matrix.map(point);
2461 p.rx() -= d->horizontalScroll();
2462 p.ry() -= d->verticalScroll();
2467
2468
2469
2470
2471
2474
2475
2476
2477
2478
2479QPolygon QGraphicsView::mapFromScene(
const QRectF &rect)
const
2481 Q_D(
const QGraphicsView);
2486 if (!d->identityMatrix) {
2487 const QTransform &x = d->matrix;
2488 tl = x.map(rect.topLeft());
2489 tr = x.map(rect.topRight());
2490 br = x.map(rect.bottomRight());
2491 bl = x.map(rect.bottomLeft());
2493 tl = rect.topLeft();
2494 tr = rect.topRight();
2495 br = rect.bottomRight();
2496 bl = rect.bottomLeft();
2498 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
2505 poly[0] = tl.toPoint();
2506 poly[1] = tr.toPoint();
2507 poly[2] = br.toPoint();
2508 poly[3] = bl.toPoint();
2513
2514
2515
2516
2517
2520
2521
2522
2523
2524
2525QPolygon QGraphicsView::mapFromScene(
const QPolygonF &polygon)
const
2528 poly.reserve(polygon.size());
2529 for (
const QPointF &point : polygon)
2530 poly << mapFromScene(point);
2535
2536
2537
2538
2539
2540QPainterPath QGraphicsView::mapFromScene(
const QPainterPath &path)
const
2542 Q_D(
const QGraphicsView);
2543 QTransform matrix = d->matrix;
2544 matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
2545 return matrix.map(path);
2549
2550
2551QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query)
const
2553 Q_D(
const QGraphicsView);
2557 QVariant value = d->scene->inputMethodQuery(query);
2558 if (value.userType() == QMetaType::QRectF)
2559 value = d->mapRectFromScene(value.toRectF());
2560 else if (value.userType() == QMetaType::QPointF)
2561 value = mapFromScene(value.toPointF());
2562 else if (value.userType() == QMetaType::QRect)
2563 value = d->mapRectFromScene(value.toRect()).toRect();
2564 else if (value.userType() == QMetaType::QPoint)
2565 value = mapFromScene(value.toPoint());
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582QBrush QGraphicsView::backgroundBrush()
const
2584 Q_D(
const QGraphicsView);
2585 return d->backgroundBrush;
2587void QGraphicsView::setBackgroundBrush(
const QBrush &brush)
2590 d->backgroundBrush = brush;
2593 if (d->cacheMode & CacheBackground) {
2595 d->mustResizeBackgroundPixmap =
true;
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612QBrush QGraphicsView::foregroundBrush()
const
2614 Q_D(
const QGraphicsView);
2615 return d->foregroundBrush;
2617void QGraphicsView::setForegroundBrush(
const QBrush &brush)
2620 d->foregroundBrush = brush;
2625
2626
2627
2628
2629void QGraphicsView::updateScene(
const QList<QRectF> &rects)
2637 if (d->fullUpdatePending || d->viewportUpdateMode == QGraphicsView::NoViewportUpdate)
2641 QList<QRect> dirtyViewportRects;
2642 dirtyViewportRects.reserve(d->dirtyRegion.rectCount() + rects.size());
2643 for (
const QRect &dirtyRect : d->dirtyRegion)
2644 dirtyViewportRects += dirtyRect;
2645 d->dirtyRegion = QRegion();
2646 d->dirtyBoundingRect = QRect();
2648 bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
2649 bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
2650 || (d->viewportUpdateMode == QGraphicsView::SmartViewportUpdate
2651 && ((dirtyViewportRects.size() + rects.size()) >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD));
2653 QRegion updateRegion;
2655 QRect viewportRect = viewport()->rect();
2656 bool redraw =
false;
2657 QTransform transform = viewportTransform();
2660 for (
const QRectF &rect : rects) {
2661 QRect xrect = transform.mapRect(rect).toAlignedRect();
2662 if (!(d->optimizationFlags & DontAdjustForAntialiasing))
2663 xrect.adjust(-2, -2, 2, 2);
2665 xrect.adjust(-1, -1, 1, 1);
2666 if (!viewportRect.intersects(xrect))
2668 dirtyViewportRects << xrect;
2671 for (
const QRect &rect : std::as_const(dirtyViewportRects)) {
2674 if (!boundingRectUpdate) {
2675 updateRegion += rect;
2677 boundingRect |= rect;
2691 viewport()->update();
2692 else if (boundingRectUpdate)
2693 viewport()->update(boundingRect);
2695 viewport()->update(updateRegion);
2699
2700
2701
2702
2703
2704
2705void QGraphicsView::updateSceneRect(
const QRectF &rect)
2708 if (!d->hasSceneRect) {
2709 d->sceneRect = rect;
2710 d->recalculateContentSize();
2715
2716
2717
2718
2719
2720
2721void QGraphicsView::setupViewport(QWidget *widget)
2726 qWarning(
"QGraphicsView::setupViewport: cannot initialize null widget");
2730 const bool isGLWidget = widget->inherits(
"QOpenGLWidget");
2732 d->accelerateScrolling = !(isGLWidget);
2734 widget->setFocusPolicy(Qt::StrongFocus);
2737 d->stereoEnabled = QWidgetPrivate::get(widget)->isStereoEnabled();
2741 widget->setAutoFillBackground(
true);
2747 if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
2748 || !d->scene->d_func()->allItemsUseDefaultCursor))
2749 || d->transformationAnchor == AnchorUnderMouse
2750 || d->resizeAnchor == AnchorUnderMouse) {
2751 widget->setMouseTracking(
true);
2755 if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
2756 widget->setAttribute(Qt::WA_AcceptTouchEvents);
2758#ifndef QT_NO_GESTURES
2760 const auto gestures = d->scene->d_func()->grabbedGestures.keys();
2761 for (Qt::GestureType gesture : gestures)
2762 widget->grabGesture(gesture);
2766 widget->setAcceptDrops(acceptDrops());
2770
2771
2772bool QGraphicsView::event(QEvent *event)
2776 if (d->sceneInteractionAllowed) {
2777 switch (event->type()) {
2778 case QEvent::ShortcutOverride:
2780 return QCoreApplication::sendEvent(d->scene, event);
2782 case QEvent::KeyPress:
2784 QKeyEvent *k =
static_cast<QKeyEvent *>(event);
2785 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
2792 QCoreApplication::sendEvent(d->scene, event);
2793 if (event->isAccepted())
2807 return QAbstractScrollArea::event(event);
2811
2812
2813bool QGraphicsView::viewportEvent(QEvent *event)
2817 return QAbstractScrollArea::viewportEvent(event);
2819 switch (event->type()) {
2821 QCoreApplication::sendEvent(d->scene, event);
2823 case QEvent::WindowActivate:
2824 QCoreApplication::sendEvent(d->scene, event);
2826 case QEvent::WindowDeactivate:
2831 if (!d->scene->d_func()->popupWidgets.isEmpty())
2832 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.constFirst());
2833 QCoreApplication::sendEvent(d->scene, event);
2836 if (d->scene && isActiveWindow()) {
2837 QEvent windowActivate(QEvent::WindowActivate);
2838 QCoreApplication::sendEvent(d->scene, &windowActivate);
2843 if (!event->spontaneous() && d->scene && isActiveWindow()) {
2844 QEvent windowDeactivate(QEvent::WindowDeactivate);
2845 QCoreApplication::sendEvent(d->scene, &windowDeactivate);
2848 case QEvent::Leave: {
2852 if ((QApplication::activePopupWidget() && QApplication::activePopupWidget() != window())
2853 || (QApplication::activeModalWidget() && QApplication::activeModalWidget() != window())
2854 || (QApplication::activeWindow() != window())) {
2855 if (!d->scene->d_func()->popupWidgets.isEmpty())
2856 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.constFirst());
2858 d->useLastMouseEvent =
false;
2859 QGraphicsSceneEvent leaveEvent(QEvent::GraphicsSceneLeave);
2860 leaveEvent.setWidget(viewport());
2861 QCoreApplication::sendEvent(d->scene, &leaveEvent);
2862 event->setAccepted(leaveEvent.isAccepted());
2865#if QT_CONFIG(tooltip)
2866 case QEvent::ToolTip: {
2867 QHelpEvent *toolTip =
static_cast<QHelpEvent *>(event);
2868 QGraphicsSceneHelpEvent helpEvent(QEvent::GraphicsSceneHelp);
2869 helpEvent.setWidget(viewport());
2870 helpEvent.setScreenPos(toolTip->globalPos());
2871 helpEvent.setScenePos(mapToScene(toolTip->pos()));
2872 QCoreApplication::sendEvent(d->scene, &helpEvent);
2873 toolTip->setAccepted(helpEvent.isAccepted());
2879 d->fullUpdatePending =
false;
2880 d->dirtyScrollOffset = QPoint();
2885 if (!d->updateSceneSlotReimplementedChecked) {
2886 d->updateSceneSlotReimplementedChecked =
true;
2887 const QMetaObject *mo = metaObject();
2888 if (mo != &QGraphicsView::staticMetaObject) {
2889 if (mo->indexOfSlot(
"updateScene(QList<QRectF>)")
2890 != QGraphicsView::staticMetaObject.indexOfSlot(
"updateScene(QList<QRectF>)")) {
2891 connect(d->scene, SIGNAL(changed(QList<QRectF>)),
2892 this, SLOT(updateScene(QList<QRectF>)));
2898 case QEvent::TouchBegin:
2899 case QEvent::TouchUpdate:
2900 case QEvent::TouchEnd:
2905 if (d->scene && d->sceneInteractionAllowed) {
2907 QTouchEvent *touchEvent =
static_cast<QTouchEvent *>(event);
2908 QMutableTouchEvent::setTarget(touchEvent, viewport());
2909 QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
2910 QCoreApplication::sendEvent(d->scene, touchEvent);
2917#ifndef QT_NO_GESTURES
2918 case QEvent::Gesture:
2919 case QEvent::GestureOverride:
2924 if (d->scene && d->sceneInteractionAllowed) {
2925 QGestureEvent *gestureEvent =
static_cast<QGestureEvent *>(event);
2926 gestureEvent->setWidget(viewport());
2927 QCoreApplication::sendEvent(d->scene, gestureEvent);
2936 return QAbstractScrollArea::viewportEvent(event);
2939#ifndef QT_NO_CONTEXTMENU
2941
2942
2943void QGraphicsView::contextMenuEvent(QContextMenuEvent *event)
2946 if (!d->scene || !d->sceneInteractionAllowed)
2949 d->mousePressViewPoint = event->pos();
2950 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
2951 d->mousePressScreenPoint = event->globalPos();
2952 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
2953 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
2955 QGraphicsSceneContextMenuEvent contextEvent(QEvent::GraphicsSceneContextMenu);
2956 contextEvent.setWidget(viewport());
2957 contextEvent.setScenePos(d->mousePressScenePoint);
2958 contextEvent.setScreenPos(d->mousePressScreenPoint);
2959 contextEvent.setModifiers(event->modifiers());
2960 contextEvent.setReason((QGraphicsSceneContextMenuEvent::Reason)(event->reason()));
2961 contextEvent.setAccepted(event->isAccepted());
2962 contextEvent.setTimestamp(event->timestamp());
2963 QCoreApplication::sendEvent(d->scene, &contextEvent);
2964 event->setAccepted(contextEvent.isAccepted());
2968#if QT_CONFIG(draganddrop)
2970
2971
2972void QGraphicsView::dropEvent(QDropEvent *event)
2975 if (!d->scene || !d->sceneInteractionAllowed)
2979 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDrop);
2980 d->populateSceneDragDropEvent(&sceneEvent, event);
2983 QCoreApplication::sendEvent(d->scene, &sceneEvent);
2986 event->setAccepted(sceneEvent.isAccepted());
2987 if (sceneEvent.isAccepted())
2988 event->setDropAction(sceneEvent.dropAction());
2990 delete d->lastDragDropEvent;
2991 d->lastDragDropEvent =
nullptr;
2995
2996
2997void QGraphicsView::dragEnterEvent(QDragEnterEvent *event)
3000 if (!d->scene || !d->sceneInteractionAllowed)
3004 d->useLastMouseEvent =
false;
3007 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragEnter);
3008 d->populateSceneDragDropEvent(&sceneEvent, event);
3011 d->storeDragDropEvent(&sceneEvent);
3014 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3017 if (sceneEvent.isAccepted()) {
3018 event->setAccepted(
true);
3019 event->setDropAction(sceneEvent.dropAction());
3024
3025
3026void QGraphicsView::dragLeaveEvent(QDragLeaveEvent *event)
3029 if (!d->scene || !d->sceneInteractionAllowed)
3031 if (!d->lastDragDropEvent) {
3032 qWarning(
"QGraphicsView::dragLeaveEvent: drag leave received before drag enter");
3037 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragLeave);
3038 sceneEvent.setScenePos(d->lastDragDropEvent->scenePos());
3039 sceneEvent.setScreenPos(d->lastDragDropEvent->screenPos());
3040 sceneEvent.setButtons(d->lastDragDropEvent->buttons());
3041 sceneEvent.setModifiers(d->lastDragDropEvent->modifiers());
3042 sceneEvent.setPossibleActions(d->lastDragDropEvent->possibleActions());
3043 sceneEvent.setProposedAction(d->lastDragDropEvent->proposedAction());
3044 sceneEvent.setDropAction(d->lastDragDropEvent->dropAction());
3045 sceneEvent.setMimeData(d->lastDragDropEvent->mimeData());
3046 sceneEvent.setWidget(d->lastDragDropEvent->widget());
3047 sceneEvent.setSource(d->lastDragDropEvent->source());
3048 delete d->lastDragDropEvent;
3049 d->lastDragDropEvent =
nullptr;
3052 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3055 if (sceneEvent.isAccepted())
3056 event->setAccepted(
true);
3060
3061
3062void QGraphicsView::dragMoveEvent(QDragMoveEvent *event)
3065 if (!d->scene || !d->sceneInteractionAllowed)
3069 QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragMove);
3070 d->populateSceneDragDropEvent(&sceneEvent, event);
3073 d->storeDragDropEvent(&sceneEvent);
3076 QCoreApplication::sendEvent(d->scene, &sceneEvent);
3079 event->setAccepted(sceneEvent.isAccepted());
3080 if (sceneEvent.isAccepted())
3081 event->setDropAction(sceneEvent.dropAction());
3086
3087
3088void QGraphicsView::focusInEvent(QFocusEvent *event)
3091 d->updateInputMethodSensitivity();
3092 QAbstractScrollArea::focusInEvent(event);
3094 QCoreApplication::sendEvent(d->scene, event);
3096 if (!d->scene || !event->isAccepted())
3097 QAbstractScrollArea::focusInEvent(event);
3101
3102
3103bool QGraphicsView::focusNextPrevChild(
bool next)
3105 return QAbstractScrollArea::focusNextPrevChild(next);
3109
3110
3111void QGraphicsView::focusOutEvent(QFocusEvent *event)
3114 QAbstractScrollArea::focusOutEvent(event);
3116 QCoreApplication::sendEvent(d->scene, event);
3120
3121
3122void QGraphicsView::keyPressEvent(QKeyEvent *event)
3125 if (!d->scene || !d->sceneInteractionAllowed) {
3126 QAbstractScrollArea::keyPressEvent(event);
3129 QCoreApplication::sendEvent(d->scene, event);
3130 if (!event->isAccepted())
3131 QAbstractScrollArea::keyPressEvent(event);
3135
3136
3137void QGraphicsView::keyReleaseEvent(QKeyEvent *event)
3140 if (!d->scene || !d->sceneInteractionAllowed)
3142 QCoreApplication::sendEvent(d->scene, event);
3143 if (!event->isAccepted())
3144 QAbstractScrollArea::keyReleaseEvent(event);
3148
3149
3150void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
3153 if (!d->scene || !d->sceneInteractionAllowed)
3156 d->storeMouseEvent(event);
3157 d->mousePressViewPoint = event->position().toPoint();
3158 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
3159 d->mousePressScreenPoint = event->globalPosition().toPoint();
3160 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
3161 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
3162 d->mousePressButton = event->button();
3164 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
3165 mouseEvent.setWidget(viewport());
3166 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3167 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3168 mouseEvent.setScenePos(mapToScene(d->mousePressViewPoint));
3169 mouseEvent.setScreenPos(d->mousePressScreenPoint);
3170 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3171 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3172 mouseEvent.setButtons(event->buttons());
3173 mouseEvent.setAccepted(
false);
3174 mouseEvent.setButton(event->button());
3175 mouseEvent.setModifiers(event->modifiers());
3176 mouseEvent.setSource(event->source());
3177 mouseEvent.setFlags(event->flags());
3178 mouseEvent.setTimestamp(event->timestamp());
3179 if (event->spontaneous())
3180 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3182 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3185 const bool isAccepted = mouseEvent.isAccepted();
3186 event->setAccepted(isAccepted);
3189 d->lastMouseEvent->setAccepted(isAccepted);
3193
3194
3195void QGraphicsView::mousePressEvent(QMouseEvent *event)
3202 d->storeMouseEvent(event);
3203 d->lastMouseEvent->setAccepted(
false);
3205 if (d->sceneInteractionAllowed) {
3207 d->mousePressViewPoint = event->position().toPoint();
3208 d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
3209 d->mousePressScreenPoint = event->globalPosition().toPoint();
3210 d->lastMouseMoveScenePoint = d->mousePressScenePoint;
3211 d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
3212 d->mousePressButton = event->button();
3216 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
3217 mouseEvent.setWidget(viewport());
3218 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3219 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3220 mouseEvent.setScenePos(d->mousePressScenePoint);
3221 mouseEvent.setScreenPos(d->mousePressScreenPoint);
3222 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3223 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3224 mouseEvent.setButtons(event->buttons());
3225 mouseEvent.setButton(event->button());
3226 mouseEvent.setModifiers(event->modifiers());
3227 mouseEvent.setSource(event->source());
3228 mouseEvent.setFlags(event->flags());
3229 mouseEvent.setAccepted(
false);
3230 mouseEvent.setTimestamp(event->timestamp());
3231 if (event->spontaneous())
3232 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3234 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3237 bool isAccepted = mouseEvent.isAccepted();
3238 event->setAccepted(isAccepted);
3241 d->lastMouseEvent->setAccepted(isAccepted);
3248#if QT_CONFIG(rubberband)
3249 if (d->dragMode == QGraphicsView::RubberBandDrag && !d->rubberBanding) {
3250 if (d->sceneInteractionAllowed) {
3253 d->rubberBanding =
true;
3254 d->rubberBandRect = QRect();
3256 bool extendSelection = (event->modifiers() & Qt::ControlModifier) != 0;
3258 if (extendSelection) {
3259 d->rubberBandSelectionOperation = Qt::AddToSelection;
3261 d->rubberBandSelectionOperation = Qt::ReplaceSelection;
3262 d->scene->clearSelection();
3268 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
3271 d->handScrolling =
true;
3272 d->handScrollMotions = 0;
3274 viewport()->setCursor(Qt::ClosedHandCursor);
3280
3281
3282void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
3286 if (d->dragMode == QGraphicsView::ScrollHandDrag) {
3287 if (d->handScrolling) {
3288 QScrollBar *hBar = horizontalScrollBar();
3289 QScrollBar *vBar = verticalScrollBar();
3290 QPoint delta = event->position().toPoint() - d->lastMouseEvent->position().toPoint();
3291 hBar->setValue(hBar->value() + (isRightToLeft() ? delta.x() : -delta.x()));
3292 vBar->setValue(vBar->value() - delta.y());
3296 ++d->handScrollMotions;
3300 d->mouseMoveEventHandler(event);
3304
3305
3306void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
3310#if QT_CONFIG(rubberband)
3311 if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed && !event->buttons()) {
3312 d->clearRubberBand();
3315 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
3320 viewport()->setCursor(Qt::OpenHandCursor);
3322 d->handScrolling =
false;
3324 if (d->scene && d->sceneInteractionAllowed && !d->lastMouseEvent->isAccepted() && d->handScrollMotions <= 6) {
3328 d->scene->clearSelection();
3332 d->storeMouseEvent(event);
3334 if (!d->sceneInteractionAllowed)
3340 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
3341 mouseEvent.setWidget(viewport());
3342 mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
3343 mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
3344 mouseEvent.setScenePos(mapToScene(event->position().toPoint()));
3345 mouseEvent.setScreenPos(event->globalPosition().toPoint());
3346 mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
3347 mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
3348 mouseEvent.setButtons(event->buttons());
3349 mouseEvent.setButton(event->button());
3350 mouseEvent.setModifiers(event->modifiers());
3351 mouseEvent.setSource(event->source());
3352 mouseEvent.setFlags(event->flags());
3353 mouseEvent.setAccepted(
false);
3354 mouseEvent.setTimestamp(event->timestamp());
3355 if (event->spontaneous())
3356 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
3358 QCoreApplication::sendEvent(d->scene, &mouseEvent);
3361 d->lastMouseEvent->setAccepted(mouseEvent.isAccepted());
3362 event->setAccepted(mouseEvent.isAccepted());
3365 if (mouseEvent.isAccepted() && mouseEvent.buttons() == 0 && viewport()->testAttribute(Qt::WA_SetCursor)) {
3367 d->_q_unsetViewportCursor();
3372#if QT_CONFIG(wheelevent)
3374
3375
3376void QGraphicsView::wheelEvent(QWheelEvent *event)
3379 if (!d->scene || !d->sceneInteractionAllowed) {
3380 QAbstractScrollArea::wheelEvent(event);
3386 QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel);
3387 wheelEvent.setWidget(viewport());
3388 wheelEvent.setScenePos(mapToScene(event->position().toPoint()));
3389 wheelEvent.setScreenPos(event->globalPosition().toPoint());
3390 wheelEvent.setButtons(event->buttons());
3391 wheelEvent.setModifiers(event->modifiers());
3392 const bool horizontal = qAbs(event->angleDelta().x()) > qAbs(event->angleDelta().y());
3393 wheelEvent.setDelta(horizontal ? event->angleDelta().x() : event->angleDelta().y());
3394 wheelEvent.setPixelDelta(event->pixelDelta());
3395 wheelEvent.setPhase(event->phase());
3396 wheelEvent.setInverted(event->isInverted());
3397 wheelEvent.setOrientation(horizontal ? Qt::Horizontal : Qt::Vertical);
3398 wheelEvent.setAccepted(
false);
3399 wheelEvent.setTimestamp(event->timestamp());
3400 QCoreApplication::sendEvent(d->scene, &wheelEvent);
3401 event->setAccepted(wheelEvent.isAccepted());
3402 if (!event->isAccepted())
3403 QAbstractScrollArea::wheelEvent(event);
3408
3409
3410void QGraphicsView::paintEvent(QPaintEvent *event)
3414 QAbstractScrollArea::paintEvent(event);
3419 d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
3422 d->exposedRegion = event->region();
3423 QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
3426 QPainter painter(viewport());
3427#if QT_CONFIG(rubberband)
3428 if (d->rubberBanding && !d->rubberBandRect.isEmpty())
3432 painter.setRenderHints(painter.renderHints(),
false);
3433 painter.setRenderHints(d->renderHints,
true);
3436 const bool viewTransformed = isTransformed();
3437 if (viewTransformed)
3438 painter.setWorldTransform(viewportTransform());
3439 const QTransform viewTransform = painter.worldTransform();
3441 const auto actuallyDraw = [&]() {
3443 if (d->cacheMode & CacheBackground) {
3446 if (d->mustResizeBackgroundPixmap) {
3447 const qreal dpr = d->viewport->devicePixelRatio();
3448 d->backgroundPixmap = QPixmap(viewport()->size() * dpr);
3449 d->backgroundPixmap.setDevicePixelRatio(dpr);
3450 QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
3451 if (!bgBrush.isOpaque())
3452 d->backgroundPixmap.fill(Qt::transparent);
3453 QPainter p(&d->backgroundPixmap);
3454 p.fillRect(0, 0, d->backgroundPixmap.width(), d->backgroundPixmap.height(), bgBrush);
3455 d->backgroundPixmapExposed = QRegion(viewport()->rect());
3456 d->mustResizeBackgroundPixmap =
false;
3460 if (!d->backgroundPixmapExposed.isEmpty()) {
3461 QPainter backgroundPainter(&d->backgroundPixmap);
3462 backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
3463 if (viewTransformed)
3464 backgroundPainter.setTransform(viewTransform);
3465 QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect();
3466 drawBackground(&backgroundPainter, backgroundExposedSceneRect);
3467 d->backgroundPixmapExposed = QRegion();
3471 if (viewTransformed) {
3472 painter.setWorldTransform(QTransform());
3473 painter.drawPixmap(QPoint(), d->backgroundPixmap);
3474 painter.setWorldTransform(viewTransform);
3476 painter.drawPixmap(QPoint(), d->backgroundPixmap);
3479 if (!(d->optimizationFlags & DontSavePainterState))
3482 drawBackground(&painter, exposedSceneRect);
3483 if (!(d->optimizationFlags & DontSavePainterState))
3488 if (!(d->optimizationFlags & IndirectPainting)) {
3489 const quint32 oldRectAdjust = d->scene->d_func()->rectAdjust;
3490 if (d->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
3491 d->scene->d_func()->rectAdjust = 1;
3493 d->scene->d_func()->rectAdjust = 2;
3494 d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform :
nullptr,
3495 &d->exposedRegion, viewport());
3496 d->scene->d_func()->rectAdjust = oldRectAdjust;
3503 if (!d->scene->d_func()->painterStateProtection)
3504 painter.setOpacity(1.0);
3505 painter.setWorldTransform(viewTransform);
3508 if (!d->scene->d_func()->unpolishedItems.isEmpty())
3509 d->scene->d_func()->_q_polishItems();
3512 d->scene->d_func()->updateAll =
false;
3515 bool allItems =
false;
3516 QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
3517 if (!itemList.isEmpty()) {
3519 const int numItems = itemList.size();
3520 QGraphicsItem **itemArray = &itemList[0];
3521 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
3522 QTransform transform(Qt::Uninitialized);
3523 for (
int i = 0; i < numItems; ++i) {
3524 QGraphicsItem *item = itemArray[i];
3525 QGraphicsItemPrivate *itemd = item->d_ptr.data();
3526 itemd->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
3532 const QRectF brect = adjustedItemEffectiveBoundingRect(item);
3533 if (!itemd->itemIsUntransformable()) {
3534 transform = item->sceneTransform();
3535 if (viewTransformed)
3536 transform *= viewTransform;
3538 transform = item->deviceTransform(viewTransform);
3540 itemd->paintedViewBoundingRects.insert(d->viewport, transform.mapRect(brect).toRect());
3543 drawItems(&painter, numItems, itemArray, styleOptionArray);
3544 d->freeStyleOptionsArray(styleOptionArray);
3549 drawForeground(&painter, exposedSceneRect);
3551 #if QT_CONFIG(rubberband)
3553 if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
3555 QStyleOptionRubberBand option;
3556 option.initFrom(viewport());
3557 option.rect = d->rubberBandRect;
3558 option.shape = QRubberBand::Rectangle;
3560 QStyleHintReturnMask mask;
3561 if (viewport()->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, viewport(), &mask)) {
3563 painter.setClipRegion(mask.region, Qt::IntersectClip);
3566 viewport()->style()->drawControl(QStyle::CE_RubberBand, &option, &painter, viewport());
3574 if (d->stereoEnabled) {
3575 QWidgetPrivate* w = QWidgetPrivate::get(viewport());
3576 if (w->toggleStereoTargetBuffer()) {
3578 w->toggleStereoTargetBuffer();
3585 d->scene->d_func()->painterStateProtection =
true;
3589
3590
3591void QGraphicsView::resizeEvent(QResizeEvent *event)
3596 QPointF oldLastCenterPoint = d->lastCenterPoint;
3598 QAbstractScrollArea::resizeEvent(event);
3599 d->recalculateContentSize();
3602 if (d->resizeAnchor == NoAnchor && !d->keepLastCenterPoint) {
3603 d->updateLastCenterPoint();
3605 d->lastCenterPoint = oldLastCenterPoint;
3607 d->centerView(d->resizeAnchor);
3608 d->keepLastCenterPoint =
false;
3610 if (d->cacheMode & CacheBackground) {
3612 d->mustResizeBackgroundPixmap =
true;
3617
3618
3619void QGraphicsView::scrollContentsBy(
int dx,
int dy)
3622 d->dirtyScroll =
true;
3623 if (d->transforming)
3625 if (isRightToLeft())
3628 if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
3629 if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
3630 if (d->accelerateScrolling) {
3631#if QT_CONFIG(rubberband)
3633 if (!d->rubberBandRect.isEmpty()) {
3634 QRegion rubberBandRegion(d->rubberBandRegion(viewport(), d->rubberBandRect));
3635 rubberBandRegion += rubberBandRegion.translated(-dx, -dy);
3636 viewport()->update(rubberBandRegion);
3639 d->dirtyScrollOffset.rx() += dx;
3640 d->dirtyScrollOffset.ry() += dy;
3641 d->dirtyRegion.translate(dx, dy);
3642 viewport()->scroll(dx, dy);
3651 d->updateLastCenterPoint();
3653 if (d->cacheMode & CacheBackground) {
3656 const qreal dpr = d->backgroundPixmap.devicePixelRatio();
3657 const qreal inverseDpr = qreal(1) / dpr;
3661 if (!d->backgroundPixmap.isNull())
3662 d->backgroundPixmap.scroll(dx * dpr, dy * dpr, d->backgroundPixmap.rect(), &exposed);
3665 d->backgroundPixmapExposed.translate(dx, dy);
3666 const QRegion exposedScaled = QTransform::fromScale(inverseDpr, inverseDpr).map(exposed);
3667 d->backgroundPixmapExposed += exposedScaled;
3671 if (d->sceneInteractionAllowed)
3672 d->replayLastMouseEvent();
3676
3677
3678void QGraphicsView::showEvent(QShowEvent *event)
3681 d->recalculateContentSize();
3682 d->centerView(d->transformationAnchor);
3683 QAbstractScrollArea::showEvent(event);
3687
3688
3689void QGraphicsView::inputMethodEvent(QInputMethodEvent *event)
3693 QCoreApplication::sendEvent(d->scene, event);
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713void QGraphicsView::drawBackground(QPainter *painter,
const QRectF &rect)
3716 if (d->scene && d->backgroundBrush.style() == Qt::NoBrush) {
3717 d->scene->drawBackground(painter, rect);
3721 const bool wasAa = painter->testRenderHint(QPainter::Antialiasing);
3723 painter->setRenderHints(QPainter::Antialiasing,
false);
3724 painter->fillRect(rect, d->backgroundBrush);
3726 painter->setRenderHints(QPainter::Antialiasing,
true);
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746void QGraphicsView::drawForeground(QPainter *painter,
const QRectF &rect)
3749 if (d->scene && d->foregroundBrush.style() == Qt::NoBrush) {
3750 d->scene->drawForeground(painter, rect);
3754 painter->fillRect(rect, d->foregroundBrush);
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774void QGraphicsView::drawItems(QPainter *painter,
int numItems,
3775 QGraphicsItem *items[],
3776 const QStyleOptionGraphicsItem options[])
3780 QWidget *widget = painter->device() == viewport() ? viewport() :
nullptr;
3781 d->scene->drawItems(painter, numItems, items, options, widget);
3786
3787
3788
3789
3790
3791QTransform QGraphicsView::transform()
const
3793 Q_D(
const QGraphicsView);
3798
3799
3800
3801
3802QTransform QGraphicsView::viewportTransform()
const
3804 Q_D(
const QGraphicsView);
3805 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
3806 return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
3810
3811
3812
3813
3814
3815
3816
3817bool QGraphicsView::isTransformed()
const
3819 Q_D(
const QGraphicsView);
3820 return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849void QGraphicsView::setTransform(
const QTransform &matrix,
bool combine )
3852 QTransform oldMatrix = d->matrix;
3856 d->matrix = matrix * d->matrix;
3857 if (oldMatrix == d->matrix)
3860 d->identityMatrix = d->matrix.isIdentity();
3861 d->transforming =
true;
3863 d->recalculateContentSize();
3864 d->centerView(d->transformationAnchor);
3866 d->updateLastCenterPoint();
3869 if (d->sceneInteractionAllowed)
3870 d->replayLastMouseEvent();
3871 d->transforming =
false;
3878
3879
3880
3881
3882void QGraphicsView::resetTransform()
3884 setTransform(QTransform());
3887QPointF QGraphicsViewPrivate::mapToScene(
const QPointF &point)
const
3890 p.rx() += horizontalScroll();
3891 p.ry() += verticalScroll();
3892 return identityMatrix ? p : matrix.inverted().map(p);
3895QRectF QGraphicsViewPrivate::mapToScene(
const QRectF &rect)
const
3897 QPointF scrollOffset(horizontalScroll(), verticalScroll());
3898 QPointF tl = scrollOffset + rect.topLeft();
3899 QPointF tr = scrollOffset + rect.topRight();
3900 QPointF br = scrollOffset + rect.bottomRight();
3901 QPointF bl = scrollOffset + rect.bottomLeft();
3904 if (!identityMatrix) {
3905 QTransform x = matrix.inverted();
3906 poly[0] = x.map(tl);
3907 poly[1] = x.map(tr);
3908 poly[2] = x.map(br);
3909 poly[3] = x.map(bl);
3916 return poly.boundingRect();
3921#include "moc_qgraphicsview.cpp"
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)