Changeset 561 for trunk/src/gui/graphicsview/qgraphicsview.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/gui/graphicsview/qgraphicsview.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the QtGui module of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** 40 40 ****************************************************************************/ 41 42 //#define QGRAPHICSVIEW_DEBUG43 41 44 42 static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50; … … 51 49 contents of a QGraphicsScene. 52 50 \since 4.2 53 \ingroup multimedia54 51 \ingroup graphicsview-api 55 \mainclass 52 56 53 57 54 QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable … … 100 97 widget. 101 98 102 QGraphicsView supports affine transformations, using Q Matrix. You can103 either pass a matrix to set Matrix(), or you can call one of the99 QGraphicsView supports affine transformations, using QTransform. You can 100 either pass a matrix to setTransform(), or you can call one of the 104 101 convenience functions rotate(), scale(), translate() or shear(). The most 105 102 two common transformations are scaling, which is used to implement … … 201 198 can vary between paint devices and platforms. 202 199 203 \value DontClipPainter QGraphicsView sometimes clips the painter when 204 rendering the scene contents. This can generally improve performance 205 (e.g., rendering only small parts of a large pixmap), and protects against 206 rendering mistakes (e.g., drawing outside bounding rectangles, or outside 207 the exposed area). In some situations, however, the painter clip can slow 208 down rendering; especially when all painting is restricted to inside 209 exposed areas. By enabling this flag, QGraphicsView will completely 210 disable its implicit clipping. Note that rendering artifacts from using a 211 semi-transparent foreground or background brush can occur if clipping is 212 disabled. 200 \value DontClipPainter This value is obsolete and has no effect. 213 201 214 202 \value DontSavePainterState When rendering, QGraphicsView protects the … … 229 217 common side effect is that items that do draw with antialiasing can leave 230 218 painting traces behind on the scene as they are moved. 219 220 \value IndirectPainting Since Qt 4.6, restore the old painting algorithm 221 that calls QGraphicsView::drawItems() and QGraphicsScene::drawItems(). 222 To be used only for compatibility with old code. 231 223 */ 232 224 … … 290 282 #include <QtGui/qscrollbar.h> 291 283 #include <QtGui/qstyleoption.h> 284 #include <QtGui/qinputcontext.h> 292 285 #ifdef Q_WS_X11 286 #include <QtGui/qpaintengine.h> 293 287 #include <private/qt_x11_p.h> 294 288 #endif 295 289 290 #include <private/qevent_p.h> 291 296 292 QT_BEGIN_NAMESPACE 293 294 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); 297 295 298 296 inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision … … 303 301 return INT_MAX; 304 302 return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1); 303 } 304 305 void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent) 306 { 307 QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); 308 for (int i = 0; i < touchPoints.count(); ++i) { 309 QTouchEvent::TouchPoint &touchPoint = touchPoints[i]; 310 // the scene will set the item local pos, startPos, lastPos, and rect before delivering to 311 // an item, but for now those functions are returning the view's local coordinates 312 touchPoint.setSceneRect(d->mapToScene(touchPoint.rect())); 313 touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos())); 314 touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos())); 315 316 // screenPos, startScreenPos, lastScreenPos, and screenRect are already set 317 } 318 319 touchEvent->setTouchPoints(touchPoints); 305 320 } 306 321 … … 339 354 lastDragDropEvent(0), 340 355 fullUpdatePending(true), 341 dirtyRectCount(0),342 updatingLater(false),343 356 updateSceneSlotReimplementedChecked(false) 344 357 { … … 401 414 int right = q_round_bound(viewRect.right() - width); 402 415 if (left >= right) { 403 q->horizontalScrollBar()->setRange(0, 0);416 hbar->setRange(0, 0); 404 417 405 418 switch (alignment & Qt::AlignHorizontal_Mask) { … … 416 429 } 417 430 } else { 418 q->horizontalScrollBar()->setRange(left, right);419 q->horizontalScrollBar()->setPageStep(width);420 q->horizontalScrollBar()->setSingleStep(width / 20);431 hbar->setRange(left, right); 432 hbar->setPageStep(width); 433 hbar->setSingleStep(width / 20); 421 434 leftIndent = 0; 422 435 } … … 427 440 int bottom = q_round_bound(viewRect.bottom() - height); 428 441 if (top >= bottom) { 429 q->verticalScrollBar()->setRange(0, 0);442 vbar->setRange(0, 0); 430 443 431 444 switch (alignment & Qt::AlignVertical_Mask) { … … 442 455 } 443 456 } else { 444 q->verticalScrollBar()->setRange(top, bottom);445 q->verticalScrollBar()->setPageStep(height);446 q->verticalScrollBar()->setSingleStep(height / 20);457 vbar->setRange(top, bottom); 458 vbar->setPageStep(height); 459 vbar->setSingleStep(height / 20); 447 460 topIndent = 0; 448 461 } … … 456 469 if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) { 457 470 dirtyScroll = true; 458 q->viewport()->update();471 updateAll(); 459 472 } else if (q->isRightToLeft() && !leftIndent) { 460 473 // In reverse mode, the horizontal scroll always changes after the content … … 482 495 // Last scene pos: lastMouseMoveScenePoint 483 496 // Current mouse pos: 484 QPointF transformationDiff = q->mapToScene( q->viewport()->rect().center())485 - q->mapToScene( q->mapFromGlobal(QCursor::pos()));486 q->centerOn(lastMouseMoveScenePoint + transformationDiff); ;497 QPointF transformationDiff = q->mapToScene(viewport->rect().center()) 498 - q->mapToScene(viewport->mapFromGlobal(QCursor::pos())); 499 q->centerOn(lastMouseMoveScenePoint + transformationDiff); 487 500 } else { 488 501 q->centerOn(lastCenterPoint); … … 504 517 { 505 518 Q_Q(QGraphicsView); 506 lastCenterPoint = q->mapToScene( q->viewport()->rect().center());519 lastCenterPoint = q->mapToScene(viewport->rect().center()); 507 520 } 508 521 … … 531 544 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 532 545 return scrollY; 546 } 547 548 /*! 549 \internal 550 551 Maps the given rectangle to the scene using QTransform::mapRect() 552 */ 553 QRectF QGraphicsViewPrivate::mapRectToScene(const QRect &rect) const 554 { 555 if (dirtyScroll) 556 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 557 QRectF scrolled = QRectF(rect.translated(scrollX, scrollY)); 558 return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled); 559 } 560 561 562 /*! 563 \internal 564 565 Maps the given rectangle from the scene using QTransform::mapRect() 566 */ 567 QRectF QGraphicsViewPrivate::mapRectFromScene(const QRectF &rect) const 568 { 569 if (dirtyScroll) 570 const_cast<QGraphicsViewPrivate *>(this)->updateScroll(); 571 return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY); 533 572 } 534 573 … … 542 581 if (q->isRightToLeft()) { 543 582 if (!leftIndent) { 544 scrollX += q->horizontalScrollBar()->minimum();545 scrollX += q->horizontalScrollBar()->maximum();546 scrollX -= q->horizontalScrollBar()->value();583 scrollX += hbar->minimum(); 584 scrollX += hbar->maximum(); 585 scrollX -= hbar->value(); 547 586 } 548 587 } else { 549 scrollX += q->horizontalScrollBar()->value();550 } 551 552 scrollY = qint64( q->verticalScrollBar()->value() - topIndent);588 scrollX += hbar->value(); 589 } 590 591 scrollY = qint64(vbar->value() - topIndent); 553 592 554 593 dirtyScroll = false; … … 590 629 591 630 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); 592 mouseEvent.setWidget( q->viewport());631 mouseEvent.setWidget(viewport); 593 632 mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint); 594 633 mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint); … … 603 642 lastMouseMoveScreenPoint = mouseEvent.screenPos(); 604 643 mouseEvent.setAccepted(false); 605 QApplication::sendEvent(scene, &mouseEvent); 644 if (event->spontaneous()) 645 qt_sendSpontaneousEvent(scene, &mouseEvent); 646 else 647 QApplication::sendEvent(scene, &mouseEvent); 606 648 607 649 // Remember whether the last event was accepted or not. … … 615 657 616 658 #ifndef QT_NO_CURSOR 659 // If all the items ignore hover events, we don't look-up any items 660 // in QGraphicsScenePrivate::dispatchHoverEvent, hence the 661 // cachedItemsUnderMouse list will be empty. We therefore do the look-up 662 // for cursor items here if not all items use the default cursor. 663 if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor 664 && scene->d_func()->cachedItemsUnderMouse.isEmpty()) { 665 scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(), 666 mouseEvent.scenePos(), 667 mouseEvent.widget()); 668 } 617 669 // Find the topmost item under the mouse with a cursor. 618 670 foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) { … … 627 679 // Restore the original viewport cursor. 628 680 hasStoredOriginalCursor = false; 629 q->viewport()->setCursor(originalCursor);681 viewport->setCursor(originalCursor); 630 682 } 631 683 #endif … … 659 711 void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor) 660 712 { 661 Q_Q(QGraphicsView);662 QWidget *viewport = q->viewport();663 713 if (!hasStoredOriginalCursor) { 664 714 hasStoredOriginalCursor = true; … … 686 736 hasStoredOriginalCursor = false; 687 737 if (dragMode == QGraphicsView::ScrollHandDrag) 688 q->viewport()->setCursor(Qt::OpenHandCursor);738 viewport->setCursor(Qt::OpenHandCursor); 689 739 else 690 q->viewport()->setCursor(originalCursor);740 viewport->setCursor(originalCursor); 691 741 } 692 742 #endif … … 727 777 dest->setDropAction(source->dropAction()); 728 778 dest->setMimeData(source->mimeData()); 729 dest->setWidget( q->viewport());779 dest->setWidget(viewport); 730 780 dest->setSource(source->source()); 731 781 #else … … 750 800 751 801 // Translate-only 802 // COMBINE 752 803 QPointF offset; 753 804 const QGraphicsItem *parentItem = item; 754 805 const QGraphicsItemPrivate *itemd; 755 806 do { 756 itemd = parentItem->d_ptr ;757 if (itemd-> hasTransform)807 itemd = parentItem->d_ptr.data(); 808 if (itemd->transformData) 758 809 break; 759 810 offset += itemd->pos; … … 787 838 788 839 // Accurate bounding region 789 QTransform itv = item-> sceneTransform() * q->viewportTransform();840 QTransform itv = item->deviceTransform(q->viewportTransform()); 790 841 return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); 791 842 } 792 843 793 // QRectF::intersects() returns false always if either the source or target794 // rectangle's width or height are 0. This works around that problem.795 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)796 {797 Q_ASSERT(item);798 QRectF boundingRect(item->boundingRect());799 if (!boundingRect.width())800 boundingRect.adjust(-0.00001, 0, 0.00001, 0);801 if (!boundingRect.height())802 boundingRect.adjust(0, -0.00001, 0, 0.00001);803 return boundingRect;804 }805 806 844 /*! 807 845 \internal 808 846 */ 809 void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect) 810 { 811 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate) 812 return; 813 if (item->d_ptr->dirty) 814 updateLater(); 815 816 QRectF updateRect = rect; 817 if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) { 818 updateRect &= adjustedItemBoundingRect(item); 819 if (updateRect.isEmpty()) 820 return; 821 } 822 823 QGraphicsItem *clipItem = item; 824 if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { 825 // Minimize unnecessary redraw. 826 QGraphicsItem *parent = item; 827 while ((parent = parent->d_ptr->parent)) { 828 if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) { 829 // Map update rect to the current parent and itersect with its bounding rect. 830 updateRect = clipItem->itemTransform(parent).mapRect(updateRect) 831 & adjustedItemBoundingRect(parent); 832 if (updateRect.isEmpty()) 833 return; 834 clipItem = parent; 835 } 836 837 if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) 838 break; 839 } 840 } 841 842 // Map update rect from clipItem coordinates to view coordinates. 843 Q_ASSERT(clipItem); 844 if (!item->d_ptr->hasBoundingRegionGranularity) 845 this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect()); 846 else 847 updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect()); 848 } 849 850 void QGraphicsViewPrivate::updateLater() 851 { 852 Q_Q(QGraphicsView); 853 if (updatingLater) 854 return; 855 updatingLater = true; 856 QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection); 857 } 858 859 void QGraphicsViewPrivate::_q_updateLaterSlot() 860 { 861 Q_Q(QGraphicsView); 847 void QGraphicsViewPrivate::processPendingUpdates() 848 { 862 849 if (!scene) 863 850 return; 864 851 865 QRect vr = viewport->rect(); 866 QTransform viewTransform = q->viewportTransform(); 867 const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems; 868 for (int i = 0; i < dirtyItems.size(); ++i) { 869 const QGraphicsItem *item = dirtyItems.at(i); 870 if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false, 871 /*ignoreVisibleBit=*/false, 872 /*ignoreDirtyBit=*/true)) { 873 continue; 874 } 875 QTransform x = item->sceneTransform() * viewTransform; 876 updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr); 877 } 878 879 dirtyRectCount += dirtyRects.size(); 880 881 bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate; 882 if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) { 883 if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate 884 || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate 885 && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) { 886 if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { 887 viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); 888 } else { 889 viewport->update(dirtyBoundingRect); 890 } 891 } else { 892 // ### Improve this block, which is very slow for complex regions. We 893 // need to strike the balance between having an accurate update 894 // region, and running fast. The below approach is the simplest way to 895 // create a region from a bunch of rects, but we might want to use 896 // other approaches; e.g., a grid of a fixed size representing 897 // quadrants of the viewport, which we mark as dirty depending on the 898 // rectangles in the list. Perhaps this should go into a 899 // QRegion::fromRects(rects, how) function. 900 QRegion region; 901 if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) { 902 for (int i = 0; i < dirtyRegions.size(); ++i) { 903 QVector<QRect> rects = dirtyRegions.at(i).rects(); 904 for (int j = 0; j < rects.size(); ++j) 905 region += rects.at(j).adjusted(-2, -2, 2, 2); 906 } 907 for (int i = 0; i < dirtyRects.size(); ++i) 908 region += dirtyRects.at(i).adjusted(-2, -2, 2, 2); 909 } else { 910 for (int i = 0; i < dirtyRegions.size(); ++i) 911 region += dirtyRegions.at(i); 912 for (int i = 0; i < dirtyRects.size(); ++i) 913 region += dirtyRects.at(i); 914 } 915 916 viewport->update(region); 917 } 918 } 919 920 dirtyRegions.clear(); 921 dirtyRects.clear(); 922 dirtyRectCount = 0; 852 if (fullUpdatePending) { 853 viewport->update(); 854 } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { 855 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 856 viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); 857 else 858 viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); 859 } else { 860 viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. 861 } 862 923 863 dirtyBoundingRect = QRect(); 924 updatingLater = false; 925 } 926 927 void QGraphicsViewPrivate::updateAll() 928 { 929 Q_Q(QGraphicsView); 930 q->viewport()->update(); 931 fullUpdatePending = true; 932 dirtyRectCount = 0; 933 dirtyBoundingRect = QRect(); 934 updatingLater = false; 935 } 936 937 void QGraphicsViewPrivate::updateRegion(const QRegion &r) 938 { 939 if (r.isEmpty()) 940 return; 941 942 Q_Q(QGraphicsView); 943 944 // Rect intersects viewport - update everything? 864 dirtyRegion = QRegion(); 865 } 866 867 static inline bool intersectsViewport(const QRect &r, int width, int height) 868 { return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); } 869 870 static inline bool containsViewport(const QRect &r, int width, int height) 871 { return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; } 872 873 static inline void QRect_unite(QRect *rect, const QRect &other) 874 { 875 if (rect->isEmpty()) { 876 *rect = other; 877 } else { 878 rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()), 879 qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom())); 880 } 881 } 882 883 bool QGraphicsViewPrivate::updateRegion(const QRegion &r) 884 { 885 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) 886 return false; 887 888 const QRect boundingRect = r.boundingRect(); 889 if (!intersectsViewport(boundingRect, viewport->width(), viewport->height())) 890 return false; // Update region outside viewport. 891 945 892 switch (viewportUpdateMode) { 946 893 case QGraphicsView::FullViewportUpdate: 947 894 fullUpdatePending = true; 948 q->viewport()->update();895 viewport->update(); 949 896 break; 950 897 case QGraphicsView::BoundingRectViewportUpdate: 951 dirtyBoundingRect |= r.boundingRect();952 if ( dirtyBoundingRect == q->viewport()->rect()) {898 QRect_unite(&dirtyBoundingRect, boundingRect); 899 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { 953 900 fullUpdatePending = true; 954 q->viewport()->update(); 955 } else { 956 updateLater(); 901 viewport->update(); 957 902 } 958 903 break; 959 case QGraphicsView::SmartViewportUpdate: 960 dirtyBoundingRect |= r.boundingRect(); 961 if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) 962 dirtyRegions << r; 963 dirtyRectCount += r.numRects(); 964 updateLater(); 904 case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE 905 case QGraphicsView::MinimalViewportUpdate: 906 { 907 const QVector<QRect> &rects = r.rects(); 908 for (int i = 0; i < rects.size(); ++i) { 909 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 910 dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1); 911 else 912 dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2); 913 } 965 914 break; 966 case QGraphicsView::MinimalViewportUpdate: 967 dirtyRegions << r; 968 dirtyRectCount += r.numRects(); 969 updateLater(); 915 } 916 default: 970 917 break; 971 case QGraphicsView::NoViewportUpdate: 972 // Unreachable 973 break; 974 } 975 976 // Compress the regions... 977 if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) { 978 QRegion masterRegion; 979 for (int i=0; i<dirtyRegions.size(); ++i) { 980 masterRegion |= dirtyRegions.at(i); 981 } 982 dirtyRectCount = masterRegion.numRects(); 983 dirtyRegions.clear(); 984 dirtyRegions << masterRegion; 985 } 986 } 987 988 void QGraphicsViewPrivate::updateRect(const QRect &r) 989 { 990 if (r.isEmpty()) 991 return; 992 993 Q_Q(QGraphicsView); 994 995 // Rect intersects viewport - update everything? 918 } 919 920 return true; 921 } 922 923 bool QGraphicsViewPrivate::updateRect(const QRect &r) 924 { 925 if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate 926 || !intersectsViewport(r, viewport->width(), viewport->height())) { 927 return false; 928 } 929 996 930 switch (viewportUpdateMode) { 997 931 case QGraphicsView::FullViewportUpdate: 998 932 fullUpdatePending = true; 999 q->viewport()->update();933 viewport->update(); 1000 934 break; 1001 935 case QGraphicsView::BoundingRectViewportUpdate: 1002 dirtyBoundingRect |= r;1003 if ( dirtyBoundingRect == q->viewport()->rect()) {936 QRect_unite(&dirtyBoundingRect, r); 937 if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { 1004 938 fullUpdatePending = true; 1005 q->viewport()->update(); 1006 } else { 1007 updateLater(); 939 viewport->update(); 1008 940 } 1009 941 break; 1010 case QGraphicsView::SmartViewportUpdate: 1011 dirtyBoundingRect |= r; 1012 if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD) 1013 dirtyRects << r; 1014 updateLater(); 942 case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE 943 case QGraphicsView::MinimalViewportUpdate: 944 if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) 945 dirtyRegion += r.adjusted(-1, -1, 1, 1); 946 else 947 dirtyRegion += r.adjusted(-2, -2, 2, 2); 1015 948 break; 1016 case QGraphicsView::MinimalViewportUpdate: 1017 dirtyRects << r; 1018 updateLater(); 949 default: 1019 950 break; 1020 case QGraphicsView::NoViewportUpdate: 1021 // Unreachable 1022 break; 1023 } 951 } 952 953 return true; 1024 954 } 1025 955 … … 1047 977 extern QPainterPath qt_regionToPath(const QRegion ®ion); 1048 978 1049 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const 979 /*! 980 ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the 981 input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight() 982 (etc) when mapping the rectangle to a polygon (which is _wrong_). In 983 addition, as QGraphicsItem::boundingRect() is defined in logical space, 984 but the default pen for QPainter is cosmetic with a width of 0, QPainter 985 is at risk of painting 1 pixel outside the bounding rect. Therefore we 986 must search for items with an adjustment of (-1, -1, 1, 1). 987 */ 988 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems, 989 const QTransform &viewTransform) const 1050 990 { 1051 991 Q_Q(const QGraphicsView); 1052 const QPainterPath exposedPath(qt_regionToPath(exposedRegion)); 1053 const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); 1054 1055 if (exposedScenePath.contains(scene->d_func()->growingItemsBoundingRect)) { 992 993 // Step 1) If all items are contained within the expose region, then 994 // return a list of all visible items. ### the scene's growing bounding 995 // rect does not take into account untransformable items. 996 const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) 997 .boundingRect(); 998 if (exposedRegionSceneBounds.contains(scene->sceneRect())) { 1056 999 Q_ASSERT(allItems); 1057 1000 *allItems = true; 1058 1001 1059 // All items are guaranteed within the exposed region, don't bother using the index. 1060 QList<QGraphicsItem *> itemList(scene->items()); 1061 int i = 0; 1062 while (i < itemList.size()) { 1063 // But we only want to include items that are visible 1064 if (!itemList.at(i)->isVisible()) 1065 itemList.removeAt(i); 1066 else 1067 ++i; 1068 } 1069 1070 // Sort the items. 1071 QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled); 1072 return itemList; 1073 } 1074 1075 if (scene->d_func()->largestUntransformableItem.isNull()) { 1076 if (exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale) { 1077 return scene->d_func()->items_helper(exposedScenePath.controlPointRect(), 1078 Qt::IntersectsItemBoundingRect, 1079 Qt::DescendingOrder); 1080 } 1081 return scene->d_func()->items_helper(exposedScenePath, 1082 Qt::IntersectsItemBoundingRect, 1083 Qt::DescendingOrder); 1084 } 1085 1086 // NB! Path must be in viewport coordinates. 1087 return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); 1088 } 1089 1090 void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList, 1091 QGraphicsItem **itemArray, 1092 QStyleOptionGraphicsItem *styleOptionArray, 1093 const QTransform &worldTransform, 1094 bool allItems, 1095 const QRegion &exposedRegion) const 1096 { 1097 // Two unit vectors. 1098 QLineF v1(0, 0, 1, 0); 1099 QLineF v2(0, 0, 0, 1); 1100 QTransform itemToViewportTransform; 1101 QRectF brect; 1102 QTransform reverseMap; 1103 1104 for (int i = 0; i < itemList.size(); ++i) { 1105 QGraphicsItem *item = itemArray[i] = itemList[i]; 1106 1107 QStyleOptionGraphicsItem &option = styleOptionArray[i]; 1108 brect = item->boundingRect(); 1109 option.state = QStyle::State_None; 1110 option.rect = brect.toRect(); 1111 option.exposedRect = QRectF(); 1112 if (item->d_ptr->selected) 1113 option.state |= QStyle::State_Selected; 1114 if (item->d_ptr->enabled) 1115 option.state |= QStyle::State_Enabled; 1116 if (item->hasFocus()) 1117 option.state |= QStyle::State_HasFocus; 1118 if (scene->d_func()->hoverItems.contains(item)) 1119 option.state |= QStyle::State_MouseOver; 1120 if (item == scene->mouseGrabberItem()) 1121 option.state |= QStyle::State_Sunken; 1122 1123 // Calculate a simple level-of-detail metric. 1124 // ### almost identical code in QGraphicsScene::render() 1125 // and QGraphicsView::render() - consider refactoring 1126 if (item->d_ptr->itemIsUntransformable()) { 1127 itemToViewportTransform = item->deviceTransform(worldTransform); 1128 } else { 1129 itemToViewportTransform = item->sceneTransform() * worldTransform; 1130 } 1131 1132 if (itemToViewportTransform.type() <= QTransform::TxTranslate) { 1133 // Translation and rotation only? The LOD is 1. 1134 option.levelOfDetail = 1; 1135 } else { 1136 // LOD is the transformed area of a 1x1 rectangle. 1137 option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length()); 1138 } 1139 option.matrix = itemToViewportTransform.toAffine(); //### discards perspective 1140 1141 if (!allItems) { 1142 // Determine the item's exposed area 1143 reverseMap = itemToViewportTransform.inverted(); 1144 foreach (const QRect &rect, exposedRegion.rects()) { 1145 option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1))); 1146 if (option.exposedRect.contains(brect)) 1147 break; 1148 } 1149 option.exposedRect &= brect; 1150 } else { 1151 // The whole item is exposed 1152 option.exposedRect = brect; 1153 } 1154 } 1002 // All items are guaranteed within the exposed region. 1003 return scene->items(Qt::AscendingOrder); 1004 } 1005 1006 // Step 2) If the expose region is a simple rect and the view is only 1007 // translated or scaled, search for items using 1008 // QGraphicsScene::items(QRectF). 1009 bool simpleRectLookup = exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale; 1010 if (simpleRectLookup) { 1011 return scene->items(exposedRegionSceneBounds, 1012 Qt::IntersectsItemBoundingRect, 1013 Qt::AscendingOrder, viewTransform); 1014 } 1015 1016 // If the region is complex or the view has a complex transform, adjust 1017 // the expose region, convert it to a path, and then search for items 1018 // using QGraphicsScene::items(QPainterPath); 1019 QRegion adjustedRegion; 1020 foreach (const QRect &r, exposedRegion.rects()) 1021 adjustedRegion += r.adjusted(-1, -1, 1, 1); 1022 1023 const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); 1024 return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, 1025 Qt::AscendingOrder, viewTransform); 1026 } 1027 1028 /*! 1029 \internal 1030 1031 Enables input methods for the view if and only if the current focus item of 1032 the scene accepts input methods. Call function whenever that condition has 1033 potentially changed. 1034 */ 1035 void QGraphicsViewPrivate::updateInputMethodSensitivity() 1036 { 1037 Q_Q(QGraphicsView); 1038 bool enabled = scene && scene->focusItem() 1039 && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod); 1040 q->setAttribute(Qt::WA_InputMethodEnabled, enabled); 1041 q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled); 1155 1042 } 1156 1043 … … 1164 1051 setAcceptDrops(true); 1165 1052 setBackgroundRole(QPalette::Base); 1166 1167 // ### Ideally this would be enabled/disabled depending on whether any 1168 // widgets in the current scene enabled input methods. We could do that 1169 // using a simple reference count. The same goes for acceptDrops and mouse 1170 // tracking. 1053 // Investigate leaving these disabled by default. 1171 1054 setAttribute(Qt::WA_InputMethodEnabled); 1055 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1172 1056 } 1173 1057 … … 1183 1067 setAcceptDrops(true); 1184 1068 setBackgroundRole(QPalette::Base); 1069 // Investigate leaving these disabled by default. 1185 1070 setAttribute(Qt::WA_InputMethodEnabled); 1071 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1186 1072 } 1187 1073 … … 1195 1081 setAcceptDrops(true); 1196 1082 setBackgroundRole(QPalette::Base); 1083 // Investigate leaving these disabled by default. 1197 1084 setAttribute(Qt::WA_InputMethodEnabled); 1085 viewport()->setAttribute(Qt::WA_InputMethodEnabled); 1198 1086 } 1199 1087 … … 1249 1137 return; 1250 1138 d->renderHints = hints; 1251 viewport()->update();1139 d->updateAll(); 1252 1140 } 1253 1141 … … 1267 1155 d->renderHints &= ~hint; 1268 1156 if (oldHints != d->renderHints) 1269 viewport()->update();1157 d->updateAll(); 1270 1158 } 1271 1159 … … 1323 1211 Q_D(QGraphicsView); 1324 1212 d->transformationAnchor = anchor; 1213 1214 // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse 1215 // in order to have up-to-date information for centering the view. 1216 if (d->transformationAnchor == AnchorUnderMouse) 1217 d->viewport->setMouseTracking(true); 1325 1218 } 1326 1219 … … 1350 1243 Q_D(QGraphicsView); 1351 1244 d->resizeAnchor = anchor; 1245 1246 // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse 1247 // in order to have up-to-date information for centering the view. 1248 if (d->resizeAnchor == AnchorUnderMouse) 1249 d->viewport->setMouseTracking(true); 1352 1250 } 1353 1251 … … 1554 1452 // Background caching is enabled. 1555 1453 d->mustResizeBackgroundPixmap = true; 1556 viewport()->update();1454 d->updateAll(); 1557 1455 } else if (d->mustResizeBackgroundPixmap) { 1558 1456 // Background caching is disabled. … … 1643 1541 1644 1542 // Always update the viewport when the scene changes. 1645 viewport()->update();1543 d->updateAll(); 1646 1544 1647 1545 // Remove the previously assigned scene. … … 1651 1549 disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), 1652 1550 this, SLOT(updateSceneRect(QRectF))); 1653 d->scene->d_func()->views.removeAll(this); 1551 d->scene->d_func()->removeView(this); 1552 d->connectedToScene = false; 1553 1554 if (isActiveWindow() && isVisible()) { 1555 QEvent windowDeactivate(QEvent::WindowDeactivate); 1556 QApplication::sendEvent(d->scene, &windowDeactivate); 1557 } 1558 if(hasFocus()) 1559 d->scene->clearFocus(); 1654 1560 } 1655 1561 … … 1659 1565 this, SLOT(updateSceneRect(QRectF))); 1660 1566 d->updateSceneSlotReimplementedChecked = false; 1661 d->scene->d_func()-> views << this;1567 d->scene->d_func()->addView(this); 1662 1568 d->recalculateContentSize(); 1663 1569 d->lastCenterPoint = sceneRect().center(); 1664 1570 d->keepLastCenterPoint = true; 1571 // We are only interested in mouse tracking if items accept 1572 // hover events or use non-default cursors. 1573 if (!d->scene->d_func()->allItemsIgnoreHoverEvents 1574 || !d->scene->d_func()->allItemsUseDefaultCursor) { 1575 d->viewport->setMouseTracking(true); 1576 } 1577 1578 // enable touch events if any items is interested in them 1579 if (!d->scene->d_func()->allItemsIgnoreTouchEvents) 1580 d->viewport->setAttribute(Qt::WA_AcceptTouchEvents); 1581 1582 if (isActiveWindow() && isVisible()) { 1583 QEvent windowActivate(QEvent::WindowActivate); 1584 QApplication::sendEvent(d->scene, &windowActivate); 1585 } 1665 1586 } else { 1666 1587 d->recalculateContentSize(); 1667 1588 } 1589 1590 d->updateInputMethodSensitivity(); 1591 1592 if (d->scene && hasFocus()) 1593 d->scene->setFocus(); 1668 1594 } 1669 1595 … … 1712 1638 transformation is set, the identity matrix is returned. 1713 1639 1714 \sa setMatrix(), rotate(), scale(), shear(), translate()1640 \sa setMatrix(), transform(), rotate(), scale(), shear(), translate() 1715 1641 */ 1716 1642 QMatrix QGraphicsView::matrix() const … … 1744 1670 to map from floating point scene coordinates to view coordinates. 1745 1671 1746 \sa matrix(), rotate(), scale(), shear(), translate()1672 \sa matrix(), setTransform(), rotate(), scale(), shear(), translate() 1747 1673 */ 1748 1674 void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine) … … 1753 1679 /*! 1754 1680 Resets the view transformation matrix to the identity matrix. 1681 1682 \sa resetTransform() 1755 1683 */ 1756 1684 void QGraphicsView::resetMatrix() … … 1762 1690 Rotates the current view transformation \a angle degrees clockwise. 1763 1691 1764 \sa set Matrix(), matrix(), scale(), shear(), translate()1692 \sa setTransform(), transform(), scale(), shear(), translate() 1765 1693 */ 1766 1694 void QGraphicsView::rotate(qreal angle) … … 1775 1703 Scales the current view transformation by (\a sx, \a sy). 1776 1704 1777 \sa set Matrix(), matrix(), rotate(), shear(), translate()1705 \sa setTransform(), transform(), rotate(), shear(), translate() 1778 1706 */ 1779 1707 void QGraphicsView::scale(qreal sx, qreal sy) … … 1788 1716 Shears the current view transformation by (\a sh, \a sv). 1789 1717 1790 \sa set Matrix(), matrix(), rotate(), scale(), translate()1718 \sa setTransform(), transform(), rotate(), scale(), translate() 1791 1719 */ 1792 1720 void QGraphicsView::shear(qreal sh, qreal sv) … … 1801 1729 Translates the current view transformation by (\a dx, \a dy). 1802 1730 1803 \sa set Matrix(), matrix(), rotate(), shear()1731 \sa setTransform(), transform(), rotate(), shear() 1804 1732 */ 1805 1733 void QGraphicsView::translate(qreal dx, qreal dy) … … 1959 1887 function will do nothing. 1960 1888 1961 \sa set Matrix(), ensureVisible(), centerOn()1889 \sa setTransform(), ensureVisible(), centerOn() 1962 1890 */ 1963 1891 void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode) … … 2024 1952 { 2025 1953 QPainterPath path = item->isClipped() ? item->clipPath() : item->shape(); 2026 fitInView(item->sceneTransform().map(path).boundingRect(), aspectRatioMode); 1954 if (item->d_ptr->hasTranslateOnlySceneTransform()) { 1955 path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy()); 1956 fitInView(path.boundingRect(), aspectRatioMode); 1957 } else { 1958 fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode); 1959 } 2027 1960 } 2028 1961 … … 2050 1983 Qt::AspectRatioMode aspectRatioMode) 2051 1984 { 1985 // ### Switch to using the recursive rendering algorithm instead. 1986 2052 1987 Q_D(QGraphicsView); 2053 1988 if (!d->scene || !(painter && painter->isActive())) … … 2096 2031 2097 2032 // Setup painter matrix. 2098 QTransform moveMatrix; 2099 moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll()); 2033 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 2100 2034 QTransform painterMatrix = d->matrix * moveMatrix; 2101 2035 painterMatrix *= QTransform() … … 2104 2038 .translate(-sourceRect.left(), -sourceRect.top()); 2105 2039 2106 // Two unit vectors.2107 QLineF v1(0, 0, 1, 0);2108 QLineF v2(0, 0, 0, 1);2109 2110 2040 // Generate the style options 2111 2041 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); 2112 QStyleOptionGraphicsItem* option = styleOptionArray; 2113 for (int i = 0; i < numItems; ++i, ++option) { 2114 QGraphicsItem *item = itemArray[i]; 2115 2116 option->state = QStyle::State_None; 2117 option->rect = item->boundingRect().toRect(); 2118 if (item->isSelected()) 2119 option->state |= QStyle::State_Selected; 2120 if (item->isEnabled()) 2121 option->state |= QStyle::State_Enabled; 2122 if (item->hasFocus()) 2123 option->state |= QStyle::State_HasFocus; 2124 if (d->scene->d_func()->hoverItems.contains(item)) 2125 option->state |= QStyle::State_MouseOver; 2126 if (item == d->scene->mouseGrabberItem()) 2127 option->state |= QStyle::State_Sunken; 2128 2129 // Calculate a simple level-of-detail metric. 2130 // ### almost identical code in QGraphicsScene::render() 2131 // and QGraphicsView::paintEvent() - consider refactoring 2132 QTransform itemToViewportTransform; 2133 if (item->d_ptr->itemIsUntransformable()) { 2134 itemToViewportTransform = item->deviceTransform(painterMatrix); 2135 } else { 2136 itemToViewportTransform = item->sceneTransform() * painterMatrix; 2137 } 2138 2139 option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length()); 2140 option->matrix = itemToViewportTransform.toAffine(); 2141 2142 option->exposedRect = item->boundingRect(); 2143 option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect); 2144 } 2042 for (int i = 0; i < numItems; ++i) 2043 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect()); 2145 2044 2146 2045 painter->save(); … … 2169 2068 2170 2069 /*! 2171 Returns a list of all the items in the associated scene. 2172 2173 \sa QGraphicsScene::items() 2070 Returns a list of all the items in the associated scene, in descending 2071 stacking order (i.e., the first item in the returned list is the uppermost 2072 item). 2073 2074 \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} 2174 2075 */ 2175 2076 QList<QGraphicsItem *> QGraphicsView::items() const … … 2182 2083 2183 2084 /*! 2184 Returns all items in the area \a path, which is in viewport coordinates,2185 also taking untransformable items into consideration. This function is2186 considerably slower than just checking the scene directly. There is2187 certainly room for improvement.2188 */2189 QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,2190 Qt::ItemSelectionMode mode,2191 Qt::SortOrder order) const2192 {2193 Q_Q(const QGraphicsView);2194 2195 // Determine the size of the largest untransformable subtree of children2196 // mapped to scene coordinates.2197 QRectF untr = scene->d_func()->largestUntransformableItem;2198 QRectF ltri = matrix.inverted().mapRect(untr);2199 ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());2200 2201 QRectF rect = path.controlPointRect();2202 2203 // Find all possible items in the relevant area.2204 // ### Improve this algorithm; it might be searching a too large area.2205 QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect();2206 adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());2207 2208 // First build a (potentially large) list of all items in the vicinity2209 // that might be untransformable.2210 QList<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect);2211 2212 // Then find the minimal list of items that are inside \a path, and2213 // convert it to a set.2214 QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode);2215 QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);2216 2217 QTransform viewMatrix = q->viewportTransform();2218 2219 QList<QGraphicsItem *> result;2220 2221 // Run through all candidates and keep all items that are in candSet, or2222 // are untransformable and collide with \a path. ### We can improve this2223 // algorithm.2224 QList<QGraphicsItem *>::Iterator it = allCandidates.begin();2225 while (it != allCandidates.end()) {2226 QGraphicsItem *item = *it;2227 if (item->d_ptr->itemIsUntransformable()) {2228 // Check if this untransformable item collides with the2229 // original selection rect.2230 QTransform itemTransform = item->deviceTransform(viewMatrix);2231 if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode))2232 result << item;2233 } else {2234 if (candSet.contains(item))2235 result << item;2236 }2237 ++it;2238 }2239 2240 // ### Insertion sort would be faster.2241 if (order != Qt::SortOrder(-1))2242 QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled);2243 return result;2244 }2245 2246 /*!2247 2085 Returns a list of all the items at the position \a pos in the view. The 2248 items are listed in descending Z order (i.e., the first item in the list2249 is the top-most item, and the last item is the bottom-most item). \a pos2250 is in viewport coordinates.2086 items are listed in descending stacking order (i.e., the first item in the 2087 list is the uppermost item, and the last item is the lowermost item). \a 2088 pos is in viewport coordinates. 2251 2089 2252 2090 This function is most commonly called from within mouse event handlers in … … 2256 2094 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5 2257 2095 2258 \sa QGraphicsScene::items(), QGraphicsItem::zValue()2096 \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting} 2259 2097 */ 2260 2098 QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const … … 2263 2101 if (!d->scene) 2264 2102 return QList<QGraphicsItem *>(); 2265 if (d->scene->d_func()->largestUntransformableItem.isNull()) { 2266 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { 2267 QTransform xinv = viewportTransform().inverted(); 2268 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); 2269 } 2270 return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2)); 2271 } 2272 2273 QPainterPath path; 2274 path.addRect(QRectF(pos.x(), pos.y(), 1, 1)); 2275 return d->itemsInArea(path); 2103 // ### Unify these two, and use the items(QPointF) version in 2104 // QGraphicsScene instead. The scene items function could use the viewport 2105 // transform to map the point to a rect/polygon. 2106 if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { 2107 // Use the rect version 2108 QTransform xinv = viewportTransform().inverted(); 2109 return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), 2110 Qt::IntersectsItemShape, 2111 Qt::DescendingOrder, 2112 viewportTransform()); 2113 } 2114 // Use the polygon version 2115 return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), 2116 Qt::IntersectsItemShape, 2117 Qt::DescendingOrder, 2118 viewportTransform()); 2276 2119 } 2277 2120 … … 2293 2136 exact shape intersects with or is contained by \a rect are returned. 2294 2137 2295 \sa itemAt(), items(), mapToScene() 2138 The items are sorted in descending stacking order (i.e., the first item in 2139 the returned list is the uppermost item). 2140 2141 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2296 2142 */ 2297 2143 QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const … … 2300 2146 if (!d->scene) 2301 2147 return QList<QGraphicsItem *>(); 2302 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2303 return d->scene->items(mapToScene(rect), mode); 2304 2305 QPainterPath path; 2306 path.addRect(rect); 2307 return d->itemsInArea(path); 2148 return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform()); 2308 2149 } 2309 2150 … … 2326 2167 exact shape intersects with or is contained by \a polygon are returned. 2327 2168 2328 \sa itemAt(), items(), mapToScene() 2169 The items are sorted by descending stacking order (i.e., the first item in 2170 the returned list is the uppermost item). 2171 2172 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2329 2173 */ 2330 2174 QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const … … 2333 2177 if (!d->scene) 2334 2178 return QList<QGraphicsItem *>(); 2335 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2336 return d->scene->items(mapToScene(polygon), mode); 2337 2338 QPainterPath path; 2339 path.addPolygon(polygon); 2340 path.closeSubpath(); 2341 return d->itemsInArea(path); 2179 return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform()); 2342 2180 } 2343 2181 … … 2352 2190 exact shape intersects with or is contained by \a path are returned. 2353 2191 2354 \sa itemAt(), items(), mapToScene() 2192 \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting} 2355 2193 */ 2356 2194 QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const … … 2359 2197 if (!d->scene) 2360 2198 return QList<QGraphicsItem *>(); 2361 if (d->scene->d_func()->largestUntransformableItem.isNull()) 2362 return d->scene->items(mapToScene(path), mode); 2363 return d->itemsInArea(path); 2199 return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform()); 2364 2200 } 2365 2201 … … 2373 2209 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6 2374 2210 2375 \sa items() 2211 \sa items(), {QGraphicsItem#Sorting}{Sorting} 2376 2212 */ 2377 2213 QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const … … 2430 2266 2431 2267 QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll()); 2432 Q PointF tl = scrollOffset + rect.topLeft();2433 QPointF t r = scrollOffset + rect.topRight();2434 QPointF br = scrollOffset + rect.bottomRight();2435 QPointF b l = scrollOffset + rect.bottomLeft();2436 2437 QPolygonF poly; 2438 poly.resize(4);2268 QRect r = rect.adjusted(0, 0, 1, 1); 2269 QPointF tl = scrollOffset + r.topLeft(); 2270 QPointF tr = scrollOffset + r.topRight(); 2271 QPointF br = scrollOffset + r.bottomRight(); 2272 QPointF bl = scrollOffset + r.bottomLeft(); 2273 2274 QPolygonF poly(4); 2439 2275 if (!d->identityMatrix) { 2440 2276 QTransform x = d->matrix.inverted(); … … 2482 2318 { 2483 2319 Q_D(const QGraphicsView); 2484 QTransform m oveMatrix;2485 m oveMatrix.translate(d->horizontalScroll(), d->verticalScroll());2486 return (moveMatrix * d->matrix.inverted()).map(path);2320 QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll()); 2321 matrix *= d->matrix.inverted(); 2322 return matrix.map(path); 2487 2323 } 2488 2324 … … 2539 2375 bl -= scrollOffset; 2540 2376 2541 QPolygon poly; 2542 poly.resize(4); 2377 QPolygon poly(4); 2543 2378 poly[0] = tl.toPoint(); 2544 2379 poly[1] = tr.toPoint(); … … 2578 2413 { 2579 2414 Q_D(const QGraphicsView); 2580 QTransform m oveMatrix;2581 m oveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());2582 return (d->matrix * moveMatrix).map(path);2415 QTransform matrix = d->matrix; 2416 matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 2417 return matrix.map(path); 2583 2418 } 2584 2419 … … 2626 2461 Q_D(QGraphicsView); 2627 2462 d->backgroundBrush = brush; 2628 viewport()->update();2463 d->updateAll(); 2629 2464 2630 2465 if (d->cacheMode & CacheBackground) { … … 2656 2491 Q_D(QGraphicsView); 2657 2492 d->foregroundBrush = brush; 2658 viewport()->update();2493 d->updateAll(); 2659 2494 } 2660 2495 … … 2677 2512 // Extract and reset dirty scene rect info. 2678 2513 QVector<QRect> dirtyViewportRects; 2679 for (int i = 0; i < d->dirtyRegions.size(); ++i) 2680 dirtyViewportRects += d->dirtyRegions.at(i).rects(); 2681 d->dirtyRegions.clear(); 2514 const QVector<QRect> &dirtyRects = d->dirtyRegion.rects(); 2515 for (int i = 0; i < dirtyRects.size(); ++i) 2516 dirtyViewportRects += dirtyRects.at(i); 2517 d->dirtyRegion = QRegion(); 2518 d->dirtyBoundingRect = QRect(); 2682 2519 2683 2520 bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate; … … 2763 2600 const bool isGLWidget = widget->inherits("QGLWidget"); 2764 2601 2765 d->accelerateScrolling = !(isGLWidget 2766 || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D) 2767 || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)); 2602 d->accelerateScrolling = !(isGLWidget); 2768 2603 2769 2604 widget->setFocusPolicy(Qt::StrongFocus); … … 2774 2609 } 2775 2610 2776 widget->setMouseTracking(true); 2611 // We are only interested in mouse tracking if items 2612 // accept hover events or use non-default cursors or if 2613 // AnchorUnderMouse is used as transformation or resize anchor. 2614 if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents 2615 || !d->scene->d_func()->allItemsUseDefaultCursor)) 2616 || d->transformationAnchor == AnchorUnderMouse 2617 || d->resizeAnchor == AnchorUnderMouse) { 2618 widget->setMouseTracking(true); 2619 } 2620 2621 // enable touch events if any items is interested in them 2622 if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents) 2623 widget->setAttribute(Qt::WA_AcceptTouchEvents); 2624 2777 2625 widget->setAcceptDrops(acceptDrops()); 2778 2626 } … … 2825 2673 { 2826 2674 Q_D(QGraphicsView); 2827 2828 2675 if (!d->scene) 2829 2676 return QAbstractScrollArea::viewportEvent(event); … … 2844 2691 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first()); 2845 2692 QApplication::sendEvent(d->scene, event); 2693 break; 2694 case QEvent::Show: 2695 if (d->scene && isActiveWindow()) { 2696 QEvent windowActivate(QEvent::WindowActivate); 2697 QApplication::sendEvent(d->scene, &windowActivate); 2698 } 2699 break; 2700 case QEvent::Hide: 2701 // spontaneous event will generate a WindowDeactivate. 2702 if (!event->spontaneous() && d->scene && isActiveWindow()) { 2703 QEvent windowDeactivate(QEvent::WindowDeactivate); 2704 QApplication::sendEvent(d->scene, &windowDeactivate); 2705 } 2846 2706 break; 2847 2707 case QEvent::Leave: … … 2873 2733 // Reset full update 2874 2734 d->fullUpdatePending = false; 2735 d->dirtyScrollOffset = QPoint(); 2875 2736 if (d->scene) { 2876 2737 // Check if this view reimplements the updateScene slot; if it … … 2891 2752 } 2892 2753 break; 2754 case QEvent::TouchBegin: 2755 case QEvent::TouchUpdate: 2756 case QEvent::TouchEnd: 2757 { 2758 if (!isEnabled()) 2759 return false; 2760 2761 if (d->scene && d->sceneInteractionAllowed) { 2762 // Convert and deliver the touch event to the scene. 2763 QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event); 2764 touchEvent->setWidget(viewport()); 2765 QGraphicsViewPrivate::translateTouchEvent(d, touchEvent); 2766 (void) QApplication::sendEvent(d->scene, touchEvent); 2767 } 2768 2769 return true; 2770 } 2771 case QEvent::Gesture: 2772 case QEvent::GestureOverride: 2773 { 2774 if (!isEnabled()) 2775 return false; 2776 2777 if (d->scene && d->sceneInteractionAllowed) { 2778 QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event); 2779 gestureEvent->setWidget(viewport()); 2780 (void) QApplication::sendEvent(d->scene, gestureEvent); 2781 } 2782 return true; 2783 } 2893 2784 default: 2894 2785 break; … … 3064 2955 { 3065 2956 Q_D(QGraphicsView); 2957 d->updateInputMethodSensitivity(); 3066 2958 QAbstractScrollArea::focusInEvent(event); 3067 2959 if (d->scene) … … 3149 3041 mouseEvent.setButton(event->button()); 3150 3042 mouseEvent.setModifiers(event->modifiers()); 3151 QApplication::sendEvent(d->scene, &mouseEvent); 3043 if (event->spontaneous()) 3044 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3045 else 3046 QApplication::sendEvent(d->scene, &mouseEvent); 3152 3047 } 3153 3048 … … 3188 3083 mouseEvent.setModifiers(event->modifiers()); 3189 3084 mouseEvent.setAccepted(false); 3190 QApplication::sendEvent(d->scene, &mouseEvent); 3085 if (event->spontaneous()) 3086 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3087 else 3088 QApplication::sendEvent(d->scene, &mouseEvent); 3191 3089 3192 3090 // Update the original mouse event accepted state. … … 3249 3147 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3250 3148 else 3251 viewport()->update();3149 d->updateAll(); 3252 3150 } 3253 3151 … … 3271 3169 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3272 3170 else 3273 viewport()->update();3171 d->updateAll(); 3274 3172 } 3275 3173 // Set the new selection area … … 3278 3176 selectionArea.closeSubpath(); 3279 3177 if (d->scene) 3280 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode); 3178 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode, 3179 viewportTransform()); 3281 3180 return; 3282 3181 } … … 3314 3213 viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); 3315 3214 else 3316 viewport()->update();3215 d->updateAll(); 3317 3216 } 3318 3217 d->rubberBanding = false; … … 3321 3220 } else 3322 3221 #endif 3323 if (d->dragMode == QGraphicsView::ScrollHandDrag ) {3222 if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) { 3324 3223 #ifndef QT_NO_CURSOR 3325 3224 // Restore the open hand cursor. ### There might be items … … 3358 3257 mouseEvent.setModifiers(event->modifiers()); 3359 3258 mouseEvent.setAccepted(false); 3360 QApplication::sendEvent(d->scene, &mouseEvent); 3259 if (event->spontaneous()) 3260 qt_sendSpontaneousEvent(d->scene, &mouseEvent); 3261 else 3262 QApplication::sendEvent(d->scene, &mouseEvent); 3361 3263 3362 3264 // Update the last mouse event selected state. … … 3416 3318 3417 3319 // Determine the exposed region 3418 QRegion exposedRegion = event->region(); 3419 if (!d->accelerateScrolling) 3420 exposedRegion = viewport()->rect(); 3421 else if (d->viewportUpdateMode == BoundingRectViewportUpdate) 3422 exposedRegion = event->rect(); 3423 QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect().adjusted(0, 0, 1, 1)).boundingRect(); 3320 d->exposedRegion = event->region(); 3321 QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); 3424 3322 3425 3323 // Set up the painter 3426 3324 QPainter painter(viewport()); 3427 QTransform original = painter.worldTransform();3428 3325 #ifndef QT_NO_RUBBERBAND 3429 3326 if (d->rubberBanding && !d->rubberBandRect.isEmpty()) … … 3435 3332 3436 3333 // Set up viewport transform 3437 const QTransform viewTransform = viewportTransform(); 3438 painter.setTransform(viewTransform, true); 3439 3440 #ifdef QGRAPHICSVIEW_DEBUG 3441 QTime stopWatch; 3442 stopWatch.start(); 3443 qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ")"; 3444 #endif 3445 3446 // Find all exposed items 3447 bool allItems = false; 3448 QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems); 3449 3450 #ifdef QGRAPHICSVIEW_DEBUG 3451 int exposedTime = stopWatch.elapsed(); 3452 #endif 3453 3334 const bool viewTransformed = isTransformed(); 3335 if (viewTransformed) 3336 painter.setWorldTransform(viewportTransform()); 3337 const QTransform viewTransform = painter.worldTransform(); 3338 3339 // Draw background 3454 3340 if ((d->cacheMode & CacheBackground) 3455 3341 #ifdef Q_WS_X11 … … 3474 3360 QPainter backgroundPainter(&d->backgroundPixmap); 3475 3361 backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); 3476 backgroundPainter.setTransform(viewportTransform()); 3477 drawBackground(&backgroundPainter, exposedSceneRect); 3362 if (viewTransformed) 3363 backgroundPainter.setTransform(viewTransform); 3364 #ifdef Q_WS_X11 3365 #undef X11 3366 if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11) 3367 #define X11 qt_x11Data 3368 #endif 3369 backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); 3370 QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect(); 3371 drawBackground(&backgroundPainter, backgroundExposedSceneRect); 3478 3372 d->backgroundPixmapExposed = QRegion(); 3479 3373 } 3480 3374 3481 3375 // Blit the background from the background pixmap 3482 QTransform oldMatrix = painter.worldTransform(); 3483 painter.setWorldTransform(original); 3484 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3485 painter.setWorldTransform(oldMatrix); 3376 if (viewTransformed) { 3377 painter.setWorldTransform(QTransform()); 3378 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3379 painter.setWorldTransform(viewTransform); 3380 } else { 3381 painter.drawPixmap(QPoint(), d->backgroundPixmap); 3382 } 3486 3383 } else { 3487 3384 if (!(d->optimizationFlags & DontSavePainterState)) … … 3492 3389 } 3493 3390 3494 #ifdef QGRAPHICSVIEW_DEBUG3495 int backgroundTime = stopWatch.elapsed() - exposedTime;3496 #endif3497 3498 // Generate the style options3499 QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];3500 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());3501 3502 d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,3503 allItems, exposedRegion);3504 3505 3391 // Items 3506 drawItems(&painter, itemList.size(), itemArray, styleOptionArray); 3507 3508 #ifdef QGRAPHICSVIEW_DEBUG 3509 int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime; 3510 #endif 3392 if (!(d->optimizationFlags & IndirectPainting)) { 3393 d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0, 3394 &d->exposedRegion, viewport()); 3395 // Make sure the painter's world transform is restored correctly when 3396 // drawing without painter state protection (DontSavePainterState). 3397 // We only change the worldTransform() so there's no need to do a full-blown 3398 // save() and restore(). Also note that we don't have to do this in case of 3399 // IndirectPainting (the else branch), because in that case we always save() 3400 // and restore() in QGraphicsScene::drawItems(). 3401 if (!d->scene->d_func()->painterStateProtection) 3402 painter.setWorldTransform(viewTransform); 3403 } else { 3404 // Find all exposed items 3405 bool allItems = false; 3406 QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); 3407 if (!itemList.isEmpty()) { 3408 // Generate the style options. 3409 const int numItems = itemList.size(); 3410 QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. 3411 QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); 3412 for (int i = 0; i < numItems; ++i) { 3413 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, 3414 d->exposedRegion, allItems); 3415 } 3416 // Draw the items. 3417 drawItems(&painter, numItems, itemArray, styleOptionArray); 3418 d->freeStyleOptionsArray(styleOptionArray); 3419 } 3420 } 3511 3421 3512 3422 // Foreground 3513 3423 drawForeground(&painter, exposedSceneRect); 3514 3515 delete [] itemArray;3516 d->freeStyleOptionsArray(styleOptionArray);3517 3518 #ifdef QGRAPHICSVIEW_DEBUG3519 int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;3520 #endif3521 3424 3522 3425 #ifndef QT_NO_RUBBERBAND … … 3541 3444 painter.end(); 3542 3445 3543 #ifdef QGRAPHICSVIEW_DEBUG3544 qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"3545 << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";3546 qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";3547 qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("3548 << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";3549 qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";3550 qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("3551 << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";3552 #endif3553 3554 3446 // Restore painter state protection. 3555 3447 d->scene->d_func()->painterStateProtection = true; … … 3598 3490 if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) { 3599 3491 if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { 3600 for (int i = 0; i < d->dirtyRects.size(); ++i)3601 d->dirtyRects[i].translate(dx, dy);3602 for (int i = 0; i < d->dirtyRegions.size(); ++i)3603 d->dirtyRegions[i].translate(dx, dy);3604 3492 if (d->accelerateScrolling) { 3605 3493 #ifndef QT_NO_RUBBERBAND … … 3611 3499 } 3612 3500 #endif 3501 d->dirtyScrollOffset.rx() += dx; 3502 d->dirtyScrollOffset.ry() += dy; 3503 d->dirtyRegion.translate(dx, dy); 3613 3504 viewport()->scroll(dx, dy); 3614 3505 } else { 3615 viewport()->update();3506 d->updateAll(); 3616 3507 } 3617 3508 } else { 3618 viewport()->update();3509 d->updateAll(); 3619 3510 } 3620 3511 } … … 3627 3518 #endif 3628 3519 ) { 3520 // Scroll the background pixmap 3521 QRegion exposed; 3522 if (!d->backgroundPixmap.isNull()) 3523 d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed); 3524 3629 3525 // Invalidate the background pixmap 3630 d->backgroundPixmapExposed.translate(dx, 0); 3631 if (dx > 0) { 3632 d->backgroundPixmapExposed += QRect(0, 0, dx, viewport()->height()); 3633 } else if (dx < 0) { 3634 d->backgroundPixmapExposed += QRect(viewport()->width() + dx, 0, 3635 -dx, viewport()->height()); 3636 } 3637 d->backgroundPixmapExposed.translate(0, dy); 3638 if (dy > 0) { 3639 d->backgroundPixmapExposed += QRect(0, 0, viewport()->width(), dy); 3640 } else if (dy < 0) { 3641 d->backgroundPixmapExposed += QRect(0, viewport()->height() + dy, 3642 viewport()->width(), -dy); 3643 } 3644 3645 // Scroll the background pixmap 3646 if (!d->backgroundPixmap.isNull()) { 3647 QPixmap tmp = d->backgroundPixmap.copy(); 3648 QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole()); 3649 if (!bgBrush.isOpaque()) 3650 d->backgroundPixmap.fill(Qt::transparent); 3651 QPainter painter(&d->backgroundPixmap); 3652 painter.drawPixmap(dx, dy, tmp); 3653 } 3526 d->backgroundPixmapExposed.translate(dx, dy); 3527 d->backgroundPixmapExposed += exposed; 3654 3528 } 3655 3529 … … 3745 3619 The default implementation calls the scene's drawItems() function. 3746 3620 3621 \obsolete Since Qt 4.6, this function is not called anymore unless 3622 the QGraphicsView::IndirectPainting flag is given as an Optimization 3623 flag. 3624 3747 3625 \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems() 3748 3626 */ … … 3752 3630 { 3753 3631 Q_D(QGraphicsView); 3754 if (d->scene) 3755 d->scene->drawItems(painter, numItems, items, options, viewport()); 3632 if (d->scene) { 3633 QWidget *widget = painter->device() == viewport() ? viewport() : 0; 3634 d->scene->drawItems(painter, numItems, items, options, widget); 3635 } 3756 3636 } 3757 3637 … … 3776 3656 { 3777 3657 Q_D(const QGraphicsView); 3778 QTransform moveMatrix; 3779 moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll()); 3658 QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll()); 3780 3659 return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix; 3660 } 3661 3662 /*! 3663 \since 4.6 3664 3665 Returns true if the view is transformed (i.e., a non-identity transform 3666 has been assigned, or the scrollbars are adjusted). 3667 3668 \sa setTransform(), horizontalScrollBar(), verticalScrollBar() 3669 */ 3670 bool QGraphicsView::isTransformed() const 3671 { 3672 Q_D(const QGraphicsView); 3673 return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll(); 3781 3674 } 3782 3675 … … 3832 3725 3833 3726 // Any matrix operation requires a full update. 3834 viewport()->update();3727 d->updateAll(); 3835 3728 } 3836 3729 … … 3845 3738 } 3846 3739 3740 QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const 3741 { 3742 QPointF p = point; 3743 p.rx() += horizontalScroll(); 3744 p.ry() += verticalScroll(); 3745 return identityMatrix ? p : matrix.inverted().map(p); 3746 } 3747 3748 QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const 3749 { 3750 QPointF scrollOffset(horizontalScroll(), verticalScroll()); 3751 QPointF tl = scrollOffset + rect.topLeft(); 3752 QPointF tr = scrollOffset + rect.topRight(); 3753 QPointF br = scrollOffset + rect.bottomRight(); 3754 QPointF bl = scrollOffset + rect.bottomLeft(); 3755 3756 QPolygonF poly(4); 3757 if (!identityMatrix) { 3758 QTransform x = matrix.inverted(); 3759 poly[0] = x.map(tl); 3760 poly[1] = x.map(tr); 3761 poly[2] = x.map(br); 3762 poly[3] = x.map(bl); 3763 } else { 3764 poly[0] = tl; 3765 poly[1] = tr; 3766 poly[2] = br; 3767 poly[3] = bl; 3768 } 3769 return poly.boundingRect(); 3770 } 3771 3847 3772 QT_END_NAMESPACE 3848 3773
Note:
See TracChangeset
for help on using the changeset viewer.