src/gui/graphicsview/qgraphicsscene.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
     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
  4245     pixmapPainter.end();
  4283     pixmapPainter.end();
  4246 
  4284 
  4247     if (!subPix.isNull()) {
  4285     if (!subPix.isNull()) {
  4248         // Blit the subpixmap into the main pixmap.
  4286         // Blit the subpixmap into the main pixmap.
  4249         pixmapPainter.begin(pix);
  4287         pixmapPainter.begin(pix);
       
  4288         pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
  4250         pixmapPainter.setClipRegion(pixmapExposed);
  4289         pixmapPainter.setClipRegion(pixmapExposed);
  4251         pixmapPainter.drawPixmap(br.topLeft(), subPix);
  4290         pixmapPainter.drawPixmap(br.topLeft(), subPix);
  4252         pixmapPainter.end();
  4291         pixmapPainter.end();
  4253     }
  4292     }
  4254 }
  4293 }
  4410                          oldPainterOpacity != newPainterOpacity, painterStateProtection);
  4449                          oldPainterOpacity != newPainterOpacity, painterStateProtection);
  4411             return;
  4450             return;
  4412         }
  4451         }
  4413 
  4452 
  4414         // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
  4453         // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
       
  4454         // If the world transform is rotated we always recreate the cache to avoid
       
  4455         // wrong blending.
  4415         bool pixModified = false;
  4456         bool pixModified = false;
  4416         QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
  4457         QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
  4417         bool invertable = true;
  4458         bool invertable = true;
  4418         QTransform diff = deviceData->lastTransform.inverted(&invertable);
  4459         QTransform diff = deviceData->lastTransform.inverted(&invertable);
  4419         if (invertable)
  4460         if (invertable)
  4420             diff *= painter->worldTransform();
  4461             diff *= painter->worldTransform();
  4421         deviceData->lastTransform = painter->worldTransform();
  4462         deviceData->lastTransform = painter->worldTransform();
  4422         if (!invertable || diff.type() > QTransform::TxTranslate) {
  4463         if (!invertable
       
  4464             || diff.type() > QTransform::TxTranslate
       
  4465             || painter->worldTransform().type() > QTransform::TxScale) {
  4423             pixModified = true;
  4466             pixModified = true;
  4424             itemCache->allExposed = true;
  4467             itemCache->allExposed = true;
  4425             itemCache->exposed.clear();
  4468             itemCache->exposed.clear();
  4426             pix = QPixmap();
  4469             pix = QPixmap();
  4427         }
  4470         }
  4568 {
  4611 {
  4569     // Make sure we don't have unpolished items before we draw.
  4612     // Make sure we don't have unpolished items before we draw.
  4570     if (!unpolishedItems.isEmpty())
  4613     if (!unpolishedItems.isEmpty())
  4571         _q_polishItems();
  4614         _q_polishItems();
  4572 
  4615 
       
  4616     updateAll = false;
  4573     QRectF exposedSceneRect;
  4617     QRectF exposedSceneRect;
  4574     if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
  4618     if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
  4575         exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
  4619         exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
  4576         if (viewTransform)
  4620         if (viewTransform)
  4577             exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
  4621             exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
  4595     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4639     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4596     if (!itemHasContents && !itemHasChildren)
  4640     if (!itemHasContents && !itemHasChildren)
  4597         return; // Item has neither contents nor children!(?)
  4641         return; // Item has neither contents nor children!(?)
  4598 
  4642 
  4599     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4643     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4600     const bool itemIsFullyTransparent = (opacity < 0.0001);
  4644     const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
  4601     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
  4645     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
  4602         return;
  4646         return;
  4603 
  4647 
  4604     QTransform transform(Qt::Uninitialized);
  4648     QTransform transform(Qt::Uninitialized);
  4605     QTransform *transformPtr = 0;
  4649     QTransform *transformPtr = 0;
  4638         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
  4682         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
  4639                                                         : transformPtr->mapRect(brect).toRect();
  4683                                                         : transformPtr->mapRect(brect).toRect();
  4640         if (widget)
  4684         if (widget)
  4641             item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
  4685             item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
  4642         viewBoundingRect.adjust(-1, -1, 1, 1);
  4686         viewBoundingRect.adjust(-1, -1, 1, 1);
  4643         drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
  4687         drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
       
  4688                                  : !viewBoundingRect.normalized().isEmpty();
  4644         if (!drawItem) {
  4689         if (!drawItem) {
  4645             if (!itemHasChildren)
  4690             if (!itemHasChildren)
  4646                 return;
  4691                 return;
  4647             if (itemClipsChildrenToShape) {
  4692             if (itemClipsChildrenToShape) {
  4648                 if (wasDirtyParentSceneTransform)
  4693                 if (wasDirtyParentSceneTransform)
  4672         painter->setOpacity(opacity);
  4717         painter->setOpacity(opacity);
  4673 
  4718 
  4674         if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
  4719         if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
  4675             && sourced->lastEffectTransform != painter->worldTransform())
  4720             && sourced->lastEffectTransform != painter->worldTransform())
  4676         {
  4721         {
       
  4722             if (sourced->lastEffectTransform.type() <= QTransform::TxTranslate
       
  4723                 && painter->worldTransform().type() <= QTransform::TxTranslate)
       
  4724             {
       
  4725                 QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
       
  4726                 QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
       
  4727 
       
  4728                 sourced->setCachedOffset(effectRect.topLeft());
       
  4729             } else {
       
  4730                 sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
       
  4731             }
       
  4732 
  4677             sourced->lastEffectTransform = painter->worldTransform();
  4733             sourced->lastEffectTransform = painter->worldTransform();
  4678             sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
       
  4679         }
  4734         }
  4680 
  4735 
  4681         item->d_ptr->graphicsEffect->draw(painter);
  4736         item->d_ptr->graphicsEffect->draw(painter);
  4682         painter->setWorldTransform(restoreTransform);
  4737         painter->setWorldTransform(restoreTransform);
  4683         sourced->info = 0;
  4738         sourced->info = 0;
  4692 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
  4747 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
  4693                                  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
  4748                                  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
  4694                                  qreal opacity, const QTransform *effectTransform,
  4749                                  qreal opacity, const QTransform *effectTransform,
  4695                                  bool wasDirtyParentSceneTransform, bool drawItem)
  4750                                  bool wasDirtyParentSceneTransform, bool drawItem)
  4696 {
  4751 {
  4697     const bool itemIsFullyTransparent = (opacity < 0.0001);
  4752     const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
  4698     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
  4753     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
  4699     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4754     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
  4700 
  4755 
  4701     int i = 0;
  4756     int i = 0;
  4702     if (itemHasChildren) {
  4757     if (itemHasChildren) {
  4707             Q_ASSERT(transformPtr);
  4762             Q_ASSERT(transformPtr);
  4708             if (effectTransform)
  4763             if (effectTransform)
  4709                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4764                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4710             else
  4765             else
  4711                 painter->setWorldTransform(*transformPtr);
  4766                 painter->setWorldTransform(*transformPtr);
  4712             painter->setClipPath(item->shape(), Qt::IntersectClip);
  4767             QRectF clipRect;
       
  4768             const QPainterPath clipPath(item->shape());
       
  4769             if (QPathClipper::pathToRect(clipPath, &clipRect))
       
  4770                 painter->setClipRect(clipRect, Qt::IntersectClip);
       
  4771             else
       
  4772                 painter->setClipPath(clipPath, Qt::IntersectClip);
  4713         }
  4773         }
  4714 
  4774 
  4715         // Draw children behind
  4775         // Draw children behind
  4716         for (i = 0; i < item->d_ptr->children.size(); ++i) {
  4776         for (i = 0; i < item->d_ptr->children.size(); ++i) {
  4717             QGraphicsItem *child = item->d_ptr->children.at(i);
  4777             QGraphicsItem *child = item->d_ptr->children.at(i);
  4743                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4803                 painter->setWorldTransform(*transformPtr * *effectTransform);
  4744             else
  4804             else
  4745                 painter->setWorldTransform(*transformPtr);
  4805                 painter->setWorldTransform(*transformPtr);
  4746         }
  4806         }
  4747 
  4807 
  4748         if (itemClipsToShape)
  4808         if (itemClipsToShape) {
  4749             painter->setClipPath(item->shape(), Qt::IntersectClip);
  4809             QRectF clipRect;
       
  4810             const QPainterPath clipPath(item->shape());
       
  4811             if (QPathClipper::pathToRect(clipPath, &clipRect))
       
  4812                 painter->setClipRect(clipRect, Qt::IntersectClip);
       
  4813             else
       
  4814                 painter->setClipPath(clipPath, Qt::IntersectClip);
       
  4815         }
  4750         painter->setOpacity(opacity);
  4816         painter->setOpacity(opacity);
  4751 
  4817 
  4752         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
  4818         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
  4753             item->paint(painter, &styleOptionTmp, widget);
  4819             item->paint(painter, &styleOptionTmp, widget);
  4754         else
  4820         else
  4774     if (itemHasChildren && itemClipsChildrenToShape)
  4840     if (itemHasChildren && itemClipsChildrenToShape)
  4775         painter->restore();
  4841         painter->restore();
  4776 }
  4842 }
  4777 
  4843 
  4778 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4844 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4779                                       bool force, bool ignoreOpacity, bool removingItemFromScene)
  4845                                       bool force, bool ignoreOpacity, bool removingItemFromScene,
       
  4846                                       bool updateBoundingRect)
  4780 {
  4847 {
  4781     Q_ASSERT(item);
  4848     Q_ASSERT(item);
  4782     if (updateAll)
  4849     if (updateAll)
  4783         return;
  4850         return;
  4784 
  4851 
  4845     if (force)
  4912     if (force)
  4846         item->d_ptr->ignoreVisible = 1;
  4913         item->d_ptr->ignoreVisible = 1;
  4847     if (ignoreOpacity)
  4914     if (ignoreOpacity)
  4848         item->d_ptr->ignoreOpacity = 1;
  4915         item->d_ptr->ignoreOpacity = 1;
  4849 
  4916 
  4850     QGraphicsItem *p = item->d_ptr->parent;
  4917     if (!updateBoundingRect)
  4851     while (p) {
  4918         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 }
  4919 }
  4862 
  4920 
  4863 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4921 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4864                                 const QRectF &rect, bool itemIsUntransformable)
  4922                                 const QRectF &rect, bool itemIsUntransformable)
  4865 {
  4923 {
  4930         if (item->d_ptr->graphicsEffect)
  4988         if (item->d_ptr->graphicsEffect)
  4931             itemHasContents = true;
  4989             itemHasContents = true;
  4932     }
  4990     }
  4933 
  4991 
  4934     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4992     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
  4935     const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
  4993     const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
       
  4994                                         && QGraphicsItemPrivate::isOpacityNull(opacity);
  4936     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
  4995     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
  4937         resetDirtyItem(item, /*recursive=*/itemHasChildren);
  4996         resetDirtyItem(item, /*recursive=*/itemHasChildren);
  4938         return;
  4997         return;
  4939     }
  4998     }
  4940 
  4999 
  5065 
  5124 
  5066     resetDirtyItem(item);
  5125     resetDirtyItem(item);
  5067 }
  5126 }
  5068 
  5127 
  5069 /*!
  5128 /*!
       
  5129     \obsolete
       
  5130 
  5070     Paints the given \a items using the provided \a painter, after the
  5131     Paints the given \a items using the provided \a painter, after the
  5071     background has been drawn, and before the foreground has been
  5132     background has been drawn, and before the foreground has been
  5072     drawn.  All painting is done in \e scene coordinates. Before
  5133     drawn.  All painting is done in \e scene coordinates. Before
  5073     drawing each item, the painter must be transformed using
  5134     drawing each item, the painter must be transformed using
  5074     QGraphicsItem::sceneTransform().
  5135     QGraphicsItem::sceneTransform().
  5087 
  5148 
  5088     Example:
  5149     Example:
  5089 
  5150 
  5090     \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
  5151     \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
  5091 
  5152 
       
  5153     Since Qt 4.6, this function is not called anymore unless
       
  5154     the QGraphicsView::IndirectPainting flag is given as an Optimization
       
  5155     flag.
       
  5156 
  5092     \sa drawBackground(), drawForeground()
  5157     \sa drawBackground(), drawForeground()
  5093 */
  5158 */
  5094 void QGraphicsScene::drawItems(QPainter *painter,
  5159 void QGraphicsScene::drawItems(QPainter *painter,
  5095                                int numItems,
  5160                                int numItems,
  5096                                QGraphicsItem *items[],
  5161                                QGraphicsItem *items[],
  5099     Q_D(QGraphicsScene);
  5164     Q_D(QGraphicsScene);
  5100     // Make sure we don't have unpolished items before we draw.
  5165     // Make sure we don't have unpolished items before we draw.
  5101     if (!d->unpolishedItems.isEmpty())
  5166     if (!d->unpolishedItems.isEmpty())
  5102         d->_q_polishItems();
  5167         d->_q_polishItems();
  5103 
  5168 
       
  5169     d->updateAll = false;
  5104     QTransform viewTransform = painter->worldTransform();
  5170     QTransform viewTransform = painter->worldTransform();
  5105     Q_UNUSED(options);
  5171     Q_UNUSED(options);
  5106 
  5172 
  5107     // Determine view, expose and flags.
  5173     // Determine view, expose and flags.
  5108     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
  5174     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
  5638             // if the TouchBegin handler recurses, we assume that means the event
  5704             // if the TouchBegin handler recurses, we assume that means the event
  5639             // has been implicitly accepted and continue to send touch events
  5705             // has been implicitly accepted and continue to send touch events
  5640             item->d_ptr->acceptedTouchBeginEvent = true;
  5706             item->d_ptr->acceptedTouchBeginEvent = true;
  5641             bool res = sendTouchBeginEvent(item, &touchEvent)
  5707             bool res = sendTouchBeginEvent(item, &touchEvent)
  5642                        && touchEvent.isAccepted();
  5708                        && touchEvent.isAccepted();
  5643             if (!res)
  5709             if (!res) {
       
  5710                 // forget about these touch points, we didn't handle them
       
  5711                 for (int i = 0; i < touchEvent.touchPoints().count(); ++i) {
       
  5712                     const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i);
       
  5713                     itemForTouchPointId.remove(touchPoint.id());
       
  5714                     sceneCurrentTouchPoints.remove(touchPoint.id());
       
  5715                 }
  5644                 ignoreSceneTouchEvent = false;
  5716                 ignoreSceneTouchEvent = false;
       
  5717             }
  5645             break;
  5718             break;
  5646         }
  5719         }
  5647         default:
  5720         default:
  5648             if (item->d_ptr->acceptedTouchBeginEvent) {
  5721             if (item->d_ptr->acceptedTouchBeginEvent) {
  5649                 updateTouchPointsForItem(item, &touchEvent);
  5722                 updateTouchPointsForItem(item, &touchEvent);
  5830         if (gesture->hasHotSpot()) {
  5903         if (gesture->hasHotSpot()) {
  5831             QPoint screenPos = gesture->hotSpot().toPoint();
  5904             QPoint screenPos = gesture->hotSpot().toPoint();
  5832             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
  5905             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
  5833             QList<QGraphicsObject *> result;
  5906             QList<QGraphicsObject *> result;
  5834             for (int j = 0; j < items.size(); ++j) {
  5907             for (int j = 0; j < items.size(); ++j) {
  5835                 QGraphicsObject *item = items.at(j)->toGraphicsObject();
  5908                 QGraphicsItem *item = items.at(j);
  5836                 if (!item)
  5909 
  5837                     continue;
  5910                 // Check if the item is blocked by a modal panel and use it as
  5838                 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
  5911                 // a target instead of this item.
  5839                 if (d->gestureContext.contains(gestureType)) {
  5912                 (void) item->isBlockedByModalPanel(&item);
  5840                     result.append(item);
  5913 
       
  5914                 if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
       
  5915                     QGraphicsItemPrivate *d = item->d_func();
       
  5916                     if (d->gestureContext.contains(gestureType)) {
       
  5917                         result.append(itemobj);
       
  5918                     }
  5841                 }
  5919                 }
       
  5920                 // Don't propagate through panels.
       
  5921                 if (item->isPanel())
       
  5922                     break;
  5842             }
  5923             }
  5843             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
  5924             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
  5844                     << gesture << result;
  5925                     << gesture << result;
  5845             if (result.size() == 1) {
  5926             if (result.size() == 1) {
  5846                 normalGestures->insert(gesture, result.first());
  5927                 normalGestures->insert(gesture, result.first());
  6140                 }
  6221                 }
  6141             }
  6222             }
  6142         }
  6223         }
  6143     }
  6224     }
  6144 
  6225 
  6145     Q_ASSERT(qt_gestureManager); // it would be very odd if we got called without a manager.
  6226     QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
       
  6227     Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
  6146     for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
  6228     for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
  6147         qt_gestureManager->recycle(*setIter);
  6229         gestureManager->recycle(*setIter);
  6148         gestureTargets.remove(*setIter);
  6230         gestureTargets.remove(*setIter);
  6149     }
  6231     }
  6150 }
  6232 }
  6151 
  6233 
  6152 QT_END_NAMESPACE
  6234 QT_END_NAMESPACE