292 processDirtyItemsEmitted(false), |
292 processDirtyItemsEmitted(false), |
293 selectionChanging(0), |
293 selectionChanging(0), |
294 needSortTopLevelItems(true), |
294 needSortTopLevelItems(true), |
295 holesInTopLevelSiblingIndex(false), |
295 holesInTopLevelSiblingIndex(false), |
296 topLevelSequentialOrdering(true), |
296 topLevelSequentialOrdering(true), |
|
297 scenePosDescendantsUpdatePending(false), |
297 stickyFocus(false), |
298 stickyFocus(false), |
298 hasFocus(false), |
299 hasFocus(false), |
299 focusItem(0), |
300 focusItem(0), |
300 lastFocusItem(0), |
301 lastFocusItem(0), |
301 tabFocusFirst(0), |
302 tabFocusFirst(0), |
486 views.at(i)->d_func()->dispatchPendingUpdateRequests(); |
487 views.at(i)->d_func()->dispatchPendingUpdateRequests(); |
487 } |
488 } |
488 |
489 |
489 /*! |
490 /*! |
490 \internal |
491 \internal |
|
492 */ |
|
493 void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled) |
|
494 { |
|
495 QGraphicsItem *p = item->d_ptr->parent; |
|
496 while (p) { |
|
497 p->d_ptr->scenePosDescendants = enabled; |
|
498 p = p->d_ptr->parent; |
|
499 } |
|
500 if (!enabled && !scenePosDescendantsUpdatePending) { |
|
501 scenePosDescendantsUpdatePending = true; |
|
502 QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection); |
|
503 } |
|
504 } |
|
505 |
|
506 /*! |
|
507 \internal |
|
508 */ |
|
509 void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item) |
|
510 { |
|
511 scenePosItems.insert(item); |
|
512 setScenePosItemEnabled(item, true); |
|
513 } |
|
514 |
|
515 /*! |
|
516 \internal |
|
517 */ |
|
518 void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item) |
|
519 { |
|
520 scenePosItems.remove(item); |
|
521 setScenePosItemEnabled(item, false); |
|
522 } |
|
523 |
|
524 /*! |
|
525 \internal |
|
526 */ |
|
527 void QGraphicsScenePrivate::_q_updateScenePosDescendants() |
|
528 { |
|
529 foreach (QGraphicsItem *item, scenePosItems) { |
|
530 QGraphicsItem *p = item->d_ptr->parent; |
|
531 while (p) { |
|
532 p->d_ptr->scenePosDescendants = 1; |
|
533 p = p->d_ptr->parent; |
|
534 } |
|
535 } |
|
536 scenePosDescendantsUpdatePending = false; |
|
537 } |
|
538 |
|
539 /*! |
|
540 \internal |
491 |
541 |
492 Schedules an item for removal. This function leaves some stale indexes |
542 Schedules an item for removal. This function leaves some stale indexes |
493 around in the BSP tree if called from the item's destructor; these will |
543 around in the BSP tree if called from the item's destructor; these will |
494 be cleaned up the next time someone triggers purgeRemovedItems(). |
544 be cleaned up the next time someone triggers purgeRemovedItems(). |
495 |
545 |
503 Q_Q(QGraphicsScene); |
553 Q_Q(QGraphicsScene); |
504 |
554 |
505 // Clear focus on the item to remove any reference in the focusWidget chain. |
555 // Clear focus on the item to remove any reference in the focusWidget chain. |
506 item->clearFocus(); |
556 item->clearFocus(); |
507 |
557 |
508 markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true); |
558 markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false, |
|
559 /*ignoreOpacity=*/false, /*removingItemFromScene=*/true); |
509 |
560 |
510 if (item->d_ptr->inDestructor) { |
561 if (item->d_ptr->inDestructor) { |
511 // The item is actually in its destructor, we call the special method in the index. |
562 // The item is actually in its destructor, we call the special method in the index. |
512 index->deleteItem(item); |
563 index->deleteItem(item); |
513 } else { |
564 } else { |
516 index->removeItem(item); |
567 index->removeItem(item); |
517 } |
568 } |
518 |
569 |
519 item->d_ptr->clearSubFocus(); |
570 item->d_ptr->clearSubFocus(); |
520 |
571 |
|
572 if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) |
|
573 unregisterScenePosItem(item); |
|
574 |
|
575 QGraphicsScene *oldScene = item->d_func()->scene; |
|
576 item->d_func()->scene = 0; |
|
577 |
|
578 //We need to remove all children first because they might use their parent |
|
579 //attributes (e.g. sceneTransform). |
|
580 if (!item->d_ptr->inDestructor) { |
|
581 // Remove all children recursively |
|
582 for (int i = 0; i < item->d_ptr->children.size(); ++i) |
|
583 q->removeItem(item->d_ptr->children.at(i)); |
|
584 } |
|
585 |
521 if (!item->d_ptr->inDestructor && item == tabFocusFirst) { |
586 if (!item->d_ptr->inDestructor && item == tabFocusFirst) { |
522 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); |
587 QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); |
523 widget->d_func()->fixFocusChainBeforeReparenting(0, 0); |
588 widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0); |
524 } |
589 } |
525 |
|
526 item->d_func()->scene = 0; |
|
527 |
590 |
528 // Unregister focus proxy. |
591 // Unregister focus proxy. |
529 item->d_ptr->resetFocusProxy(); |
592 item->d_ptr->resetFocusProxy(); |
530 |
593 |
531 // Remove from parent, or unregister from toplevels. |
594 // Remove from parent, or unregister from toplevels. |
549 activePanel = 0; |
612 activePanel = 0; |
550 } |
613 } |
551 if (item == lastActivePanel) |
614 if (item == lastActivePanel) |
552 lastActivePanel = 0; |
615 lastActivePanel = 0; |
553 |
616 |
|
617 // Cancel active touches |
|
618 { |
|
619 QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin(); |
|
620 while (it != itemForTouchPointId.end()) { |
|
621 if (it.value() == item) { |
|
622 sceneCurrentTouchPoints.remove(it.key()); |
|
623 it = itemForTouchPointId.erase(it); |
|
624 } else { |
|
625 ++it; |
|
626 } |
|
627 } |
|
628 } |
|
629 |
554 // Disable selectionChanged() for individual items |
630 // Disable selectionChanged() for individual items |
555 ++selectionChanging; |
631 ++selectionChanging; |
556 int oldSelectedItemsSize = selectedItems.size(); |
632 int oldSelectedItemsSize = selectedItems.size(); |
557 |
633 |
558 // Update selected & hovered item bookkeeping |
634 // Update selected & hovered item bookkeeping |
567 while (iterator != sceneEventFilters.end()) { |
643 while (iterator != sceneEventFilters.end()) { |
568 if (iterator.value() == item || iterator.key() == item) |
644 if (iterator.value() == item || iterator.key() == item) |
569 iterator = sceneEventFilters.erase(iterator); |
645 iterator = sceneEventFilters.erase(iterator); |
570 else |
646 else |
571 ++iterator; |
647 ++iterator; |
572 } |
|
573 |
|
574 if (!item->d_ptr->inDestructor) { |
|
575 // Remove all children recursively |
|
576 for (int i = 0; i < item->d_ptr->children.size(); ++i) |
|
577 q->removeItem(item->d_ptr->children.at(i)); |
|
578 } |
648 } |
579 |
649 |
580 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) |
650 if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal) |
581 leaveModal(item); |
651 leaveModal(item); |
582 |
652 |
689 QFocusEvent event(QEvent::FocusOut, focusReason); |
759 QFocusEvent event(QEvent::FocusOut, focusReason); |
690 lastFocusItem = focusItem; |
760 lastFocusItem = focusItem; |
691 focusItem = 0; |
761 focusItem = 0; |
692 sendEvent(lastFocusItem, &event); |
762 sendEvent(lastFocusItem, &event); |
693 |
763 |
|
764 #ifndef QT_NO_IM |
694 if (lastFocusItem |
765 if (lastFocusItem |
695 && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { |
766 && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { |
696 // Reset any visible preedit text |
767 // Reset any visible preedit text |
697 QInputMethodEvent imEvent; |
768 QInputMethodEvent imEvent; |
698 sendEvent(lastFocusItem, &imEvent); |
769 sendEvent(lastFocusItem, &imEvent); |
1058 enabled, the event is sent; otherwise it is stopped. |
1130 enabled, the event is sent; otherwise it is stopped. |
1059 */ |
1131 */ |
1060 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) |
1132 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) |
1061 { |
1133 { |
1062 if (QGraphicsObject *object = item->toGraphicsObject()) { |
1134 if (QGraphicsObject *object = item->toGraphicsObject()) { |
1063 QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); |
1135 if (qt_gestureManager) { |
1064 if (qAppPriv->gestureManager) { |
1136 if (qt_gestureManager->filterEvent(object, event)) |
1065 if (qAppPriv->gestureManager->filterEvent(object, event)) |
|
1066 return true; |
1137 return true; |
1067 } |
1138 } |
1068 } |
1139 } |
1069 |
1140 |
1070 if (filterEvent(item, event)) |
1141 if (filterEvent(item, event)) |
2288 { |
2359 { |
2289 Q_D(QGraphicsScene); |
2360 Q_D(QGraphicsScene); |
2290 // NB! We have to clear the index before deleting items; otherwise the |
2361 // NB! We have to clear the index before deleting items; otherwise the |
2291 // index might try to access dangling item pointers. |
2362 // index might try to access dangling item pointers. |
2292 d->index->clear(); |
2363 d->index->clear(); |
2293 const QList<QGraphicsItem *> items = d->topLevelItems; |
2364 // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items |
2294 qDeleteAll(items); |
2365 while (!d->topLevelItems.isEmpty()) |
|
2366 delete d->topLevelItems.first(); |
2295 Q_ASSERT(d->topLevelItems.isEmpty()); |
2367 Q_ASSERT(d->topLevelItems.isEmpty()); |
2296 d->lastItemCount = 0; |
2368 d->lastItemCount = 0; |
2297 d->allItemsIgnoreHoverEvents = true; |
2369 d->allItemsIgnoreHoverEvents = true; |
2298 d->allItemsUseDefaultCursor = true; |
2370 d->allItemsUseDefaultCursor = true; |
2299 d->allItemsIgnoreTouchEvents = true; |
2371 d->allItemsIgnoreTouchEvents = true; |
2497 |
2569 |
2498 // Resolve font and palette. |
2570 // Resolve font and palette. |
2499 item->d_ptr->resolveFont(d->font.resolve()); |
2571 item->d_ptr->resolveFont(d->font.resolve()); |
2500 item->d_ptr->resolvePalette(d->palette.resolve()); |
2572 item->d_ptr->resolvePalette(d->palette.resolve()); |
2501 |
2573 |
2502 if (!item->d_ptr->explicitlyHidden) { |
2574 if (d->unpolishedItems.isEmpty()) |
2503 if (d->unpolishedItems.isEmpty()) |
2575 QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); |
2504 QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); |
2576 d->unpolishedItems.insert(item); |
2505 d->unpolishedItems.insert(item); |
|
2506 } |
|
2507 |
2577 |
2508 // Reenable selectionChanged() for individual items |
2578 // Reenable selectionChanged() for individual items |
2509 --d->selectionChanging; |
2579 --d->selectionChanging; |
2510 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize) |
2580 if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize) |
2511 emit selectionChanged(); |
2581 emit selectionChanged(); |
2535 else |
2605 else |
2536 d->lastActivePanel = item; |
2606 d->lastActivePanel = item; |
2537 } |
2607 } |
2538 } |
2608 } |
2539 |
2609 |
|
2610 if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges) |
|
2611 d->registerScenePosItem(item); |
|
2612 |
2540 // Ensure that newly added items that have subfocus set, gain |
2613 // Ensure that newly added items that have subfocus set, gain |
2541 // focus automatically if there isn't a focus item already. |
2614 // focus automatically if there isn't a focus item already. |
2542 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) |
2615 if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) |
2543 item->focusItem()->setFocus(); |
2616 item->focusItem()->setFocus(); |
2544 |
2617 |
2821 |
2894 |
2822 d->updateInputMethodSensitivityInViews(); |
2895 d->updateInputMethodSensitivityInViews(); |
2823 } |
2896 } |
2824 |
2897 |
2825 /*! |
2898 /*! |
2826 Returns the scene's current focus item, or 0 if no item currently has |
2899 When the scene is active, this functions returns the scene's current focus |
2827 focus. |
2900 item, or 0 if no item currently has focus. When the scene is inactive, this |
|
2901 functions returns the item that will gain input focus when the scene becomes |
|
2902 active. |
2828 |
2903 |
2829 The focus item receives keyboard input when the scene receives a |
2904 The focus item receives keyboard input when the scene receives a |
2830 key event. |
2905 key event. |
2831 |
2906 |
2832 \sa setFocusItem(), QGraphicsItem::hasFocus() |
2907 \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive() |
2833 */ |
2908 */ |
2834 QGraphicsItem *QGraphicsScene::focusItem() const |
2909 QGraphicsItem *QGraphicsScene::focusItem() const |
2835 { |
2910 { |
2836 Q_D(const QGraphicsScene); |
2911 Q_D(const QGraphicsScene); |
2837 return d->focusItem; |
2912 return isActive() ? d->focusItem : d->lastFocusItem; |
2838 } |
2913 } |
2839 |
2914 |
2840 /*! |
2915 /*! |
2841 Sets the scene's focus item to \a item, with the focus reason \a |
2916 Sets the scene's focus item to \a item, with the focus reason \a |
2842 focusReason, after removing focus from any previous item that may have had |
2917 focusReason, after removing focus from any previous item that may have had |
4144 QPixmap subPix; |
4219 QPixmap subPix; |
4145 QPainter pixmapPainter; |
4220 QPainter pixmapPainter; |
4146 QRect br = pixmapExposed.boundingRect(); |
4221 QRect br = pixmapExposed.boundingRect(); |
4147 |
4222 |
4148 // Don't use subpixmap if we get a full update. |
4223 // Don't use subpixmap if we get a full update. |
4149 if (pixmapExposed.isEmpty() || (pixmapExposed.numRects() == 1 && br.contains(pix->rect()))) { |
4224 if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) { |
4150 pix->fill(Qt::transparent); |
4225 pix->fill(Qt::transparent); |
4151 pixmapPainter.begin(pix); |
4226 pixmapPainter.begin(pix); |
4152 } else { |
4227 } else { |
4153 subPix = QPixmap(br.size()); |
4228 subPix = QPixmap(br.size()); |
4154 subPix.fill(Qt::transparent); |
4229 subPix.fill(Qt::transparent); |
4170 pixmapPainter.end(); |
4245 pixmapPainter.end(); |
4171 |
4246 |
4172 if (!subPix.isNull()) { |
4247 if (!subPix.isNull()) { |
4173 // Blit the subpixmap into the main pixmap. |
4248 // Blit the subpixmap into the main pixmap. |
4174 pixmapPainter.begin(pix); |
4249 pixmapPainter.begin(pix); |
4175 pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); |
|
4176 pixmapPainter.setClipRegion(pixmapExposed); |
4250 pixmapPainter.setClipRegion(pixmapExposed); |
4177 pixmapPainter.drawPixmap(br.topLeft(), subPix); |
4251 pixmapPainter.drawPixmap(br.topLeft(), subPix); |
4178 pixmapPainter.end(); |
4252 pixmapPainter.end(); |
4179 } |
4253 } |
4180 } |
4254 } |
4358 #if 0 |
4432 #if 0 |
4359 // Only if the device rect isn't fully contained. |
4433 // Only if the device rect isn't fully contained. |
4360 bool allowPartialCacheExposure = !viewRect.contains(deviceRect); |
4434 bool allowPartialCacheExposure = !viewRect.contains(deviceRect); |
4361 #else |
4435 #else |
4362 // Only if deviceRect is 20% taller or wider than the desktop. |
4436 // Only if deviceRect is 20% taller or wider than the desktop. |
4363 QRect desktopRect = QApplication::desktop()->availableGeometry(widget); |
4437 bool allowPartialCacheExposure = false; |
4364 bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() |
4438 if (widget) { |
4365 || desktopRect.height() * 1.2 < deviceRect.height()); |
4439 QRect desktopRect = QApplication::desktop()->availableGeometry(widget); |
|
4440 allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width() |
|
4441 || desktopRect.height() * 1.2 < deviceRect.height()); |
|
4442 } |
4366 #endif |
4443 #endif |
4367 QRegion scrollExposure; |
4444 QRegion scrollExposure; |
4368 if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) { |
4445 if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) { |
4369 // Part of pixmap is drawn. Either device contains viewrect (big |
4446 // Part of pixmap is drawn. Either device contains viewrect (big |
4370 // item covers whole screen) or parts of device are outside the |
4447 // item covers whole screen) or parts of device are outside the |
4576 } // else we know for sure this item has children we must process. |
4653 } // else we know for sure this item has children we must process. |
4577 |
4654 |
4578 if (itemHasChildren && itemClipsChildrenToShape) |
4655 if (itemHasChildren && itemClipsChildrenToShape) |
4579 ENSURE_TRANSFORM_PTR; |
4656 ENSURE_TRANSFORM_PTR; |
4580 |
4657 |
|
4658 #ifndef QT_NO_GRAPHICSEFFECT |
4581 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { |
4659 if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { |
4582 ENSURE_TRANSFORM_PTR; |
4660 ENSURE_TRANSFORM_PTR; |
4583 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, |
4661 QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, |
4584 painter, opacity, wasDirtyParentSceneTransform, drawItem); |
4662 painter, opacity, wasDirtyParentSceneTransform, drawItem); |
4585 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; |
4663 QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; |
4591 painter->setWorldTransform(*transformPtr * *effectTransform); |
4669 painter->setWorldTransform(*transformPtr * *effectTransform); |
4592 else |
4670 else |
4593 painter->setWorldTransform(*transformPtr); |
4671 painter->setWorldTransform(*transformPtr); |
4594 painter->setOpacity(opacity); |
4672 painter->setOpacity(opacity); |
4595 |
4673 |
4596 if (sourced->lastEffectTransform != painter->worldTransform()) { |
4674 if (sourced->currentCachedSystem() != Qt::LogicalCoordinates |
|
4675 && sourced->lastEffectTransform != painter->worldTransform()) |
|
4676 { |
4597 sourced->lastEffectTransform = painter->worldTransform(); |
4677 sourced->lastEffectTransform = painter->worldTransform(); |
4598 sourced->invalidateCache(); |
4678 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged); |
4599 } |
4679 } |
4600 item->d_ptr->graphicsEffect->draw(painter, source); |
4680 |
|
4681 item->d_ptr->graphicsEffect->draw(painter); |
4601 painter->setWorldTransform(restoreTransform); |
4682 painter->setWorldTransform(restoreTransform); |
4602 sourced->info = 0; |
4683 sourced->info = 0; |
4603 } else { |
4684 } else |
|
4685 #endif //QT_NO_GRAPHICSEFFECT |
|
4686 { |
4604 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, |
4687 draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, |
4605 effectTransform, wasDirtyParentSceneTransform, drawItem); |
4688 effectTransform, wasDirtyParentSceneTransform, drawItem); |
4606 } |
4689 } |
4607 } |
4690 } |
4608 |
4691 |
4691 if (itemHasChildren && itemClipsChildrenToShape) |
4774 if (itemHasChildren && itemClipsChildrenToShape) |
4692 painter->restore(); |
4775 painter->restore(); |
4693 } |
4776 } |
4694 |
4777 |
4695 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, |
4778 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren, |
4696 bool maybeDirtyClipPath, bool force, bool ignoreOpacity, |
4779 bool force, bool ignoreOpacity, bool removingItemFromScene) |
4697 bool removingItemFromScene) |
|
4698 { |
4780 { |
4699 Q_ASSERT(item); |
4781 Q_ASSERT(item); |
4700 if (updateAll) |
4782 if (updateAll) |
4701 return; |
4783 return; |
4702 |
4784 |
4703 if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, |
4785 if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force, |
4704 /*ignoreVisibleBit=*/force, |
|
4705 /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, |
4786 /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, |
4706 /*ignoreOpacity=*/ignoreOpacity)) { |
4787 /*ignoreOpacity=*/ignoreOpacity)) { |
4707 if (item->d_ptr->dirty) { |
4788 if (item->d_ptr->dirty) { |
4708 // The item is already marked as dirty and will be processed later. However, |
4789 // The item is already marked as dirty and will be processed later. However, |
4709 // we have to make sure ignoreVisible and ignoreOpacity are set properly; |
4790 // we have to make sure ignoreVisible and ignoreOpacity are set properly; |
4767 item->d_ptr->ignoreOpacity = 1; |
4848 item->d_ptr->ignoreOpacity = 1; |
4768 |
4849 |
4769 QGraphicsItem *p = item->d_ptr->parent; |
4850 QGraphicsItem *p = item->d_ptr->parent; |
4770 while (p) { |
4851 while (p) { |
4771 p->d_ptr->dirtyChildren = 1; |
4852 p->d_ptr->dirtyChildren = 1; |
|
4853 #ifndef QT_NO_GRAPHICSEFFECT |
4772 if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { |
4854 if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) { |
4773 p->d_ptr->dirty = 1; |
4855 p->d_ptr->dirty = 1; |
4774 p->d_ptr->fullUpdatePending = 1; |
4856 p->d_ptr->fullUpdatePending = 1; |
4775 } |
4857 } |
|
4858 #endif //QT_NO_GRAPHICSEFFECT |
4776 p = p->d_ptr->parent; |
4859 p = p->d_ptr->parent; |
4777 } |
4860 } |
4778 } |
4861 } |
4779 |
4862 |
4780 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, |
4863 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, |
4912 // it is inside the viewport, but for now we can pretend that it is outside. |
4995 // it is inside the viewport, but for now we can pretend that it is outside. |
4913 paintedViewBoundingRect = QRect(-1, -1, -1, -1); |
4996 paintedViewBoundingRect = QRect(-1, -1, -1, -1); |
4914 continue; |
4997 continue; |
4915 } |
4998 } |
4916 |
4999 |
4917 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) { |
5000 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { |
4918 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); |
5001 paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); |
4919 if (!viewPrivate->updateRect(paintedViewBoundingRect)) |
5002 if (!viewPrivate->updateRect(paintedViewBoundingRect)) |
4920 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. |
5003 paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. |
4921 } |
5004 } |
4922 |
5005 |
5611 updateTouchPointsForItem(item, touchEvent); |
5694 updateTouchPointsForItem(item, touchEvent); |
5612 bool acceptTouchEvents = item->acceptTouchEvents(); |
5695 bool acceptTouchEvents = item->acceptTouchEvents(); |
5613 touchEvent->setAccepted(acceptTouchEvents); |
5696 touchEvent->setAccepted(acceptTouchEvents); |
5614 res = acceptTouchEvents && sendEvent(item, touchEvent); |
5697 res = acceptTouchEvents && sendEvent(item, touchEvent); |
5615 eventAccepted = touchEvent->isAccepted(); |
5698 eventAccepted = touchEvent->isAccepted(); |
5616 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted); |
5699 if (itemForTouchPointId.value(touchEvent->touchPoints().first().id()) == 0) { |
|
5700 // item was deleted |
|
5701 item = 0; |
|
5702 } else { |
|
5703 item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted); |
|
5704 } |
5617 touchEvent->spont = false; |
5705 touchEvent->spont = false; |
5618 if (res && eventAccepted) { |
5706 if (res && eventAccepted) { |
5619 // the first item to accept the TouchBegin gets an implicit grab. |
5707 // the first item to accept the TouchBegin gets an implicit grab. |
5620 for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { |
5708 for (int i = 0; i < touchEvent->touchPoints().count(); ++i) { |
5621 const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); |
5709 const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i); |
5622 itemForTouchPointId[touchPoint.id()] = item; |
5710 itemForTouchPointId[touchPoint.id()] = item; // can be zero |
5623 } |
5711 } |
5624 break; |
5712 break; |
5625 } |
5713 } |
5626 if (item->isPanel()) |
5714 if (item && item->isPanel()) |
5627 break; |
5715 break; |
5628 } |
5716 } |
5629 |
5717 |
5630 touchEvent->setAccepted(eventAccepted); |
5718 touchEvent->setAccepted(eventAccepted); |
5631 return res; |
5719 return res; |
5767 void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) |
5855 void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) |
5768 { |
5856 { |
5769 QWidget *viewport = event->widget(); |
5857 QWidget *viewport = event->widget(); |
5770 if (!viewport) |
5858 if (!viewport) |
5771 return; |
5859 return; |
5772 QList<QGesture *> allGestures = event->allGestures(); |
5860 QList<QGesture *> allGestures = event->gestures(); |
5773 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
5861 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
5774 << "Delivering gestures:" << allGestures; |
5862 << "Delivering gestures:" << allGestures; |
5775 |
5863 |
5776 typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem; |
5864 typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem; |
5777 GesturesPerItem gesturesPerItem; |
5865 GesturesPerItem gesturesPerItem; |
5906 if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item |
5994 if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item |
5907 continue; |
5995 continue; |
5908 |
5996 |
5909 QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func(); |
5997 QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func(); |
5910 foreach(QGesture *g, alreadyIgnoredGestures) { |
5998 foreach(QGesture *g, alreadyIgnoredGestures) { |
5911 if (gid->gestureContext.contains(g->gestureType())) |
5999 QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit = |
|
6000 gid->gestureContext.find(g->gestureType()); |
|
6001 bool deliver = contextit != gid->gestureContext.end() && |
|
6002 (g->state() == Qt::GestureStarted || |
|
6003 (contextit.value() & Qt::ReceivePartialGestures)); |
|
6004 if (deliver) |
5912 gestures += g; |
6005 gestures += g; |
5913 } |
6006 } |
5914 if (gestures.isEmpty()) |
6007 if (gestures.isEmpty()) |
5915 continue; |
6008 continue; |
5916 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
6009 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
5919 QGestureEvent ev(gestures); |
6012 QGestureEvent ev(gestures); |
5920 ev.setWidget(event->widget()); |
6013 ev.setWidget(event->widget()); |
5921 sendEvent(item, &ev); |
6014 sendEvent(item, &ev); |
5922 QSet<QGesture *> ignoredGestures; |
6015 QSet<QGesture *> ignoredGestures; |
5923 foreach (QGesture *g, gestures) { |
6016 foreach (QGesture *g, gestures) { |
5924 if (!ev.isAccepted() && !ev.isAccepted(g)) |
6017 if (!ev.isAccepted() && !ev.isAccepted(g)) { |
5925 ignoredGestures.insert(g); |
6018 ignoredGestures.insert(g); |
|
6019 } else { |
|
6020 if (g->state() == Qt::GestureStarted) |
|
6021 gestureTargets[g] = item; |
|
6022 } |
5926 } |
6023 } |
5927 if (!ignoredGestures.isEmpty()) { |
6024 if (!ignoredGestures.isEmpty()) { |
5928 // get a list of items under the (current) hotspot of each ignored |
6025 // get a list of items under the (current) hotspot of each ignored |
5929 // gesture and start delivery again from the beginning |
6026 // gesture and start delivery again from the beginning |
5930 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
6027 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" |
5947 << "new targets:" << targetItems; |
6044 << "new targets:" << targetItems; |
5948 i = -1; // start delivery again |
6045 i = -1; // start delivery again |
5949 continue; |
6046 continue; |
5950 } |
6047 } |
5951 } |
6048 } |
|
6049 foreach (QGesture *g, startedGestures) { |
|
6050 if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) { |
|
6051 DEBUG() << "lets try to cancel some"; |
|
6052 // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them |
|
6053 cancelGesturesForChildren(g, event->widget()); |
|
6054 } |
|
6055 } |
5952 |
6056 |
5953 // forget about targets for gestures that have ended |
6057 // forget about targets for gestures that have ended |
5954 foreach (QGesture *g, allGestures) { |
6058 foreach (QGesture *g, allGestures) { |
5955 switch (g->state()) { |
6059 switch (g->state()) { |
5956 case Qt::GestureFinished: |
6060 case Qt::GestureFinished: |
5961 break; |
6065 break; |
5962 } |
6066 } |
5963 } |
6067 } |
5964 } |
6068 } |
5965 |
6069 |
|
6070 void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport) |
|
6071 { |
|
6072 Q_ASSERT(original); |
|
6073 QGraphicsItem *originalItem = gestureTargets.value(original); |
|
6074 Q_ASSERT(originalItem); |
|
6075 |
|
6076 // iterate over all active gestures and for each find the owner |
|
6077 // if the owner is part of our sub-hierarchy, cancel it. |
|
6078 |
|
6079 QSet<QGesture *> canceledGestures; |
|
6080 QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin(); |
|
6081 while (iter != gestureTargets.end()) { |
|
6082 QGraphicsObject *item = iter.value(); |
|
6083 // note that we don't touch the gestures for our originalItem |
|
6084 if (item != originalItem && originalItem->isAncestorOf(item)) { |
|
6085 DEBUG() << " found a gesture to cancel" << iter.key(); |
|
6086 iter.key()->d_func()->state = Qt::GestureCanceled; |
|
6087 canceledGestures << iter.key(); |
|
6088 } |
|
6089 ++iter; |
|
6090 } |
|
6091 |
|
6092 // sort them per target item by cherry picking from almostCanceledGestures and delivering |
|
6093 QSet<QGesture *> almostCanceledGestures = canceledGestures; |
|
6094 QSet<QGesture *>::Iterator setIter; |
|
6095 while (!almostCanceledGestures.isEmpty()) { |
|
6096 QGraphicsObject *target = 0; |
|
6097 QSet<QGesture*> gestures; |
|
6098 setIter = almostCanceledGestures.begin(); |
|
6099 // sort per target item |
|
6100 while (setIter != almostCanceledGestures.end()) { |
|
6101 QGraphicsObject *item = gestureTargets.value(*setIter); |
|
6102 if (target == 0) |
|
6103 target = item; |
|
6104 if (target == item) { |
|
6105 gestures << *setIter; |
|
6106 setIter = almostCanceledGestures.erase(setIter); |
|
6107 } else { |
|
6108 ++setIter; |
|
6109 } |
|
6110 } |
|
6111 Q_ASSERT(target); |
|
6112 |
|
6113 QList<QGesture *> list = gestures.toList(); |
|
6114 QGestureEvent ev(list); |
|
6115 sendEvent(target, &ev); |
|
6116 |
|
6117 foreach (QGesture *g, list) { |
|
6118 if (ev.isAccepted() || ev.isAccepted(g)) |
|
6119 gestures.remove(g); |
|
6120 } |
|
6121 |
|
6122 foreach (QGesture *g, gestures) { |
|
6123 if (!g->hasHotSpot()) |
|
6124 continue; |
|
6125 |
|
6126 QPoint screenPos = g->hotSpot().toPoint(); |
|
6127 QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport); |
|
6128 for (int j = 0; j < items.size(); ++j) { |
|
6129 QGraphicsObject *item = items.at(j)->toGraphicsObject(); |
|
6130 if (!item) |
|
6131 continue; |
|
6132 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); |
|
6133 if (d->gestureContext.contains(g->gestureType())) { |
|
6134 QList<QGesture *> list; |
|
6135 list << g; |
|
6136 QGestureEvent ev(list); |
|
6137 sendEvent(item, &ev); |
|
6138 if (ev.isAccepted() || ev.isAccepted(g)) |
|
6139 break; // successfully delivered |
|
6140 } |
|
6141 } |
|
6142 } |
|
6143 } |
|
6144 |
|
6145 Q_ASSERT(qt_gestureManager); // it would be very odd if we got called without a manager. |
|
6146 for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) { |
|
6147 qt_gestureManager->recycle(*setIter); |
|
6148 gestureTargets.remove(*setIter); |
|
6149 } |
|
6150 } |
|
6151 |
5966 QT_END_NAMESPACE |
6152 QT_END_NAMESPACE |
5967 |
6153 |
5968 #include "moc_qgraphicsscene.cpp" |
6154 #include "moc_qgraphicsscene.cpp" |
5969 |
6155 |
5970 #endif // QT_NO_GRAPHICSVIEW |
6156 #endif // QT_NO_GRAPHICSVIEW |