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);
1309void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent)
1311 Q_Q(QGraphicsScene);
1314 mouseEvent->ignore();
1317 if (!mouseGrabberItems.isEmpty()) {
1318 if (mouseGrabberItems.constLast()->isBlockedByModalPanel())
1322 sendMouseEvent(mouseEvent);
1328 if (cachedItemsUnderMouse.isEmpty()) {
1329 cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(),
1330 mouseEvent->scenePos(),
1331 mouseEvent->widget());
1335 QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
1336 QGraphicsWidget *newActiveWindow = topItem ? topItem->window() :
nullptr;
1337 if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
1339 newActiveWindow = topItem ? topItem->window() :
nullptr;
1342 if (newActiveWindow != q->activeWindow())
1343 q->setActiveWindow(newActiveWindow);
1346 bool setFocus =
false;
1348 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1349 if (item->isBlockedByModalPanel()
1350 || (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling)) {
1355 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable))) {
1356 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
1358 if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
1359 q->setFocusItem(item, Qt::MouseFocusReason);
1363 if (item->isPanel())
1365 if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
1370 bool sceneModality =
false;
1371 for (
auto modalPanel : std::as_const(modalPanels)) {
1372 if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
1373 sceneModality =
true;
1379 if (!stickyFocus && !setFocus && !sceneModality)
1380 q->setFocusItem(
nullptr, Qt::MouseFocusReason);
1383 if (sceneModality && cachedItemsUnderMouse.isEmpty())
1384 cachedItemsUnderMouse << modalPanels.constFirst();
1390 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
1391 if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
1398 (
void) item->isBlockedByModalPanel(&item);
1400 grabMouse(item,
true);
1401 mouseEvent->accept();
1404 bool disabled = !item->isEnabled();
1405 bool isPanel = item->isPanel();
1406 if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
1407 && item != lastMouseGrabberItem && lastMouseGrabberItem) {
1412 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1413 mousePress.m_spont = mouseEvent->spontaneous();
1414 mousePress.accept();
1415 mousePress.setButton(mouseEvent->button());
1416 mousePress.setButtons(mouseEvent->buttons());
1417 mousePress.setScreenPos(mouseEvent->screenPos());
1418 mousePress.setScenePos(mouseEvent->scenePos());
1419 mousePress.setModifiers(mouseEvent->modifiers());
1420 mousePress.setWidget(mouseEvent->widget());
1421 mousePress.setButtonDownPos(mouseEvent->button(),
1422 mouseEvent->buttonDownPos(mouseEvent->button()));
1423 mousePress.setButtonDownScenePos(mouseEvent->button(),
1424 mouseEvent->buttonDownScenePos(mouseEvent->button()));
1425 mousePress.setButtonDownScreenPos(mouseEvent->button(),
1426 mouseEvent->buttonDownScreenPos(mouseEvent->button()));
1427 sendMouseEvent(&mousePress);
1428 mouseEvent->setAccepted(mousePress.isAccepted());
1430 sendMouseEvent(mouseEvent);
1433 bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.constLast() != item;
1435 ungrabMouse(item, dontSendUngrabEvents);
1438 if (mouseEvent->isAccepted()) {
1439 if (!mouseGrabberItems.isEmpty())
1440 storeMouseButtonsForMouseGrabber(mouseEvent);
1441 lastMouseGrabberItem = item;
1444 ungrabMouse(item, dontSendUngrabEvents);
1455 if (!mouseEvent->isAccepted()) {
1456 clearMouseGrabber();
1458 QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
1459 bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
1460 bool extendSelection = (mouseEvent->modifiers() & Qt::ControlModifier) != 0;
1461 dontClearSelection |= extendSelection;
1462 if (!dontClearSelection) {
1466 q->clearSelection();
1746void QGraphicsScene::render(QPainter *painter,
const QRectF &target,
const QRectF &source,
1747 Qt::AspectRatioMode aspectRatioMode)
1752 QRectF sourceRect = source;
1753 if (sourceRect.isNull())
1754 sourceRect = sceneRect();
1757 QRectF targetRect = target;
1758 if (targetRect.isNull()) {
1759 if (painter->device()->devType() == QInternal::Picture)
1760 targetRect = sourceRect;
1762 targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
1766 qreal xratio = targetRect.width() / sourceRect.width();
1767 qreal yratio = targetRect.height() / sourceRect.height();
1770 switch (aspectRatioMode) {
1771 case Qt::KeepAspectRatio:
1772 xratio = yratio = qMin(xratio, yratio);
1774 case Qt::KeepAspectRatioByExpanding:
1775 xratio = yratio = qMax(xratio, yratio);
1777 case Qt::IgnoreAspectRatio:
1783 QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect);
1784 QGraphicsItem **itemArray =
new QGraphicsItem *[itemList.size()];
1785 const qsizetype numItems = itemList.size();
1786 for (qsizetype i = 0; i < numItems; ++i)
1787 itemArray[numItems - i - 1] = itemList.at(i);
1793 painter->setClipRect(targetRect, Qt::IntersectClip);
1794 QTransform painterTransform;
1795 painterTransform *= QTransform()
1796 .translate(targetRect.left(), targetRect.top())
1797 .scale(xratio, yratio)
1798 .translate(-sourceRect.left(), -sourceRect.top());
1799 painter->setWorldTransform(painterTransform,
true);
1802 QStyleOptionGraphicsItem *styleOptionArray =
new QStyleOptionGraphicsItem[numItems];
1803 for (qsizetype i = 0; i < numItems; ++i)
1804 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
1807 drawBackground(painter, sourceRect);
1808 drawItems(painter, numItems, itemArray, styleOptionArray);
1809 drawForeground(painter, sourceRect);
1811 delete [] itemArray;
1812 delete [] styleOptionArray;
2396void QGraphicsScene::addItem(QGraphicsItem *item)
2398 Q_D(QGraphicsScene);
2400 qWarning(
"QGraphicsScene::addItem: cannot add null item");
2403 if (item->d_ptr->scene ==
this) {
2404 qWarning(
"QGraphicsScene::addItem: item has already been added to this scene");
2408 if (QGraphicsScene *oldScene = item->d_ptr->scene)
2409 oldScene->removeItem(item);
2413 const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
2414 QVariant::fromValue<QGraphicsScene *>(
this)));
2415 QGraphicsScene *targetScene = qvariant_cast<QGraphicsScene *>(newSceneVariant);
2416 if (targetScene !=
this) {
2417 if (targetScene && item->d_ptr->scene != targetScene)
2418 targetScene->addItem(item);
2422 if (d->unpolishedItems.isEmpty()) {
2423 QMetaMethod method = metaObject()->method(d->polishItemsIndex);
2424 method.invoke(
this, Qt::QueuedConnection);
2426 d->unpolishedItems.append(item);
2427 item->d_ptr->pendingPolish =
true;
2431 if (QGraphicsItem *itemParent = item->d_ptr->parent) {
2432 if (itemParent->d_ptr->scene !=
this)
2433 item->setParentItem(
nullptr);
2437 item->d_func()->scene = targetScene;
2440 d->index->addItem(item);
2443 if (!item->d_ptr->parent)
2444 d->registerTopLevelItem(item);
2450 d->dirtyGrowingItemsBoundingRect =
true;
2453 ++d->selectionChanging;
2454 int oldSelectedItemSize = d->selectedItems.size();
2460 auto needsMouseTracking = [](
const QGraphicsItemPrivate *item) {
2461 return item->acceptsHover
2462 || (item->isWidget &&
static_cast<
const QGraphicsWidgetPrivate *>(item)->hasDecoration());
2465 if (d->allItemsIgnoreHoverEvents && needsMouseTracking(item->d_ptr.data())) {
2466 d->allItemsIgnoreHoverEvents =
false;
2467 d->enableMouseTrackingOnViews();
2470 if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
2471 d->allItemsUseDefaultCursor =
false;
2472 if (d->allItemsIgnoreHoverEvents)
2473 d->enableMouseTrackingOnViews();
2478 if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
2479 d->allItemsIgnoreTouchEvents =
false;
2480 d->enableTouchEventsOnViews();
2483#ifndef QT_NO_GESTURES
2484 for (
auto it = item->d_ptr->gestureContext.constBegin();
2485 it != item->d_ptr->gestureContext.constEnd(); ++it)
2486 d->grabGesture(item, it.key());
2490 if (item->isSelected())
2491 d->selectedItems << item;
2492 if (item->isWidget() && item->isVisible() &&
static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
2493 d->addPopup(
static_cast<QGraphicsWidget *>(item));
2494 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
2495 d->enterModal(item);
2499 if (item->isWidget()) {
2500 QGraphicsWidget *widget =
static_cast<QGraphicsWidget *>(item);
2501 if (!d->tabFocusFirst) {
2504 d->tabFocusFirst = widget;
2505 }
else if (!widget->parentWidget() && !widget->isPanel()) {
2507 QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev;
2508 myNewPrev->d_func()->focusNext = widget;
2509 widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst;
2510 d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev;
2511 widget->d_func()->focusPrev = myNewPrev;
2516 item->d_ptr->ensureSortedChildren();
2517 for (
auto child : std::as_const(item->d_ptr->children))
2521 item->d_ptr->resolveFont(d->font.resolveMask());
2522 item->d_ptr->resolvePalette(d->palette.resolveMask());
2526 --d->selectionChanging;
2527 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
2528 emit selectionChanged();
2531 item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
2534 bool autoActivate =
true;
2535 if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
2536 d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
2537 if (d->childExplicitActivation && item->isPanel()) {
2538 if (d->childExplicitActivation == 1)
2539 setActivePanel(item);
2541 autoActivate =
false;
2542 d->childExplicitActivation = 0;
2543 }
else if (!item->d_ptr->parent) {
2544 d->childExplicitActivation = 0;
2549 if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
2551 setActivePanel(item);
2553 d->lastActivePanel = item;
2557 if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges)
2558 d->registerScenePosItem(item);
2562 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
2563 item->focusItem()->setFocus();
2565 d->updateInputMethodSensitivityInViews();
3233bool QGraphicsScene::event(QEvent *event)
3235 Q_D(QGraphicsScene);
3237 switch (event->type()) {
3238 case QEvent::GraphicsSceneMousePress:
3239 case QEvent::GraphicsSceneMouseMove:
3240 case QEvent::GraphicsSceneMouseRelease:
3241 case QEvent::GraphicsSceneMouseDoubleClick:
3242 case QEvent::GraphicsSceneHoverEnter:
3243 case QEvent::GraphicsSceneHoverLeave:
3244 case QEvent::GraphicsSceneHoverMove:
3245 case QEvent::TouchBegin:
3246 case QEvent::TouchUpdate:
3247 case QEvent::TouchEnd:
3255 d->cachedItemsUnderMouse.clear();
3261 switch (event->type()) {
3262 case QEvent::GraphicsSceneDragEnter:
3263 dragEnterEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3265 case QEvent::GraphicsSceneDragMove:
3266 dragMoveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3268 case QEvent::GraphicsSceneDragLeave:
3269 dragLeaveEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3271 case QEvent::GraphicsSceneDrop:
3272 dropEvent(
static_cast<QGraphicsSceneDragDropEvent *>(event));
3274 case QEvent::GraphicsSceneContextMenu:
3275 contextMenuEvent(
static_cast<QGraphicsSceneContextMenuEvent *>(event));
3277 case QEvent::KeyPress:
3278 if (!d->focusItem) {
3279 QKeyEvent *k =
static_cast<QKeyEvent *>(event);
3280 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
3281 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {
3283 if (k->key() == Qt::Key_Backtab
3284 || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
3285 res = focusNextPrevChild(
false);
3286 }
else if (k->key() == Qt::Key_Tab) {
3287 res = focusNextPrevChild(
true);
3295 keyPressEvent(
static_cast<QKeyEvent *>(event));
3297 case QEvent::KeyRelease:
3298 keyReleaseEvent(
static_cast<QKeyEvent *>(event));
3300 case QEvent::ShortcutOverride: {
3301 QGraphicsItem *parent = focusItem();
3303 d->sendEvent(parent, event);
3304 if (event->isAccepted())
3306 parent = parent->parentItem();
3310 case QEvent::GraphicsSceneMouseMove:
3312 QGraphicsSceneMouseEvent *mouseEvent =
static_cast<QGraphicsSceneMouseEvent *>(event);
3313 d->lastSceneMousePos = mouseEvent->scenePos();
3314 mouseMoveEvent(mouseEvent);
3317 case QEvent::GraphicsSceneMousePress:
3318 mousePressEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3320 case QEvent::GraphicsSceneMouseRelease:
3321 mouseReleaseEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3323 case QEvent::GraphicsSceneMouseDoubleClick:
3324 mouseDoubleClickEvent(
static_cast<QGraphicsSceneMouseEvent *>(event));
3326 case QEvent::GraphicsSceneWheel:
3327 wheelEvent(
static_cast<QGraphicsSceneWheelEvent *>(event));
3329 case QEvent::FocusIn:
3330 focusInEvent(
static_cast<QFocusEvent *>(event));
3332 case QEvent::FocusOut:
3333 focusOutEvent(
static_cast<QFocusEvent *>(event));
3335 case QEvent::GraphicsSceneHoverEnter:
3336 case QEvent::GraphicsSceneHoverLeave:
3337 case QEvent::GraphicsSceneHoverMove:
3339 QGraphicsSceneHoverEvent *hoverEvent =
static_cast<QGraphicsSceneHoverEvent *>(event);
3340 d->lastSceneMousePos = hoverEvent->scenePos();
3341 d->dispatchHoverEvent(hoverEvent);
3345 Q_ASSERT_X(
false,
"QGraphicsScene::event",
3346 "QGraphicsScene must not receive QEvent::Leave, use GraphicsSceneLeave");
3348 case QEvent::GraphicsSceneLeave:
3350 auto *leaveEvent =
static_cast<QGraphicsSceneEvent*>(event);
3351 d->leaveScene(leaveEvent->widget());
3354 case QEvent::GraphicsSceneHelp:
3355 helpEvent(
static_cast<QGraphicsSceneHelpEvent *>(event));
3357 case QEvent::InputMethod:
3358 inputMethodEvent(
static_cast<QInputMethodEvent *>(event));
3360 case QEvent::WindowActivate:
3361 if (!d->activationRefCount++) {
3362 if (d->lastActivePanel) {
3364 d->setActivePanelHelper(d->lastActivePanel,
true);
3365 }
else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
3368 d->setActivePanelHelper(d->tabFocusFirst,
true);
3371 QEvent event(QEvent::WindowActivate);
3372 const auto items_ = items();
3373 for (QGraphicsItem *item : items_) {
3374 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3375 sendEvent(item, &event);
3380 case QEvent::WindowDeactivate:
3381 if (!--d->activationRefCount) {
3382 if (d->activePanel) {
3385 QGraphicsItem *lastActivePanel = d->activePanel;
3386 d->setActivePanelHelper(
nullptr,
true);
3387 d->lastActivePanel = lastActivePanel;
3390 QEvent event(QEvent::WindowDeactivate);
3391 const auto items_ = items();
3392 for (QGraphicsItem *item : items_) {
3393 if (item->isVisible() && !item->isPanel() && !item->parentItem())
3394 sendEvent(item, &event);
3399 case QEvent::ApplicationFontChange: {
3404 case QEvent::FontChange:
3408 case QEvent::ApplicationPaletteChange: {
3410 d->resolvePalette();
3413 case QEvent::PaletteChange:
3417 case QEvent::StyleChange:
3422 case QEvent::StyleAnimationUpdate:
3427 case QEvent::TouchBegin:
3428 case QEvent::TouchUpdate:
3429 case QEvent::TouchEnd:
3430 d->touchEventHandler(
static_cast<QTouchEvent *>(event));
3432#ifndef QT_NO_GESTURES
3433 case QEvent::Gesture:
3434 case QEvent::GestureOverride:
3435 d->gestureEventHandler(
static_cast<QGestureEvent *>(event));
3439 return QObject::event(event);
3529void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
3531 Q_D(QGraphicsScene);
3534 if (!d->mouseGrabberItems.isEmpty()) {
3536 d->clearMouseGrabber();
3537 d->mouseGrabberButtonDownPos.clear();
3538 d->mouseGrabberButtonDownScenePos.clear();
3539 d->mouseGrabberButtonDownScreenPos.clear();
3542 bool eventDelivered =
false;
3546 const auto items = d->itemsAtPosition(event->screenPos(),
3549 for (QGraphicsItem *item : items) {
3550 if (!item->isEnabled() || !item->acceptDrops())
3553 if (item != d->dragDropItem) {
3556 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
3557 d->cloneDragDropEvent(&dragEnter, event);
3558 dragEnter.setDropAction(event->proposedAction());
3559 d->sendDragDropEvent(item, &dragEnter);
3560 event->setAccepted(dragEnter.isAccepted());
3561 event->setDropAction(dragEnter.dropAction());
3562 if (!event->isAccepted()) {
3567 d->lastDropAction = event->dropAction();
3569 if (d->dragDropItem) {
3574 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3575 d->cloneDragDropEvent(&dragLeave, event);
3576 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3580 d->dragDropItem = item;
3584 event->setDropAction(d->lastDropAction);
3586 d->sendDragDropEvent(item, event);
3587 if (event->isAccepted())
3588 d->lastDropAction = event->dropAction();
3589 eventDelivered =
true;
3593 if (!eventDelivered) {
3594 if (d->dragDropItem) {
3596 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
3597 d->cloneDragDropEvent(&dragLeave, event);
3598 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
3599 d->dragDropItem =
nullptr;
3602 event->setDropAction(Qt::IgnoreAction);
3763bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
3765 if (allItemsIgnoreHoverEvents)
3770 if (cachedItemsUnderMouse.isEmpty()) {
3771 cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(),
3772 hoverEvent->scenePos(),
3773 hoverEvent->widget());
3776 QGraphicsItem *item =
nullptr;
3777 for (
auto tmp : std::as_const(cachedItemsUnderMouse)) {
3778 if (itemAcceptsHoverEvents_helper(tmp)) {
3786 QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.constLast()) :
nullptr;
3787 while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
3788 commonAncestorItem = commonAncestorItem->parentItem();
3789 if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
3792 commonAncestorItem =
nullptr;
3796 int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
3799 for (
int i = hoverItems.size() - 1; i > index; --i) {
3800 QGraphicsItem *lastItem = hoverItems.takeLast();
3801 if (itemAcceptsHoverEvents_helper(lastItem))
3802 sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
3807 QList<QGraphicsItem *> parents;
3808 QGraphicsItem *parent = item;
3809 while (parent && parent != commonAncestorItem) {
3810 parents.append(parent);
3811 if (parent->isPanel()) {
3815 parent = parent->parentItem();
3817 for (
auto it = parents.crbegin(), end = parents.crend(); it != end; ++it) {
3818 QGraphicsItem *parent = *it;
3819 hoverItems << parent;
3820 if (itemAcceptsHoverEvents_helper(parent))
3821 sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent);
3826 && !hoverItems.isEmpty()
3827 && item == hoverItems.constLast()) {
3828 sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
4304void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter,
4305 const QStyleOptionGraphicsItem *option, QWidget *widget,
4306 bool painterStateProtection)
4308 QGraphicsItemPrivate *itemd = item->d_ptr.data();
4309 QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
4312 if (cacheMode == QGraphicsItem::NoCache) {
4313 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
true, painterStateProtection);
4317 const qreal devicePixelRatio = painter->device()->devicePixelRatio();
4318 const qreal oldPainterOpacity = painter->opacity();
4319 qreal newPainterOpacity = oldPainterOpacity;
4320 QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(
static_cast<QGraphicsWidget *>(item)) : 0;
4321 if (proxy && proxy->widget()) {
4322 const qreal windowOpacity = proxy->widget()->windowOpacity();
4323 if (windowOpacity < 1.0)
4324 newPainterOpacity *= windowOpacity;
4328 QRectF brect = item->boundingRect();
4329 QRectF adjustedBrect(brect);
4330 _q_adjustRect(&adjustedBrect);
4331 if (adjustedBrect.isEmpty())
4335 QPixmapCache::Key pixmapKey;
4339 QGraphicsItemCache *itemCache = itemd->extraItemCache();
4340 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4341 pixmapKey = itemCache->key;
4343 pixmapKey = itemCache->deviceData.value(widget).key;
4347 pixmapFound = QPixmapCache::find(pixmapKey, &pix);
4350 if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
4352 bool fixedCacheSize = itemCache->fixedSize.isValid();
4353 QRect br = brect.toAlignedRect();
4354 if (fixedCacheSize) {
4355 pixmapSize = itemCache->fixedSize;
4357 pixmapSize = br.size();
4360 pixmapSize *= devicePixelRatio;
4363 int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
4364 QSize adjustSize(adjust*2, adjust*2);
4365 br.adjust(-adjust / devicePixelRatio, -adjust / devicePixelRatio, adjust / devicePixelRatio, adjust / devicePixelRatio);
4366 if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
4367 pix = QPixmap(pixmapSize + adjustSize);
4368 itemCache->boundingRect = br;
4369 itemCache->exposed.clear();
4370 itemCache->allExposed =
true;
4371 }
else if (itemCache->boundingRect != br) {
4372 itemCache->boundingRect = br;
4373 itemCache->exposed.clear();
4374 itemCache->allExposed =
true;
4378 if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
4383 QPixmapCache::remove(pixmapKey);
4386 QTransform itemToPixmap;
4387 if (fixedCacheSize) {
4388 const QPointF scale((pixmapSize.width() / devicePixelRatio) / brect.width(),
4389 (pixmapSize.height() / devicePixelRatio) / brect.height());
4390 itemToPixmap.scale(scale.x(), scale.y());
4392 itemToPixmap.translate(-br.x(), -br.y());
4396 styleOptionTmp = *option;
4397 QRegion pixmapExposed;
4399 if (!itemCache->allExposed) {
4400 for (
const auto &rect : std::as_const(itemCache->exposed)) {
4401 exposedRect |= rect;
4402 pixmapExposed += itemToPixmap.mapRect(rect).toAlignedRect();
4405 exposedRect = brect;
4407 styleOptionTmp.exposedRect = exposedRect;
4410 pix.setDevicePixelRatio(devicePixelRatio);
4411 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4412 &styleOptionTmp, painterStateProtection);
4415 itemCache->key = QPixmapCache::insert(pix);
4418 itemCache->allExposed =
false;
4419 itemCache->exposed.clear();
4425 if (newPainterOpacity != oldPainterOpacity) {
4426 painter->setOpacity(newPainterOpacity);
4427 painter->drawPixmap(br.topLeft(), pix);
4428 painter->setOpacity(oldPainterOpacity);
4430 painter->drawPixmap(br.topLeft(), pix);
4436 if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
4438 QRectF deviceBounds = painter->worldTransform().mapRect(brect);
4439 QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
4440 if (deviceRect.isEmpty())
4442 QRect viewRect = widget ? widget->rect() : QRect();
4443 if (widget && !viewRect.intersects(deviceRect))
4448 QSize maximumCacheSize =
4449 itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
4450 if (!maximumCacheSize.isEmpty()
4451 && (deviceRect.width() > maximumCacheSize.width()
4452 || deviceRect.height() > maximumCacheSize.height())) {
4453 _q_paintItem(
static_cast<QGraphicsWidget *>(item), painter, option, widget,
4454 oldPainterOpacity != newPainterOpacity, painterStateProtection);
4461 bool pixModified =
false;
4462 QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
4463 bool invertable =
true;
4464 QTransform diff = deviceData->lastTransform.inverted(&invertable);
4466 diff *= painter->worldTransform();
4467 deviceData->lastTransform = painter->worldTransform();
4468 bool allowPartialCacheExposure =
false;
4469 bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
4470 && transformIsSimple(painter->worldTransform());
4471 if (!simpleTransform) {
4473 itemCache->allExposed =
true;
4474 itemCache->exposed.clear();
4475 deviceData->cacheIndent = QPoint();
4477 }
else if (!viewRect.isNull()) {
4478 allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
4483 if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
4484 allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
4485 || (viewRect.height() * 1.2 < deviceRect.height());
4488 QRegion scrollExposure;
4489 if (allowPartialCacheExposure) {
4494 int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
4495 int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
4496 QPoint newCacheIndent(dx, dy);
4497 deviceRect &= viewRect;
4500 deviceData->cacheIndent = QPoint();
4501 itemCache->allExposed =
true;
4502 itemCache->exposed.clear();
4508 if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size() / devicePixelRatio) {
4509 QPoint diff = newCacheIndent - deviceData->cacheIndent;
4510 QPixmap newPix(deviceRect.size() * devicePixelRatio);
4513 newPix.fill(Qt::transparent);
4514 if (!pix.isNull()) {
4515 newPix.setDevicePixelRatio(devicePixelRatio);
4516 QPainter newPixPainter(&newPix);
4517 newPixPainter.drawPixmap(-diff, pix);
4518 newPixPainter.end();
4521 exposed += QRect(QPoint(0,0), newPix.size() / devicePixelRatio);
4523 exposed -= QRect(-diff, pix.size() / devicePixelRatio);
4524 scrollExposure = exposed;
4529 deviceData->cacheIndent = newCacheIndent;
4532 deviceData->cacheIndent = QPoint();
4535 if (deviceRect.size() != pix.size() / devicePixelRatio) {
4537 pix = QPixmap(deviceRect.size() * devicePixelRatio);
4539 itemCache->allExposed =
true;
4540 itemCache->exposed.clear();
4545 if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
4549 QPixmapCache::remove(pixmapKey);
4552 QPointF p = deviceRect.topLeft();
4553 QTransform itemToPixmap = painter->worldTransform();
4555 itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
4558 QRegion pixmapExposed = scrollExposure;
4559 if (!itemCache->allExposed) {
4560 for (
const auto &rect : std::as_const(itemCache->exposed))
4561 pixmapExposed += itemToPixmap.mapRect(rect).toRect().adjusted(-1, -1, 1, 1);
4566 if (itemCache->allExposed) {
4567 br = item->boundingRect();
4569 for (
const auto &rect : std::as_const(itemCache->exposed))
4571 QTransform pixmapToItem = itemToPixmap.inverted();
4572 for (
const QRect &r : std::as_const(scrollExposure))
4573 br |= pixmapToItem.mapRect(r);
4575 styleOptionTmp = *option;
4576 styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
4579 pix.setDevicePixelRatio(devicePixelRatio);
4580 _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
4581 &styleOptionTmp, painterStateProtection);
4585 itemCache->allExposed =
false;
4586 itemCache->exposed.clear();
4591 deviceData->key = QPixmapCache::insert(pix);
4596 QTransform restoreTransform = painter->worldTransform();
4597 painter->setWorldTransform(QTransform());
4598 if (newPainterOpacity != oldPainterOpacity) {
4599 painter->setOpacity(newPainterOpacity);
4600 painter->drawPixmap(deviceRect.topLeft(), pix);
4601 painter->setOpacity(oldPainterOpacity);
4603 painter->drawPixmap(deviceRect.topLeft(), pix);
4605 painter->setWorldTransform(restoreTransform);
4629void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
4630 const QTransform *
const viewTransform,
4631 QRegion *exposedRegion, QWidget *widget,
4632 qreal parentOpacity,
const QTransform *
const effectTransform)
4636 if (!item->d_ptr->visible)
4639 const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
4640 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
4641 if (!itemHasContents && !itemHasChildren)
4644 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
4645 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4646 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
4649 QTransform transform(Qt::Uninitialized);
4650 QTransform *transformPtr =
nullptr;
4651 bool translateOnlyTransform =
false;
4652#define ENSURE_TRANSFORM_PTR
4653 if (!transformPtr) {
4654 Q_ASSERT(!itemIsUntransformable);
4655 if (viewTransform) {
4656 transform = item->d_ptr->sceneTransform;
4657 transform *= *viewTransform;
4658 transformPtr = &transform;
4660 transformPtr = &item->d_ptr->sceneTransform;
4661 translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly;
4667 bool wasDirtyParentSceneTransform =
false;
4668 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
4669 if (itemIsUntransformable) {
4670 transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
4671 transformPtr = &transform;
4672 }
else if (item->d_ptr->dirtySceneTransform) {
4673 item->d_ptr->updateSceneTransformFromParent();
4674 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
4675 wasDirtyParentSceneTransform =
true;
4678 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
4679 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
4680 bool drawItem = itemHasContents && !itemIsFullyTransparent;
4681 if (drawItem || minimumRenderSize > 0.0) {
4682 const QRectF brect = adjustedItemEffectiveBoundingRect(item);
4684 QRectF preciseViewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy())
4685 : transformPtr->mapRect(brect);
4687 bool itemIsTooSmallToRender =
false;
4688 if (minimumRenderSize > 0.0
4689 && (preciseViewBoundingRect.width() < minimumRenderSize
4690 || preciseViewBoundingRect.height() < minimumRenderSize)) {
4691 itemIsTooSmallToRender =
true;
4695 bool itemIsOutsideVisibleRect =
false;
4697 QRect viewBoundingRect = preciseViewBoundingRect.toAlignedRect();
4698 viewBoundingRect.adjust(-
int(rectAdjust), -
int(rectAdjust), rectAdjust, rectAdjust);
4700 item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
4701 drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
4702 : !viewBoundingRect.normalized().isEmpty();
4703 itemIsOutsideVisibleRect = !drawItem;
4706 if (itemIsTooSmallToRender || itemIsOutsideVisibleRect) {
4712 if (!itemHasChildren)
4714 if (itemClipsChildrenToShape) {
4715 if (wasDirtyParentSceneTransform)
4716 item->d_ptr->invalidateChildrenSceneTransform();
4722 if (itemHasChildren && itemClipsChildrenToShape)
4725#if QT_CONFIG(graphicseffect)
4726 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
4727 ENSURE_TRANSFORM_PTR;
4728 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
4729 painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
4730 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
4731 QGraphicsItemEffectSourcePrivate *sourced =
static_cast<QGraphicsItemEffectSourcePrivate *>
4733 sourced->info = &info;
4734 const QTransform restoreTransform = painter->worldTransform();
4735 if (effectTransform)
4736 painter->setWorldTransform(*transformPtr * *effectTransform);
4738 painter->setWorldTransform(*transformPtr);
4739 painter->setOpacity(opacity);
4741 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
4742 && sourced->lastEffectTransform != painter->worldTransform())
4744 if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
4745 && painter->worldTransform().type() <= QTransform::TxTranslate)
4747 QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
4748 QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
4750 sourced->setCachedOffset(effectRect.topLeft());
4752 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
4755 sourced->lastEffectTransform = painter->worldTransform();
4758 item->d_ptr->graphicsEffect->draw(painter);
4759 painter->setWorldTransform(restoreTransform);
4760 sourced->info =
nullptr;
4764 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
4765 effectTransform, wasDirtyParentSceneTransform, drawItem);
4790void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter,
const QTransform *
const viewTransform,
4791 const QTransform *
const transformPtr, QRegion *exposedRegion, QWidget *widget,
4792 qreal opacity,
const QTransform *effectTransform,
4793 bool wasDirtyParentSceneTransform,
bool drawItem)
4795 const auto &children = item->d_ptr->children;
4797 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
4798 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
4799 const bool itemHasChildren = !children.isEmpty();
4800 bool setChildClip = itemClipsChildrenToShape;
4801 bool itemHasChildrenStackedBehind =
false;
4804 if (itemHasChildren) {
4805 if (itemClipsChildrenToShape)
4806 setWorldTransform(painter, transformPtr, effectTransform);
4808 item->d_ptr->ensureSortedChildren();
4811 itemHasChildrenStackedBehind = (children.at(0)->d_ptr->flags
4812 & QGraphicsItem::ItemStacksBehindParent);
4814 if (itemHasChildrenStackedBehind) {
4815 if (itemClipsChildrenToShape) {
4816 setClip(painter, item);
4817 setChildClip =
false;
4821 for (i = 0; i < children.size(); ++i) {
4822 QGraphicsItem *child = children.at(i);
4823 if (wasDirtyParentSceneTransform)
4824 child->d_ptr->dirtySceneTransform = 1;
4825 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
4827 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4829 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4836 Q_ASSERT(!itemIsFullyTransparent);
4837 Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
4838 Q_ASSERT(transformPtr);
4839 item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
4840 ? *exposedRegion : QRegion(), exposedRegion ==
nullptr);
4842 const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
4843 bool restorePainterClip =
false;
4845 if (!itemHasChildren || !itemClipsChildrenToShape) {
4847 setWorldTransform(painter, transformPtr, effectTransform);
4848 if ((restorePainterClip = itemClipsToShape))
4849 setClip(painter, item);
4850 }
else if (itemHasChildrenStackedBehind){
4853 if (itemClipsToShape) {
4855 setWorldTransform(painter, transformPtr, effectTransform);
4859 setChildClip =
true;
4861 }
else if (itemClipsToShape) {
4865 setClip(painter, item);
4866 setChildClip =
false;
4869 if (painterStateProtection && !restorePainterClip)
4872 painter->setOpacity(opacity);
4873 if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
4874 item->paint(painter, &styleOptionTmp, widget);
4876 drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
4878 if (painterStateProtection || restorePainterClip)
4881 static int drawRect = qEnvironmentVariableIntValue(
"QT_DRAW_SCENE_ITEM_RECTS");
4883 QPen oldPen = painter->pen();
4884 QBrush oldBrush = painter->brush();
4885 quintptr ptr =
reinterpret_cast<quintptr>(item);
4886 const QColor color = QColor::fromHsv(ptr % 255, 255, 255);
4887 painter->setPen(color);
4888 painter->setBrush(Qt::NoBrush);
4889 painter->drawRect(adjustedItemBoundingRect(item));
4890 painter->setPen(oldPen);
4891 painter->setBrush(oldBrush);
4896 if (itemHasChildren) {
4898 setClip(painter, item);
4900 for (; i < children.size(); ++i) {
4901 QGraphicsItem *child = children.at(i);
4902 if (wasDirtyParentSceneTransform)
4903 child->d_ptr->dirtySceneTransform = 1;
4904 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
4906 drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
4910 if (itemClipsChildrenToShape)
4915void QGraphicsScenePrivate::markDirty(QGraphicsItem *item,
const QRectF &rect,
bool invalidateChildren,
4916 bool force,
bool ignoreOpacity,
bool removingItemFromScene,
4917 bool updateBoundingRect)
4923 if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
4931 QGraphicsItem *p = item->d_ptr->parent;
4933 if (p->d_ptr->ignoreOpacity) {
4934 item->d_ptr->ignoreOpacity =
true;
4937 p = p->d_ptr->parent;
4941 if (item->d_ptr->discardUpdateRequest(force,
4942 removingItemFromScene || invalidateChildren,
4944 if (item->d_ptr->dirty) {
4950 item->d_ptr->ignoreVisible = 1;
4952 item->d_ptr->ignoreOpacity = 1;
4957 const bool fullItemUpdate = rect.isNull();
4958 if (!fullItemUpdate && rect.isEmpty())
4961 if (!processDirtyItemsEmitted) {
4962 QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
4963 method.invoke(q_ptr, Qt::QueuedConnection);
4965 processDirtyItemsEmitted =
true;
4968 if (removingItemFromScene) {
4971 if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
4979 for (
auto view : std::as_const(views)) {
4980 QGraphicsViewPrivate *viewPrivate = view->d_func();
4981 QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
4982 rect.translate(viewPrivate->dirtyScrollOffset);
4983 viewPrivate->updateRect(rect);
4988 bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
4989 if (!hasNoContents) {
4990 item->d_ptr->dirty = 1;
4992 item->d_ptr->fullUpdatePending = 1;
4993 else if (!item->d_ptr->fullUpdatePending)
4994 item->d_ptr->needsRepaint |= rect;
4995 }
else if (item->d_ptr->graphicsEffect) {
4996 invalidateChildren =
true;
4999 if (invalidateChildren) {
5000 item->d_ptr->allChildrenDirty = 1;
5001 item->d_ptr->dirtyChildren = 1;
5005 item->d_ptr->ignoreVisible = 1;
5007 item->d_ptr->ignoreOpacity = 1;
5009 if (!updateBoundingRect)
5010 item->d_ptr->markParentDirty();
5050void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item,
bool dirtyAncestorContainsChildren,
5051 qreal parentOpacity)
5053 Q_Q(QGraphicsScene);
5055 Q_ASSERT(!updateAll);
5057 if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
5058 resetDirtyItem(item);
5062 const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
5064 resetDirtyItem(item,
true);
5068 bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
5069 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
5070 if (!itemHasContents) {
5071 if (!itemHasChildren) {
5072 resetDirtyItem(item);
5075 if (item->d_ptr->graphicsEffect)
5076 itemHasContents =
true;
5079 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
5080 const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
5081 && QGraphicsItemPrivate::isOpacityNull(opacity);
5082 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
5083 resetDirtyItem(item, itemHasChildren);
5087 bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
5088 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
5089 if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
5090 item->d_ptr->updateSceneTransformFromParent();
5091 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
5094 const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
5095 if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
5097 item->d_ptr->dirty = 0;
5098 item->d_ptr->fullUpdatePending = 0;
5100 if (itemIsFullyTransparent || !itemHasContents)
5101 item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
5104 if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
5106 if (item->d_ptr->sceneTransformTranslateOnly) {
5107 growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
5108 item->d_ptr->sceneTransform.dy());
5110 growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
5115 if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5116 const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
5117 const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
5119 if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
5123 if (item->d_ptr->sceneTransformTranslateOnly) {
5124 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
5125 item->d_ptr->sceneTransform.dy()));
5127 QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
5128 if (!rect.isEmpty())
5133 bool uninitializedDirtyRect =
true;
5135 for (
auto view : std::as_const(views)) {
5136 QGraphicsViewPrivate *viewPrivate = view->d_func();
5137 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
5138 if (viewPrivate->fullUpdatePending
5139 || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
5143 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5147 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5148 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
5149 if (!viewPrivate->updateRect(paintedViewBoundingRect))
5150 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5153 if (!item->d_ptr->dirty)
5156 if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
5157 && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
5158 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
5162 if (uninitializedDirtyRect) {
5163 dirtyRect = itemBoundingRect;
5164 if (!item->d_ptr->fullUpdatePending) {
5165 _q_adjustRect(&item->d_ptr->needsRepaint);
5166 dirtyRect &= item->d_ptr->needsRepaint;
5168 uninitializedDirtyRect =
false;
5171 if (dirtyRect.isEmpty())
5174 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
5175 && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
5176 paintedViewBoundingRect = QRect(-1, -1, -1, -1);
5183 if (itemHasChildren && item->d_ptr->dirtyChildren) {
5184 const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
5185 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape;
5190 const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
5191 if (itemClipsChildrenToShape && !bypassUpdateClip) {
5193 for (
auto view : std::as_const(views))
5194 view->d_func()->setUpdateClip(item);
5196 if (!dirtyAncestorContainsChildren) {
5197 dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
5198 && itemClipsChildrenToShape;
5200 const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
5201 const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
5202 const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
5203 for (
auto child : std::as_const(item->d_ptr->children)) {
5204 if (wasDirtyParentSceneTransform)
5205 child->d_ptr->dirtySceneTransform = 1;
5206 if (wasDirtyParentViewBoundingRects)
5207 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
5208 if (parentIgnoresVisible)
5209 child->d_ptr->ignoreVisible = 1;
5210 if (parentIgnoresOpacity)
5211 child->d_ptr->ignoreOpacity = 1;
5212 if (allChildrenDirty) {
5213 child->d_ptr->dirty = 1;
5214 child->d_ptr->fullUpdatePending = 1;
5215 child->d_ptr->dirtyChildren = 1;
5216 child->d_ptr->allChildrenDirty = 1;
5218 processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
5221 if (itemClipsChildrenToShape) {
5223 for (
auto view : std::as_const(views))
5224 view->d_func()->setUpdateClip(
nullptr);
5226 }
else if (wasDirtyParentSceneTransform) {
5227 item->d_ptr->invalidateChildrenSceneTransform();
5230 resetDirtyItem(item);
5324bool QGraphicsScene::focusNextPrevChild(
bool next)
5326 Q_D(QGraphicsScene);
5328 QGraphicsItem *item = focusItem();
5329 if (item && !item->isWidget()) {
5334 if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
5337 setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5340 if (d->activePanel) {
5341 if (d->activePanel->flags() & QGraphicsItem::ItemIsFocusable) {
5342 setFocusItem(d->activePanel, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5345 if (d->activePanel->isWidget()) {
5346 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(d->activePanel);
5347 QGraphicsWidget *fw = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5349 if (fw->focusPolicy() & Qt::TabFocus) {
5350 setFocusItem(fw, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5353 fw = next ? fw->d_func()->focusNext : fw->d_func()->focusPrev;
5354 }
while (fw != d->activePanel);
5358 if (!item && !d->tabFocusFirst) {
5364 QGraphicsWidget *widget =
nullptr;
5366 widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
5368 QGraphicsWidget *test =
static_cast<QGraphicsWidget *>(item);
5369 widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
5370 if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
5375 QGraphicsWidget *widgetThatHadFocus = widget;
5379 if (widget->flags() & QGraphicsItem::ItemIsFocusable
5380 && widget->isEnabled() && widget->isVisibleTo(
nullptr)
5381 && (widget->focusPolicy() & Qt::TabFocus)
5382 && (!item || !item->isPanel() || item->isAncestorOf(widget))
5384 setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
5387 widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
5388 if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
5390 }
while (widget != widgetThatHadFocus);
5833void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
5835 typedef std::pair<QEventPoint::States, QList<QEventPoint> > StatesAndTouchPoints;
5836 QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
5838 const auto &touchPoints = sceneTouchEvent->points();
5839 for (
const auto &touchPoint : touchPoints) {
5841 QGraphicsItem *item =
nullptr;
5842 if (touchPoint.state() == QEventPoint::State::Pressed) {
5843 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchPad) {
5845 item = itemForTouchPointId.isEmpty()
5847 : itemForTouchPointId.constBegin().value();
5852 cachedItemsUnderMouse = itemsAtPosition(touchPoint.globalPosition().toPoint(),
5853 touchPoint.scenePosition(),
5854 static_cast<QWidget *>(sceneTouchEvent->target()));
5855 item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.constFirst();
5858 if (sceneTouchEvent->pointingDevice()->type() == QInputDevice::DeviceType::TouchScreen) {
5860 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePosition());
5861 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
5862 if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
5868 itemForTouchPointId.insert(touchPoint.id(), item);
5869 sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
5870 }
else if (touchPoint.state() == QEventPoint::State::Released) {
5871 item = itemForTouchPointId.take(touchPoint.id());
5875 sceneCurrentTouchPoints.remove(touchPoint.id());
5877 item = itemForTouchPointId.value(touchPoint.id());
5880 Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
5881 sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
5884 StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
5885 statesAndTouchPoints.first = QEventPoint::States(statesAndTouchPoints.first | touchPoint.state());
5886 statesAndTouchPoints.second.append(touchPoint);
5889 if (itemsNeedingEvents.isEmpty()) {
5890 sceneTouchEvent->ignore();
5894 bool ignoreSceneTouchEvent =
true;
5895 QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
5896 const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
5897 for (; it != end; ++it) {
5898 QGraphicsItem *item = it.key();
5900 (
void) item->isBlockedByModalPanel(&item);
5903 QEvent::Type eventType;
5904 switch (it.value().first) {
5905 case QEventPoint::State::Pressed:
5907 eventType = QEvent::TouchBegin;
5909 case QEventPoint::State::Released:
5911 eventType = QEvent::TouchEnd;
5913 case QEventPoint::State::Stationary:
5918 eventType = QEvent::TouchUpdate;
5922 QMutableTouchEvent touchEvent(eventType, sceneTouchEvent->pointingDevice(), sceneTouchEvent->modifiers(), it.value().second);
5923 touchEvent.setTarget(sceneTouchEvent->target());
5924 touchEvent.setModifiers(sceneTouchEvent->modifiers());
5925 touchEvent.setTimestamp(sceneTouchEvent->timestamp());
5927 switch (touchEvent.type()) {
5928 case QEvent::TouchBegin:
5932 item->d_ptr->acceptedTouchBeginEvent =
true;
5933 bool res = sendTouchBeginEvent(item, &touchEvent) && touchEvent.isAccepted();
5936 const auto &unhandledTouchPoints = touchEvent.points();
5937 for (
const auto &touchPoint : unhandledTouchPoints) {
5938 itemForTouchPointId.remove(touchPoint.id());
5939 sceneCurrentTouchPoints.remove(touchPoint.id());
5941 ignoreSceneTouchEvent =
false;
5946 if (item->d_ptr->acceptedTouchBeginEvent) {
5947 updateTouchPointsForItem(item, &touchEvent);
5948 (
void) sendEvent(item, &touchEvent);
5949 ignoreSceneTouchEvent =
false;
5955 sceneTouchEvent->QInputEvent::setAccepted(ignoreSceneTouchEvent);
5958bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
5960 Q_Q(QGraphicsScene);
5963 if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.constFirst() != origin) {
5964 const QEventPoint &firstTouchPoint = touchEvent->points().first();
5965 cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.globalPosition().toPoint(),
5966 firstTouchPoint.scenePosition(),
5967 static_cast<QWidget *>(touchEvent->target()));
5971 bool setFocus =
false;
5973 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
5974 if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
5975 if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
5977 if (item != q->focusItem())
5978 q->setFocusItem(item, Qt::MouseFocusReason);
5982 if (item->isPanel())
5984 if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
5986 if (item->d_ptr->flags & QGraphicsItem::ItemStopsFocusHandling) {
5994 if (!stickyFocus && !setFocus)
5995 q->setFocusItem(
nullptr, Qt::MouseFocusReason);
5999 bool eventAccepted = touchEvent->isAccepted();
6000 for (QGraphicsItem *item : std::as_const(cachedItemsUnderMouse)) {
6002 updateTouchPointsForItem(item, touchEvent);
6003 bool acceptTouchEvents = item->acceptTouchEvents();
6004 touchEvent->setAccepted(acceptTouchEvents);
6005 res = acceptTouchEvents && sendEvent(item, touchEvent);
6006 eventAccepted = touchEvent->isAccepted();
6007 if (itemForTouchPointId.value(touchEvent->points().first().id()) == 0) {
6011 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
6013 touchEvent->m_spont =
false;
6014 if (res && eventAccepted) {
6016 const auto &touchPoints = touchEvent->points();
6017 for (
const auto &touchPoint : touchPoints)
6018 itemForTouchPointId[touchPoint.id()] = item;
6021 if (item && item->isPanel())
6026 touchEvent->QInputEvent::setAccepted(eventAccepted);
6182void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
6184 QWidget *viewport = event->widget();
6187 QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
6191 const QList<QGesture *> allGestures = event->gestures();
6192 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6193 <<
"Gestures:" << allGestures;
6195 QSet<QGesture *> startedGestures;
6196 QPoint delta = viewport->mapFromGlobal(QPoint());
6197 QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
6198 * graphicsView->viewportTransform().inverted();
6199 for (QGesture *gesture : allGestures) {
6201 if (gesture->hasHotSpot()) {
6202 gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
6204 gesture->d_func()->sceneHotSpot = QPointF();
6207 QGraphicsObject *target = gestureTargets.value(gesture, 0);
6211 if (gesture->state() == Qt::GestureStarted)
6212 startedGestures.insert(gesture);
6216 if (!startedGestures.isEmpty()) {
6217 QSet<QGesture *> normalGestures;
6218 QSet<QGesture *> conflictedGestures;
6219 gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures,
nullptr,
6220 &normalGestures, &conflictedGestures);
6221 cachedTargetItems = cachedItemGestures.keys();
6222 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6223 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6224 <<
"Normal gestures:" << normalGestures
6225 <<
"Conflicting gestures:" << conflictedGestures;
6229 if (!conflictedGestures.isEmpty()) {
6230 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6231 QPointer<QGraphicsObject> item = cachedTargetItems.at(i);
6234 const QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
6235 if (gestures.isEmpty())
6238 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6239 <<
"delivering override to"
6240 << item.data() << gestures;
6242 QGestureEvent ev(gestures.values());
6243 ev.t = QEvent::GestureOverride;
6244 ev.setWidget(event->widget());
6247 for (QGesture *g : gestures)
6248 ev.setAccepted(g,
false);
6249 sendEvent(item.data(), &ev);
6251 for (QGesture *g : gestures) {
6252 if (ev.isAccepted() || ev.isAccepted(g)) {
6253 conflictedGestures.remove(g);
6256 gestureTargets.insert(g, item.data());
6257 QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e;
6258 it = cachedItemGestures.begin();
6259 e = cachedItemGestures.end();
6260 for(; it != e; ++it)
6261 it.value().remove(g);
6262 cachedItemGestures[item.data()].insert(g);
6264 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6265 <<
"override was accepted:"
6266 << g << item.data();
6271 if (!gestureTargets.contains(g) && item)
6272 gestureTargets.insert(g, item.data());
6275 if (conflictedGestures.isEmpty())
6281 if (!normalGestures.isEmpty()) {
6282 for (
int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
6283 QGraphicsObject *item = cachedTargetItems.at(i);
6286 const auto gestures = cachedItemGestures.value(item);
6287 for (QGesture *g : gestures) {
6288 if (!gestureTargets.contains(g)) {
6289 gestureTargets.insert(g, item);
6290 normalGestures.remove(g);
6299 QSet<QGesture *> undeliveredGestures;
6300 QSet<QGesture *> parentPropagatedGestures;
6301 for (QGesture *gesture : allGestures) {
6302 if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
6303 cachedItemGestures[target].insert(gesture);
6304 cachedTargetItems.append(target);
6305 undeliveredGestures.insert(gesture);
6306 QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
6307 const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
6308 if (flags & Qt::IgnoredGesturesPropagateToParent)
6309 parentPropagatedGestures.insert(gesture);
6311 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6312 <<
"no target for" << gesture <<
"at"
6313 << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
6316 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6317 for (
int i = 0; i < cachedTargetItems.size(); ++i) {
6318 QPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
6319 const QSet<QGesture *> gestures = (undeliveredGestures
6320 & cachedItemGestures.value(receiver.data()))
6321 - cachedAlreadyDeliveredGestures.value(receiver.data());
6323 if (gestures.isEmpty())
6326 cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
6327 const bool isPanel = receiver.data()->isPanel();
6329 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6331 << receiver.data() << gestures;
6332 QGestureEvent ev(gestures.values());
6333 ev.setWidget(event->widget());
6334 sendEvent(receiver.data(), &ev);
6335 QSet<QGesture *> ignoredGestures;
6336 for (QGesture *g : gestures) {
6337 if (!ev.isAccepted() && !ev.isAccepted(g)) {
6343 if (receiver && receiver.data() == gestureTargets.value(g, 0))
6344 ignoredGestures.insert(g);
6346 if (receiver && g->state() == Qt::GestureStarted) {
6349 gestureTargets[g] = receiver.data();
6351 undeliveredGestures.remove(g);
6354 if (undeliveredGestures.isEmpty())
6359 if (!ignoredGestures.isEmpty() && !isPanel) {
6363 QSet<QGraphicsObject *> targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd());
6367 for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
6368 it != ignoredGestures.end();) {
6369 if (parentPropagatedGestures.contains(*it)) {
6370 QGesture *gesture = *it;
6371 const Qt::GestureType gestureType = gesture->gestureType();
6372 QGraphicsItem *item = receiver.data();
6374 if (QGraphicsObject *obj = item->toGraphicsObject()) {
6375 if (item->d_func()->gestureContext.contains(gestureType)) {
6376 targetsSet.insert(obj);
6377 cachedItemGestures[obj].insert(gesture);
6380 if (item->isPanel())
6382 item = item->parentItem();
6385 it = ignoredGestures.erase(it);
6392 gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
6393 &cachedItemGestures, &targetsSet,
nullptr,
nullptr);
6395 cachedTargetItems = targetsSet.values();
6396 std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
6397 DEBUG() <<
"QGraphicsScenePrivate::gestureEventHandler:"
6398 <<
"new targets:" << cachedTargetItems;
6404 for (QGesture *g : std::as_const(startedGestures)) {
6405 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
6406 DEBUG() <<
"lets try to cancel some";
6408 cancelGesturesForChildren(g);
6413 for (QGesture *g : allGestures) {
6414 switch (g->state()) {
6415 case Qt::GestureFinished:
6416 case Qt::GestureCanceled:
6417 gestureTargets.remove(g);
6424 cachedTargetItems.clear();
6425 cachedItemGestures.clear();
6426 cachedAlreadyDeliveredGestures.clear();
6429void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
6432 QGraphicsItem *originalItem = gestureTargets.value(original);
6433 if (originalItem ==
nullptr)
6439 QSet<QGesture *> canceledGestures;
6440 QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin();
6441 while (iter != gestureTargets.end()) {
6442 QGraphicsObject *item = iter.value();
6444 if (item != originalItem && originalItem->isAncestorOf(item)) {
6445 DEBUG() <<
" found a gesture to cancel" << iter.key();
6446 iter.key()->d_func()->state = Qt::GestureCanceled;
6447 canceledGestures << iter.key();
6453 QSet<QGesture *> almostCanceledGestures = canceledGestures;
6454 QSet<QGesture *>::Iterator setIter;
6455 while (!almostCanceledGestures.isEmpty()) {
6456 QGraphicsObject *target =
nullptr;
6457 QSet<QGesture*> gestures;
6458 setIter = almostCanceledGestures.begin();
6460 while (setIter != almostCanceledGestures.end()) {
6461 QGraphicsObject *item = gestureTargets.value(*setIter);
6462 if (target ==
nullptr)
6464 if (target == item) {
6465 gestures << *setIter;
6466 setIter = almostCanceledGestures.erase(setIter);
6473 const QList<QGesture *> list = gestures.values();
6474 QGestureEvent ev(list);
6475 sendEvent(target, &ev);
6477 if (!ev.isAccepted()) {
6478 for (QGesture *g : list) {
6480 if (ev.isAccepted(g))
6483 if (!g->hasHotSpot())
6486 const QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot,
nullptr);
6487 for (
const auto &item : items) {
6488 QGraphicsObject *object = item->toGraphicsObject();
6491 QGraphicsItemPrivate *d = object->QGraphicsItem::d_func();
6492 if (d->gestureContext.contains(g->gestureType())) {
6493 QList<QGesture *> list;
6495 QGestureEvent ev(list);
6496 sendEvent(object, &ev);
6497 if (ev.isAccepted() || ev.isAccepted(g))
6505 QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
6506 Q_ASSERT(gestureManager);
6507 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
6508 gestureManager->recycle(*setIter);
6509 gestureTargets.remove(*setIter);