diff -r 5dc02b23752f -r 3e2da88830cd src/gui/graphicsview/qgraphicsscene.cpp --- a/src/gui/graphicsview/qgraphicsscene.cpp Tue Jul 06 15:10:48 2010 +0300 +++ b/src/gui/graphicsview/qgraphicsscene.cpp Wed Aug 18 10:37:55 2010 +0300 @@ -699,6 +699,7 @@ if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize) emit q->selectionChanged(); +#ifndef QT_NO_GESTURES QHash::iterator it; for (it = gestureTargets.begin(); it != gestureTargets.end();) { if (it.value() == item) @@ -706,6 +707,7 @@ else ++it; } + QGraphicsObject *dummy = static_cast(item); cachedTargetItems.removeOne(dummy); cachedItemGestures.remove(dummy); @@ -713,6 +715,7 @@ foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) ungrabGesture(item, gesture); +#endif // QT_NO_GESTURES } /*! @@ -882,8 +885,7 @@ ungrabKeyboard(static_cast(widget), itemIsDying); } if (!itemIsDying && widget->isVisible()) { - widget->hide(); - widget->QGraphicsItem::d_ptr->explicitlyHidden = 0; + widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false); } } } @@ -1180,11 +1182,13 @@ bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) { if (QGraphicsObject *object = item->toGraphicsObject()) { +#ifndef QT_NO_GESTURES QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager; if (gestureManager) { if (gestureManager->filterEvent(object, event)) return true; } +#endif // QT_NO_GESTURES } if (filterEvent(item, event)) @@ -1331,6 +1335,8 @@ break; } } + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; if (item->isPanel()) break; } @@ -2602,8 +2608,10 @@ d->enableTouchEventsOnViews(); } +#ifndef QT_NO_GESTURES foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) d->grabGesture(item, gesture); +#endif // Update selection lists if (item->isSelected()) @@ -3525,10 +3533,12 @@ case QEvent::TouchEnd: d->touchEventHandler(static_cast(event)); break; +#ifndef QT_NO_GESTURES case QEvent::Gesture: case QEvent::GestureOverride: d->gestureEventHandler(static_cast(event)); break; +#endif // QT_NO_GESTURES default: return QObject::event(event); } @@ -4154,6 +4164,25 @@ wheelEvent->scenePos(), wheelEvent->widget()); +#ifdef Q_WS_MAC + // On Mac, ignore the event if the first item under the mouse is not the last opened + // popup (or one of its descendant) + if (!d->popupWidgets.isEmpty() && !wheelCandidates.isEmpty() && wheelCandidates.first() != d->popupWidgets.back() && !d->popupWidgets.back()->isAncestorOf(wheelCandidates.first())) { + wheelEvent->accept(); + return; + } +#else + // Find the first popup under the mouse (including the popup's descendants) starting from the last. + // Remove all popups after the one found, or all or them if no popup is under the mouse. + // Then continue with the event. + QList::const_iterator iter = d->popupWidgets.end(); + while (--iter >= d->popupWidgets.begin() && !wheelCandidates.isEmpty()) { + if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first())) + break; + d->removePopup(*iter); + } +#endif + bool hasSetFocus = false; foreach (QGraphicsItem *item, wheelCandidates) { if (!hasSetFocus && item->isEnabled() @@ -4889,6 +4918,24 @@ if (updateAll) return; + if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) { + // If any of the item's ancestors ignore opacity, it means that the opacity + // was set to 0 (and the update request has not yet been processed). That + // also means that we have to ignore the opacity for the item itself; otherwise + // things like: parent->setOpacity(0); scene->removeItem(child) won't work. + // Note that we only do this when removing items from the scene. In all other + // cases the ignoreOpacity bit propagates properly in processDirtyItems, but + // since the item is removed immediately it won't be processed there. + QGraphicsItem *p = item->d_ptr->parent; + while (p) { + if (p->d_ptr->ignoreOpacity) { + item->d_ptr->ignoreOpacity = true; + break; + } + p = p->d_ptr->parent; + } + } + if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force, /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, /*ignoreOpacity=*/ignoreOpacity)) { @@ -5131,7 +5178,12 @@ // Process children. if (itemHasChildren && item->d_ptr->dirtyChildren) { const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; - if (itemClipsChildrenToShape) { + // Items with no content are threated as 'dummy' items which means they are never drawn and + // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever + // such an item changes geometry, its children have to take care of the update regardless + // of whether the item clips children to shape or not. + const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects; + if (itemClipsChildrenToShape && !bypassUpdateClip) { // Make sure child updates are clipped to the item's bounding rect. for (int i = 0; i < views.size(); ++i) views.at(i)->d_func()->setUpdateClip(item); @@ -5619,8 +5671,10 @@ void QGraphicsScenePrivate::addView(QGraphicsView *view) { views << view; +#ifndef QT_NO_GESTURES foreach (Qt::GestureType gesture, grabbedGestures.keys()) view->viewport()->grabGesture(gesture); +#endif } void QGraphicsScenePrivate::removeView(QGraphicsView *view) @@ -5950,6 +6004,7 @@ dispatchHoverEvent(&hoverEvent); } +#ifndef QT_NO_GESTURES void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet &gestures, Qt::GestureFlag flag, QHash > *targets, @@ -6070,8 +6125,15 @@ if (ev.isAccepted() || ev.isAccepted(g)) { conflictedGestures.remove(g); // mark the item as a gesture target - if (item) + if (item) { gestureTargets.insert(g, item.data()); + QHash >::iterator it, e; + it = cachedItemGestures.begin(); + e = cachedItemGestures.end(); + for(; it != e; ++it) + it.value().remove(g); + cachedItemGestures[item.data()].insert(g); + } DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" << "override was accepted:" << g << item.data(); @@ -6240,7 +6302,8 @@ { Q_ASSERT(original); QGraphicsItem *originalItem = gestureTargets.value(original); - Q_ASSERT(originalItem); + if (originalItem == 0) // we only act on accepted gestures, which implies it has a target. + return; // iterate over all active gestures and for each find the owner // if the owner is part of our sub-hierarchy, cancel it. @@ -6338,6 +6401,7 @@ view->viewport()->ungrabGesture(gesture); } } +#endif // QT_NO_GESTURES QT_END_NAMESPACE