src/gui/graphicsview/qgraphicsscene.cpp
branchRCL_3
changeset 5 d3bac044e0f0
parent 4 3b1da2848fc7
child 7 3f74d0d4af4c
equal deleted inserted replaced
4:3b1da2848fc7 5:d3bac044e0f0
   290       updateAll(false),
   290       updateAll(false),
   291       calledEmitUpdated(false),
   291       calledEmitUpdated(false),
   292       processDirtyItemsEmitted(false),
   292       processDirtyItemsEmitted(false),
   293       selectionChanging(0),
   293       selectionChanging(0),
   294       needSortTopLevelItems(true),
   294       needSortTopLevelItems(true),
   295       unpolishedItemsModified(true),
       
   296       holesInTopLevelSiblingIndex(false),
   295       holesInTopLevelSiblingIndex(false),
   297       topLevelSequentialOrdering(true),
   296       topLevelSequentialOrdering(true),
   298       scenePosDescendantsUpdatePending(false),
   297       scenePosDescendantsUpdatePending(false),
   299       stickyFocus(false),
   298       stickyFocus(false),
   300       hasFocus(false),
   299       hasFocus(false),
   427 /*!
   426 /*!
   428     \internal
   427     \internal
   429 */
   428 */
   430 void QGraphicsScenePrivate::_q_polishItems()
   429 void QGraphicsScenePrivate::_q_polishItems()
   431 {
   430 {
   432     QSet<QGraphicsItem *>::Iterator it = unpolishedItems.begin();
   431     if (unpolishedItems.isEmpty())
       
   432         return;
       
   433 
   433     const QVariant booleanTrueVariant(true);
   434     const QVariant booleanTrueVariant(true);
   434     while (!unpolishedItems.isEmpty()) {
   435     QGraphicsItem *item = 0;
   435         QGraphicsItem *item = *it;
   436     QGraphicsItemPrivate *itemd = 0;
   436         it = unpolishedItems.erase(it);
   437     const int oldUnpolishedCount = unpolishedItems.count();
   437         unpolishedItemsModified = false;
   438 
   438         if (!item->d_ptr->explicitlyHidden) {
   439     for (int i = 0; i < oldUnpolishedCount; ++i) {
       
   440         item = unpolishedItems.at(i);
       
   441         if (!item)
       
   442             continue;
       
   443         itemd = item->d_ptr.data();
       
   444         itemd->pendingPolish = false;
       
   445         if (!itemd->explicitlyHidden) {
   439             item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
   446             item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
   440             item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
   447             item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
   441         }
   448         }
   442         if (item->isWidget()) {
   449         if (itemd->isWidget) {
   443             QEvent event(QEvent::Polish);
   450             QEvent event(QEvent::Polish);
   444             QApplication::sendEvent((QGraphicsWidget *)item, &event);
   451             QApplication::sendEvent((QGraphicsWidget *)item, &event);
   445         }
   452         }
   446         if (unpolishedItemsModified)
   453     }
   447             it = unpolishedItems.begin();
   454 
       
   455     if (unpolishedItems.count() == oldUnpolishedCount) {
       
   456         // No new items were added to the vector.
       
   457         unpolishedItems.clear();
       
   458     } else {
       
   459         // New items were appended; keep them and remove the old ones.
       
   460         unpolishedItems.remove(0, oldUnpolishedCount);
       
   461         unpolishedItems.squeeze();
       
   462         QMetaObject::invokeMethod(q_ptr, "_q_polishItems", Qt::QueuedConnection);
   448     }
   463     }
   449 }
   464 }
   450 
   465 
   451 void QGraphicsScenePrivate::_q_processDirtyItems()
   466 void QGraphicsScenePrivate::_q_processDirtyItems()
   452 {
   467 {
   597     // Remove from parent, or unregister from toplevels.
   612     // Remove from parent, or unregister from toplevels.
   598     if (QGraphicsItem *parentItem = item->parentItem()) {
   613     if (QGraphicsItem *parentItem = item->parentItem()) {
   599         if (parentItem->scene()) {
   614         if (parentItem->scene()) {
   600             Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
   615             Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
   601                        "Parent item's scene is different from this item's scene");
   616                        "Parent item's scene is different from this item's scene");
   602             item->d_ptr->setParentItemHelper(0);
   617             item->setParentItem(0);
   603         }
   618         }
   604     } else {
   619     } else {
   605         unregisterTopLevelItem(item);
   620         unregisterTopLevelItem(item);
   606     }
   621     }
   607 
   622 
   636 
   651 
   637     // Update selected & hovered item bookkeeping
   652     // Update selected & hovered item bookkeeping
   638     selectedItems.remove(item);
   653     selectedItems.remove(item);
   639     hoverItems.removeAll(item);
   654     hoverItems.removeAll(item);
   640     cachedItemsUnderMouse.removeAll(item);
   655     cachedItemsUnderMouse.removeAll(item);
   641     unpolishedItems.remove(item);
   656     if (item->d_ptr->pendingPolish) {
   642     unpolishedItemsModified = true;
   657         const int unpolishedIndex = unpolishedItems.indexOf(item);
       
   658         if (unpolishedIndex != -1)
       
   659             unpolishedItems[unpolishedIndex] = 0;
       
   660         item->d_ptr->pendingPolish = false;
       
   661     }
   643     resetDirtyItem(item);
   662     resetDirtyItem(item);
   644 
   663 
   645     //We remove all references of item from the sceneEventFilter arrays
   664     //We remove all references of item from the sceneEventFilter arrays
   646     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
   665     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
   647     while (iterator != sceneEventFilters.end()) {
   666     while (iterator != sceneEventFilters.end()) {
  1934     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
  1953     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
  1935     \obsolete
  1954     \obsolete
  1936     \since 4.3
  1955     \since 4.3
  1937 
  1956 
  1938     This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
  1957     This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
  1939     
  1958 
  1940     This function is deprecated and returns incorrect results if the scene
  1959     This function is deprecated and returns incorrect results if the scene
  1941     contains items that ignore transformations. Use the overload that takes
  1960     contains items that ignore transformations. Use the overload that takes
  1942     a QTransform instead.
  1961     a QTransform instead.
  1943 */
  1962 */
  1944 
  1963 
  2480     Q_D(QGraphicsScene);
  2499     Q_D(QGraphicsScene);
  2481     if (!item) {
  2500     if (!item) {
  2482         qWarning("QGraphicsScene::addItem: cannot add null item");
  2501         qWarning("QGraphicsScene::addItem: cannot add null item");
  2483         return;
  2502         return;
  2484     }
  2503     }
  2485     if (item->scene() == this) {
  2504     if (item->d_ptr->scene == this) {
  2486         qWarning("QGraphicsScene::addItem: item has already been added to this scene");
  2505         qWarning("QGraphicsScene::addItem: item has already been added to this scene");
  2487         return;
  2506         return;
  2488     }
  2507     }
  2489     // Remove this item from its existing scene
  2508     // Remove this item from its existing scene
  2490     if (QGraphicsScene *oldScene = item->scene())
  2509     if (QGraphicsScene *oldScene = item->d_ptr->scene)
  2491         oldScene->removeItem(item);
  2510         oldScene->removeItem(item);
  2492 
  2511 
  2493     // Notify the item that its scene is changing, and allow the item to
  2512     // Notify the item that its scene is changing, and allow the item to
  2494     // react.
  2513     // react.
  2495     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
  2514     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
  2496                                                     qVariantFromValue<QGraphicsScene *>(this)));
  2515                                                     qVariantFromValue<QGraphicsScene *>(this)));
  2497     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
  2516     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
  2498     if (targetScene != this) {
  2517     if (targetScene != this) {
  2499         if (targetScene && item->scene() != targetScene)
  2518         if (targetScene && item->d_ptr->scene != targetScene)
  2500             targetScene->addItem(item);
  2519             targetScene->addItem(item);
  2501         return;
  2520         return;
  2502     }
  2521     }
  2503 
  2522 
       
  2523     if (d->unpolishedItems.isEmpty())
       
  2524         QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
       
  2525     d->unpolishedItems.append(item);
       
  2526     item->d_ptr->pendingPolish = true;
       
  2527 
  2504     // Detach this item from its parent if the parent's scene is different
  2528     // Detach this item from its parent if the parent's scene is different
  2505     // from this scene.
  2529     // from this scene.
  2506     if (QGraphicsItem *itemParent = item->parentItem()) {
  2530     if (QGraphicsItem *itemParent = item->d_ptr->parent) {
  2507         if (itemParent->scene() != this)
  2531         if (itemParent->d_ptr->scene != this)
  2508             item->setParentItem(0);
  2532             item->setParentItem(0);
  2509     }
  2533     }
  2510 
  2534 
  2511     // Add the item to this scene
  2535     // Add the item to this scene
  2512     item->d_func()->scene = targetScene;
  2536     item->d_func()->scene = targetScene;
  2532     if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
  2556     if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
  2533         d->allItemsIgnoreHoverEvents = false;
  2557         d->allItemsIgnoreHoverEvents = false;
  2534         d->enableMouseTrackingOnViews();
  2558         d->enableMouseTrackingOnViews();
  2535     }
  2559     }
  2536 #ifndef QT_NO_CURSOR
  2560 #ifndef QT_NO_CURSOR
  2537     if (d->allItemsUseDefaultCursor && item->hasCursor()) {
  2561     if (d->allItemsUseDefaultCursor && item->d_ptr->hasCursor) {
  2538         d->allItemsUseDefaultCursor = false;
  2562         d->allItemsUseDefaultCursor = false;
  2539         if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
  2563         if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
  2540             d->enableMouseTrackingOnViews();
  2564             d->enableMouseTrackingOnViews();
  2541     }
  2565     }
  2542 #endif //QT_NO_CURSOR
  2566 #endif //QT_NO_CURSOR
  2543 
  2567 
  2544     // Enable touch events if the item accepts touch events.
  2568     // Enable touch events if the item accepts touch events.
  2545     if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) {
  2569     if (d->allItemsIgnoreTouchEvents && item->d_ptr->acceptTouchEvents) {
  2546         d->allItemsIgnoreTouchEvents = false;
  2570         d->allItemsIgnoreTouchEvents = false;
  2547         d->enableTouchEventsOnViews();
  2571         d->enableTouchEventsOnViews();
  2548     }
  2572     }
  2549 
  2573 
  2550     // Update selection lists
  2574     // Update selection lists
  2573             lastNew->d_func()->focusNext = d->tabFocusFirst;
  2597             lastNew->d_func()->focusNext = d->tabFocusFirst;
  2574         }
  2598         }
  2575     }
  2599     }
  2576 
  2600 
  2577     // Add all children recursively
  2601     // Add all children recursively
  2578     foreach (QGraphicsItem *child, item->children())
  2602     item->d_ptr->ensureSortedChildren();
  2579         addItem(child);
  2603     for (int i = 0; i < item->d_ptr->children.size(); ++i)
       
  2604         addItem(item->d_ptr->children.at(i));
  2580 
  2605 
  2581     // Resolve font and palette.
  2606     // Resolve font and palette.
  2582     item->d_ptr->resolveFont(d->font.resolve());
  2607     item->d_ptr->resolveFont(d->font.resolve());
  2583     item->d_ptr->resolvePalette(d->palette.resolve());
  2608     item->d_ptr->resolvePalette(d->palette.resolve());
  2584 
  2609 
  2585     if (d->unpolishedItems.isEmpty())
       
  2586         QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
       
  2587     d->unpolishedItems.insert(item);
       
  2588     d->unpolishedItemsModified = true;
       
  2589 
  2610 
  2590     // Reenable selectionChanged() for individual items
  2611     // Reenable selectionChanged() for individual items
  2591     --d->selectionChanging;
  2612     --d->selectionChanging;
  2592     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
  2613     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
  2593         emit selectionChanged();
  2614         emit selectionChanged();
  2617             else
  2638             else
  2618                 d->lastActivePanel = item;
  2639                 d->lastActivePanel = item;
  2619         }
  2640         }
  2620     }
  2641     }
  2621 
  2642 
  2622     if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
  2643     if (item->d_ptr->flags & QGraphicsItem::ItemSendsScenePositionChanges)
  2623         d->registerScenePosItem(item);
  2644         d->registerScenePosItem(item);
  2624 
  2645 
  2625     // Ensure that newly added items that have subfocus set, gain
  2646     // Ensure that newly added items that have subfocus set, gain
  2626     // focus automatically if there isn't a focus item already.
  2647     // focus automatically if there isn't a focus item already.
  2627     if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
  2648     if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
  3764 #endif
  3785 #endif
  3765 }
  3786 }
  3766 
  3787 
  3767 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
  3788 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
  3768 {
  3789 {
  3769     return (!item->isBlockedByModalPanel() &&
  3790     return (item->d_ptr->acceptsHover
  3770             (item->acceptHoverEvents()
  3791             || (item->d_ptr->isWidget
  3771              || (item->isWidget()
  3792                 && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration()))
  3772                  && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())));
  3793            && !item->isBlockedByModalPanel();
  3773 }
  3794 }
  3774 
  3795 
  3775 /*!
  3796 /*!
  3776     This event handler, for event \a hoverEvent, can be reimplemented in a
  3797     This event handler, for event \a hoverEvent, can be reimplemented in a
  3777     subclass to receive hover enter events. The default implementation
  3798     subclass to receive hover enter events. The default implementation
  4809     if (itemHasChildren && itemClipsChildrenToShape)
  4830     if (itemHasChildren && itemClipsChildrenToShape)
  4810         painter->restore();
  4831         painter->restore();
  4811 }
  4832 }
  4812 
  4833 
  4813 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4834 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
  4814                                       bool force, bool ignoreOpacity, bool removingItemFromScene)
  4835                                       bool force, bool ignoreOpacity, bool removingItemFromScene,
       
  4836                                       bool updateBoundingRect)
  4815 {
  4837 {
  4816     Q_ASSERT(item);
  4838     Q_ASSERT(item);
  4817     if (updateAll)
  4839     if (updateAll)
  4818         return;
  4840         return;
  4819 
  4841 
  4880     if (force)
  4902     if (force)
  4881         item->d_ptr->ignoreVisible = 1;
  4903         item->d_ptr->ignoreVisible = 1;
  4882     if (ignoreOpacity)
  4904     if (ignoreOpacity)
  4883         item->d_ptr->ignoreOpacity = 1;
  4905         item->d_ptr->ignoreOpacity = 1;
  4884 
  4906 
  4885     QGraphicsItem *p = item->d_ptr->parent;
  4907     if (!updateBoundingRect)
  4886     while (p) {
  4908         item->d_ptr->markParentDirty();
  4887         p->d_ptr->dirtyChildren = 1;
       
  4888 #ifndef QT_NO_GRAPHICSEFFECT
       
  4889         if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
       
  4890             p->d_ptr->dirty = 1;
       
  4891             p->d_ptr->fullUpdatePending = 1;
       
  4892         }
       
  4893 #endif //QT_NO_GRAPHICSEFFECT
       
  4894         p = p->d_ptr->parent;
       
  4895     }
       
  4896 }
  4909 }
  4897 
  4910 
  4898 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4911 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
  4899                                 const QRectF &rect, bool itemIsUntransformable)
  4912                                 const QRectF &rect, bool itemIsUntransformable)
  4900 {
  4913 {