src/gui/graphicsview/qgraphicsscene.cpp
changeset 18 2f34d5167611
parent 3 41300fa6a67c
child 19 fcece45ef507
equal deleted inserted replaced
3:41300fa6a67c 18:2f34d5167611
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     7 ** This file is part of the QtGui module of the Qt Toolkit.
     8 **
     8 **
   249 #ifdef Q_WS_X11
   249 #ifdef Q_WS_X11
   250 #include <private/qt_x11_p.h>
   250 #include <private/qt_x11_p.h>
   251 #endif
   251 #endif
   252 #include <private/qgraphicseffect_p.h>
   252 #include <private/qgraphicseffect_p.h>
   253 #include <private/qgesturemanager_p.h>
   253 #include <private/qgesturemanager_p.h>
       
   254 #include <private/qpathclipper_p.h>
   254 
   255 
   255 // #define GESTURE_DEBUG
   256 // #define GESTURE_DEBUG
   256 #ifndef GESTURE_DEBUG
   257 #ifndef GESTURE_DEBUG
   257 # define DEBUG if (0) qDebug
   258 # define DEBUG if (0) qDebug
   258 #else
   259 #else
   370                 q->connect(q, SIGNAL(changed(QList<QRectF>)),
   371                 q->connect(q, SIGNAL(changed(QList<QRectF>)),
   371                            views.at(i), SLOT(updateScene(QList<QRectF>)));
   372                            views.at(i), SLOT(updateScene(QList<QRectF>)));
   372             }
   373             }
   373         }
   374         }
   374     } else {
   375     } else {
   375         updateAll = false;
   376         if (views.isEmpty()) {
       
   377             updateAll = false;
       
   378             return;
       
   379         }
   376         for (int i = 0; i < views.size(); ++i)
   380         for (int i = 0; i < views.size(); ++i)
   377             views.at(i)->d_func()->processPendingUpdates();
   381             views.at(i)->d_func()->processPendingUpdates();
   378         // It's important that we update all views before we dispatch, hence two for-loops.
   382         // It's important that we update all views before we dispatch, hence two for-loops.
   379         for (int i = 0; i < views.size(); ++i)
   383         for (int i = 0; i < views.size(); ++i)
   380             views.at(i)->d_func()->dispatchPendingUpdateRequests();
   384             views.at(i)->d_func()->dispatchPendingUpdateRequests();
   426 /*!
   430 /*!
   427     \internal
   431     \internal
   428 */
   432 */
   429 void QGraphicsScenePrivate::_q_polishItems()
   433 void QGraphicsScenePrivate::_q_polishItems()
   430 {
   434 {
   431     QSet<QGraphicsItem *>::Iterator it;
   435     if (unpolishedItems.isEmpty())
       
   436         return;
       
   437 
   432     const QVariant booleanTrueVariant(true);
   438     const QVariant booleanTrueVariant(true);
   433     while (!unpolishedItems.isEmpty()) {
   439     QGraphicsItem *item = 0;
   434         it = unpolishedItems.begin();
   440     QGraphicsItemPrivate *itemd = 0;
   435         QGraphicsItem *item = *it;
   441     const int oldUnpolishedCount = unpolishedItems.count();
   436         unpolishedItems.erase(it);
   442 
   437         if (!item->d_ptr->explicitlyHidden) {
   443     for (int i = 0; i < oldUnpolishedCount; ++i) {
       
   444         item = unpolishedItems.at(i);
       
   445         if (!item)
       
   446             continue;
       
   447         itemd = item->d_ptr.data();
       
   448         itemd->pendingPolish = false;
       
   449         if (!itemd->explicitlyHidden) {
   438             item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
   450             item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
   439             item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
   451             item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
   440         }
   452         }
   441         if (item->isWidget()) {
   453         if (itemd->isWidget) {
   442             QEvent event(QEvent::Polish);
   454             QEvent event(QEvent::Polish);
   443             QApplication::sendEvent((QGraphicsWidget *)item, &event);
   455             QApplication::sendEvent((QGraphicsWidget *)item, &event);
   444         }
   456         }
       
   457     }
       
   458 
       
   459     if (unpolishedItems.count() == oldUnpolishedCount) {
       
   460         // No new items were added to the vector.
       
   461         unpolishedItems.clear();
       
   462     } else {
       
   463         // New items were appended; keep them and remove the old ones.
       
   464         unpolishedItems.remove(0, oldUnpolishedCount);
       
   465         unpolishedItems.squeeze();
       
   466         QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection);
   445     }
   467     }
   446 }
   468 }
   447 
   469 
   448 void QGraphicsScenePrivate::_q_processDirtyItems()
   470 void QGraphicsScenePrivate::_q_processDirtyItems()
   449 {
   471 {
   594     // Remove from parent, or unregister from toplevels.
   616     // Remove from parent, or unregister from toplevels.
   595     if (QGraphicsItem *parentItem = item->parentItem()) {
   617     if (QGraphicsItem *parentItem = item->parentItem()) {
   596         if (parentItem->scene()) {
   618         if (parentItem->scene()) {
   597             Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
   619             Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
   598                        "Parent item's scene is different from this item's scene");
   620                        "Parent item's scene is different from this item's scene");
   599             item->d_ptr->setParentItemHelper(0);
   621             item->setParentItem(0);
   600         }
   622         }
   601     } else {
   623     } else {
   602         unregisterTopLevelItem(item);
   624         unregisterTopLevelItem(item);
   603     }
   625     }
   604 
   626 
   633 
   655 
   634     // Update selected & hovered item bookkeeping
   656     // Update selected & hovered item bookkeeping
   635     selectedItems.remove(item);
   657     selectedItems.remove(item);
   636     hoverItems.removeAll(item);
   658     hoverItems.removeAll(item);
   637     cachedItemsUnderMouse.removeAll(item);
   659     cachedItemsUnderMouse.removeAll(item);
   638     unpolishedItems.remove(item);
   660     if (item->d_ptr->pendingPolish) {
       
   661         const int unpolishedIndex = unpolishedItems.indexOf(item);
       
   662         if (unpolishedIndex != -1)
       
   663             unpolishedItems[unpolishedIndex] = 0;
       
   664         item->d_ptr->pendingPolish = false;
       
   665     }
   639     resetDirtyItem(item);
   666     resetDirtyItem(item);
   640 
   667 
   641     //We remove all references of item from the sceneEventFilter arrays
   668     //We remove all references of item from the sceneEventFilter arrays
   642     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
   669     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
   643     while (iterator != sceneEventFilters.end()) {
   670     while (iterator != sceneEventFilters.end()) {
   772             // automatically by removing WA_InputMethodEnabled on
   799             // automatically by removing WA_InputMethodEnabled on
   773             // the views, but if we are changing focus, we have to
   800             // the views, but if we are changing focus, we have to
   774             // do it ourselves.
   801             // do it ourselves.
   775             if (item) {
   802             if (item) {
   776                 for (int i = 0; i < views.size(); ++i)
   803                 for (int i = 0; i < views.size(); ++i)
   777                     views.at(i)->inputContext()->reset();
   804                     if (views.at(i)->inputContext())
       
   805                         views.at(i)->inputContext()->reset();
   778             }
   806             }
   779         }
   807         }
   780 #endif //QT_NO_IM
   808 #endif //QT_NO_IM
   781     }
   809     }
   782 
   810 
  1130     enabled, the event is sent; otherwise it is stopped.
  1158     enabled, the event is sent; otherwise it is stopped.
  1131 */
  1159 */
  1132 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
  1160 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
  1133 {
  1161 {
  1134     if (QGraphicsObject *object = item->toGraphicsObject()) {
  1162     if (QGraphicsObject *object = item->toGraphicsObject()) {
  1135         if (qt_gestureManager) {
  1163         QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
  1136             if (qt_gestureManager->filterEvent(object, event))
  1164         if (gestureManager) {
       
  1165             if (gestureManager->filterEvent(object, event))
  1137                 return true;
  1166                 return true;
  1138         }
  1167         }
  1139     }
  1168     }
  1140 
  1169 
  1141     if (filterEvent(item, event))
  1170     if (filterEvent(item, event))
  1559     d_func()->init();
  1588     d_func()->init();
  1560     setSceneRect(x, y, width, height);
  1589     setSceneRect(x, y, width, height);
  1561 }
  1590 }
  1562 
  1591 
  1563 /*!
  1592 /*!
  1564     Destroys the QGraphicsScene object.
  1593   Removes and deletes all items from the scene object
       
  1594   before destroying the scene object. The scene object
       
  1595   is removed from the application's global scene list,
       
  1596   and it is removed from all associated views.
  1565 */
  1597 */
  1566 QGraphicsScene::~QGraphicsScene()
  1598 QGraphicsScene::~QGraphicsScene()
  1567 {
  1599 {
  1568     Q_D(QGraphicsScene);
  1600     Q_D(QGraphicsScene);
  1569 
  1601 
  1926     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
  1958     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
  1927     \obsolete
  1959     \obsolete
  1928     \since 4.3
  1960     \since 4.3
  1929 
  1961 
  1930     This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
  1962     This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
  1931     
  1963 
  1932     This function is deprecated and returns incorrect results if the scene
  1964     This function is deprecated and returns incorrect results if the scene
  1933     contains items that ignore transformations. Use the overload that takes
  1965     contains items that ignore transformations. Use the overload that takes
  1934     a QTransform instead.
  1966     a QTransform instead.
  1935 */
  1967 */
  1936 
  1968 
  2441     removeItem(group);
  2473     removeItem(group);
  2442     delete group;
  2474     delete group;
  2443 }
  2475 }
  2444 
  2476 
  2445 /*!
  2477 /*!
  2446     Adds or moves the item \a item and all its childen to the scene.
  2478     Adds or moves the \a item and all its childen to this scene.
       
  2479     This scene takes ownership of the \a item.
  2447 
  2480 
  2448     If the item is visible (i.e., QGraphicsItem::isVisible() returns
  2481     If the item is visible (i.e., QGraphicsItem::isVisible() returns
  2449     true), QGraphicsScene will emit changed() once control goes back
  2482     true), QGraphicsScene will emit changed() once control goes back
  2450     to the event loop.
  2483     to the event loop.
  2451 
  2484 
  2452     If the item is already in a different scene, it will first be removed from
  2485     If the item is already in a different scene, it will first be
  2453     its old scene, and then added to this scene as a top-level.
  2486     removed from its old scene, and then added to this scene as a
  2454 
  2487     top-level.
  2455     QGraphicsScene will send ItemSceneChange notifications to \a item while
  2488 
  2456     it is added to the scene. If item does not currently belong to a scene, only one
  2489     QGraphicsScene will send ItemSceneChange notifications to \a item
  2457     notification is sent. If it does belong to scene already (i.e., it is
  2490     while it is added to the scene. If item does not currently belong
  2458     moved to this scene), QGraphicsScene will send an addition notification as
  2491     to a scene, only one notification is sent. If it does belong to
  2459     the item is removed from its previous scene.
  2492     scene already (i.e., it is moved to this scene), QGraphicsScene
  2460 
  2493     will send an addition notification as the item is removed from its
  2461     If the item is a panel, the scene is active, and there is no active panel
  2494     previous scene.
  2462     in the scene, then the item will be activated.
  2495 
       
  2496     If the item is a panel, the scene is active, and there is no
       
  2497     active panel in the scene, then the item will be activated.
  2463 
  2498 
  2464     \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
  2499     \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
  2465     addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
  2500     addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
  2466 */
  2501 */
  2467 void QGraphicsScene::addItem(QGraphicsItem *item)
  2502 void QGraphicsScene::addItem(QGraphicsItem *item)
  2469     Q_D(QGraphicsScene);
  2504     Q_D(QGraphicsScene);
  2470     if (!item) {
  2505     if (!item) {
  2471         qWarning("QGraphicsScene::addItem: cannot add null item");
  2506         qWarning("QGraphicsScene::addItem: cannot add null item");
  2472         return;
  2507         return;
  2473     }
  2508     }
  2474     if (item->scene() == this) {
  2509     if (item->d_ptr->scene == this) {
  2475         qWarning("QGraphicsScene::addItem: item has already been added to this scene");
  2510         qWarning("QGraphicsScene::addItem: item has already been added to this scene");
  2476         return;
  2511         return;
  2477     }
  2512     }
  2478     // Remove this item from its existing scene
  2513     // Remove this item from its existing scene
  2479     if (QGraphicsScene *oldScene = item->scene())
  2514     if (QGraphicsScene *oldScene = item->d_ptr->scene)
  2480         oldScene->removeItem(item);
  2515         oldScene->removeItem(item);
  2481 
  2516 
  2482     // Notify the item that its scene is changing, and allow the item to
  2517     // Notify the item that its scene is changing, and allow the item to
  2483     // react.
  2518     // react.
  2484     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
  2519     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
  2485                                                     qVariantFromValue<QGraphicsScene *>(this)));
  2520                                                     qVariantFromValue<QGraphicsScene *>(this)));
  2486     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
  2521     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
  2487     if (targetScene != this) {
  2522     if (targetScene != this) {
  2488         if (targetScene && item->scene() != targetScene)
  2523         if (targetScene && item->d_ptr->scene != targetScene)
  2489             targetScene->addItem(item);
  2524             targetScene->addItem(item);
  2490         return;
  2525         return;
  2491     }
  2526     }
  2492 
  2527 
       
  2528     if (d->unpolishedItems.isEmpty())
       
  2529         QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
       
  2530     d->unpolishedItems.append(item);
       
  2531     item->d_ptr->pendingPolish = true;
       
  2532 
  2493     // Detach this item from its parent if the parent's scene is different
  2533     // Detach this item from its parent if the parent's scene is different
  2494     // from this scene.
  2534     // from this scene.
  2495     if (QGraphicsItem *itemParent = item->parentItem()) {
  2535     if (QGraphicsItem *itemParent = item->d_ptr->parent) {
  2496         if (itemParent->scene() != this)
  2536         if (itemParent->d_ptr->scene != this)
  2497             item->setParentItem(0);
  2537             item->setParentItem(0);
  2498     }
  2538     }
  2499 
  2539 
  2500     // Add the item to this scene
  2540     // Add the item to this scene
  2501     item->d_func()->scene = targetScene;
  2541     item->d_func()->scene = targetScene;
  2521     if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
  2561     if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
  2522         d->allItemsIgnoreHoverEvents = false;
  2562         d->allItemsIgnoreHoverEvents = false;
  2523         d->enableMouseTrackingOnViews();
  2563         d->enableMouseTrackingOnViews();
  2524     }
  2564     }
  2525 #ifndef QT_NO_CURSOR
  2565 #ifndef QT_NO_CURSOR
  2526     if (d->allItemsUseDefaultCursor && item->hasCursor()) {
  2566     if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
  2527         d->allItemsUseDefaultCursor = false;
  2567         d->allItemsUseDefaultCursor = false;
  2528         if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
  2568         if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
  2529             d->enableMouseTrackingOnViews();
  2569             d->enableMouseTrackingOnViews();
  2530     }
  2570     }
  2531 #endif //QT_NO_CURSOR
  2571 #endif //QT_NO_CURSOR
  2532 
  2572 
  2533     // Enable touch events if the item accepts touch events.
  2573     // Enable touch events if the item accepts touch events.
  2534     if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) {
  2574     if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
  2535         d->allItemsIgnoreTouchEvents = false;
  2575         d->allItemsIgnoreTouchEvents = false;
  2536         d->enableTouchEventsOnViews();
  2576         d->enableTouchEventsOnViews();
  2537     }
  2577     }
  2538 
  2578 
  2539     // Update selection lists
  2579     // Update selection lists
  2562             lastNew->d_func()->focusNext = d->tabFocusFirst;
  2602             lastNew->d_func()->focusNext = d->tabFocusFirst;
  2563         }
  2603         }
  2564     }
  2604     }
  2565 
  2605 
  2566     // Add all children recursively
  2606     // Add all children recursively
  2567     foreach (QGraphicsItem *child, item->children())
  2607     item->d_ptr->ensureSortedChildren();
  2568         addItem(child);
  2608     for (int i = 0; i < item->d_ptr->children.size(); ++i)
       
  2609         addItem(item->d_ptr->children.at(i));
  2569 
  2610 
  2570     // Resolve font and palette.
  2611     // Resolve font and palette.
  2571     item->d_ptr->resolveFont(d->font.resolve());
  2612     item->d_ptr->resolveFont(d->font.resolve());
  2572     item->d_ptr->resolvePalette(d->palette.resolve());
  2613     item->d_ptr->resolvePalette(d->palette.resolve());
  2573 
  2614 
  2574    if (d->unpolishedItems.isEmpty())
       
  2575        QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
       
  2576    d->unpolishedItems.insert(item);
       
  2577 
  2615 
  2578     // Reenable selectionChanged() for individual items
  2616     // Reenable selectionChanged() for individual items
  2579     --d->selectionChanging;
  2617     --d->selectionChanging;
  2580     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
  2618     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
  2581         emit selectionChanged();
  2619         emit selectionChanged();
  2605             else
  2643             else
  2606                 d->lastActivePanel = item;
  2644                 d->lastActivePanel = item;
  2607         }
  2645         }
  2608     }
  2646     }
  2609 
  2647 
  2610     if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
  2648     if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges)
  2611         d->registerScenePosItem(item);
  2649         d->registerScenePosItem(item);
  2612 
  2650 
  2613     // Ensure that newly added items that have subfocus set, gain
  2651     // Ensure that newly added items that have subfocus set, gain
  2614     // focus automatically if there isn't a focus item already.
  2652     // focus automatically if there isn't a focus item already.
  2615     if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
  2653     if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
  3752 #endif
  3790 #endif
  3753 }
  3791 }
  3754 
  3792 
  3755 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
  3793 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
  3756 {
  3794 {
  3757     return (!item->isBlockedByModalPanel() &&
  3795     return (item->d_ptr->acceptsHover
  3758             (item->acceptHoverEvents()
  3796             || (item->d_ptr->isWidget
  3759              || (item->isWidget()
  3797                 && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))
  3760                  && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())));
  3798            && !item->isBlockedByModalPanel();
  3761 }
  3799 }
  3762 
  3800 
  3763 /*!
  3801 /*!
  3764     This event handler, for event \a hoverEvent, can be reimplemented in a
  3802     This event handler, for event \a hoverEvent, can be reimplemented in a
  3765     subclass to receive hover enter events. The default implementation
  3803     subclass to receive hover enter events. The default implementation
  4568 {
  4606 {
  4569     // Make sure we don't have unpolished items before we draw.
  4607     // Make sure we don't have unpolished items before we draw.
  4570     if (!unpolishedItems.isEmpty())
  4608     if (!unpolishedItems.isEmpty())
  4571         _q_polishItems();
  4609         _q_polishItems();
  4572 
  4610 
       
  4611     updateAll = false;
  4573     QRectF exposedSceneRect;
  4612     QRectF exposedSceneRect;
  4574     if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
  4613     if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
  4575         exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
  4614         exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
  4576         if (viewTransform)
  4615         if (viewTransform)
  4577             exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
  4616             exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
  4595     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4634     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4596     if (!itemHasContents && !itemHasChildren)
  4635     if (!itemHasContents && !itemHasChildren)
  4597         return; // Item has neither contents nor children!(?)
  4636         return; // Item has neither contents nor children!(?)
  4598 
  4637 
  4599     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4638     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4600     const bool itemIsFullyTransparent = (opacity < 0.0001);
  4639     const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
  4601     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
  4640     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
  4602         return;
  4641         return;
  4603 
  4642 
  4604     QTransform transform(Qt::Uninitialized);
  4643     QTransform transform(Qt::Uninitialized);
  4605     QTransform *transformPtr = 0;
  4644     QTransform *transformPtr = 0;
  4638         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
  4677         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
  4639                                                         : transformPtr->mapRect(brect).toRect();
  4678                                                         : transformPtr->mapRect(brect).toRect();
  4640         if (widget)
  4679         if (widget)
  4641             item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
  4680             item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
  4642         viewBoundingRect.adjust(-1, -1, 1, 1);
  4681         viewBoundingRect.adjust(-1, -1, 1, 1);
  4643         drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
  4682         drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
       
  4683                                  : !viewBoundingRect.normalized().isEmpty();
  4644         if (!drawItem) {
  4684         if (!drawItem) {
  4645             if (!itemHasChildren)
  4685             if (!itemHasChildren)
  4646                 return;
  4686                 return;
  4647             if (itemClipsChildrenToShape) {
  4687             if (itemClipsChildrenToShape) {
  4648                 if (wasDirtyParentSceneTransform)
  4688                 if (wasDirtyParentSceneTransform)
  4672         painter->setOpacity(opacity);
  4712         painter->setOpacity(opacity);
  4673 
  4713 
  4674         if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
  4714         if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
  4675             && sourced->lastEffectTransform != painter->worldTransform())
  4715             && sourced->lastEffectTransform != painter->worldTransform())
  4676         {
  4716         {
       
  4717             bool unclipped = false;
       
  4718             if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
       
  4719                 && painter->worldTransform().type() <= QTransform::TxTranslate)
       
  4720             {
       
  4721                 QRectF itemRect = item->boundingRect();
       
  4722                 if (!item->d_ptr->children.isEmpty())
       
  4723                     itemRect |= item->childrenBoundingRect();
       
  4724 
       
  4725                 QRectF oldSourceRect = sourced->lastEffectTransform.mapRect(itemRect);
       
  4726                 QRectF newSourceRect = painter->worldTransform().mapRect(itemRect);
       
  4727 
       
  4728                 QRect oldEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), oldSourceRect);
       
  4729                 QRect newEffectRect = sourced->paddedEffectRect(sourced->currentCachedSystem(), sourced->currentCachedMode(), newSourceRect);
       
  4730 
       
  4731                 QRect deviceRect(0, 0, painter->device()->width(), painter->device()->height());
       
  4732                 if (deviceRect.contains(oldEffectRect) && deviceRect.contains(newEffectRect)) {
       
  4733                     sourced->setCachedOffset(newEffectRect.topLeft());
       
  4734                     unclipped = true;
       
  4735                 }
       
  4736             }
       
  4737 
  4677             sourced->lastEffectTransform = painter->worldTransform();
  4738             sourced->lastEffectTransform = painter->worldTransform();
  4678             sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
  4739 
       
  4740             if (!unclipped)
       
  4741                 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
  4679         }
  4742         }
  4680 
  4743 
  4681         item->d_ptr->graphicsEffect->draw(painter);
  4744         item->d_ptr->graphicsEffect->draw(painter);
  4682         painter->setWorldTransform(restoreTransform);
  4745         painter->setWorldTransform(restoreTransform);
  4683         sourced->info = 0;
  4746         sourced->info = 0;
  4692 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
  4755 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
  4693                                  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
  4756                                  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
  4694                                  qreal opacity, const QTransform *effectTransform,
  4757                                  qreal opacity, const QTransform *effectTransform,
  4695                                  bool wasDirtyParentSceneTransform, bool drawItem)
  4758                                  bool wasDirtyParentSceneTransform, bool drawItem)
  4696 {
  4759 {
  4697     const bool itemIsFullyTransparent = (opacity < 0.0001);
  4760     const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
  4698     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
  4761     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
  4699     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4762     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4700 
  4763 
  4701     int i = 0;
  4764     int i = 0;
  4702     if (itemHasChildren) {
  4765     if (itemHasChildren) {
  4707             Q_ASSERT(transformPtr);
  4770             Q_ASSERT(transformPtr);
  4708             if (effectTransform)
  4771             if (effectTransform)
  4709                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4772                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4710             else
  4773             else
  4711                 painter->setWorldTransform(*transformPtr);
  4774                 painter->setWorldTransform(*transformPtr);
  4712             painter->setClipPath(item->shape(), Qt::IntersectClip);
  4775             QRectF clipRect;
       
  4776             const QPainterPath clipPath(item->shape());
       
  4777             if (QPathClipper::pathToRect(clipPath, &clipRect))
       
  4778                 painter->setClipRect(clipRect, Qt::IntersectClip);
       
  4779             else
       
  4780                 painter->setClipPath(clipPath, Qt::IntersectClip);
  4713         }
  4781         }
  4714 
  4782 
  4715         // Draw children behind
  4783         // Draw children behind
  4716         for (i = 0; i < item->d_ptr->children.size(); ++i) {
  4784         for (i = 0; i < item->d_ptr->children.size(); ++i) {
  4717             QGraphicsItem *child = item->d_ptr->children.at(i);
  4785             QGraphicsItem *child = item->d_ptr->children.at(i);
  4743                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4811                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4744             else
  4812             else
  4745                 painter->setWorldTransform(*transformPtr);
  4813                 painter->setWorldTransform(*transformPtr);
  4746         }
  4814         }
  4747 
  4815 
  4748         if (itemClipsToShape)
  4816         if (itemClipsToShape) {
  4749             painter->setClipPath(item->shape(), Qt::IntersectClip);
  4817             QRectF clipRect;
       
  4818             const QPainterPath clipPath(item->shape());
       
  4819             if (QPathClipper::pathToRect(clipPath, &clipRect))
       
  4820                 painter->setClipRect(clipRect, Qt::IntersectClip);
       
  4821             else
       
  4822                 painter->setClipPath(clipPath, Qt::IntersectClip);
       
  4823         }
  4750         painter->setOpacity(opacity);
  4824         painter->setOpacity(opacity);
  4751 
  4825 
  4752         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
  4826         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
  4753             item->paint(painter, &styleOptionTmp, widget);
  4827             item->paint(painter, &styleOptionTmp, widget);
  4754         else
  4828         else
  4774     if (itemHasChildren && itemClipsChildrenToShape)
  4848     if (itemHasChildren && itemClipsChildrenToShape)
  4775         painter->restore();
  4849         painter->restore();
  4776 }
  4850 }
  4777 
  4851 
  4778 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4852 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4779                                       bool force, bool ignoreOpacity, bool removingItemFromScene)
  4853                                       bool force, bool ignoreOpacity, bool removingItemFromScene,
       
  4854                                       bool updateBoundingRect)
  4780 {
  4855 {
  4781     Q_ASSERT(item);
  4856     Q_ASSERT(item);
  4782     if (updateAll)
  4857     if (updateAll)
  4783         return;
  4858         return;
  4784 
  4859 
  4845     if (force)
  4920     if (force)
  4846         item->d_ptr->ignoreVisible = 1;
  4921         item->d_ptr->ignoreVisible = 1;
  4847     if (ignoreOpacity)
  4922     if (ignoreOpacity)
  4848         item->d_ptr->ignoreOpacity = 1;
  4923         item->d_ptr->ignoreOpacity = 1;
  4849 
  4924 
  4850     QGraphicsItem *p = item->d_ptr->parent;
  4925     if (!updateBoundingRect)
  4851     while (p) {
  4926         item->d_ptr->markParentDirty();
  4852         p->d_ptr->dirtyChildren = 1;
       
  4853 #ifndef QT_NO_GRAPHICSEFFECT
       
  4854         if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
       
  4855             p->d_ptr->dirty = 1;
       
  4856             p->d_ptr->fullUpdatePending = 1;
       
  4857         }
       
  4858 #endif //QT_NO_GRAPHICSEFFECT
       
  4859         p = p->d_ptr->parent;
       
  4860     }
       
  4861 }
  4927 }
  4862 
  4928 
  4863 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4929 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4864                                 const QRectF &rect, bool itemIsUntransformable)
  4930                                 const QRectF &rect, bool itemIsUntransformable)
  4865 {
  4931 {
  4930         if (item->d_ptr->graphicsEffect)
  4996         if (item->d_ptr->graphicsEffect)
  4931             itemHasContents = true;
  4997             itemHasContents = true;
  4932     }
  4998     }
  4933 
  4999 
  4934     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  5000     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4935     const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
  5001     const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
       
  5002                                         && QGraphicsItemPrivate::isOpacityNull(opacity);
  4936     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
  5003     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
  4937         resetDirtyItem(item, /*recursive=*/itemHasChildren);
  5004         resetDirtyItem(item, /*recursive=*/itemHasChildren);
  4938         return;
  5005         return;
  4939     }
  5006     }
  4940 
  5007 
  5065 
  5132 
  5066     resetDirtyItem(item);
  5133     resetDirtyItem(item);
  5067 }
  5134 }
  5068 
  5135 
  5069 /*!
  5136 /*!
       
  5137     \obsolete
       
  5138 
  5070     Paints the given \a items using the provided \a painter, after the
  5139     Paints the given \a items using the provided \a painter, after the
  5071     background has been drawn, and before the foreground has been
  5140     background has been drawn, and before the foreground has been
  5072     drawn.  All painting is done in \e scene coordinates. Before
  5141     drawn.  All painting is done in \e scene coordinates. Before
  5073     drawing each item, the painter must be transformed using
  5142     drawing each item, the painter must be transformed using
  5074     QGraphicsItem::sceneTransform().
  5143     QGraphicsItem::sceneTransform().
  5087 
  5156 
  5088     Example:
  5157     Example:
  5089 
  5158 
  5090     \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
  5159     \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
  5091 
  5160 
       
  5161     Since Qt 4.6, this function is not called anymore unless
       
  5162     the QGraphicsView::IndirectPainting flag is given as an Optimization
       
  5163     flag.
       
  5164 
  5092     \sa drawBackground(), drawForeground()
  5165     \sa drawBackground(), drawForeground()
  5093 */
  5166 */
  5094 void QGraphicsScene::drawItems(QPainter *painter,
  5167 void QGraphicsScene::drawItems(QPainter *painter,
  5095                                int numItems,
  5168                                int numItems,
  5096                                QGraphicsItem *items[],
  5169                                QGraphicsItem *items[],
  5099     Q_D(QGraphicsScene);
  5172     Q_D(QGraphicsScene);
  5100     // Make sure we don't have unpolished items before we draw.
  5173     // Make sure we don't have unpolished items before we draw.
  5101     if (!d->unpolishedItems.isEmpty())
  5174     if (!d->unpolishedItems.isEmpty())
  5102         d->_q_polishItems();
  5175         d->_q_polishItems();
  5103 
  5176 
       
  5177     d->updateAll = false;
  5104     QTransform viewTransform = painter->worldTransform();
  5178     QTransform viewTransform = painter->worldTransform();
  5105     Q_UNUSED(options);
  5179     Q_UNUSED(options);
  5106 
  5180 
  5107     // Determine view, expose and flags.
  5181     // Determine view, expose and flags.
  5108     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
  5182     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
  5638             // if the TouchBegin handler recurses, we assume that means the event
  5712             // if the TouchBegin handler recurses, we assume that means the event
  5639             // has been implicitly accepted and continue to send touch events
  5713             // has been implicitly accepted and continue to send touch events
  5640             item->d_ptr->acceptedTouchBeginEvent = true;
  5714             item->d_ptr->acceptedTouchBeginEvent = true;
  5641             bool res = sendTouchBeginEvent(item, &touchEvent)
  5715             bool res = sendTouchBeginEvent(item, &touchEvent)
  5642                        && touchEvent.isAccepted();
  5716                        && touchEvent.isAccepted();
  5643             if (!res)
  5717             if (!res) {
       
  5718                 // forget about these touch points, we didn't handle them
       
  5719                 for (int i = 0; i < touchEvent.touchPoints().count(); ++i) {
       
  5720                     const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i);
       
  5721                     itemForTouchPointId.remove(touchPoint.id());
       
  5722                     sceneCurrentTouchPoints.remove(touchPoint.id());
       
  5723                 }
  5644                 ignoreSceneTouchEvent = false;
  5724                 ignoreSceneTouchEvent = false;
       
  5725             }
  5645             break;
  5726             break;
  5646         }
  5727         }
  5647         default:
  5728         default:
  5648             if (item->d_ptr->acceptedTouchBeginEvent) {
  5729             if (item->d_ptr->acceptedTouchBeginEvent) {
  5649                 updateTouchPointsForItem(item, &touchEvent);
  5730                 updateTouchPointsForItem(item, &touchEvent);
  5830         if (gesture->hasHotSpot()) {
  5911         if (gesture->hasHotSpot()) {
  5831             QPoint screenPos = gesture->hotSpot().toPoint();
  5912             QPoint screenPos = gesture->hotSpot().toPoint();
  5832             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
  5913             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
  5833             QList<QGraphicsObject *> result;
  5914             QList<QGraphicsObject *> result;
  5834             for (int j = 0; j < items.size(); ++j) {
  5915             for (int j = 0; j < items.size(); ++j) {
  5835                 QGraphicsObject *item = items.at(j)->toGraphicsObject();
  5916                 QGraphicsItem *item = items.at(j);
  5836                 if (!item)
  5917 
  5837                     continue;
  5918                 // Check if the item is blocked by a modal panel and use it as
  5838                 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
  5919                 // a target instead of this item.
  5839                 if (d->gestureContext.contains(gestureType)) {
  5920                 (void) item->isBlockedByModalPanel(&item);
  5840                     result.append(item);
  5921 
       
  5922                 if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
       
  5923                     QGraphicsItemPrivate *d = item->d_func();
       
  5924                     if (d->gestureContext.contains(gestureType)) {
       
  5925                         result.append(itemobj);
       
  5926                     }
  5841                 }
  5927                 }
       
  5928                 // Don't propagate through panels.
       
  5929                 if (item->isPanel())
       
  5930                     break;
  5842             }
  5931             }
  5843             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
  5932             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
  5844                     << gesture << result;
  5933                     << gesture << result;
  5845             if (result.size() == 1) {
  5934             if (result.size() == 1) {
  5846                 normalGestures->insert(gesture, result.first());
  5935                 normalGestures->insert(gesture, result.first());
  6140                 }
  6229                 }
  6141             }
  6230             }
  6142         }
  6231         }
  6143     }
  6232     }
  6144 
  6233 
  6145     Q_ASSERT(qt_gestureManager); // it would be very odd if we got called without a manager.
  6234     QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
       
  6235     Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
  6146     for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
  6236     for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
  6147         qt_gestureManager->recycle(*setIter);
  6237         gestureManager->recycle(*setIter);
  6148         gestureTargets.remove(*setIter);
  6238         gestureTargets.remove(*setIter);
  6149     }
  6239     }
  6150 }
  6240 }
  6151 
  6241 
  6152 QT_END_NAMESPACE
  6242 QT_END_NAMESPACE