Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/graphicsview/qgraphicsview.cpp

    r2 r561  
    22**
    33** 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)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** 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.
    3838** $QT_END_LICENSE$
    3939**
    4040****************************************************************************/
    41 
    42 //#define QGRAPHICSVIEW_DEBUG
    4341
    4442static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
     
    5149    contents of a QGraphicsScene.
    5250    \since 4.2
    53     \ingroup multimedia
    5451    \ingroup graphicsview-api
    55     \mainclass
     52
    5653
    5754    QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable
     
    10097    widget.
    10198
    102     QGraphicsView supports affine transformations, using QMatrix. You can
    103     either pass a matrix to setMatrix(), or you can call one of the
     99    QGraphicsView supports affine transformations, using QTransform. You can
     100    either pass a matrix to setTransform(), or you can call one of the
    104101    convenience functions rotate(), scale(), translate() or shear(). The most
    105102    two common transformations are scaling, which is used to implement
     
    201198    can vary between paint devices and platforms.
    202199
    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.
    213201
    214202    \value DontSavePainterState When rendering, QGraphicsView protects the
     
    229217    common side effect is that items that do draw with antialiasing can leave
    230218    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.
    231223*/
    232224
     
    290282#include <QtGui/qscrollbar.h>
    291283#include <QtGui/qstyleoption.h>
     284#include <QtGui/qinputcontext.h>
    292285#ifdef Q_WS_X11
     286#include <QtGui/qpaintengine.h>
    293287#include <private/qt_x11_p.h>
    294288#endif
    295289
     290#include <private/qevent_p.h>
     291
    296292QT_BEGIN_NAMESPACE
     293
     294bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
    297295
    298296inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision
     
    303301        return INT_MAX;
    304302    return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1);
     303}
     304
     305void 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);
    305320}
    306321
     
    339354      lastDragDropEvent(0),
    340355      fullUpdatePending(true),
    341       dirtyRectCount(0),
    342       updatingLater(false),
    343356      updateSceneSlotReimplementedChecked(false)
    344357{
     
    401414    int right = q_round_bound(viewRect.right() - width);
    402415    if (left >= right) {
    403         q->horizontalScrollBar()->setRange(0, 0);
     416        hbar->setRange(0, 0);
    404417
    405418        switch (alignment & Qt::AlignHorizontal_Mask) {
     
    416429        }
    417430    } 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);
    421434        leftIndent = 0;
    422435    }
     
    427440    int bottom = q_round_bound(viewRect.bottom()  - height);
    428441    if (top >= bottom) {
    429         q->verticalScrollBar()->setRange(0, 0);
     442        vbar->setRange(0, 0);
    430443
    431444        switch (alignment & Qt::AlignVertical_Mask) {
     
    442455        }
    443456    } 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);
    447460        topIndent = 0;
    448461    }
     
    456469    if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
    457470        dirtyScroll = true;
    458         q->viewport()->update();
     471        updateAll();
    459472    } else if (q->isRightToLeft() && !leftIndent) {
    460473        // In reverse mode, the horizontal scroll always changes after the content
     
    482495            // Last scene pos: lastMouseMoveScenePoint
    483496            // 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);
    487500        } else {
    488501            q->centerOn(lastCenterPoint);
     
    504517{
    505518    Q_Q(QGraphicsView);
    506     lastCenterPoint = q->mapToScene(q->viewport()->rect().center());
     519    lastCenterPoint = q->mapToScene(viewport->rect().center());
    507520}
    508521
     
    531544        const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
    532545    return scrollY;
     546}
     547
     548/*!
     549    \internal
     550
     551    Maps the given rectangle to the scene using QTransform::mapRect()
     552*/
     553QRectF 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*/
     567QRectF 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);
    533572}
    534573
     
    542581    if (q->isRightToLeft()) {
    543582        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();
    547586        }
    548587    } 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);
    553592
    554593    dirtyScroll = false;
     
    590629
    591630    QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
    592     mouseEvent.setWidget(q->viewport());
     631    mouseEvent.setWidget(viewport);
    593632    mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
    594633    mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
     
    603642    lastMouseMoveScreenPoint = mouseEvent.screenPos();
    604643    mouseEvent.setAccepted(false);
    605     QApplication::sendEvent(scene, &mouseEvent);
     644    if (event->spontaneous())
     645        qt_sendSpontaneousEvent(scene, &mouseEvent);
     646    else
     647        QApplication::sendEvent(scene, &mouseEvent);
    606648
    607649    // Remember whether the last event was accepted or not.
     
    615657
    616658#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    }
    617669    // Find the topmost item under the mouse with a cursor.
    618670    foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
     
    627679        // Restore the original viewport cursor.
    628680        hasStoredOriginalCursor = false;
    629         q->viewport()->setCursor(originalCursor);
     681        viewport->setCursor(originalCursor);
    630682    }
    631683#endif
     
    659711void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
    660712{
    661     Q_Q(QGraphicsView);
    662     QWidget *viewport = q->viewport();
    663713    if (!hasStoredOriginalCursor) {
    664714        hasStoredOriginalCursor = true;
     
    686736    hasStoredOriginalCursor = false;
    687737    if (dragMode == QGraphicsView::ScrollHandDrag)
    688         q->viewport()->setCursor(Qt::OpenHandCursor);
     738        viewport->setCursor(Qt::OpenHandCursor);
    689739    else
    690         q->viewport()->setCursor(originalCursor);
     740        viewport->setCursor(originalCursor);
    691741}
    692742#endif
     
    727777    dest->setDropAction(source->dropAction());
    728778    dest->setMimeData(source->mimeData());
    729     dest->setWidget(q->viewport());
     779    dest->setWidget(viewport);
    730780    dest->setSource(source->source());
    731781#else
     
    750800
    751801    // Translate-only
     802    // COMBINE
    752803    QPointF offset;
    753804    const QGraphicsItem *parentItem = item;
    754805    const QGraphicsItemPrivate *itemd;
    755806    do {
    756         itemd = parentItem->d_ptr;
    757         if (itemd->hasTransform)
     807        itemd = parentItem->d_ptr.data();
     808        if (itemd->transformData)
    758809            break;
    759810        offset += itemd->pos;
     
    787838
    788839    // Accurate bounding region
    789     QTransform itv = item->sceneTransform() * q->viewportTransform();
     840    QTransform itv = item->deviceTransform(q->viewportTransform());
    790841    return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
    791842}
    792843
    793 // QRectF::intersects() returns false always if either the source or target
    794 // 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 
    806844/*!
    807845    \internal
    808846*/
    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);
     847void QGraphicsViewPrivate::processPendingUpdates()
     848{
    862849    if (!scene)
    863850        return;
    864851
    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
    923863    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
     867static 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
     870static 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
     873static 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
     883bool 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
    945892    switch (viewportUpdateMode) {
    946893    case QGraphicsView::FullViewportUpdate:
    947894        fullUpdatePending = true;
    948         q->viewport()->update();
     895        viewport->update();
    949896        break;
    950897    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())) {
    953900            fullUpdatePending = true;
    954             q->viewport()->update();
    955         } else {
    956             updateLater();
     901            viewport->update();
    957902        }
    958903        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        }
    965914        break;
    966     case QGraphicsView::MinimalViewportUpdate:
    967         dirtyRegions << r;
    968         dirtyRectCount += r.numRects();
    969         updateLater();
     915    }
     916    default:
    970917        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
     923bool QGraphicsViewPrivate::updateRect(const QRect &r)
     924{
     925    if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
     926        || !intersectsViewport(r, viewport->width(), viewport->height())) {
     927        return false;
     928    }
     929
    996930    switch (viewportUpdateMode) {
    997931    case QGraphicsView::FullViewportUpdate:
    998932        fullUpdatePending = true;
    999         q->viewport()->update();
     933        viewport->update();
    1000934        break;
    1001935    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())) {
    1004938            fullUpdatePending = true;
    1005             q->viewport()->update();
    1006         } else {
    1007             updateLater();
     939            viewport->update();
    1008940        }
    1009941        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);
    1015948        break;
    1016     case QGraphicsView::MinimalViewportUpdate:
    1017         dirtyRects << r;
    1018         updateLater();
     949    default:
    1019950        break;
    1020     case QGraphicsView::NoViewportUpdate:
    1021         // Unreachable
    1022         break;
    1023     }
     951    }
     952
     953    return true;
    1024954}
    1025955
     
    1047977extern QPainterPath qt_regionToPath(const QRegion &region);
    1048978
    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*/
     988QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems,
     989                                                       const QTransform &viewTransform) const
    1050990{
    1051991    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())) {
    1056999        Q_ASSERT(allItems);
    10571000        *allItems = true;
    10581001
    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*/
     1035void 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);
    11551042}
    11561043
     
    11641051    setAcceptDrops(true);
    11651052    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.
    11711054    setAttribute(Qt::WA_InputMethodEnabled);
     1055    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11721056}
    11731057
     
    11831067    setAcceptDrops(true);
    11841068    setBackgroundRole(QPalette::Base);
     1069    // Investigate leaving these disabled by default.
    11851070    setAttribute(Qt::WA_InputMethodEnabled);
     1071    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11861072}
    11871073
     
    11951081    setAcceptDrops(true);
    11961082    setBackgroundRole(QPalette::Base);
     1083    // Investigate leaving these disabled by default.
    11971084    setAttribute(Qt::WA_InputMethodEnabled);
     1085    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11981086}
    11991087
     
    12491137        return;
    12501138    d->renderHints = hints;
    1251     viewport()->update();
     1139    d->updateAll();
    12521140}
    12531141
     
    12671155        d->renderHints &= ~hint;
    12681156    if (oldHints != d->renderHints)
    1269         viewport()->update();
     1157        d->updateAll();
    12701158}
    12711159
     
    13231211    Q_D(QGraphicsView);
    13241212    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);
    13251218}
    13261219
     
    13501243    Q_D(QGraphicsView);
    13511244    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);
    13521250}
    13531251
     
    15541452        // Background caching is enabled.
    15551453        d->mustResizeBackgroundPixmap = true;
    1556         viewport()->update();
     1454        d->updateAll();
    15571455    } else if (d->mustResizeBackgroundPixmap) {
    15581456        // Background caching is disabled.
     
    16431541
    16441542    // Always update the viewport when the scene changes.
    1645     viewport()->update();
     1543    d->updateAll();
    16461544
    16471545    // Remove the previously assigned scene.
     
    16511549        disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
    16521550                   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();
    16541560    }
    16551561
     
    16591565                this, SLOT(updateSceneRect(QRectF)));
    16601566        d->updateSceneSlotReimplementedChecked = false;
    1661         d->scene->d_func()->views << this;
     1567        d->scene->d_func()->addView(this);
    16621568        d->recalculateContentSize();
    16631569        d->lastCenterPoint = sceneRect().center();
    16641570        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        }
    16651586    } else {
    16661587        d->recalculateContentSize();
    16671588    }
     1589
     1590    d->updateInputMethodSensitivity();
     1591
     1592    if (d->scene && hasFocus())
     1593        d->scene->setFocus();
    16681594}
    16691595
     
    17121638    transformation is set, the identity matrix is returned.
    17131639
    1714     \sa setMatrix(), rotate(), scale(), shear(), translate()
     1640    \sa setMatrix(), transform(), rotate(), scale(), shear(), translate()
    17151641*/
    17161642QMatrix QGraphicsView::matrix() const
     
    17441670    to map from floating point scene coordinates to view coordinates.
    17451671
    1746     \sa matrix(), rotate(), scale(), shear(), translate()
     1672    \sa matrix(), setTransform(), rotate(), scale(), shear(), translate()
    17471673*/
    17481674void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
     
    17531679/*!
    17541680    Resets the view transformation matrix to the identity matrix.
     1681
     1682    \sa resetTransform()
    17551683*/
    17561684void QGraphicsView::resetMatrix()
     
    17621690    Rotates the current view transformation \a angle degrees clockwise.
    17631691
    1764     \sa setMatrix(), matrix(), scale(), shear(), translate()
     1692    \sa setTransform(), transform(), scale(), shear(), translate()
    17651693*/
    17661694void QGraphicsView::rotate(qreal angle)
     
    17751703    Scales the current view transformation by (\a sx, \a sy).
    17761704
    1777     \sa setMatrix(), matrix(), rotate(), shear(), translate()
     1705    \sa setTransform(), transform(), rotate(), shear(), translate()
    17781706*/
    17791707void QGraphicsView::scale(qreal sx, qreal sy)
     
    17881716    Shears the current view transformation by (\a sh, \a sv).
    17891717
    1790     \sa setMatrix(), matrix(), rotate(), scale(), translate()
     1718    \sa setTransform(), transform(), rotate(), scale(), translate()
    17911719*/
    17921720void QGraphicsView::shear(qreal sh, qreal sv)
     
    18011729    Translates the current view transformation by (\a dx, \a dy).
    18021730
    1803     \sa setMatrix(), matrix(), rotate(), shear()
     1731    \sa setTransform(), transform(), rotate(), shear()
    18041732*/
    18051733void QGraphicsView::translate(qreal dx, qreal dy)
     
    19591887    function will do nothing.
    19601888
    1961     \sa setMatrix(), ensureVisible(), centerOn()
     1889    \sa setTransform(), ensureVisible(), centerOn()
    19621890*/
    19631891void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
     
    20241952{
    20251953    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    }
    20271960}
    20281961
     
    20501983                           Qt::AspectRatioMode aspectRatioMode)
    20511984{
     1985    // ### Switch to using the recursive rendering algorithm instead.
     1986
    20521987    Q_D(QGraphicsView);
    20531988    if (!d->scene || !(painter && painter->isActive()))
     
    20962031
    20972032    // Setup painter matrix.
    2098     QTransform moveMatrix;
    2099     moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
     2033    QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
    21002034    QTransform painterMatrix = d->matrix * moveMatrix;
    21012035    painterMatrix *= QTransform()
     
    21042038                     .translate(-sourceRect.left(), -sourceRect.top());
    21052039
    2106     // Two unit vectors.
    2107     QLineF v1(0, 0, 1, 0);
    2108     QLineF v2(0, 0, 0, 1);
    2109 
    21102040    // Generate the style options
    21112041    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());
    21452044
    21462045    painter->save();
     
    21692068
    21702069/*!
    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}
    21742075*/
    21752076QList<QGraphicsItem *> QGraphicsView::items() const
     
    21822083
    21832084/*!
    2184     Returns all items in the area \a path, which is in viewport coordinates,
    2185     also taking untransformable items into consideration. This function is
    2186     considerably slower than just checking the scene directly. There is
    2187     certainly room for improvement.
    2188 */
    2189 QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,
    2190                                                          Qt::ItemSelectionMode mode,
    2191                                                          Qt::SortOrder order) const
    2192 {
    2193     Q_Q(const QGraphicsView);
    2194 
    2195     // Determine the size of the largest untransformable subtree of children
    2196     // 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 vicinity
    2209     // 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, and
    2213     // 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, or
    2222     // are untransformable and collide with \a path. ### We can improve this
    2223     // 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 the
    2229             // 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 /*!
    22472085    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 list
    2249     is the top-most item, and the last item is the bottom-most item). \a pos
    2250     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.
    22512089
    22522090    This function is most commonly called from within mouse event handlers in
     
    22562094    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5
    22572095
    2258     \sa QGraphicsScene::items(), QGraphicsItem::zValue()
     2096    \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
    22592097*/
    22602098QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
     
    22632101    if (!d->scene)
    22642102        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());
    22762119}
    22772120
     
    22932136    exact shape intersects with or is contained by \a rect are returned.
    22942137
    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}
    22962142*/
    22972143QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const
     
    23002146    if (!d->scene)
    23012147        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());
    23082149}
    23092150
     
    23262167    exact shape intersects with or is contained by \a polygon are returned.
    23272168
    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}
    23292173*/
    23302174QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const
     
    23332177    if (!d->scene)
    23342178        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());
    23422180}
    23432181
     
    23522190    exact shape intersects with or is contained by \a path are returned.
    23532191
    2354     \sa itemAt(), items(), mapToScene()
     2192    \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
    23552193*/
    23562194QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
     
    23592197    if (!d->scene)
    23602198        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());
    23642200}
    23652201
     
    23732209    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6
    23742210
    2375     \sa items()
     2211    \sa items(), {QGraphicsItem#Sorting}{Sorting}
    23762212*/
    23772213QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
     
    24302266
    24312267    QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
    2432     QPointF tl = scrollOffset + rect.topLeft();
    2433     QPointF tr = scrollOffset + rect.topRight();
    2434     QPointF br = scrollOffset + rect.bottomRight();
    2435     QPointF bl = 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);
    24392275    if (!d->identityMatrix) {
    24402276        QTransform x = d->matrix.inverted();
     
    24822318{
    24832319    Q_D(const QGraphicsView);
    2484     QTransform moveMatrix;
    2485     moveMatrix.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);
    24872323}
    24882324
     
    25392375    bl -= scrollOffset;
    25402376
    2541     QPolygon poly;
    2542     poly.resize(4);
     2377    QPolygon poly(4);
    25432378    poly[0] = tl.toPoint();
    25442379    poly[1] = tr.toPoint();
     
    25782413{
    25792414    Q_D(const QGraphicsView);
    2580     QTransform moveMatrix;
    2581     moveMatrix.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);
    25832418}
    25842419
     
    26262461    Q_D(QGraphicsView);
    26272462    d->backgroundBrush = brush;
    2628     viewport()->update();
     2463    d->updateAll();
    26292464
    26302465    if (d->cacheMode & CacheBackground) {
     
    26562491    Q_D(QGraphicsView);
    26572492    d->foregroundBrush = brush;
    2658     viewport()->update();
     2493    d->updateAll();
    26592494}
    26602495
     
    26772512    // Extract and reset dirty scene rect info.
    26782513    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();
    26822519
    26832520    bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
     
    27632600    const bool isGLWidget = widget->inherits("QGLWidget");
    27642601
    2765     d->accelerateScrolling = !(isGLWidget
    2766                                || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D)
    2767                                || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault));
     2602    d->accelerateScrolling = !(isGLWidget);
    27682603
    27692604    widget->setFocusPolicy(Qt::StrongFocus);
     
    27742609    }
    27752610
    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
    27772625    widget->setAcceptDrops(acceptDrops());
    27782626}
     
    28252673{
    28262674    Q_D(QGraphicsView);
    2827 
    28282675    if (!d->scene)
    28292676        return QAbstractScrollArea::viewportEvent(event);
     
    28442691            d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
    28452692        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        }
    28462706        break;
    28472707    case QEvent::Leave:
     
    28732733        // Reset full update
    28742734        d->fullUpdatePending = false;
     2735        d->dirtyScrollOffset = QPoint();
    28752736        if (d->scene) {
    28762737            // Check if this view reimplements the updateScene slot; if it
     
    28912752        }
    28922753        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    }
    28932784    default:
    28942785        break;
     
    30642955{
    30652956    Q_D(QGraphicsView);
     2957    d->updateInputMethodSensitivity();
    30662958    QAbstractScrollArea::focusInEvent(event);
    30672959    if (d->scene)
     
    31493041    mouseEvent.setButton(event->button());
    31503042    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);
    31523047}
    31533048
     
    31883083            mouseEvent.setModifiers(event->modifiers());
    31893084            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);
    31913089
    31923090            // Update the original mouse event accepted state.
     
    32493147                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    32503148                else
    3251                     viewport()->update();
     3149                    d->updateAll();
    32523150            }
    32533151
     
    32713169                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    32723170                else
    3273                     viewport()->update();
     3171                    d->updateAll();
    32743172            }
    32753173            // Set the new selection area
     
    32783176            selectionArea.closeSubpath();
    32793177            if (d->scene)
    3280                 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode);
     3178                d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode,
     3179                                           viewportTransform());
    32813180            return;
    32823181        }
     
    33143213                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    33153214                else
    3316                     viewport()->update();
     3215                    d->updateAll();
    33173216            }
    33183217            d->rubberBanding = false;
     
    33213220    } else
    33223221#endif
    3323     if (d->dragMode == QGraphicsView::ScrollHandDrag) {
     3222    if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
    33243223#ifndef QT_NO_CURSOR
    33253224        // Restore the open hand cursor. ### There might be items
     
    33583257    mouseEvent.setModifiers(event->modifiers());
    33593258    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);
    33613263
    33623264    // Update the last mouse event selected state.
     
    34163318
    34173319    // 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();
    34243322
    34253323    // Set up the painter
    34263324    QPainter painter(viewport());
    3427     QTransform original = painter.worldTransform();
    34283325#ifndef QT_NO_RUBBERBAND
    34293326    if (d->rubberBanding && !d->rubberBandRect.isEmpty())
     
    34353332
    34363333    // 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
    34543340    if ((d->cacheMode & CacheBackground)
    34553341#ifdef Q_WS_X11
     
    34743360            QPainter backgroundPainter(&d->backgroundPixmap);
    34753361            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);
    34783372            d->backgroundPixmapExposed = QRegion();
    34793373        }
    34803374
    34813375        // 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        }
    34863383    } else {
    34873384        if (!(d->optimizationFlags & DontSavePainterState))
     
    34923389    }
    34933390
    3494 #ifdef QGRAPHICSVIEW_DEBUG
    3495     int backgroundTime = stopWatch.elapsed() - exposedTime;
    3496 #endif
    3497 
    3498     // Generate the style options
    3499     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 
    35053391    // 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    }
    35113421
    35123422    // Foreground
    35133423    drawForeground(&painter, exposedSceneRect);
    3514 
    3515     delete [] itemArray;
    3516     d->freeStyleOptionsArray(styleOptionArray);
    3517 
    3518 #ifdef QGRAPHICSVIEW_DEBUG
    3519     int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
    3520 #endif
    35213424
    35223425#ifndef QT_NO_RUBBERBAND
     
    35413444    painter.end();
    35423445
    3543 #ifdef QGRAPHICSVIEW_DEBUG
    3544     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 #endif
    3553 
    35543446    // Restore painter state protection.
    35553447    d->scene->d_func()->painterStateProtection = true;
     
    35983490    if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
    35993491        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);
    36043492            if (d->accelerateScrolling) {
    36053493#ifndef QT_NO_RUBBERBAND
     
    36113499                }
    36123500#endif
     3501                d->dirtyScrollOffset.rx() += dx;
     3502                d->dirtyScrollOffset.ry() += dy;
     3503                d->dirtyRegion.translate(dx, dy);
    36133504                viewport()->scroll(dx, dy);
    36143505            } else {
    3615                 viewport()->update();
     3506                d->updateAll();
    36163507            }
    36173508        } else {
    3618             viewport()->update();
     3509            d->updateAll();
    36193510        }
    36203511    }
     
    36273518#endif
    36283519        ) {
     3520        // Scroll the background pixmap
     3521        QRegion exposed;
     3522        if (!d->backgroundPixmap.isNull())
     3523            d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
     3524
    36293525        // 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;
    36543528    }
    36553529
     
    37453619    The default implementation calls the scene's drawItems() function.
    37463620
     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
    37473625    \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems()
    37483626*/
     
    37523630{
    37533631    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    }
    37563636}
    37573637
     
    37763656{
    37773657    Q_D(const QGraphicsView);
    3778     QTransform moveMatrix;
    3779     moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
     3658    QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
    37803659    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*/
     3670bool QGraphicsView::isTransformed() const
     3671{
     3672    Q_D(const QGraphicsView);
     3673    return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
    37813674}
    37823675
     
    38323725
    38333726    // Any matrix operation requires a full update.
    3834     viewport()->update();
     3727    d->updateAll();
    38353728}
    38363729
     
    38453738}
    38463739
     3740QPointF 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
     3748QRectF 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
    38473772QT_END_NAMESPACE
    38483773
Note: See TracChangeset for help on using the changeset viewer.