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 { |