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();
3239bool QGraphicsScene::event(QEvent *event)
3241 Q_D(QGraphicsScene);
3243 switch (event->type()) {
3244 case QEvent::GraphicsSceneMousePress:
3245 case QEvent::GraphicsSceneMouseMove:
3246 case QEvent::GraphicsSceneMouseRelease:
3247 case QEvent::GraphicsSceneMouseDoubleClick:
3248 case QEvent::GraphicsSceneHoverEnter:
3249 case QEvent::GraphicsSceneHoverLeave:
3250 case QEvent::GraphicsSceneHoverMove:
3251 case QEvent::TouchBegin:
3252 case QEvent::TouchUpdate:
3253 case QEvent::TouchEnd:
3261 d->cachedItemsUnderMouse.clear();
3267 switch (event->type()) {
3268 case QEvent::GraphicsSceneDragEnter:
3269 dragEnterEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3271 case QEvent::GraphicsSceneDragMove:
3272 dragMoveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3274 case QEvent::GraphicsSceneDragLeave:
3275 dragLeaveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3277 case QEvent::GraphicsSceneDrop:
3278 dropEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3280 case QEvent::GraphicsSceneContextMenu:
3281 contextMenuEvent(
static_cast<QGraphicsSceneContextMenuEvent *>(event));
3283 case QEvent::KeyPress:
3284 if (!d->focusItem) {
3285 QKeyEvent *k =
static_cast<QKeyEvent *>(event);
3286 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
3287 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {
3289 if (k->key() == Qt::Key_Backtab
3290 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
3291 res = focusNextPrevChild(
false);
3292 }
else if (k->key() == Qt::Key_Tab) {
3293 res = focusNextPrevChild(
true);
3301 keyPressEvent(
static_cast<QKeyEvent *>(event));
3303 case QEvent::KeyRelease:
3304 keyReleaseEvent(
static_cast<QKeyEvent *>(event));
3306 case QEvent::ShortcutOverride: {
3307 QGraphicsItem *parent = focusItem();
3309 d->sendEvent(parent, event);
3310 if (event->isAccepted())
3312 parent = parent->parentItem();
3316 case QEvent::GraphicsSceneMouseMove:
3318 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *>(event);
3319 d->lastSceneMousePos = mouseEvent->scenePos();
3320 mouseMoveEvent(mouseEvent);
3323 case QEvent::GraphicsSceneMousePress:
3324 mousePressEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3326 case QEvent::GraphicsSceneMouseRelease:
3327 mouseReleaseEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3329 case QEvent::GraphicsSceneMouseDoubleClick:
3330 mouseDoubleClickEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3332 case QEvent::GraphicsSceneWheel:
3333 wheelEvent(
static_cast<QGraphicsSceneWheelEvent *>(event));
3335 case QEvent::FocusIn:
3336 focusInEvent(
static_cast<QFocusEvent *>(event));
3338 case QEvent::FocusOut:
3339 focusOutEvent(
static_cast<QFocusEvent *>(event));
3341 case QEvent::GraphicsSceneHoverEnter:
3342 case QEvent::GraphicsSceneHoverLeave:
3343 case QEvent::GraphicsSceneHoverMove:
3345 QGraphicsSceneHoverEvent *hoverEvent =
static_cast<QGraphicsSceneHoverEvent *>(event);
3346 d->lastSceneMousePos = hoverEvent->scenePos();
3347 d->dispatchHoverEvent(hoverEvent);
3351 Q_ASSERT_X(
false,
"QGraphicsScene::event",
3352 "QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
3354 case QEvent::GraphicsSceneLeave:
3356 auto *leaveEvent =
static_cast<QGraphicsSceneEvent*>(event);
3357 d->leaveScene(leaveEvent->widget());
3360 case QEvent::GraphicsSceneHelp:
3361 helpEvent(
static_cast<QGraphicsSceneHelpEvent *>(event));
3363 case QEvent::InputMethod:
3364 inputMethodEvent(
static_cast<QInputMethodEvent *>(event));
3366 case QEvent::WindowActivate:
3367 if (!d->activationRefCount++) {
3368 if (d->lastActivePanel) {
3370 d->setActivePanelHelper(d->lastActivePanel,
true);
3371 }
else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
3374 d->setActivePanelHelper(d->tabFocusFirst,
true);
3377 QEvent event(QEvent::WindowActivate);
3378 const auto items_ = items();
3379 for (QGraphicsItem *item : items_) {
3380 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3381 sendEvent(item, &event);
3386 case QEvent::WindowDeactivate:
3387 if (!--d->activationRefCount) {
3388 if (d->activePanel) {
3391 QGraphicsItem *lastActivePanel = d->activePanel;
3392 d->setActivePanelHelper(
nullptr,
true);
3393 d->lastActivePanel = lastActivePanel;
3396 QEvent event(QEvent::WindowDeactivate);
3397 const auto items_ = items();
3398 for (QGraphicsItem *item : items_) {
3399 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3400 sendEvent(item, &event);
3405 case QEvent::ApplicationFontChange: {
3410 case QEvent::FontChange:
3414 case QEvent::ApplicationPaletteChange: {
3416 d->resolvePalette();
3419 case QEvent::PaletteChange:
3423 case QEvent::StyleChange:
3428 case QEvent::StyleAnimationUpdate:
3433 case QEvent::TouchBegin:
3434 case QEvent::TouchUpdate:
3435 case QEvent::TouchEnd:
3436 d->touchEventHandler(
static_cast<QTouchEvent *>(event));
3438#ifndef QT_NO_GESTURES
3439 case QEvent::Gesture:
3440 case QEvent::GestureOverride:
3441 d->gestureEventHandler(
static_cast<QGestureEvent *>(event));
3445 return QObject::event(event);
3535void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
3537 Q_D(QGraphicsScene);
3540 if (!d->mouseGrabberItems.isEmpty()) {
3542 d->clearMouseGrabber();
3543 d->mouseGrabberButtonDownPos.clear();
3544 d->mouseGrabberButtonDownScenePos.clear();
3545 d->mouseGrabberButtonDownScreenPos.clear();
3548 bool eventDelivered =
false;
3552 const auto items = d->itemsAtPosition(event->screenPos(),
3555 for (QGraphicsItem *item : items) {
3556 if (!item->isEnabled() || !item->acceptDrops())
3559 if (item != d->dragDropItem) {
3562 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
3563 d->cloneDragDropEvent(&dragEnter, event);
3564 dragEnter.setDropAction(event->proposedAction());
3565 d->sendDragDropEvent(item, &dragEnter);
3566 event->setAccepted(dragEnter.isAccepted());
3567 event->setDropAction(dragEnter.dropAction());
3568 if (!event->isAccepted()) {
3573 d->lastDropAction = event->dropAction();
3575 if (d->dragDropItem) {
3580 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3581 d->cloneDragDropEvent(&dragLeave, event);
3582 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3586 d->dragDropItem = item;
3590 event->setDropAction(d->lastDropAction);
3592 d->sendDragDropEvent(item, event);
3593 if (event->isAccepted())
3594 d->lastDropAction = event->dropAction();
3595 eventDelivered =
true;
3599 if (!eventDelivered) {
3600 if (d->dragDropItem) {
3602 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3603 d->cloneDragDropEvent(&dragLeave, event);
3604 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3605 d->dragDropItem =
nullptr;
3608 event->setDropAction(Qt::IgnoreAction);
3769bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
3771 if (allItemsIgnoreHoverEvents)
3776 if (cachedItemsUnderMouse.isEmpty()) {
3777 cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(),
3778 hoverEvent->scenePos(),
3779 hoverEvent->widget());
3782 QGraphicsItem *item =
nullptr;
3783 for (
auto tmp : std::as_const(cachedItemsUnderMouse)) {
3784 if (itemAcceptsHoverEvents_helper(tmp)) {
3792 QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.constLast()) :
nullptr;
3793 while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
3794 commonAncestorItem = commonAncestorItem->parentItem();
3795 if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
3798 commonAncestorItem =
nullptr;
3802 int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
3805 for (
int i = hoverItems.size() - 1; i > index; --i) {
3806 QGraphicsItem *lastItem = hoverItems.takeLast();
3807 if (itemAcceptsHoverEvents_helper(lastItem))
3808 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
3813 QList<QGraphicsItem *> parents;
3814 QGraphicsItem *parent = item;
3815 while (parent && parent != commonAncestorItem) {
3816 parents.append(parent);
3817 if (parent->isPanel()) {
3821 parent = parent->parentItem();
3823 for (
auto it = parents.crbegin(), end = parents.crend(); it != end; ++it) {
3824 QGraphicsItem *parent = *it;
3825 hoverItems << parent;
3826 if (itemAcceptsHoverEvents_helper(parent))
3827 sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent);
3832 && !hoverItems.isEmpty()
3833 && item == hoverItems.constLast()) {
3834 sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
4310void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter,
4311 const QStyleOptionGraphicsItem *option, QWidget *widget,
4312 bool painterStateProtection)
4314 QGraphicsItemPrivate *itemd = item->d_ptr.data();
4315 QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
4318 if (cacheMode == QGraphicsItem::NoCache) {
4319 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
true, painterStateProtection);
4323 const qreal devicePixelRatio = painter->device()->devicePixelRatio();
4324 const qreal oldPainterOpacity = painter->opacity();
4325 qreal newPainterOpacity = oldPainterOpacity;
4326 QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(
static_cast<QGraphicsWidget *>(item)) : 0;
4327 if (proxy && proxy->widget()) {
4328 const qreal windowOpacity = proxy->widget()->windowOpacity();
4329 if (windowOpacity < 1.0)
4330 newPainterOpacity *= windowOpacity;
4334 QRectF brect = item->boundingRect();
4335 QRectF adjustedBrect(brect);
4336 _q_adjustRect(&adjustedBrect);
4337 if (adjustedBrect.isEmpty())
4341 QPixmapCache::Key pixmapKey;
4345 QGraphicsItemCache *itemCache = itemd->extraItemCache();
4346 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4347 pixmapKey = itemCache->key;
4349 pixmapKey = itemCache->deviceData.value(widget).key;
4353 pixmapFound = QPixmapCache::find(pixmapKey, &pix);
4356 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4358 bool fixedCacheSize = itemCache->fixedSize.isValid();
4359 QRect br = brect.toAlignedRect();
4360 if (fixedCacheSize) {
4361 pixmapSize = itemCache->fixedSize;
4363 pixmapSize = br.size();
4366 pixmapSize *= devicePixelRatio;
4369 int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
4370 QSize adjustSize(adjust*2, adjust*2);
4371 br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
4372 if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
4373 pix = QPixmap(pixmapSize + adjustSize);
4374 itemCache->boundingRect = br;
4375 itemCache->exposed.clear();
4376 itemCache->allExposed =
true;
4377 }
else if (itemCache->boundingRect != br) {
4378 itemCache->boundingRect = br;
4379 itemCache->exposed.clear();
4380 itemCache->allExposed =
true;
4384 if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
4389 QPixmapCache::remove(pixmapKey);
4392 QTransform itemToPixmap;
4393 if (fixedCacheSize) {
4394 const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
4395 (pixmapSize.height() / devicePixelRatio) / brect.height());
4396 itemToPixmap.scale(scale.x(), scale.y());
4398 itemToPixmap.translate(-br.x(), -br.y());
4402 styleOptionTmp = *option;
4403 QRegion pixmapExposed;
4405 if (!itemCache->allExposed) {
4406 for (
const auto &rect : std::as_const(itemCache->exposed)) {
4407 exposedRect |= rect;
4408 pixmapExposed += itemToPixmap.mapRect(rect).toAlignedRect();
4411 exposedRect = brect;
4413 styleOptionTmp.exposedRect = exposedRect;
4416 pix.setDevicePixelRatio(devicePixelRatio);
4417 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4418 &styleOptionTmp, painterStateProtection);
4421 itemCache->key = QPixmapCache::insert(pix);
4424 itemCache->allExposed =
false;
4425 itemCache->exposed.clear();
4431 if (newPainterOpacity != oldPainterOpacity) {
4432 painter->setOpacity(newPainterOpacity);
4433 painter->drawPixmap(br.topLeft(), pix);
4434 painter->setOpacity(oldPainterOpacity);
4436 painter->drawPixmap(br.topLeft(), pix);
4442 if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
4444 QRectF deviceBounds = painter->worldTransform().mapRect(brect);
4445 QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
4446 if (deviceRect.isEmpty())
4448 QRect viewRect = widget ? widget->rect() : QRect();
4449 if (widget && !viewRect.intersects(deviceRect))
4454 QSize maximumCacheSize =
4455 itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
4456 if (!maximumCacheSize.isEmpty()
4457 && (deviceRect.width() > maximumCacheSize.width()
4458 || deviceRect.height() > maximumCacheSize.height())) {
4459 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
4460 oldPainterOpacity != newPainterOpacity, painterStateProtection);
4467 bool pixModified =
false;
4468 QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
4469 bool invertable =
true;
4470 QTransform diff = deviceData->lastTransform.inverted(&invertable);
4472 diff *= painter->worldTransform();
4473 deviceData->lastTransform = painter->worldTransform();
4474 bool allowPartialCacheExposure =
false;
4475 bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
4476 && transformIsSimple(painter->worldTransform());
4477 if (!simpleTransform) {
4479 itemCache->allExposed =
true;
4480 itemCache->exposed.clear();
4481 deviceData->cacheIndent = QPoint();
4483 }
else if (!viewRect.isNull()) {
4484 allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
4489 if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
4490 allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
4491 || (viewRect.height() * 1.2 < deviceRect.height());
4494 QRegion scrollExposure;
4495 if (allowPartialCacheExposure) {
4500 int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
4501 int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
4502 QPoint newCacheIndent(dx, dy);
4503 deviceRect &= viewRect;
4506 deviceData->cacheIndent = QPoint();
4507 itemCache->allExposed =
true;
4508 itemCache->exposed.clear();
4514 if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
4515 QPoint diff = newCacheIndent - deviceData->cacheIndent;
4516 QPixmap newPix(deviceRect.size() * devicePixelRatio);
4519 newPix.fill(Qt::transparent);
4520 if (!pix.isNull()) {
4521 newPix.setDevicePixelRatio(devicePixelRatio);
4522 QPainter newPixPainter(&newPix);
4523 newPixPainter.drawPixmap(-diff, pix);
4524 newPixPainter.end();
4527 exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
4529 exposed -= QRect(-diff, pix.size() / devicePixelRatio);
4530 scrollExposure = exposed;
4535 deviceData->cacheIndent = newCacheIndent;
4538 deviceData->cacheIndent = QPoint();
4541 if (deviceRect.size() != pix.size() / devicePixelRatio) {
4543 pix = QPixmap(deviceRect.size() * devicePixelRatio);
4545 itemCache->allExposed =
true;
4546 itemCache->exposed.clear();
4551 if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
4555 QPixmapCache::remove(pixmapKey);
4558 QPointF p = deviceRect.topLeft();
4559 QTransform itemToPixmap = painter->worldTransform();
4561 itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
4564 QRegion pixmapExposed = scrollExposure;
4565 if (!itemCache->allExposed) {
4566 for (
const auto &rect : std::as_const(itemCache->exposed))
4567 pixmapExposed += itemToPixmap.mapRect(rect).toRect().adjusted(-1, -1, 1, 1);
4572 if (itemCache->allExposed) {
4573 br = item->boundingRect();
4575 for (
const auto &rect : std::as_const(itemCache->exposed))
4577 QTransform pixmapToItem = itemToPixmap.inverted();
4578 for (
const QRect &r : std::as_const(scrollExposure))
4579 br |= pixmapToItem.mapRect(r);
4581 styleOptionTmp = *option;
4582 styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
4585 pix.setDevicePixelRatio(devicePixelRatio);
4586 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4587 &styleOptionTmp, painterStateProtection);
4591 itemCache->allExposed =
false;
4592 itemCache->exposed.clear();
4597 deviceData->key = QPixmapCache::insert(pix);
4602 QTransform restoreTransform = painter->worldTransform();
4603 painter->setWorldTransform(QTransform());
4604 if (newPainterOpacity != oldPainterOpacity) {
4605 painter->setOpacity(newPainterOpacity);
4606 painter->drawPixmap(deviceRect.topLeft(), pix);
4607 painter->setOpacity(oldPainterOpacity);
4609 painter->drawPixmap(deviceRect.topLeft(), pix);
4611 painter->setWorldTransform(restoreTransform);
4635void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
4636 const QTransform *
const viewTransform,
4637 QRegion *exposedRegion, QWidget *widget,
4638 qreal parentOpacity,
const QTransform *
const effectTransform)
4642 if (!item->d_ptr->visible)
4645 const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
4646 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
4647 if (!itemHasContents && !itemHasChildren)
4650 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
4651 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4652 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
4655 QTransform transform(Qt::Uninitialized);
4656 QTransform *transformPtr =
nullptr;
4657 bool translateOnlyTransform =
false;
4658#define ENSURE_TRANSFORM_PTR
4659 if (!transformPtr) {
4660 Q_ASSERT(!itemIsUntransformable);
4661 if (viewTransform) {
4662 transform = item->d_ptr->sceneTransform;
4663 transform *= *viewTransform;
4664 transformPtr = &transform;
4666 transformPtr = &item->d_ptr->sceneTransform;
4667 translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly;
4673 bool wasDirtyParentSceneTransform =
false;
4674 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
4675 if (itemIsUntransformable) {
4676 transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
4677 transformPtr = &transform;
4678 }
else if (item->d_ptr->dirtySceneTransform) {
4679 item->d_ptr->updateSceneTransformFromParent();
4680 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
4681 wasDirtyParentSceneTransform =
true;
4684 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
4685 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
4686 bool drawItem = itemHasContents && !itemIsFullyTransparent;
4687 if (drawItem || minimumRenderSize > 0.0) {
4688 const QRectF brect = adjustedItemEffectiveBoundingRect(item);
4690 QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
4691 : transformPtr->mapRect(brect);
4693 bool itemIsTooSmallToRender =
false;
4694 if (minimumRenderSize > 0.0
4695 && (preciseViewBoundingRect.width() < minimumRenderSize
4696 || preciseViewBoundingRect.height() < minimumRenderSize)) {
4697 itemIsTooSmallToRender =
true;
4701 bool itemIsOutsideVisibleRect =
false;
4703 QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
4704 viewBoundingRect.adjust(-
int(rectAdjust), -
int(rectAdjust), rectAdjust, rectAdjust);
4706 item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
4707 drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
4708 : !viewBoundingRect.normalized().isEmpty();
4709 itemIsOutsideVisibleRect = !drawItem;
4712 if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
4718 if (!itemHasChildren)
4720 if (itemClipsChildrenToShape) {
4721 if (wasDirtyParentSceneTransform)
4722 item->d_ptr->invalidateChildrenSceneTransform();
4728 if (itemHasChildren && itemClipsChildrenToShape)
4731#if QT_CONFIG(graphicseffect)
4732 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
4733 ENSURE_TRANSFORM_PTR;
4734 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
4735 painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
4736 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
4737 QGraphicsItemEffectSourcePrivate *sourced =
static_cast<QGraphicsItemEffectSourcePrivate *>
4739 sourced->info = &info;
4740 const QTransform restoreTransform = painter->worldTransform();
4741 if (effectTransform)
4742 painter->setWorldTransform(*transformPtr * *effectTransform);
4744 painter->setWorldTransform(*transformPtr);
4745 painter->setOpacity(opacity);
4747 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
4748 && sourced->lastEffectTransform != painter->worldTransform())
4750 if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
4751 && painter->worldTransform().type() <= QTransform::TxTranslate)
4753 QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
4754 QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
4756 sourced->setCachedOffset(effectRect.topLeft());
4758 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
4761 sourced->lastEffectTransform = painter->worldTransform();
4764 item->d_ptr->graphicsEffect->draw(painter);
4765 painter->setWorldTransform(restoreTransform);
4766 sourced->info =
nullptr;
4770 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
4771 effectTransform, wasDirtyParentSceneTransform, drawItem);
4796void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter,
const QTransform *
const viewTransform,
4797 const QTransform *
const transformPtr, QRegion *exposedRegion, QWidget *widget,
4798 qreal opacity,
const QTransform *effectTransform,
4799 bool wasDirtyParentSceneTransform,
bool drawItem)
4801 const auto &children = item->d_ptr->children;
4803 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4804 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
4805 const bool itemHasChildren = !children.isEmpty();
4806 bool setChildClip = itemClipsChildrenToShape;
4807 bool itemHasChildrenStackedBehind =
false;
4810 if (itemHasChildren) {
4811 if (itemClipsChildrenToShape)
4812 setWorldTransform(painter, transformPtr, effectTransform);
4814 item->d_ptr->ensureSortedChildren();
4817 itemHasChildrenStackedBehind = (children.at(0)->d_ptr->flags
4818 & QGraphicsItem::ItemStacksBehindParent);
4820 if (itemHasChildrenStackedBehind) {
4821 if (itemClipsChildrenToShape) {
4822 setClip(painter, item);
4823 setChildClip =
false;
4827 for (i = 0; i < children.size(); ++i) {
4828 QGraphicsItem *child = children.at(i);
4829 if (wasDirtyParentSceneTransform)
4830 child->d_ptr->dirtySceneTransform = 1;
4831 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
4833 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4835 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4842 Q_ASSERT(!itemIsFullyTransparent);
4843 Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
4844 Q_ASSERT(transformPtr);
4845 item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
4846 ? *exposedRegion : QRegion(), exposedRegion ==
nullptr);
4848 const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
4849 bool restorePainterClip =
false;
4851 if (!itemHasChildren || !itemClipsChildrenToShape) {
4853 setWorldTransform(painter, transformPtr, effectTransform);
4854 if ((restorePainterClip = itemClipsToShape))
4855 setClip(painter, item);
4856 }
else if (itemHasChildrenStackedBehind){
4859 if (itemClipsToShape) {
4861 setWorldTransform(painter, transformPtr, effectTransform);
4865 setChildClip =
true;
4867 }
else if (itemClipsToShape) {
4871 setClip(painter, item);
4872 setChildClip =
false;
4875 if (painterStateProtection && !restorePainterClip)
4878 painter->setOpacity(opacity);
4879 if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
4880 item->paint(painter, &styleOptionTmp, widget);
4882 drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
4884 if (painterStateProtection || restorePainterClip)
4887 static int drawRect = qEnvironmentVariableIntValue(
"QT_DRAW_SCENE_ITEM_RECTS");
4889 QPen oldPen = painter->pen();
4890 QBrush oldBrush = painter->brush();
4891 quintptr ptr =
reinterpret_cast<quintptr>(item);
4892 const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
4893 painter->setPen(color);
4894 painter->setBrush(Qt::NoBrush);
4895 painter->drawRect(adjustedItemBoundingRect(item));
4896 painter->setPen(oldPen);
4897 painter->setBrush(oldBrush);
4902 if (itemHasChildren) {
4904 setClip(painter, item);
4906 for (; i < children.size(); ++i) {
4907 QGraphicsItem *child = children.at(i);
4908 if (wasDirtyParentSceneTransform)
4909 child->d_ptr->dirtySceneTransform = 1;
4910 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4912 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4916 if (itemClipsChildrenToShape)
4921void QGraphicsScenePrivate::markDirty(QGraphicsItem *item,
const QRectF &rect,
bool invalidateChildren,
4922 bool force,
bool ignoreOpacity,
bool removingItemFromScene,
4923 bool updateBoundingRect)
4929 if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
4937 QGraphicsItem *p = item->d_ptr->parent;
4939 if (p->d_ptr->ignoreOpacity) {
4940 item->d_ptr->ignoreOpacity =
true;
4943 p = p->d_ptr->parent;
4947 if (item->d_ptr->discardUpdateRequest(force,
4948 removingItemFromScene || invalidateChildren,
4950 if (item->d_ptr->dirty) {
4956 item->d_ptr->ignoreVisible = 1;
4958 item->d_ptr->ignoreOpacity = 1;
4963 const bool fullItemUpdate = rect.isNull();
4964 if (!fullItemUpdate && rect.isEmpty())
4967 if (!processDirtyItemsEmitted) {
4968 QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
4969 method.invoke(q_ptr, Qt::QueuedConnection);
4971 processDirtyItemsEmitted =
true;
4974 if (removingItemFromScene) {
4977 if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
4985 for (
auto view : std::as_const(views)) {
4986 QGraphicsViewPrivate *viewPrivate = view->d_func();
4987 QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
4988 rect.translate(viewPrivate->dirtyScrollOffset);
4989 viewPrivate->updateRect(rect);
4994 bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
4995 if (!hasNoContents) {
4996 item->d_ptr->dirty = 1;
4998 item->d_ptr->fullUpdatePending = 1;
4999 else if (!item->d_ptr->fullUpdatePending)
5000 item->d_ptr->needsRepaint |= rect;
5001 }
else if (item->d_ptr->graphicsEffect) {
5002 invalidateChildren =
true;
5005 if (invalidateChildren) {
5006 item->d_ptr->allChildrenDirty = 1;
5007 item->d_ptr->dirtyChildren = 1;
5011 item->d_ptr->ignoreVisible = 1;
5013 item->d_ptr->ignoreOpacity = 1;
5015 if (!updateBoundingRect)
5016 item->d_ptr->markParentDirty();
5056void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item,
bool dirtyAncestorContainsChildren,
5057 qreal parentOpacity)
5059 Q_Q(QGraphicsScene);
5061 Q_ASSERT(!updateAll);
5063 if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
5064 resetDirtyItem(item);
5068 const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
5070 resetDirtyItem(item,
true);
5074 bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
5075 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
5076 if (!itemHasContents) {
5077 if (!itemHasChildren) {
5078 resetDirtyItem(item);
5081 if (item->d_ptr->graphicsEffect)
5082 itemHasContents =
true;
5085 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
5086 const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
5087 && QGraphicsItemPrivate::isOpacityNull(opacity);
5088 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
5089 resetDirtyItem(item, itemHasChildren);
5093 bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
5094 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
5095 if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
5096 item->d_ptr->updateSceneTransformFromParent();
5097 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
5100 const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
5101 if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
5103 item->d_ptr->dirty = 0;
5104 item->d_ptr->fullUpdatePending = 0;
5106 if (itemIsFullyTransparent || !itemHasContents)
5107 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
5110 if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
5112 if (item->d_ptr->sceneTransformTranslateOnly) {
5113 growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
5114 item->d_ptr->sceneTransform.dy());
5116 growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
5121 if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5122 const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
5123 const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
5125 if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
5129 if (item->d_ptr->sceneTransformTranslateOnly) {
5130 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
5131 item->d_ptr->sceneTransform.dy()));
5133 QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
5134 if (!rect.isEmpty())
5139 bool uninitializedDirtyRect =
true;
5141 for (
auto view : std::as_const(views)) {
5142 QGraphicsViewPrivate *viewPrivate = view->d_func();
5143 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
5144 if (viewPrivate->fullUpdatePending
5145 || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
5149 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5153 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5154 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
5155 if (!viewPrivate->updateRect(paintedViewBoundingRect))
5156 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5159 if (!item->d_ptr->dirty)
5162 if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
5163 && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
5164 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
5168 if (uninitializedDirtyRect) {
5169 dirtyRect = itemBoundingRect;
5170 if (!item->d_ptr->fullUpdatePending) {
5171 _q_adjustRect(&item->d_ptr->needsRepaint);
5172 dirtyRect &= item->d_ptr->needsRepaint;
5174 uninitializedDirtyRect =
false;
5177 if (dirtyRect.isEmpty())
5180 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
5181 && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5182 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5189 if (itemHasChildren && item->d_ptr->dirtyChildren) {
5190 const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
5191 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
5196 const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
5197 if (itemClipsChildrenToShape && !bypassUpdateClip) {
5199 for (
auto view : std::as_const(views))
5200 view->d_func()->setUpdateClip(item);
5202 if (!dirtyAncestorContainsChildren) {
5203 dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
5204 && itemClipsChildrenToShape;
5206 const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
5207 const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
5208 const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
5209 for (
auto child : std::as_const(item->d_ptr->children)) {
5210 if (wasDirtyParentSceneTransform)
5211 child->d_ptr->dirtySceneTransform = 1;
5212 if (wasDirtyParentViewBoundingRects)
5213 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
5214 if (parentIgnoresVisible)
5215 child->d_ptr->ignoreVisible = 1;
5216 if (parentIgnoresOpacity)
5217 child->d_ptr->ignoreOpacity = 1;
5218 if (allChildrenDirty) {
5219 child->d_ptr->dirty = 1;
5220 child->d_ptr->fullUpdatePending = 1;
5221 child->d_ptr->dirtyChildren = 1;
5222 child->d_ptr->allChildrenDirty = 1;
5224 processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
5227 if (itemClipsChildrenToShape) {
5229 for (
auto view : std::as_const(views))
5230 view->d_func()->setUpdateClip(
nullptr);
5232 }
else if (wasDirtyParentSceneTransform) {
5233 item->d_ptr->invalidateChildrenSceneTransform();
5236 resetDirtyItem(item);
5330bool QGraphicsScene::focusNextPrevChild(
bool next)
5332 Q_D(QGraphicsScene);
5334 QGraphicsItem *item = focusItem();
5335 if (item && !item->isWidget()) {
5340 if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
5343 setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5346 if (d->activePanel) {
5347 if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) {
5348 setFocusItem(d->activePanel, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5351 if (d->activePanel->isWidget()) {
5352 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(d->activePanel);
5353 QGraphicsWidget *fw = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5355 if (fw->focusPolicy() & Qt::TabFocus) {
5356 setFocusItem(fw, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5359 fw = next ? fw->d_func()->focusNext : fw->d_func()->focusPrev;
5360 }
while (fw != d->activePanel);
5364 if (!item && !d->tabFocusFirst) {
5370 QGraphicsWidget *widget =
nullptr;
5372 widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
5374 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(item);
5375 widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5376 if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
5381 QGraphicsWidget *widgetThatHadFocus = widget;
5385 if (widget->flags() & QGraphicsItem::ItemIsFocusable
5386 && widget->isEnabled() && widget->isVisibleTo(
nullptr)
5387 && (widget->focusPolicy() & Qt::TabFocus)
5388 && (!item || !item->isPanel() || item->isAncestorOf(widget))
5390 setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5393 widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
5394 if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
5396 }
while (widget != widgetThatHadFocus);
5839void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
5841 typedef std::pair<QEventPoint::States, QList<QEventPoint> > StatesAndTouchPoints;
5842 QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
5844 const auto &touchPoints = sceneTouchEvent->points();
5845 for (
const auto &touchPoint : touchPoints) {
5847 QGraphicsItem *item =
nullptr;
5848 if (touchPoint.state() == QEventPoint::State::Pressed) {
5849 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
5851 item = itemForTouchPointId.isEmpty()
5853 : itemForTouchPointId.constBegin().value();
5858 cachedItemsUnderMouse = itemsAtPosition(touchPoint.globalPosition().toPoint(),
5859 touchPoint.scenePosition(),
5860 static_cast<QWidget *>(sceneTouchEvent->target()));
5861 item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.constFirst();
5864 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchScreen) {
5866 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePosition());
5867 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
5868 if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
5874 itemForTouchPointId.insert(touchPoint.id(), item);
5875 sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
5876 }
else if (touchPoint.state() == QEventPoint::State::Released) {
5877 item = itemForTouchPointId.take(touchPoint.id());
5881 sceneCurrentTouchPoints.remove(touchPoint.id());
5883 item = itemForTouchPointId.value(touchPoint.id());
5886 Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
5887 sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
5890 StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
5891 statesAndTouchPoints.first = QEventPoint::States(statesAndTouchPoints.first | touchPoint.state());
5892 statesAndTouchPoints.second.append(touchPoint);
5895 if (itemsNeedingEvents.isEmpty()) {
5896 sceneTouchEvent->ignore();
5900 bool ignoreSceneTouchEvent =
true;
5901 QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
5902 const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
5903 for (; it != end; ++it) {
5904 QGraphicsItem *item = it.key();
5906 (
void) item->isBlockedByModalPanel(&item);
5909 QEvent::Type eventType;
5910 switch (it.value().first) {
5911 case QEventPoint::State::Pressed:
5913 eventType = QEvent::TouchBegin;
5915 case QEventPoint::State::Released:
5917 eventType = QEvent::TouchEnd;
5919 case QEventPoint::State::Stationary:
5924 eventType = QEvent::TouchUpdate;
5928 QMutableTouchEvent touchEvent(eventType, sceneTouchEvent->pointingDevice(), sceneTouchEvent->modifiers(), it.value().second);
5929 touchEvent.setTarget(sceneTouchEvent->target());
5930 touchEvent.setModifiers(sceneTouchEvent->modifiers());
5931 touchEvent.setTimestamp(sceneTouchEvent->timestamp());
5933 switch (touchEvent.type()) {
5934 case QEvent::TouchBegin:
5938 item->d_ptr->acceptedTouchBeginEvent =
true;
5939 bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted();
5942 const auto &unhandledTouchPoints = touchEvent.points();
5943 for (
const auto &touchPoint : unhandledTouchPoints) {
5944 itemForTouchPointId.remove(touchPoint.id());
5945 sceneCurrentTouchPoints.remove(touchPoint.id());
5947 ignoreSceneTouchEvent =
false;
5952 if (item->d_ptr->acceptedTouchBeginEvent) {
5953 updateTouchPointsForItem(item, &touchEvent);
5954 (
void) sendEvent(item, &touchEvent);
5955 ignoreSceneTouchEvent =
false;
5961 sceneTouchEvent->QInputEvent::setAccepted(ignoreSceneTouchEvent);
5964bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
5966 Q_Q(QGraphicsScene);
5969 if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.constFirst() != origin) {
5970 const QEventPoint &firstTouchPoint = touchEvent->points().first();
5971 cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.globalPosition().toPoint(),
5972 firstTouchPoint.scenePosition(),
5973 static_cast<QWidget *>(touchEvent->target()));
5977 bool setFocus =
false;
5979 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
5980 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
5981 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
5983 if (item != q->focusItem())
5984 q->setFocusItem(item, Qt::MouseFocusReason);
5988 if (item->isPanel())
5990 if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
5992 if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
6000 if (!stickyFocus && !setFocus)
6001 q->setFocusItem(
nullptr, Qt::MouseFocusReason);
6005 bool eventAccepted = touchEvent->isAccepted();
6006 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
6008 updateTouchPointsForItem(item, touchEvent);
6009 bool acceptTouchEvents = item->acceptTouchEvents();
6010 touchEvent->setAccepted(acceptTouchEvents);
6011 res = acceptTouchEvents && sendEvent(item, touchEvent);
6012 eventAccepted = touchEvent->isAccepted();
6013 if (itemForTouchPointId.value(touchEvent->points().first().id()) == 0) {
6017 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
6019 touchEvent->m_spont =
false;
6020 if (res && eventAccepted) {
6022 const auto &touchPoints = touchEvent->points();
6023 for (
const auto &touchPoint : touchPoints)
6024 itemForTouchPointId[touchPoint.id()] = item;
6027 if (item && item->isPanel())
6032 touchEvent->QInputEvent::setAccepted(eventAccepted);
6188void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
6190 QWidget *viewport = event->widget();
6193 QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
6197 const QList<QGesture *> allGestures = event->gestures();
6198 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6199 <<
"Gestures:" << allGestures;
6201 QSet<QGesture *> startedGestures;
6202 QPoint delta = viewport->mapFromGlobal(QPoint());
6203 QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
6204 * graphicsView->viewportTransform().inverted();
6205 for (QGesture *gesture : allGestures) {
6207 if (gesture->hasHotSpot()) {
6208 gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
6210 gesture->d_func()->sceneHotSpot = QPointF();
6213 QGraphicsObject *target = gestureTargets.value(gesture, 0);
6217 if (gesture->state() == Qt::GestureStarted)
6218 startedGestures.insert(gesture);
6222 if (!startedGestures.isEmpty()) {
6223 QSet<QGesture *> normalGestures;
6224 QSet<QGesture *> conflictedGestures;
6225 gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures,
nullptr,
6226 &normalGestures, &conflictedGestures);
6227 cachedTargetItems = cachedItemGestures.keys();
6228 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6229 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6230 <<
"Normal gestures:" << normalGestures
6231 <<
"Conflicting gestures:" << conflictedGestures;
6235 if (!conflictedGestures.isEmpty()) {
6236 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6237 QPointer<QGraphicsObject> item = cachedTargetItems.at(i);
6240 const QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
6241 if (gestures.isEmpty())
6244 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6245 <<
"delivering override to"
6246 << item.data() << gestures;
6248 QGestureEvent ev(gestures.values());
6249 ev.t = QEvent::GestureOverride;
6250 ev.setWidget(event->widget());
6253 for (QGesture *g : gestures)
6254 ev.setAccepted(g,
false);
6255 sendEvent(item.data(), &ev);
6257 for (QGesture *g : gestures) {
6258 if (ev.isAccepted() || ev.isAccepted(g)) {
6259 conflictedGestures.remove(g);
6262 gestureTargets.insert(g, item.data());
6263 QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e;
6264 it = cachedItemGestures.begin();
6265 e = cachedItemGestures.end();
6266 for(; it != e; ++it)
6267 it.value().remove(g);
6268 cachedItemGestures[item.data()].insert(g);
6270 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6271 <<
"override was accepted:"
6272 << g << item.data();
6277 if (!gestureTargets.contains(g) && item)
6278 gestureTargets.insert(g, item.data());
6281 if (conflictedGestures.isEmpty())
6287 if (!normalGestures.isEmpty()) {
6288 for (
int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
6289 QGraphicsObject *item = cachedTargetItems.at(i);
6292 const auto gestures = cachedItemGestures.value(item);
6293 for (QGesture *g : gestures) {
6294 if (!gestureTargets.contains(g)) {
6295 gestureTargets.insert(g, item);
6296 normalGestures.remove(g);
6305 QSet<QGesture *> undeliveredGestures;
6306 QSet<QGesture *> parentPropagatedGestures;
6307 for (QGesture *gesture : allGestures) {
6308 if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
6309 cachedItemGestures[target].insert(gesture);
6310 cachedTargetItems.append(target);
6311 undeliveredGestures.insert(gesture);
6312 QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
6313 const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
6314 if (flags & Qt::IgnoredGesturesPropagateToParent)
6315 parentPropagatedGestures.insert(gesture);
6317 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6318 <<
"no target for" << gesture <<
"at"
6319 << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
6322 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6323 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6324 QPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
6325 const QSet<QGesture *> gestures = (undeliveredGestures
6326 & cachedItemGestures.value(receiver.data()))
6327 - cachedAlreadyDeliveredGestures.value(receiver.data());
6329 if (gestures.isEmpty())
6332 cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
6333 const bool isPanel = receiver.data()->isPanel();
6335 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6337 << receiver.data() << gestures;
6338 QGestureEvent ev(gestures.values());
6339 ev.setWidget(event->widget());
6340 sendEvent(receiver.data(), &ev);
6341 QSet<QGesture *> ignoredGestures;
6342 for (QGesture *g : gestures) {
6343 if (!ev.isAccepted() && !ev.isAccepted(g)) {
6349 if (receiver && receiver.data() == gestureTargets.value(g, 0))
6350 ignoredGestures.insert(g);
6352 if (receiver && g->state() == Qt::GestureStarted) {
6355 gestureTargets[g] = receiver.data();
6357 undeliveredGestures.remove(g);
6360 if (undeliveredGestures.isEmpty())
6365 if (!ignoredGestures.isEmpty() && !isPanel) {
6369 QSet<QGraphicsObject *> targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd());
6373 for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
6374 it != ignoredGestures.end();) {
6375 if (parentPropagatedGestures.contains(*it)) {
6376 QGesture *gesture = *it;
6377 const Qt::GestureType gestureType = gesture->gestureType();
6378 QGraphicsItem *item = receiver.data();
6380 if (QGraphicsObject *obj = item->toGraphicsObject()) {
6381 if (item->d_func()->gestureContext.contains(gestureType)) {
6382 targetsSet.insert(obj);
6383 cachedItemGestures[obj].insert(gesture);
6386 if (item->isPanel())
6388 item = item->parentItem();
6391 it = ignoredGestures.erase(it);
6398 gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
6399 &cachedItemGestures, &targetsSet,
nullptr,
nullptr);
6401 cachedTargetItems = targetsSet.values();
6402 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6403 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6404 <<
"new targets:" << cachedTargetItems;
6410 for (QGesture *g : std::as_const(startedGestures)) {
6411 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
6412 DEBUG() <<
"lets try to cancel some";
6414 cancelGesturesForChildren(g);
6419 for (QGesture *g : allGestures) {
6420 switch (g->state()) {
6421 case Qt::GestureFinished:
6422 case Qt::GestureCanceled:
6423 gestureTargets.remove(g);
6430 cachedTargetItems.clear();
6431 cachedItemGestures.clear();
6432 cachedAlreadyDeliveredGestures.clear();
6435void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
6438 QGraphicsItem *originalItem = gestureTargets.value(original);
6439 if (originalItem ==
nullptr)
6445 QSet<QGesture *> canceledGestures;
6446 QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin();
6447 while (iter != gestureTargets.end()) {
6448 QGraphicsObject *item = iter.value();
6450 if (item != originalItem && originalItem->isAncestorOf(item)) {
6451 DEBUG() <<
" found a gesture to cancel" << iter.key();
6452 iter.key()->d_func()->state = Qt::GestureCanceled;
6453 canceledGestures << iter.key();
6459 QSet<QGesture *> almostCanceledGestures = canceledGestures;
6460 QSet<QGesture *>::Iterator setIter;
6461 while (!almostCanceledGestures.isEmpty()) {
6462 QGraphicsObject *target =
nullptr;
6463 QSet<QGesture*> gestures;
6464 setIter = almostCanceledGestures.begin();
6466 while (setIter != almostCanceledGestures.end()) {
6467 QGraphicsObject *item = gestureTargets.value(*setIter);
6468 if (target ==
nullptr)
6470 if (target == item) {
6471 gestures << *setIter;
6472 setIter = almostCanceledGestures.erase(setIter);
6479 const QList<QGesture *> list = gestures.values();
6480 QGestureEvent ev(list);
6481 sendEvent(target, &ev);
6483 if (!ev.isAccepted()) {
6484 for (QGesture *g : list) {
6486 if (ev.isAccepted(g))
6489 if (!g->hasHotSpot())
6492 const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot,
nullptr);
6493 for (
const auto &item : items) {
6494 QGraphicsObject *object = item->toGraphicsObject();
6497 QGraphicsItemPrivate *d = object->QGraphicsItem::d_func();
6498 if (d->gestureContext.contains(g->gestureType())) {
6499 QList<QGesture *> list;
6501 QGestureEvent ev(list);
6502 sendEvent(object, &ev);
6503 if (ev.isAccepted() || ev.isAccepted(g))
6511 QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
6512 Q_ASSERT(gestureManager);
6513 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
6514 gestureManager->recycle(*setIter);
6515 gestureTargets.remove(*setIter);