548void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
555 markDirty(item, QRectF(),
false,
false,
558 if (item->d_ptr->inDestructor) {
560 index->deleteItem(item);
564 index->removeItem(item);
567 item->d_ptr->clearSubFocus();
569 if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
570 unregisterScenePosItem(item);
572 QGraphicsScene *oldScene = item->d_func()->scene;
573 item->d_func()->scene =
nullptr;
577 if (!item->d_ptr->inDestructor) {
579 for (
auto child : std::as_const(item->d_ptr->children))
580 q->removeItem(child);
583 if (!item->d_ptr->inDestructor && !item->parentItem() && item->isWidget()) {
584 QGraphicsWidget *widget =
static_cast<QGraphicsWidget *>(item);
585 widget->d_func()->fixFocusChainBeforeReparenting(
nullptr, oldScene,
nullptr);
589 item->d_ptr->resetFocusProxy();
592 if (QGraphicsItem *parentItem = item->parentItem()) {
593 if (parentItem->scene()) {
594 Q_ASSERT_X(parentItem->scene() == q,
"QGraphicsScene::removeItem",
595 "Parent item's scene is different from this item's scene");
596 item->setParentItem(
nullptr);
599 unregisterTopLevelItem(item);
603 if (item == focusItem)
605 if (item == lastFocusItem)
606 lastFocusItem =
nullptr;
607 if (item == passiveFocusItem)
608 passiveFocusItem =
nullptr;
609 if (item == activePanel) {
611 activePanel =
nullptr;
613 if (item == lastActivePanel)
614 lastActivePanel =
nullptr;
617 if (item == tabFocusFirst) {
618 QGraphicsWidgetPrivate *wd = tabFocusFirst->d_func();
619 if (wd->focusNext && wd->focusNext != tabFocusFirst && wd->focusNext->scene() == q)
620 tabFocusFirst = wd->focusNext;
622 tabFocusFirst =
nullptr;
627 QMap<
int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin();
628 while (it != itemForTouchPointId.end()) {
629 if (it.value() == item) {
630 sceneCurrentTouchPoints.remove(it.key());
631 it = itemForTouchPointId.erase(it);
640 int oldSelectedItemsSize = selectedItems.size();
643 selectedItems.remove(item);
644 hoverItems.removeAll(item);
645 cachedItemsUnderMouse.removeAll(item);
646 if (item->d_ptr->pendingPolish) {
647 const int unpolishedIndex = unpolishedItems.indexOf(item);
648 if (unpolishedIndex != -1)
649 unpolishedItems[unpolishedIndex] = 0;
650 item->d_ptr->pendingPolish =
false;
652 resetDirtyItem(item);
655 QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
656 while (iterator != sceneEventFilters.end()) {
657 if (iterator.value() == item || iterator.key() == item)
658 iterator = sceneEventFilters.erase(iterator);
663 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
667 if (mouseGrabberItems.contains(item))
668 ungrabMouse(item, item->d_ptr->inDestructor);
671 if (keyboardGrabberItems.contains(item))
672 ungrabKeyboard(item, item->d_ptr->inDestructor);
675 if (item == lastMouseGrabberItem)
676 lastMouseGrabberItem =
nullptr;
679 if (item == dragDropItem)
680 dragDropItem =
nullptr;
684 if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
685 emit q->selectionChanged();
687#ifndef QT_NO_GESTURES
688 for (
auto it = gestureTargets.begin(); it != gestureTargets.end();) {
689 if (it.value() == item)
690 it = gestureTargets.erase(it);
695 if (QGraphicsObject *dummy = item->toGraphicsObject()) {
696 cachedTargetItems.removeOne(dummy);
697 cachedItemGestures.remove(dummy);
698 cachedAlreadyDeliveredGestures.remove(dummy);
701 for (
auto it = item->d_ptr->gestureContext.constBegin();
702 it != item->d_ptr->gestureContext.constEnd(); ++it)
703 ungrabGesture(item, it.key());
710void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item,
bool duringActivationEvent)
713 if (item && item->scene() != q) {
714 qWarning(
"QGraphicsScene::setActivePanel: item %p must be part of this scene",
720 q->setFocus(Qt::ActiveWindowFocusReason);
723 QGraphicsItem *panel = item ? item->panel() :
nullptr;
724 lastActivePanel = panel ? activePanel :
nullptr;
725 if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
728 QGraphicsItem *oldFocusItem = focusItem;
732 if (QGraphicsItem *fi = activePanel->focusItem()) {
734 if (fi == q->focusItem())
735 setFocusItemHelper(
nullptr, Qt::ActiveWindowFocusReason,
false);
738 QEvent event(QEvent::WindowDeactivate);
739 q->sendEvent(activePanel, &event);
740 }
else if (panel && !duringActivationEvent) {
742 const auto items = q->items();
743 QEvent event(QEvent::WindowDeactivate);
744 for (QGraphicsItem *item : items) {
745 if (item->isVisible() && !item->isPanel() && !item->parentItem())
746 q->sendEvent(item, &event);
752 QEvent event(QEvent::ActivationChange);
753 QCoreApplication::sendEvent(q, &event);
757 QEvent event(QEvent::WindowActivate);
758 q->sendEvent(panel, &event);
763 if (QGraphicsItem *focusItem = panel->focusItem()) {
764 setFocusItemHelper(focusItem, Qt::ActiveWindowFocusReason,
false);
765 }
else if (panel->flags() & QGraphicsItem::ItemIsFocusable) {
766 setFocusItemHelper(panel, Qt::ActiveWindowFocusReason,
false);
767 }
else if (panel->isWidget()) {
768 QGraphicsWidget *fw =
static_cast<QGraphicsWidget *>(panel)->d_func()->focusNext;
770 if (fw->focusPolicy() & Qt::TabFocus) {
771 setFocusItemHelper(fw, Qt::ActiveWindowFocusReason,
false);
774 fw = fw->d_func()->focusNext;
775 }
while (fw != panel);
777 }
else if (q->isActive()) {
778 const auto items = q->items();
780 QEvent event(QEvent::WindowActivate);
781 for (QGraphicsItem *item : items) {
782 if (item->isVisible() && !item->isPanel() && !item->parentItem())
783 q->sendEvent(item, &event);
787 emit q->focusItemChanged(focusItem, oldFocusItem, Qt::ActiveWindowFocusReason);
1315void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent)
1317 Q_Q(QGraphicsScene);
1320 mouseEvent->ignore();
1323 if (!mouseGrabberItems.isEmpty()) {
1324 if (mouseGrabberItems.constLast()->isBlockedByModalPanel())
1328 sendMouseEvent(mouseEvent);
1334 if (cachedItemsUnderMouse.isEmpty()) {
1335 cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(),
1336 mouseEvent->scenePos(),
1337 mouseEvent->widget());
1341 QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
1342 QGraphicsWidget *newActiveWindow = topItem ? topItem->window() :
nullptr;
1343 if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
1345 newActiveWindow = topItem ? topItem->window() :
nullptr;
1348 if (newActiveWindow != q->activeWindow())
1349 q->setActiveWindow(newActiveWindow);
1352 bool setFocus =
false;
1354 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1355 if (item->isBlockedByModalPanel()
1356 || (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling)) {
1361 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable))) {
1362 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
1364 if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
1365 q->setFocusItem(item, Qt::MouseFocusReason);
1369 if (item->isPanel())
1371 if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
1376 bool sceneModality =
false;
1377 for (
auto modalPanel : std::as_const(modalPanels)) {
1378 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
1379 sceneModality =
true;
1385 if (!stickyFocus && !setFocus && !sceneModality)
1386 q->setFocusItem(
nullptr, Qt::MouseFocusReason);
1389 if (sceneModality && cachedItemsUnderMouse.isEmpty())
1390 cachedItemsUnderMouse << modalPanels.constFirst();
1396 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1397 if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
1404 (
void) item->isBlockedByModalPanel(&item);
1406 grabMouse(item,
true);
1407 mouseEvent->accept();
1410 bool disabled = !item->isEnabled();
1411 bool isPanel = item->isPanel();
1412 if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
1413 && item != lastMouseGrabberItem && lastMouseGrabberItem) {
1418 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1419 mousePress.m_spont = mouseEvent->spontaneous();
1420 mousePress.accept();
1421 mousePress.setButton(mouseEvent->button());
1422 mousePress.setButtons(mouseEvent->buttons());
1423 mousePress.setScreenPos(mouseEvent->screenPos());
1424 mousePress.setScenePos(mouseEvent->scenePos());
1425 mousePress.setModifiers(mouseEvent->modifiers());
1426 mousePress.setWidget(mouseEvent->widget());
1427 mousePress.setButtonDownPos(mouseEvent->button(),
1428 mouseEvent->buttonDownPos(mouseEvent->button()));
1429 mousePress.setButtonDownScenePos(mouseEvent->button(),
1430 mouseEvent->buttonDownScenePos(mouseEvent->button()));
1431 mousePress.setButtonDownScreenPos(mouseEvent->button(),
1432 mouseEvent->buttonDownScreenPos(mouseEvent->button()));
1433 sendMouseEvent(&mousePress);
1434 mouseEvent->setAccepted(mousePress.isAccepted());
1436 sendMouseEvent(mouseEvent);
1439 bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.constLast() != item;
1441 ungrabMouse(item, dontSendUngrabEvents);
1444 if (mouseEvent->isAccepted()) {
1445 if (!mouseGrabberItems.isEmpty())
1446 storeMouseButtonsForMouseGrabber(mouseEvent);
1447 lastMouseGrabberItem = item;
1450 ungrabMouse(item, dontSendUngrabEvents);
1461 if (!mouseEvent->isAccepted()) {
1462 clearMouseGrabber();
1464 QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
1465 bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
1466 bool extendSelection = (mouseEvent->modifiers() & Qt::ControlModifier) != 0;
1467 dontClearSelection |= extendSelection;
1468 if (!dontClearSelection) {
1472 q->clearSelection();
1752void QGraphicsScene::render(QPainter *painter,
const QRectF &target,
const QRectF &source,
1753 Qt::AspectRatioMode aspectRatioMode)
1758 QRectF sourceRect = source;
1759 if (sourceRect.isNull())
1760 sourceRect = sceneRect();
1763 QRectF targetRect = target;
1764 if (targetRect.isNull()) {
1765 if (painter->device()->devType() == QInternal::Picture)
1766 targetRect = sourceRect;
1768 targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
1772 qreal xratio = targetRect.width() / sourceRect.width();
1773 qreal yratio = targetRect.height() / sourceRect.height();
1776 switch (aspectRatioMode) {
1777 case Qt::KeepAspectRatio:
1778 xratio = yratio = qMin(xratio, yratio);
1780 case Qt::KeepAspectRatioByExpanding:
1781 xratio = yratio = qMax(xratio, yratio);
1783 case Qt::IgnoreAspectRatio:
1789 QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect);
1790 QGraphicsItem **itemArray =
new QGraphicsItem *[itemList.size()];
1791 const qsizetype numItems = itemList.size();
1792 for (qsizetype i = 0; i < numItems; ++i)
1793 itemArray[numItems - i - 1] = itemList.at(i);
1799 painter->setClipRect(targetRect, Qt::IntersectClip);
1800 QTransform painterTransform;
1801 painterTransform *= QTransform()
1802 .translate(targetRect.left(), targetRect.top())
1803 .scale(xratio, yratio)
1804 .translate(-sourceRect.left(), -sourceRect.top());
1805 painter->setWorldTransform(painterTransform,
true);
1808 QStyleOptionGraphicsItem *styleOptionArray =
new QStyleOptionGraphicsItem[numItems];
1809 for (qsizetype i = 0; i < numItems; ++i)
1810 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
1813 drawBackground(painter, sourceRect);
1814 drawItems(painter, numItems, itemArray, styleOptionArray);
1815 drawForeground(painter, sourceRect);
1817 delete [] itemArray;
1818 delete [] styleOptionArray;
2402void QGraphicsScene::addItem(QGraphicsItem *item)
2404 Q_D(QGraphicsScene);
2406 qWarning(
"QGraphicsScene::addItem: cannot add null item");
2409 if (item->d_ptr->scene ==
this) {
2410 qWarning(
"QGraphicsScene::addItem: item has already been added to this scene");
2414 if (QGraphicsScene *oldScene = item->d_ptr->scene)
2415 oldScene->removeItem(item);
2419 const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
2420 QVariant::fromValue<QGraphicsScene *>(
this)));
2421 QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2422 if (targetScene !=
this) {
2423 if (targetScene && item->d_ptr->scene != targetScene)
2424 targetScene->addItem(item);
2428 if (d->unpolishedItems.isEmpty()) {
2429 QMetaMethod method = metaObject()->method(d->polishItemsIndex);
2430 method.invoke(
this, Qt::QueuedConnection);
2432 d->unpolishedItems.append(item);
2433 item->d_ptr->pendingPolish =
true;
2437 if (QGraphicsItem *itemParent = item->d_ptr->parent) {
2438 if (itemParent->d_ptr->scene !=
this)
2439 item->setParentItem(
nullptr);
2443 item->d_func()->scene = targetScene;
2446 d->index->addItem(item);
2449 if (!item->d_ptr->parent)
2450 d->registerTopLevelItem(item);
2456 d->dirtyGrowingItemsBoundingRect =
true;
2459 ++d->selectionChanging;
2460 int oldSelectedItemSize = d->selectedItems.size();
2466 auto needsMouseTracking = [](
const QGraphicsItemPrivate *item) {
2467 return item->acceptsHover
2468 || (item->isWidget &&
static_cast<
const QGraphicsWidgetPrivate *>(item)->hasDecoration());
2471 if (d->allItemsIgnoreHoverEvents && needsMouseTracking(item->d_ptr.data())) {
2472 d->allItemsIgnoreHoverEvents =
false;
2473 d->enableMouseTrackingOnViews();
2476 if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
2477 d->allItemsUseDefaultCursor =
false;
2478 if (d->allItemsIgnoreHoverEvents)
2479 d->enableMouseTrackingOnViews();
2484 if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
2485 d->allItemsIgnoreTouchEvents =
false;
2486 d->enableTouchEventsOnViews();
2489#ifndef QT_NO_GESTURES
2490 for (
auto it = item->d_ptr->gestureContext.constBegin();
2491 it != item->d_ptr->gestureContext.constEnd(); ++it)
2492 d->grabGesture(item, it.key());
2496 if (item->isSelected())
2497 d->selectedItems << item;
2498 if (item->isWidget() && item->isVisible() &&
static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
2499 d->addPopup(
static_cast<QGraphicsWidget *>(item));
2500 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
2501 d->enterModal(item);
2505 if (item->isWidget()) {
2506 QGraphicsWidget *widget =
static_cast<QGraphicsWidget *>(item);
2507 if (!d->tabFocusFirst) {
2510 d->tabFocusFirst = widget;
2511 }
else if (!widget->parentWidget() && !widget->isPanel()) {
2513 QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev;
2514 myNewPrev->d_func()->focusNext = widget;
2515 widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst;
2516 d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev;
2517 widget->d_func()->focusPrev = myNewPrev;
2522 item->d_ptr->ensureSortedChildren();
2523 for (
auto child : std::as_const(item->d_ptr->children))
2527 item->d_ptr->resolveFont(d->font.resolveMask());
2528 item->d_ptr->resolvePalette(d->palette.resolveMask());
2532 --d->selectionChanging;
2533 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
2534 emit selectionChanged();
2537 item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
2540 bool autoActivate =
true;
2541 if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
2542 d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
2543 if (d->childExplicitActivation && item->isPanel()) {
2544 if (d->childExplicitActivation == 1)
2545 setActivePanel(item);
2547 autoActivate =
false;
2548 d->childExplicitActivation = 0;
2549 }
else if (!item->d_ptr->parent) {
2550 d->childExplicitActivation = 0;
2555 if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
2557 setActivePanel(item);
2559 d->lastActivePanel = item;
2563 if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges)
2564 d->registerScenePosItem(item);
2568 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
2569 item->focusItem()->setFocus();
2571 d->updateInputMethodSensitivityInViews();
3236bool QGraphicsScene::event(QEvent *event)
3238 Q_D(QGraphicsScene);
3240 switch (event->type()) {
3241 case QEvent::GraphicsSceneMousePress:
3242 case QEvent::GraphicsSceneMouseMove:
3243 case QEvent::GraphicsSceneMouseRelease:
3244 case QEvent::GraphicsSceneMouseDoubleClick:
3245 case QEvent::GraphicsSceneHoverEnter:
3246 case QEvent::GraphicsSceneHoverLeave:
3247 case QEvent::GraphicsSceneHoverMove:
3248 case QEvent::TouchBegin:
3249 case QEvent::TouchUpdate:
3250 case QEvent::TouchEnd:
3258 d->cachedItemsUnderMouse.clear();
3264 switch (event->type()) {
3265 case QEvent::GraphicsSceneDragEnter:
3266 dragEnterEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3268 case QEvent::GraphicsSceneDragMove:
3269 dragMoveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3271 case QEvent::GraphicsSceneDragLeave:
3272 dragLeaveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3274 case QEvent::GraphicsSceneDrop:
3275 dropEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3277 case QEvent::GraphicsSceneContextMenu:
3278 contextMenuEvent(
static_cast<QGraphicsSceneContextMenuEvent *>(event));
3280 case QEvent::KeyPress:
3281 if (!d->focusItem) {
3282 QKeyEvent *k =
static_cast<QKeyEvent *>(event);
3283 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
3284 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {
3286 if (k->key() == Qt::Key_Backtab
3287 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
3288 res = focusNextPrevChild(
false);
3289 }
else if (k->key() == Qt::Key_Tab) {
3290 res = focusNextPrevChild(
true);
3298 keyPressEvent(
static_cast<QKeyEvent *>(event));
3300 case QEvent::KeyRelease:
3301 keyReleaseEvent(
static_cast<QKeyEvent *>(event));
3303 case QEvent::ShortcutOverride: {
3304 QGraphicsItem *parent = focusItem();
3306 d->sendEvent(parent, event);
3307 if (event->isAccepted())
3309 parent = parent->parentItem();
3313 case QEvent::GraphicsSceneMouseMove:
3315 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *>(event);
3316 d->lastSceneMousePos = mouseEvent->scenePos();
3317 mouseMoveEvent(mouseEvent);
3320 case QEvent::GraphicsSceneMousePress:
3321 mousePressEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3323 case QEvent::GraphicsSceneMouseRelease:
3324 mouseReleaseEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3326 case QEvent::GraphicsSceneMouseDoubleClick:
3327 mouseDoubleClickEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3329 case QEvent::GraphicsSceneWheel:
3330 wheelEvent(
static_cast<QGraphicsSceneWheelEvent *>(event));
3332 case QEvent::FocusIn:
3333 focusInEvent(
static_cast<QFocusEvent *>(event));
3335 case QEvent::FocusOut:
3336 focusOutEvent(
static_cast<QFocusEvent *>(event));
3338 case QEvent::GraphicsSceneHoverEnter:
3339 case QEvent::GraphicsSceneHoverLeave:
3340 case QEvent::GraphicsSceneHoverMove:
3342 QGraphicsSceneHoverEvent *hoverEvent =
static_cast<QGraphicsSceneHoverEvent *>(event);
3343 d->lastSceneMousePos = hoverEvent->scenePos();
3344 d->dispatchHoverEvent(hoverEvent);
3348 Q_ASSERT_X(
false,
"QGraphicsScene::event",
3349 "QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
3351 case QEvent::GraphicsSceneLeave:
3353 auto *leaveEvent =
static_cast<QGraphicsSceneEvent*>(event);
3354 d->leaveScene(leaveEvent->widget());
3357 case QEvent::GraphicsSceneHelp:
3358 helpEvent(
static_cast<QGraphicsSceneHelpEvent *>(event));
3360 case QEvent::InputMethod:
3361 inputMethodEvent(
static_cast<QInputMethodEvent *>(event));
3363 case QEvent::WindowActivate:
3364 if (!d->activationRefCount++) {
3365 if (d->lastActivePanel) {
3367 d->setActivePanelHelper(d->lastActivePanel,
true);
3368 }
else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
3371 d->setActivePanelHelper(d->tabFocusFirst,
true);
3374 QEvent event(QEvent::WindowActivate);
3375 const auto items_ = items();
3376 for (QGraphicsItem *item : items_) {
3377 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3378 sendEvent(item, &event);
3383 case QEvent::WindowDeactivate:
3384 if (!--d->activationRefCount) {
3385 if (d->activePanel) {
3388 QGraphicsItem *lastActivePanel = d->activePanel;
3389 d->setActivePanelHelper(
nullptr,
true);
3390 d->lastActivePanel = lastActivePanel;
3393 QEvent event(QEvent::WindowDeactivate);
3394 const auto items_ = items();
3395 for (QGraphicsItem *item : items_) {
3396 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3397 sendEvent(item, &event);
3402 case QEvent::ApplicationFontChange: {
3407 case QEvent::FontChange:
3411 case QEvent::ApplicationPaletteChange: {
3413 d->resolvePalette();
3416 case QEvent::PaletteChange:
3420 case QEvent::StyleChange:
3425 case QEvent::StyleAnimationUpdate:
3430 case QEvent::TouchBegin:
3431 case QEvent::TouchUpdate:
3432 case QEvent::TouchEnd:
3433 d->touchEventHandler(
static_cast<QTouchEvent *>(event));
3435#ifndef QT_NO_GESTURES
3436 case QEvent::Gesture:
3437 case QEvent::GestureOverride:
3438 d->gestureEventHandler(
static_cast<QGestureEvent *>(event));
3442 return QObject::event(event);
3532void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
3534 Q_D(QGraphicsScene);
3537 if (!d->mouseGrabberItems.isEmpty()) {
3539 d->clearMouseGrabber();
3540 d->mouseGrabberButtonDownPos.clear();
3541 d->mouseGrabberButtonDownScenePos.clear();
3542 d->mouseGrabberButtonDownScreenPos.clear();
3545 bool eventDelivered =
false;
3549 const auto items = d->itemsAtPosition(event->screenPos(),
3552 for (QGraphicsItem *item : items) {
3553 if (!item->isEnabled() || !item->acceptDrops())
3556 if (item != d->dragDropItem) {
3559 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
3560 d->cloneDragDropEvent(&dragEnter, event);
3561 dragEnter.setDropAction(event->proposedAction());
3562 d->sendDragDropEvent(item, &dragEnter);
3563 event->setAccepted(dragEnter.isAccepted());
3564 event->setDropAction(dragEnter.dropAction());
3565 if (!event->isAccepted()) {
3570 d->lastDropAction = event->dropAction();
3572 if (d->dragDropItem) {
3577 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3578 d->cloneDragDropEvent(&dragLeave, event);
3579 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3583 d->dragDropItem = item;
3587 event->setDropAction(d->lastDropAction);
3589 d->sendDragDropEvent(item, event);
3590 if (event->isAccepted())
3591 d->lastDropAction = event->dropAction();
3592 eventDelivered =
true;
3596 if (!eventDelivered) {
3597 if (d->dragDropItem) {
3599 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3600 d->cloneDragDropEvent(&dragLeave, event);
3601 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3602 d->dragDropItem =
nullptr;
3605 event->setDropAction(Qt::IgnoreAction);
3766bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
3768 if (allItemsIgnoreHoverEvents)
3773 if (cachedItemsUnderMouse.isEmpty()) {
3774 cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(),
3775 hoverEvent->scenePos(),
3776 hoverEvent->widget());
3779 QGraphicsItem *item =
nullptr;
3780 for (
auto tmp : std::as_const(cachedItemsUnderMouse)) {
3781 if (itemAcceptsHoverEvents_helper(tmp)) {
3789 QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.constLast()) :
nullptr;
3790 while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
3791 commonAncestorItem = commonAncestorItem->parentItem();
3792 if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
3795 commonAncestorItem =
nullptr;
3799 int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
3802 for (
int i = hoverItems.size() - 1; i > index; --i) {
3803 QGraphicsItem *lastItem = hoverItems.takeLast();
3804 if (itemAcceptsHoverEvents_helper(lastItem))
3805 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
3810 QList<QGraphicsItem *> parents;
3811 QGraphicsItem *parent = item;
3812 while (parent && parent != commonAncestorItem) {
3813 parents.append(parent);
3814 if (parent->isPanel()) {
3818 parent = parent->parentItem();
3820 for (
auto it = parents.crbegin(), end = parents.crend(); it != end; ++it) {
3821 QGraphicsItem *parent = *it;
3822 hoverItems << parent;
3823 if (itemAcceptsHoverEvents_helper(parent))
3824 sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent);
3829 && !hoverItems.isEmpty()
3830 && item == hoverItems.constLast()) {
3831 sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
4307void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter,
4308 const QStyleOptionGraphicsItem *option, QWidget *widget,
4309 bool painterStateProtection)
4311 QGraphicsItemPrivate *itemd = item->d_ptr.data();
4312 QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
4315 if (cacheMode == QGraphicsItem::NoCache) {
4316 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
true, painterStateProtection);
4320 const qreal devicePixelRatio = painter->device()->devicePixelRatio();
4321 const qreal oldPainterOpacity = painter->opacity();
4322 qreal newPainterOpacity = oldPainterOpacity;
4323 QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(
static_cast<QGraphicsWidget *>(item)) : 0;
4324 if (proxy && proxy->widget()) {
4325 const qreal windowOpacity = proxy->widget()->windowOpacity();
4326 if (windowOpacity < 1.0)
4327 newPainterOpacity *= windowOpacity;
4331 QRectF brect = item->boundingRect();
4332 QRectF adjustedBrect(brect);
4333 _q_adjustRect(&adjustedBrect);
4334 if (adjustedBrect.isEmpty())
4338 QPixmapCache::Key pixmapKey;
4342 QGraphicsItemCache *itemCache = itemd->extraItemCache();
4343 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4344 pixmapKey = itemCache->key;
4346 pixmapKey = itemCache->deviceData.value(widget).key;
4350 pixmapFound = QPixmapCache::find(pixmapKey, &pix);
4353 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4355 bool fixedCacheSize = itemCache->fixedSize.isValid();
4356 QRect br = brect.toAlignedRect();
4357 if (fixedCacheSize) {
4358 pixmapSize = itemCache->fixedSize;
4360 pixmapSize = br.size();
4363 pixmapSize *= devicePixelRatio;
4366 int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
4367 QSize adjustSize(adjust*2, adjust*2);
4368 br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
4369 if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
4370 pix = QPixmap(pixmapSize + adjustSize);
4371 itemCache->boundingRect = br;
4372 itemCache->exposed.clear();
4373 itemCache->allExposed =
true;
4374 }
else if (itemCache->boundingRect != br) {
4375 itemCache->boundingRect = br;
4376 itemCache->exposed.clear();
4377 itemCache->allExposed =
true;
4381 if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
4386 QPixmapCache::remove(pixmapKey);
4389 QTransform itemToPixmap;
4390 if (fixedCacheSize) {
4391 const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
4392 (pixmapSize.height() / devicePixelRatio) / brect.height());
4393 itemToPixmap.scale(scale.x(), scale.y());
4395 itemToPixmap.translate(-br.x(), -br.y());
4399 styleOptionTmp = *option;
4400 QRegion pixmapExposed;
4402 if (!itemCache->allExposed) {
4403 for (
const auto &rect : std::as_const(itemCache->exposed)) {
4404 exposedRect |= rect;
4405 pixmapExposed += itemToPixmap.mapRect(rect).toAlignedRect();
4408 exposedRect = brect;
4410 styleOptionTmp.exposedRect = exposedRect;
4413 pix.setDevicePixelRatio(devicePixelRatio);
4414 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4415 &styleOptionTmp, painterStateProtection);
4418 itemCache->key = QPixmapCache::insert(pix);
4421 itemCache->allExposed =
false;
4422 itemCache->exposed.clear();
4428 if (newPainterOpacity != oldPainterOpacity) {
4429 painter->setOpacity(newPainterOpacity);
4430 painter->drawPixmap(br.topLeft(), pix);
4431 painter->setOpacity(oldPainterOpacity);
4433 painter->drawPixmap(br.topLeft(), pix);
4439 if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
4441 QRectF deviceBounds = painter->worldTransform().mapRect(brect);
4442 QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
4443 if (deviceRect.isEmpty())
4445 QRect viewRect = widget ? widget->rect() : QRect();
4446 if (widget && !viewRect.intersects(deviceRect))
4451 QSize maximumCacheSize =
4452 itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
4453 if (!maximumCacheSize.isEmpty()
4454 && (deviceRect.width() > maximumCacheSize.width()
4455 || deviceRect.height() > maximumCacheSize.height())) {
4456 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
4457 oldPainterOpacity != newPainterOpacity, painterStateProtection);
4464 bool pixModified =
false;
4465 QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
4466 bool invertable =
true;
4467 QTransform diff = deviceData->lastTransform.inverted(&invertable);
4469 diff *= painter->worldTransform();
4470 deviceData->lastTransform = painter->worldTransform();
4471 bool allowPartialCacheExposure =
false;
4472 bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
4473 && transformIsSimple(painter->worldTransform());
4474 if (!simpleTransform) {
4476 itemCache->allExposed =
true;
4477 itemCache->exposed.clear();
4478 deviceData->cacheIndent = QPoint();
4480 }
else if (!viewRect.isNull()) {
4481 allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
4486 if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
4487 allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
4488 || (viewRect.height() * 1.2 < deviceRect.height());
4491 QRegion scrollExposure;
4492 if (allowPartialCacheExposure) {
4497 int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
4498 int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
4499 QPoint newCacheIndent(dx, dy);
4500 deviceRect &= viewRect;
4503 deviceData->cacheIndent = QPoint();
4504 itemCache->allExposed =
true;
4505 itemCache->exposed.clear();
4511 if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
4512 QPoint diff = newCacheIndent - deviceData->cacheIndent;
4513 QPixmap newPix(deviceRect.size() * devicePixelRatio);
4516 newPix.fill(Qt::transparent);
4517 if (!pix.isNull()) {
4518 newPix.setDevicePixelRatio(devicePixelRatio);
4519 QPainter newPixPainter(&newPix);
4520 newPixPainter.drawPixmap(-diff, pix);
4521 newPixPainter.end();
4524 exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
4526 exposed -= QRect(-diff, pix.size() / devicePixelRatio);
4527 scrollExposure = exposed;
4532 deviceData->cacheIndent = newCacheIndent;
4535 deviceData->cacheIndent = QPoint();
4538 if (deviceRect.size() != pix.size() / devicePixelRatio) {
4540 pix = QPixmap(deviceRect.size() * devicePixelRatio);
4542 itemCache->allExposed =
true;
4543 itemCache->exposed.clear();
4548 if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
4552 QPixmapCache::remove(pixmapKey);
4555 QPointF p = deviceRect.topLeft();
4556 QTransform itemToPixmap = painter->worldTransform();
4558 itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
4561 QRegion pixmapExposed = scrollExposure;
4562 if (!itemCache->allExposed) {
4563 for (
const auto &rect : std::as_const(itemCache->exposed))
4564 pixmapExposed += itemToPixmap.mapRect(rect).toRect().adjusted(-1, -1, 1, 1);
4569 if (itemCache->allExposed) {
4570 br = item->boundingRect();
4572 for (
const auto &rect : std::as_const(itemCache->exposed))
4574 QTransform pixmapToItem = itemToPixmap.inverted();
4575 for (
const QRect &r : std::as_const(scrollExposure))
4576 br |= pixmapToItem.mapRect(r);
4578 styleOptionTmp = *option;
4579 styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
4582 pix.setDevicePixelRatio(devicePixelRatio);
4583 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4584 &styleOptionTmp, painterStateProtection);
4588 itemCache->allExposed =
false;
4589 itemCache->exposed.clear();
4594 deviceData->key = QPixmapCache::insert(pix);
4599 QTransform restoreTransform = painter->worldTransform();
4600 painter->setWorldTransform(QTransform());
4601 if (newPainterOpacity != oldPainterOpacity) {
4602 painter->setOpacity(newPainterOpacity);
4603 painter->drawPixmap(deviceRect.topLeft(), pix);
4604 painter->setOpacity(oldPainterOpacity);
4606 painter->drawPixmap(deviceRect.topLeft(), pix);
4608 painter->setWorldTransform(restoreTransform);
4632void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
4633 const QTransform *
const viewTransform,
4634 QRegion *exposedRegion, QWidget *widget,
4635 qreal parentOpacity,
const QTransform *
const effectTransform)
4639 if (!item->d_ptr->visible)
4642 const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
4643 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
4644 if (!itemHasContents && !itemHasChildren)
4647 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
4648 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4649 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
4652 QTransform transform(Qt::Uninitialized);
4653 QTransform *transformPtr =
nullptr;
4654 bool translateOnlyTransform =
false;
4655#define ENSURE_TRANSFORM_PTR
4656 if (!transformPtr) {
4657 Q_ASSERT(!itemIsUntransformable);
4658 if (viewTransform) {
4659 transform = item->d_ptr->sceneTransform;
4660 transform *= *viewTransform;
4661 transformPtr = &transform;
4663 transformPtr = &item->d_ptr->sceneTransform;
4664 translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly;
4670 bool wasDirtyParentSceneTransform =
false;
4671 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
4672 if (itemIsUntransformable) {
4673 transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
4674 transformPtr = &transform;
4675 }
else if (item->d_ptr->dirtySceneTransform) {
4676 item->d_ptr->updateSceneTransformFromParent();
4677 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
4678 wasDirtyParentSceneTransform =
true;
4681 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
4682 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
4683 bool drawItem = itemHasContents && !itemIsFullyTransparent;
4684 if (drawItem || minimumRenderSize > 0.0) {
4685 const QRectF brect = adjustedItemEffectiveBoundingRect(item);
4687 QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
4688 : transformPtr->mapRect(brect);
4690 bool itemIsTooSmallToRender =
false;
4691 if (minimumRenderSize > 0.0
4692 && (preciseViewBoundingRect.width() < minimumRenderSize
4693 || preciseViewBoundingRect.height() < minimumRenderSize)) {
4694 itemIsTooSmallToRender =
true;
4698 bool itemIsOutsideVisibleRect =
false;
4700 QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
4701 viewBoundingRect.adjust(-
int(rectAdjust), -
int(rectAdjust), rectAdjust, rectAdjust);
4703 item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
4704 drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
4705 : !viewBoundingRect.normalized().isEmpty();
4706 itemIsOutsideVisibleRect = !drawItem;
4709 if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
4715 if (!itemHasChildren)
4717 if (itemClipsChildrenToShape) {
4718 if (wasDirtyParentSceneTransform)
4719 item->d_ptr->invalidateChildrenSceneTransform();
4725 if (itemHasChildren && itemClipsChildrenToShape)
4728#if QT_CONFIG(graphicseffect)
4729 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
4730 ENSURE_TRANSFORM_PTR;
4731 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
4732 painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
4733 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
4734 QGraphicsItemEffectSourcePrivate *sourced =
static_cast<QGraphicsItemEffectSourcePrivate *>
4736 sourced->info = &info;
4737 const QTransform restoreTransform = painter->worldTransform();
4738 if (effectTransform)
4739 painter->setWorldTransform(*transformPtr * *effectTransform);
4741 painter->setWorldTransform(*transformPtr);
4742 painter->setOpacity(opacity);
4744 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
4745 && sourced->lastEffectTransform != painter->worldTransform())
4747 if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
4748 && painter->worldTransform().type() <= QTransform::TxTranslate)
4750 QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
4751 QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
4753 sourced->setCachedOffset(effectRect.topLeft());
4755 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
4758 sourced->lastEffectTransform = painter->worldTransform();
4761 item->d_ptr->graphicsEffect->draw(painter);
4762 painter->setWorldTransform(restoreTransform);
4763 sourced->info =
nullptr;
4767 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
4768 effectTransform, wasDirtyParentSceneTransform, drawItem);
4793void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter,
const QTransform *
const viewTransform,
4794 const QTransform *
const transformPtr, QRegion *exposedRegion, QWidget *widget,
4795 qreal opacity,
const QTransform *effectTransform,
4796 bool wasDirtyParentSceneTransform,
bool drawItem)
4798 const auto &children = item->d_ptr->children;
4800 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4801 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
4802 const bool itemHasChildren = !children.isEmpty();
4803 bool setChildClip = itemClipsChildrenToShape;
4804 bool itemHasChildrenStackedBehind =
false;
4807 if (itemHasChildren) {
4808 if (itemClipsChildrenToShape)
4809 setWorldTransform(painter, transformPtr, effectTransform);
4811 item->d_ptr->ensureSortedChildren();
4814 itemHasChildrenStackedBehind = (children.at(0)->d_ptr->flags
4815 & QGraphicsItem::ItemStacksBehindParent);
4817 if (itemHasChildrenStackedBehind) {
4818 if (itemClipsChildrenToShape) {
4819 setClip(painter, item);
4820 setChildClip =
false;
4824 for (i = 0; i < children.size(); ++i) {
4825 QGraphicsItem *child = children.at(i);
4826 if (wasDirtyParentSceneTransform)
4827 child->d_ptr->dirtySceneTransform = 1;
4828 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
4830 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4832 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4839 Q_ASSERT(!itemIsFullyTransparent);
4840 Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
4841 Q_ASSERT(transformPtr);
4842 item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
4843 ? *exposedRegion : QRegion(), exposedRegion ==
nullptr);
4845 const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
4846 bool restorePainterClip =
false;
4848 if (!itemHasChildren || !itemClipsChildrenToShape) {
4850 setWorldTransform(painter, transformPtr, effectTransform);
4851 if ((restorePainterClip = itemClipsToShape))
4852 setClip(painter, item);
4853 }
else if (itemHasChildrenStackedBehind){
4856 if (itemClipsToShape) {
4858 setWorldTransform(painter, transformPtr, effectTransform);
4862 setChildClip =
true;
4864 }
else if (itemClipsToShape) {
4868 setClip(painter, item);
4869 setChildClip =
false;
4872 if (painterStateProtection && !restorePainterClip)
4875 painter->setOpacity(opacity);
4876 if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
4877 item->paint(painter, &styleOptionTmp, widget);
4879 drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
4881 if (painterStateProtection || restorePainterClip)
4884 static int drawRect = qEnvironmentVariableIntValue(
"QT_DRAW_SCENE_ITEM_RECTS");
4886 QPen oldPen = painter->pen();
4887 QBrush oldBrush = painter->brush();
4888 quintptr ptr =
reinterpret_cast<quintptr>(item);
4889 const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
4890 painter->setPen(color);
4891 painter->setBrush(Qt::NoBrush);
4892 painter->drawRect(adjustedItemBoundingRect(item));
4893 painter->setPen(oldPen);
4894 painter->setBrush(oldBrush);
4899 if (itemHasChildren) {
4901 setClip(painter, item);
4903 for (; i < children.size(); ++i) {
4904 QGraphicsItem *child = children.at(i);
4905 if (wasDirtyParentSceneTransform)
4906 child->d_ptr->dirtySceneTransform = 1;
4907 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4909 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4913 if (itemClipsChildrenToShape)
4918void QGraphicsScenePrivate::markDirty(QGraphicsItem *item,
const QRectF &rect,
bool invalidateChildren,
4919 bool force,
bool ignoreOpacity,
bool removingItemFromScene,
4920 bool updateBoundingRect)
4926 if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
4934 QGraphicsItem *p = item->d_ptr->parent;
4936 if (p->d_ptr->ignoreOpacity) {
4937 item->d_ptr->ignoreOpacity =
true;
4940 p = p->d_ptr->parent;
4944 if (item->d_ptr->discardUpdateRequest(force,
4945 removingItemFromScene || invalidateChildren,
4947 if (item->d_ptr->dirty) {
4953 item->d_ptr->ignoreVisible = 1;
4955 item->d_ptr->ignoreOpacity = 1;
4960 const bool fullItemUpdate = rect.isNull();
4961 if (!fullItemUpdate && rect.isEmpty())
4964 if (!processDirtyItemsEmitted) {
4965 QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
4966 method.invoke(q_ptr, Qt::QueuedConnection);
4968 processDirtyItemsEmitted =
true;
4971 if (removingItemFromScene) {
4974 if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
4982 for (
auto view : std::as_const(views)) {
4983 QGraphicsViewPrivate *viewPrivate = view->d_func();
4984 QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
4985 rect.translate(viewPrivate->dirtyScrollOffset);
4986 viewPrivate->updateRect(rect);
4991 bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
4992 if (!hasNoContents) {
4993 item->d_ptr->dirty = 1;
4995 item->d_ptr->fullUpdatePending = 1;
4996 else if (!item->d_ptr->fullUpdatePending)
4997 item->d_ptr->needsRepaint |= rect;
4998 }
else if (item->d_ptr->graphicsEffect) {
4999 invalidateChildren =
true;
5002 if (invalidateChildren) {
5003 item->d_ptr->allChildrenDirty = 1;
5004 item->d_ptr->dirtyChildren = 1;
5008 item->d_ptr->ignoreVisible = 1;
5010 item->d_ptr->ignoreOpacity = 1;
5012 if (!updateBoundingRect)
5013 item->d_ptr->markParentDirty();
5053void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item,
bool dirtyAncestorContainsChildren,
5054 qreal parentOpacity)
5056 Q_Q(QGraphicsScene);
5058 Q_ASSERT(!updateAll);
5060 if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
5061 resetDirtyItem(item);
5065 const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
5067 resetDirtyItem(item,
true);
5071 bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
5072 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
5073 if (!itemHasContents) {
5074 if (!itemHasChildren) {
5075 resetDirtyItem(item);
5078 if (item->d_ptr->graphicsEffect)
5079 itemHasContents =
true;
5082 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
5083 const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
5084 && QGraphicsItemPrivate::isOpacityNull(opacity);
5085 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
5086 resetDirtyItem(item, itemHasChildren);
5090 bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
5091 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
5092 if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
5093 item->d_ptr->updateSceneTransformFromParent();
5094 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
5097 const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
5098 if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
5100 item->d_ptr->dirty = 0;
5101 item->d_ptr->fullUpdatePending = 0;
5103 if (itemIsFullyTransparent || !itemHasContents)
5104 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
5107 if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
5109 if (item->d_ptr->sceneTransformTranslateOnly) {
5110 growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
5111 item->d_ptr->sceneTransform.dy());
5113 growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
5118 if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5119 const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
5120 const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
5122 if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
5126 if (item->d_ptr->sceneTransformTranslateOnly) {
5127 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
5128 item->d_ptr->sceneTransform.dy()));
5130 QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
5131 if (!rect.isEmpty())
5136 bool uninitializedDirtyRect =
true;
5138 for (
auto view : std::as_const(views)) {
5139 QGraphicsViewPrivate *viewPrivate = view->d_func();
5140 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
5141 if (viewPrivate->fullUpdatePending
5142 || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
5146 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5150 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5151 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
5152 if (!viewPrivate->updateRect(paintedViewBoundingRect))
5153 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5156 if (!item->d_ptr->dirty)
5159 if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
5160 && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
5161 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
5165 if (uninitializedDirtyRect) {
5166 dirtyRect = itemBoundingRect;
5167 if (!item->d_ptr->fullUpdatePending) {
5168 _q_adjustRect(&item->d_ptr->needsRepaint);
5169 dirtyRect &= item->d_ptr->needsRepaint;
5171 uninitializedDirtyRect =
false;
5174 if (dirtyRect.isEmpty())
5177 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
5178 && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5179 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5186 if (itemHasChildren && item->d_ptr->dirtyChildren) {
5187 const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
5188 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
5193 const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
5194 if (itemClipsChildrenToShape && !bypassUpdateClip) {
5196 for (
auto view : std::as_const(views))
5197 view->d_func()->setUpdateClip(item);
5199 if (!dirtyAncestorContainsChildren) {
5200 dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
5201 && itemClipsChildrenToShape;
5203 const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
5204 const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
5205 const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
5206 for (
auto child : std::as_const(item->d_ptr->children)) {
5207 if (wasDirtyParentSceneTransform)
5208 child->d_ptr->dirtySceneTransform = 1;
5209 if (wasDirtyParentViewBoundingRects)
5210 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
5211 if (parentIgnoresVisible)
5212 child->d_ptr->ignoreVisible = 1;
5213 if (parentIgnoresOpacity)
5214 child->d_ptr->ignoreOpacity = 1;
5215 if (allChildrenDirty) {
5216 child->d_ptr->dirty = 1;
5217 child->d_ptr->fullUpdatePending = 1;
5218 child->d_ptr->dirtyChildren = 1;
5219 child->d_ptr->allChildrenDirty = 1;
5221 processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
5224 if (itemClipsChildrenToShape) {
5226 for (
auto view : std::as_const(views))
5227 view->d_func()->setUpdateClip(
nullptr);
5229 }
else if (wasDirtyParentSceneTransform) {
5230 item->d_ptr->invalidateChildrenSceneTransform();
5233 resetDirtyItem(item);
5327bool QGraphicsScene::focusNextPrevChild(
bool next)
5329 Q_D(QGraphicsScene);
5331 QGraphicsItem *item = focusItem();
5332 if (item && !item->isWidget()) {
5337 if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
5340 setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5343 if (d->activePanel) {
5344 if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) {
5345 setFocusItem(d->activePanel, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5348 if (d->activePanel->isWidget()) {
5349 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(d->activePanel);
5350 QGraphicsWidget *fw = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5352 if (fw->focusPolicy() & Qt::TabFocus) {
5353 setFocusItem(fw, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5356 fw = next ? fw->d_func()->focusNext : fw->d_func()->focusPrev;
5357 }
while (fw != d->activePanel);
5361 if (!item && !d->tabFocusFirst) {
5367 QGraphicsWidget *widget =
nullptr;
5369 widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
5371 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(item);
5372 widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5373 if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
5378 QGraphicsWidget *widgetThatHadFocus = widget;
5382 if (widget->flags() & QGraphicsItem::ItemIsFocusable
5383 && widget->isEnabled() && widget->isVisibleTo(
nullptr)
5384 && (widget->focusPolicy() & Qt::TabFocus)
5385 && (!item || !item->isPanel() || item->isAncestorOf(widget))
5387 setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5390 widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
5391 if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
5393 }
while (widget != widgetThatHadFocus);
5836void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
5838 typedef std::pair<QEventPoint::States, QList<QEventPoint> > StatesAndTouchPoints;
5839 QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
5841 const auto &touchPoints = sceneTouchEvent->points();
5842 for (
const auto &touchPoint : touchPoints) {
5844 QGraphicsItem *item =
nullptr;
5845 if (touchPoint.state() == QEventPoint::State::Pressed) {
5846 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
5848 item = itemForTouchPointId.isEmpty()
5850 : itemForTouchPointId.constBegin().value();
5855 cachedItemsUnderMouse = itemsAtPosition(touchPoint.globalPosition().toPoint(),
5856 touchPoint.scenePosition(),
5857 static_cast<QWidget *>(sceneTouchEvent->target()));
5858 item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.constFirst();
5861 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchScreen) {
5863 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePosition());
5864 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
5865 if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
5871 itemForTouchPointId.insert(touchPoint.id(), item);
5872 sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
5873 }
else if (touchPoint.state() == QEventPoint::State::Released) {
5874 item = itemForTouchPointId.take(touchPoint.id());
5878 sceneCurrentTouchPoints.remove(touchPoint.id());
5880 item = itemForTouchPointId.value(touchPoint.id());
5883 Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
5884 sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
5887 StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
5888 statesAndTouchPoints.first = QEventPoint::States(statesAndTouchPoints.first | touchPoint.state());
5889 statesAndTouchPoints.second.append(touchPoint);
5892 if (itemsNeedingEvents.isEmpty()) {
5893 sceneTouchEvent->ignore();
5897 bool ignoreSceneTouchEvent =
true;
5898 QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
5899 const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
5900 for (; it != end; ++it) {
5901 QGraphicsItem *item = it.key();
5903 (
void) item->isBlockedByModalPanel(&item);
5906 QEvent::Type eventType;
5907 switch (it.value().first) {
5908 case QEventPoint::State::Pressed:
5910 eventType = QEvent::TouchBegin;
5912 case QEventPoint::State::Released:
5914 eventType = QEvent::TouchEnd;
5916 case QEventPoint::State::Stationary:
5921 eventType = QEvent::TouchUpdate;
5925 QMutableTouchEvent touchEvent(eventType, sceneTouchEvent->pointingDevice(), sceneTouchEvent->modifiers(), it.value().second);
5926 touchEvent.setTarget(sceneTouchEvent->target());
5927 touchEvent.setModifiers(sceneTouchEvent->modifiers());
5928 touchEvent.setTimestamp(sceneTouchEvent->timestamp());
5930 switch (touchEvent.type()) {
5931 case QEvent::TouchBegin:
5935 item->d_ptr->acceptedTouchBeginEvent =
true;
5936 bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted();
5939 const auto &unhandledTouchPoints = touchEvent.points();
5940 for (
const auto &touchPoint : unhandledTouchPoints) {
5941 itemForTouchPointId.remove(touchPoint.id());
5942 sceneCurrentTouchPoints.remove(touchPoint.id());
5944 ignoreSceneTouchEvent =
false;
5949 if (item->d_ptr->acceptedTouchBeginEvent) {
5950 updateTouchPointsForItem(item, &touchEvent);
5951 (
void) sendEvent(item, &touchEvent);
5952 ignoreSceneTouchEvent =
false;
5958 sceneTouchEvent->QInputEvent::setAccepted(ignoreSceneTouchEvent);
5961bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
5963 Q_Q(QGraphicsScene);
5966 if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.constFirst() != origin) {
5967 const QEventPoint &firstTouchPoint = touchEvent->points().first();
5968 cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.globalPosition().toPoint(),
5969 firstTouchPoint.scenePosition(),
5970 static_cast<QWidget *>(touchEvent->target()));
5974 bool setFocus =
false;
5976 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
5977 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
5978 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
5980 if (item != q->focusItem())
5981 q->setFocusItem(item, Qt::MouseFocusReason);
5985 if (item->isPanel())
5987 if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
5989 if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
5997 if (!stickyFocus && !setFocus)
5998 q->setFocusItem(
nullptr, Qt::MouseFocusReason);
6002 bool eventAccepted = touchEvent->isAccepted();
6003 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
6005 updateTouchPointsForItem(item, touchEvent);
6006 bool acceptTouchEvents = item->acceptTouchEvents();
6007 touchEvent->setAccepted(acceptTouchEvents);
6008 res = acceptTouchEvents && sendEvent(item, touchEvent);
6009 eventAccepted = touchEvent->isAccepted();
6010 if (itemForTouchPointId.value(touchEvent->points().first().id()) == 0) {
6014 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
6016 touchEvent->m_spont =
false;
6017 if (res && eventAccepted) {
6019 const auto &touchPoints = touchEvent->points();
6020 for (
const auto &touchPoint : touchPoints)
6021 itemForTouchPointId[touchPoint.id()] = item;
6024 if (item && item->isPanel())
6029 touchEvent->QInputEvent::setAccepted(eventAccepted);
6185void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
6187 QWidget *viewport = event->widget();
6190 QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
6194 const QList<QGesture *> allGestures = event->gestures();
6195 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6196 <<
"Gestures:" << allGestures;
6198 QSet<QGesture *> startedGestures;
6199 QPoint delta = viewport->mapFromGlobal(QPoint());
6200 QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
6201 * graphicsView->viewportTransform().inverted();
6202 for (QGesture *gesture : allGestures) {
6204 if (gesture->hasHotSpot()) {
6205 gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
6207 gesture->d_func()->sceneHotSpot = QPointF();
6210 QGraphicsObject *target = gestureTargets.value(gesture, 0);
6214 if (gesture->state() == Qt::GestureStarted)
6215 startedGestures.insert(gesture);
6219 if (!startedGestures.isEmpty()) {
6220 QSet<QGesture *> normalGestures;
6221 QSet<QGesture *> conflictedGestures;
6222 gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures,
nullptr,
6223 &normalGestures, &conflictedGestures);
6224 cachedTargetItems = cachedItemGestures.keys();
6225 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6226 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6227 <<
"Normal gestures:" << normalGestures
6228 <<
"Conflicting gestures:" << conflictedGestures;
6232 if (!conflictedGestures.isEmpty()) {
6233 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6234 QPointer<QGraphicsObject> item = cachedTargetItems.at(i);
6237 const QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
6238 if (gestures.isEmpty())
6241 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6242 <<
"delivering override to"
6243 << item.data() << gestures;
6245 QGestureEvent ev(gestures.values());
6246 ev.t = QEvent::GestureOverride;
6247 ev.setWidget(event->widget());
6250 for (QGesture *g : gestures)
6251 ev.setAccepted(g,
false);
6252 sendEvent(item.data(), &ev);
6254 for (QGesture *g : gestures) {
6255 if (ev.isAccepted() || ev.isAccepted(g)) {
6256 conflictedGestures.remove(g);
6259 gestureTargets.insert(g, item.data());
6260 QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e;
6261 it = cachedItemGestures.begin();
6262 e = cachedItemGestures.end();
6263 for(; it != e; ++it)
6264 it.value().remove(g);
6265 cachedItemGestures[item.data()].insert(g);
6267 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6268 <<
"override was accepted:"
6269 << g << item.data();
6274 if (!gestureTargets.contains(g) && item)
6275 gestureTargets.insert(g, item.data());
6278 if (conflictedGestures.isEmpty())
6284 if (!normalGestures.isEmpty()) {
6285 for (
int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
6286 QGraphicsObject *item = cachedTargetItems.at(i);
6289 const auto gestures = cachedItemGestures.value(item);
6290 for (QGesture *g : gestures) {
6291 if (!gestureTargets.contains(g)) {
6292 gestureTargets.insert(g, item);
6293 normalGestures.remove(g);
6302 QSet<QGesture *> undeliveredGestures;
6303 QSet<QGesture *> parentPropagatedGestures;
6304 for (QGesture *gesture : allGestures) {
6305 if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
6306 cachedItemGestures[target].insert(gesture);
6307 cachedTargetItems.append(target);
6308 undeliveredGestures.insert(gesture);
6309 QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
6310 const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
6311 if (flags & Qt::IgnoredGesturesPropagateToParent)
6312 parentPropagatedGestures.insert(gesture);
6314 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6315 <<
"no target for" << gesture <<
"at"
6316 << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
6319 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6320 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6321 QPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
6322 const QSet<QGesture *> gestures = (undeliveredGestures
6323 & cachedItemGestures.value(receiver.data()))
6324 - cachedAlreadyDeliveredGestures.value(receiver.data());
6326 if (gestures.isEmpty())
6329 cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
6330 const bool isPanel = receiver.data()->isPanel();
6332 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6334 << receiver.data() << gestures;
6335 QGestureEvent ev(gestures.values());
6336 ev.setWidget(event->widget());
6337 sendEvent(receiver.data(), &ev);
6338 QSet<QGesture *> ignoredGestures;
6339 for (QGesture *g : gestures) {
6340 if (!ev.isAccepted() && !ev.isAccepted(g)) {
6346 if (receiver && receiver.data() == gestureTargets.value(g, 0))
6347 ignoredGestures.insert(g);
6349 if (receiver && g->state() == Qt::GestureStarted) {
6352 gestureTargets[g] = receiver.data();
6354 undeliveredGestures.remove(g);
6357 if (undeliveredGestures.isEmpty())
6362 if (!ignoredGestures.isEmpty() && !isPanel) {
6366 QSet<QGraphicsObject *> targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd());
6370 for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
6371 it != ignoredGestures.end();) {
6372 if (parentPropagatedGestures.contains(*it)) {
6373 QGesture *gesture = *it;
6374 const Qt::GestureType gestureType = gesture->gestureType();
6375 QGraphicsItem *item = receiver.data();
6377 if (QGraphicsObject *obj = item->toGraphicsObject()) {
6378 if (item->d_func()->gestureContext.contains(gestureType)) {
6379 targetsSet.insert(obj);
6380 cachedItemGestures[obj].insert(gesture);
6383 if (item->isPanel())
6385 item = item->parentItem();
6388 it = ignoredGestures.erase(it);
6395 gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
6396 &cachedItemGestures, &targetsSet,
nullptr,
nullptr);
6398 cachedTargetItems = targetsSet.values();
6399 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6400 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6401 <<
"new targets:" << cachedTargetItems;
6407 for (QGesture *g : std::as_const(startedGestures)) {
6408 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
6409 DEBUG() <<
"lets try to cancel some";
6411 cancelGesturesForChildren(g);
6416 for (QGesture *g : allGestures) {
6417 switch (g->state()) {
6418 case Qt::GestureFinished:
6419 case Qt::GestureCanceled:
6420 gestureTargets.remove(g);
6427 cachedTargetItems.clear();
6428 cachedItemGestures.clear();
6429 cachedAlreadyDeliveredGestures.clear();
6432void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
6435 QGraphicsItem *originalItem = gestureTargets.value(original);
6436 if (originalItem ==
nullptr)
6442 QSet<QGesture *> canceledGestures;
6443 QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin();
6444 while (iter != gestureTargets.end()) {
6445 QGraphicsObject *item = iter.value();
6447 if (item != originalItem && originalItem->isAncestorOf(item)) {
6448 DEBUG() <<
" found a gesture to cancel" << iter.key();
6449 iter.key()->d_func()->state = Qt::GestureCanceled;
6450 canceledGestures << iter.key();
6456 QSet<QGesture *> almostCanceledGestures = canceledGestures;
6457 QSet<QGesture *>::Iterator setIter;
6458 while (!almostCanceledGestures.isEmpty()) {
6459 QGraphicsObject *target =
nullptr;
6460 QSet<QGesture*> gestures;
6461 setIter = almostCanceledGestures.begin();
6463 while (setIter != almostCanceledGestures.end()) {
6464 QGraphicsObject *item = gestureTargets.value(*setIter);
6465 if (target ==
nullptr)
6467 if (target == item) {
6468 gestures << *setIter;
6469 setIter = almostCanceledGestures.erase(setIter);
6476 const QList<QGesture *> list = gestures.values();
6477 QGestureEvent ev(list);
6478 sendEvent(target, &ev);
6480 if (!ev.isAccepted()) {
6481 for (QGesture *g : list) {
6483 if (ev.isAccepted(g))
6486 if (!g->hasHotSpot())
6489 const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot,
nullptr);
6490 for (
const auto &item : items) {
6491 QGraphicsObject *object = item->toGraphicsObject();
6494 QGraphicsItemPrivate *d = object->QGraphicsItem::d_func();
6495 if (d->gestureContext.contains(g->gestureType())) {
6496 QList<QGesture *> list;
6498 QGestureEvent ev(list);
6499 sendEvent(object, &ev);
6500 if (ev.isAccepted() || ev.isAccepted(g))
6508 QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
6509 Q_ASSERT(gestureManager);
6510 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
6511 gestureManager->recycle(*setIter);
6512 gestureTargets.remove(*setIter);