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()); |