src/gui/graphicsview/qgraphicsscene.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   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);
   704             if (item) {
   775             if (item) {
   705                 for (int i = 0; i < views.size(); ++i)
   776                 for (int i = 0; i < views.size(); ++i)
   706                     views.at(i)->inputContext()->reset();
   777                     views.at(i)->inputContext()->reset();
   707             }
   778             }
   708         }
   779         }
       
   780 #endif //QT_NO_IM
   709     }
   781     }
   710 
   782 
   711     if (item) {
   783     if (item) {
   712         focusItem = item;
   784         focusItem = item;
   713         QFocusEvent event(QEvent::FocusIn, focusReason);
   785         QFocusEvent event(QEvent::FocusIn, focusReason);
  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