src/gui/graphicsview/qgraphicsview.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    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 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
       
    43 
       
    44 static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9
       
    45 
       
    46 /*!
       
    47     \class QGraphicsView
       
    48     \brief The QGraphicsView class provides a widget for displaying the
       
    49     contents of a QGraphicsScene.
       
    50     \since 4.2
       
    51     \ingroup graphicsview-api
       
    52 
       
    53 
       
    54     QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable
       
    55     viewport. To create a scene with geometrical items, see QGraphicsScene's
       
    56     documentation. QGraphicsView is part of \l{The Graphics View Framework}.
       
    57 
       
    58     To visualize a scene, you start by constructing a QGraphicsView object,
       
    59     passing the address of the scene you want to visualize to QGraphicsView's
       
    60     constructor. Alternatively, you can call setScene() to set the scene at a
       
    61     later point. After you call show(), the view will by default scroll to the
       
    62     center of the scene and display any items that are visible at this
       
    63     point. For example:
       
    64 
       
    65     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 0
       
    66 
       
    67     You can explicitly scroll to any position on the scene by using the
       
    68     scroll bars, or by calling centerOn(). By passing a point to centerOn(),
       
    69     QGraphicsView will scroll its viewport to ensure that the point is
       
    70     centered in the view. An overload is provided for scrolling to a
       
    71     QGraphicsItem, in which case QGraphicsView will see to that the center of
       
    72     the item is centered in the view. If all you want is to ensure that a
       
    73     certain area is visible, (but not necessarily centered,) you can call
       
    74     ensureVisible() instead.
       
    75 
       
    76     QGraphicsView can be used to visualize a whole scene, or only parts of it.
       
    77     The visualized area is by default detected automatically when the view is
       
    78     displayed for the first time (by calling
       
    79     QGraphicsScene::itemsBoundingRect()). To set the visualized area rectangle
       
    80     yourself, you can call setSceneRect(). This will adjust the scroll bars'
       
    81     ranges appropriately. Note that although the scene supports a virtually
       
    82     unlimited size, the range of the scroll bars will never exceed the range of
       
    83     an integer (INT_MIN, INT_MAX). When the scene is larger than the scroll
       
    84     bars' values, you can choose to use translate() to navigate the scene
       
    85     instead.
       
    86 
       
    87     QGraphicsView visualizes the scene by calling render(). By default, the
       
    88     items are drawn onto the viewport by using a regular QPainter, and using
       
    89     default render hints. To change the default render hints that
       
    90     QGraphicsView passes to QPainter when painting items, you can call
       
    91     setRenderHints().
       
    92 
       
    93     By default, QGraphicsView provides a regular QWidget for the viewport
       
    94     widget. You can access this widget by calling viewport(), or you can
       
    95     replace it by calling setViewport(). To render using OpenGL, simply call
       
    96     setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport
       
    97     widget.
       
    98 
       
    99     QGraphicsView supports affine transformations, using QTransform. You can
       
   100     either pass a matrix to setTransform(), or you can call one of the
       
   101     convenience functions rotate(), scale(), translate() or shear(). The most
       
   102     two common transformations are scaling, which is used to implement
       
   103     zooming, and rotation. QGraphicsView keeps the center of the view fixed
       
   104     during a transformation.
       
   105 
       
   106     You can interact with the items on the scene by using the mouse and
       
   107     keyboard. QGraphicsView translates the mouse and key events into \e scene
       
   108     events, (events that inherit QGraphicsSceneEvent,), and forward them to
       
   109     the visualized scene. In the end, it's the individual item that handles
       
   110     the events and reacts to them. For example, if you click on a selectable
       
   111     item, the item will typically let the scene know that it has been
       
   112     selected, and it will also redraw itself to display a selection
       
   113     rectangle. Similiary, if you click and drag the mouse to move a movable
       
   114     item, it's the item that handles the mouse moves and moves itself.  Item
       
   115     interaction is enabled by default, and you can toggle it by calling
       
   116     setInteractive().
       
   117 
       
   118     You can also provide your own custom scene interaction, by creating a
       
   119     subclass of QGraphicsView, and reimplementing the mouse and key event
       
   120     handlers. To simplify how you programmatically interact with items in the
       
   121     view, QGraphicsView provides the mapping functions mapToScene() and
       
   122     mapFromScene(), and the item accessors items() and itemAt(). These
       
   123     functions allow you to map points, rectangles, polygons and paths between
       
   124     view coordinates and scene coordinates, and to find items on the scene
       
   125     using view coordinates.
       
   126 
       
   127     \img graphicsview-view.png
       
   128 
       
   129     \sa QGraphicsScene, QGraphicsItem, QGraphicsSceneEvent
       
   130 */
       
   131 
       
   132 /*!
       
   133     \enum QGraphicsView::ViewportAnchor
       
   134 
       
   135     This enums describe the possible anchors that QGraphicsView can
       
   136     use when the user resizes the view or when the view is
       
   137     transformed.
       
   138 
       
   139     \value NoAnchor No anchor, i.e. the view leaves the scene's
       
   140                     position unchanged.
       
   141     \value AnchorViewCenter The scene point at the center of the view
       
   142                             is used as the anchor.
       
   143     \value AnchorUnderMouse The point under the mouse is used as the anchor.
       
   144 
       
   145     \sa resizeAnchor, transformationAnchor
       
   146 */
       
   147 
       
   148 /*!
       
   149     \enum QGraphicsView::ViewportUpdateMode
       
   150 
       
   151     \since 4.3
       
   152 
       
   153     This enum describes how QGraphicsView updates its viewport when the scene
       
   154     contents change or are exposed.
       
   155 
       
   156     \value FullViewportUpdate When any visible part of the scene changes or is
       
   157     reexposed, QGraphicsView will update the entire viewport. This approach is
       
   158     fastest when QGraphicsView spends more time figuring out what to draw than
       
   159     it would spend drawing (e.g., when very many small items are repeatedly
       
   160     updated). This is the preferred update mode for viewports that do not
       
   161     support partial updates, such as QGLWidget, and for viewports that need to
       
   162     disable scroll optimization.
       
   163 
       
   164     \value MinimalViewportUpdate QGraphicsView will determine the minimal
       
   165     viewport region that requires a redraw, minimizing the time spent drawing
       
   166     by avoiding a redraw of areas that have not changed. This is
       
   167     QGraphicsView's default mode. Although this approach provides the best
       
   168     performance in general, if there are many small visible changes on the
       
   169     scene, QGraphicsView might end up spending more time finding the minimal
       
   170     approach than it will spend drawing.
       
   171 
       
   172     \value SmartViewportUpdate QGraphicsView will attempt to find an optimal
       
   173     update mode by analyzing the areas that require a redraw.
       
   174 
       
   175     \value BoundingRectViewportUpdate The bounding rectangle of all changes in
       
   176     the viewport will be redrawn. This mode has the advantage that
       
   177     QGraphicsView searches only one region for changes, minimizing time spent
       
   178     determining what needs redrawing. The disadvantage is that areas that have
       
   179     not changed also need to be redrawn.
       
   180 
       
   181     \value NoViewportUpdate QGraphicsView will never update its viewport when
       
   182     the scene changes; the user is expected to control all updates. This mode
       
   183     disables all (potentially slow) item visibility testing in QGraphicsView,
       
   184     and is suitable for scenes that either require a fixed frame rate, or where
       
   185     the viewport is otherwise updated externally.
       
   186 
       
   187     \sa viewportUpdateMode
       
   188 */
       
   189 
       
   190 /*!
       
   191     \enum QGraphicsView::OptimizationFlag
       
   192 
       
   193     \since 4.3
       
   194 
       
   195     This enum describes flags that you can enable to improve rendering
       
   196     performance in QGraphicsView. By default, none of these flags are set.
       
   197     Note that setting a flag usually imposes a side effect, and this effect
       
   198     can vary between paint devices and platforms.
       
   199 
       
   200     \value DontClipPainter This value is obsolete and has no effect.
       
   201 
       
   202     \value DontSavePainterState When rendering, QGraphicsView protects the
       
   203     painter state (see QPainter::save()) when rendering the background or
       
   204     foreground, and when rendering each item. This allows you to leave the
       
   205     painter in an altered state (i.e., you can call QPainter::setPen() or
       
   206     QPainter::setBrush() without restoring the state after painting). However,
       
   207     if the items consistently do restore the state, you should enable this
       
   208     flag to prevent QGraphicsView from doing the same.
       
   209 
       
   210     \value DontAdjustForAntialiasing Disables QGraphicsView's antialiasing
       
   211     auto-adjustment of exposed areas. Items that render antialiased lines on
       
   212     the boundaries of their QGraphicsItem::boundingRect() can end up rendering
       
   213     parts of the line outside. To prevent rendering artifacts, QGraphicsView
       
   214     expands all exposed regions by 2 pixels in all directions. If you enable
       
   215     this flag, QGraphicsView will no longer perform these adjustments,
       
   216     minimizing the areas that require redrawing, which improves performance. A
       
   217     common side effect is that items that do draw with antialiasing can leave
       
   218     painting traces behind on the scene as they are moved.
       
   219 
       
   220     \omitvalue IndirectPainting
       
   221 */
       
   222 
       
   223 /*!
       
   224     \enum QGraphicsView::CacheModeFlag
       
   225 
       
   226     This enum describes the flags that you can set for a QGraphicsView's cache
       
   227     mode.
       
   228 
       
   229     \value CacheNone All painting is done directly onto the viewport.
       
   230 
       
   231     \value CacheBackground The background is cached. This affects both custom
       
   232     backgrounds, and backgrounds based on the backgroundBrush property. When
       
   233     this flag is enabled, QGraphicsView will allocate one pixmap with the full
       
   234     size of the viewport.
       
   235 
       
   236     \sa cacheMode
       
   237 */
       
   238 
       
   239 /*!
       
   240     \enum QGraphicsView::DragMode
       
   241 
       
   242     This enum describes the default action for the view when pressing and
       
   243     dragging the mouse over the viewport.
       
   244 
       
   245     \value NoDrag Nothing happens; the mouse event is ignored.
       
   246 
       
   247     \value ScrollHandDrag The cursor changes into a pointing hand, and
       
   248     dragging the mouse around will scroll the scrolbars. This mode works both
       
   249     in \l{QGraphicsView::interactive}{interactive} and non-interactive mode.
       
   250 
       
   251     \value RubberBandDrag A rubber band will appear. Dragging the mouse will
       
   252     set the rubber band geometry, and all items covered by the rubber band are
       
   253     selected. This mode is disabled for non-interactive views.
       
   254 
       
   255     \sa dragMode, QGraphicsScene::setSelectionArea()
       
   256 */
       
   257 
       
   258 #include "qgraphicsview.h"
       
   259 #include "qgraphicsview_p.h"
       
   260 
       
   261 #ifndef QT_NO_GRAPHICSVIEW
       
   262 
       
   263 #include "qgraphicsitem.h"
       
   264 #include "qgraphicsitem_p.h"
       
   265 #include "qgraphicsscene.h"
       
   266 #include "qgraphicsscene_p.h"
       
   267 #include "qgraphicssceneevent.h"
       
   268 #include "qgraphicswidget.h"
       
   269 
       
   270 #include <QtCore/qdatetime.h>
       
   271 #include <QtCore/qdebug.h>
       
   272 #include <QtCore/qmath.h>
       
   273 #include <QtGui/qapplication.h>
       
   274 #include <QtGui/qdesktopwidget.h>
       
   275 #include <QtGui/qevent.h>
       
   276 #include <QtGui/qlayout.h>
       
   277 #include <QtGui/qtransform.h>
       
   278 #include <QtGui/qmatrix.h>
       
   279 #include <QtGui/qpainter.h>
       
   280 #include <QtGui/qscrollbar.h>
       
   281 #include <QtGui/qstyleoption.h>
       
   282 #include <QtGui/qinputcontext.h>
       
   283 #ifdef Q_WS_X11
       
   284 #include <private/qt_x11_p.h>
       
   285 #endif
       
   286 
       
   287 #include <private/qevent_p.h>
       
   288 
       
   289 QT_BEGIN_NAMESPACE
       
   290 
       
   291 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
       
   292 
       
   293 inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision
       
   294 {
       
   295     if (d <= (qreal) INT_MIN)
       
   296         return INT_MIN;
       
   297     else if (d >= (qreal) INT_MAX)
       
   298         return INT_MAX;
       
   299     return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1);
       
   300 }
       
   301 
       
   302 void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
       
   303 {
       
   304     QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
       
   305     for (int i = 0; i < touchPoints.count(); ++i) {
       
   306         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
       
   307         // the scene will set the item local pos, startPos, lastPos, and rect before delivering to
       
   308         // an item, but for now those functions are returning the view's local coordinates
       
   309         touchPoint.setSceneRect(d->mapToScene(touchPoint.rect()));
       
   310         touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos()));
       
   311         touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos()));
       
   312 
       
   313         // screenPos, startScreenPos, lastScreenPos, and screenRect are already set
       
   314     }
       
   315 
       
   316     touchEvent->setTouchPoints(touchPoints);
       
   317 }
       
   318 
       
   319 /*!
       
   320     \internal
       
   321 */
       
   322 QGraphicsViewPrivate::QGraphicsViewPrivate()
       
   323     : renderHints(QPainter::TextAntialiasing),
       
   324       dragMode(QGraphicsView::NoDrag),
       
   325       sceneInteractionAllowed(true), hasSceneRect(false),
       
   326       connectedToScene(false),
       
   327       mousePressButton(Qt::NoButton),
       
   328       identityMatrix(true),
       
   329       dirtyScroll(true),
       
   330       accelerateScrolling(true),
       
   331       leftIndent(0), topIndent(0),
       
   332       lastMouseEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0),
       
   333       useLastMouseEvent(false),
       
   334       keepLastCenterPoint(true),
       
   335       alignment(Qt::AlignCenter),
       
   336       transforming(false),
       
   337       transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor),
       
   338       viewportUpdateMode(QGraphicsView::MinimalViewportUpdate),
       
   339       optimizationFlags(0),
       
   340       scene(0),
       
   341 #ifndef QT_NO_RUBBERBAND
       
   342       rubberBanding(false),
       
   343       rubberBandSelectionMode(Qt::IntersectsItemShape),
       
   344 #endif
       
   345       handScrolling(false), handScrollMotions(0), cacheMode(0),
       
   346       mustAllocateStyleOptions(false),
       
   347       mustResizeBackgroundPixmap(true),
       
   348 #ifndef QT_NO_CURSOR
       
   349       hasStoredOriginalCursor(false),
       
   350 #endif
       
   351       lastDragDropEvent(0),
       
   352       fullUpdatePending(true),
       
   353       updateSceneSlotReimplementedChecked(false)
       
   354 {
       
   355     styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
       
   356 }
       
   357 
       
   358 /*!
       
   359     \internal
       
   360 */
       
   361 void QGraphicsViewPrivate::recalculateContentSize()
       
   362 {
       
   363     Q_Q(QGraphicsView);
       
   364 
       
   365     QSize maxSize = q->maximumViewportSize();
       
   366     int width = maxSize.width();
       
   367     int height = maxSize.height();
       
   368     QRectF viewRect = matrix.mapRect(q->sceneRect());
       
   369 
       
   370     bool frameOnlyAround = (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q));
       
   371     if (frameOnlyAround) {
       
   372         if (hbarpolicy == Qt::ScrollBarAlwaysOn)
       
   373             height -= frameWidth * 2;
       
   374         if (vbarpolicy == Qt::ScrollBarAlwaysOn)
       
   375             width -= frameWidth * 2;
       
   376     }
       
   377 
       
   378     // Adjust the maximum width and height of the viewport based on the width
       
   379     // of visible scroll bars.
       
   380     int scrollBarExtent = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q);
       
   381     if (frameOnlyAround)
       
   382         scrollBarExtent += frameWidth * 2;
       
   383 
       
   384     bool useHorizontalScrollBar = (viewRect.width() > width) && hbarpolicy != Qt::ScrollBarAlwaysOff;
       
   385     bool useVerticalScrollBar = (viewRect.height() > height) && vbarpolicy != Qt::ScrollBarAlwaysOff;
       
   386     if (useHorizontalScrollBar && !useVerticalScrollBar) {
       
   387         if (viewRect.height() > height - scrollBarExtent)
       
   388             useVerticalScrollBar = true;
       
   389     }
       
   390     if (useVerticalScrollBar && !useHorizontalScrollBar) {
       
   391         if (viewRect.width() > width - scrollBarExtent)
       
   392             useHorizontalScrollBar = true;
       
   393     }
       
   394     if (useHorizontalScrollBar && hbarpolicy != Qt::ScrollBarAlwaysOn)
       
   395         height -= scrollBarExtent;
       
   396     if (useVerticalScrollBar && vbarpolicy != Qt::ScrollBarAlwaysOn)
       
   397         width -= scrollBarExtent;
       
   398 
       
   399     // Setting the ranges of these scroll bars can/will cause the values to
       
   400     // change, and scrollContentsBy() will be called correspondingly. This
       
   401     // will reset the last center point.
       
   402     QPointF savedLastCenterPoint = lastCenterPoint;
       
   403 
       
   404     // Remember the former indent settings
       
   405     qreal oldLeftIndent = leftIndent;
       
   406     qreal oldTopIndent = topIndent;
       
   407 
       
   408     // If the whole scene fits horizontally, we center the scene horizontally,
       
   409     // and ignore the horizontal scroll bars.
       
   410     int left =  q_round_bound(viewRect.left());
       
   411     int right = q_round_bound(viewRect.right() - width);
       
   412     if (left >= right) {
       
   413         hbar->setRange(0, 0);
       
   414 
       
   415         switch (alignment & Qt::AlignHorizontal_Mask) {
       
   416         case Qt::AlignLeft:
       
   417             leftIndent = -viewRect.left();
       
   418             break;
       
   419         case Qt::AlignRight:
       
   420             leftIndent = width - viewRect.width() - viewRect.left() - 1;
       
   421             break;
       
   422         case Qt::AlignHCenter:
       
   423         default:
       
   424             leftIndent = width / 2 - (viewRect.left() + viewRect.right()) / 2;
       
   425             break;
       
   426         }
       
   427     } else {
       
   428         hbar->setRange(left, right);
       
   429         hbar->setPageStep(width);
       
   430         hbar->setSingleStep(width / 20);
       
   431         leftIndent = 0;
       
   432     }
       
   433 
       
   434     // If the whole scene fits vertically, we center the scene vertically, and
       
   435     // ignore the vertical scroll bars.
       
   436     int top = q_round_bound(viewRect.top());
       
   437     int bottom = q_round_bound(viewRect.bottom()  - height);
       
   438     if (top >= bottom) {
       
   439         vbar->setRange(0, 0);
       
   440 
       
   441         switch (alignment & Qt::AlignVertical_Mask) {
       
   442         case Qt::AlignTop:
       
   443             topIndent = -viewRect.top();
       
   444             break;
       
   445         case Qt::AlignBottom:
       
   446             topIndent = height - viewRect.height() - viewRect.top() - 1;
       
   447             break;
       
   448         case Qt::AlignVCenter:
       
   449         default:
       
   450             topIndent = height / 2 - (viewRect.top() + viewRect.bottom()) / 2;
       
   451             break;
       
   452         }
       
   453     } else {
       
   454         vbar->setRange(top, bottom);
       
   455         vbar->setPageStep(height);
       
   456         vbar->setSingleStep(height / 20);
       
   457         topIndent = 0;
       
   458     }
       
   459 
       
   460     // Restorethe center point from before the ranges changed.
       
   461     lastCenterPoint = savedLastCenterPoint;
       
   462 
       
   463     // Issue a full update if the indents change.
       
   464     // ### If the transform is still the same, we can get away with just a
       
   465     // scroll instead.
       
   466     if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
       
   467         dirtyScroll = true;
       
   468         updateAll();
       
   469     } else if (q->isRightToLeft() && !leftIndent) {
       
   470         // In reverse mode, the horizontal scroll always changes after the content
       
   471         // size has changed, as the scroll is calculated by summing the min and
       
   472         // max values of the range and subtracting the current value. In normal
       
   473         // mode the scroll remains unchanged unless the indent has changed.
       
   474         dirtyScroll = true;
       
   475     }
       
   476 
       
   477     if (cacheMode & QGraphicsView::CacheBackground) {
       
   478         // Invalidate the background pixmap
       
   479         mustResizeBackgroundPixmap = true;
       
   480     }
       
   481 }
       
   482 
       
   483 /*!
       
   484     \internal
       
   485 */
       
   486 void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
       
   487 {
       
   488     Q_Q(QGraphicsView);
       
   489     switch (anchor) {
       
   490     case QGraphicsView::AnchorUnderMouse: {
       
   491         if (q->underMouse()) {
       
   492             // Last scene pos: lastMouseMoveScenePoint
       
   493             // Current mouse pos:
       
   494             QPointF transformationDiff = q->mapToScene(viewport->rect().center())
       
   495                                          - q->mapToScene(viewport->mapFromGlobal(QCursor::pos()));
       
   496             q->centerOn(lastMouseMoveScenePoint + transformationDiff);
       
   497         } else {
       
   498             q->centerOn(lastCenterPoint);
       
   499         }
       
   500         break;
       
   501     }
       
   502     case QGraphicsView::AnchorViewCenter:
       
   503         q->centerOn(lastCenterPoint);
       
   504         break;
       
   505     case QGraphicsView::NoAnchor:
       
   506         break;
       
   507     }
       
   508 }
       
   509 
       
   510 /*!
       
   511     \internal
       
   512 */
       
   513 void QGraphicsViewPrivate::updateLastCenterPoint()
       
   514 {
       
   515     Q_Q(QGraphicsView);
       
   516     lastCenterPoint = q->mapToScene(viewport->rect().center());
       
   517 }
       
   518 
       
   519 /*!
       
   520     \internal
       
   521 
       
   522     Returns the horizontal scroll value (the X value of the left edge of the
       
   523     viewport).
       
   524 */
       
   525 qint64 QGraphicsViewPrivate::horizontalScroll() const
       
   526 {
       
   527     if (dirtyScroll)
       
   528         const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
       
   529     return scrollX;
       
   530 }
       
   531 
       
   532 /*!
       
   533     \internal
       
   534 
       
   535     Returns the vertical scroll value (the X value of the top edge of the
       
   536     viewport).
       
   537 */
       
   538 qint64 QGraphicsViewPrivate::verticalScroll() const
       
   539 {
       
   540     if (dirtyScroll)
       
   541         const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
       
   542     return scrollY;
       
   543 }
       
   544 
       
   545 /*!
       
   546     \internal
       
   547 */
       
   548 void QGraphicsViewPrivate::updateScroll()
       
   549 {
       
   550     Q_Q(QGraphicsView);
       
   551     scrollX = qint64(-leftIndent);
       
   552     if (q->isRightToLeft()) {
       
   553         if (!leftIndent) {
       
   554             scrollX += hbar->minimum();
       
   555             scrollX += hbar->maximum();
       
   556             scrollX -= hbar->value();
       
   557         }
       
   558     } else {
       
   559         scrollX += hbar->value();
       
   560     }
       
   561 
       
   562     scrollY = qint64(vbar->value() - topIndent);
       
   563 
       
   564     dirtyScroll = false;
       
   565 }
       
   566 
       
   567 /*!
       
   568     \internal
       
   569 */
       
   570 void QGraphicsViewPrivate::replayLastMouseEvent()
       
   571 {
       
   572     if (!useLastMouseEvent || !scene)
       
   573         return;
       
   574     mouseMoveEventHandler(&lastMouseEvent);
       
   575 }
       
   576 
       
   577 /*!
       
   578     \internal
       
   579 */
       
   580 void QGraphicsViewPrivate::storeMouseEvent(QMouseEvent *event)
       
   581 {
       
   582     useLastMouseEvent = true;
       
   583     lastMouseEvent = QMouseEvent(QEvent::MouseMove, event->pos(), event->globalPos(),
       
   584                                  event->button(), event->buttons(), event->modifiers());
       
   585 }
       
   586 
       
   587 void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
       
   588 {
       
   589     Q_Q(QGraphicsView);
       
   590 
       
   591     storeMouseEvent(event);
       
   592     lastMouseEvent.setAccepted(false);
       
   593 
       
   594     if (!sceneInteractionAllowed)
       
   595         return;
       
   596     if (handScrolling)
       
   597         return;
       
   598     if (!scene)
       
   599         return;
       
   600 
       
   601     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
       
   602     mouseEvent.setWidget(viewport);
       
   603     mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
       
   604     mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
       
   605     mouseEvent.setScenePos(q->mapToScene(event->pos()));
       
   606     mouseEvent.setScreenPos(event->globalPos());
       
   607     mouseEvent.setLastScenePos(lastMouseMoveScenePoint);
       
   608     mouseEvent.setLastScreenPos(lastMouseMoveScreenPoint);
       
   609     mouseEvent.setButtons(event->buttons());
       
   610     mouseEvent.setButton(event->button());
       
   611     mouseEvent.setModifiers(event->modifiers());
       
   612     lastMouseMoveScenePoint = mouseEvent.scenePos();
       
   613     lastMouseMoveScreenPoint = mouseEvent.screenPos();
       
   614     mouseEvent.setAccepted(false);
       
   615     if (event->spontaneous())
       
   616         qt_sendSpontaneousEvent(scene, &mouseEvent);
       
   617     else
       
   618         QApplication::sendEvent(scene, &mouseEvent);
       
   619 
       
   620     // Remember whether the last event was accepted or not.
       
   621     lastMouseEvent.setAccepted(mouseEvent.isAccepted());
       
   622 
       
   623     if (mouseEvent.isAccepted() && mouseEvent.buttons() != 0) {
       
   624         // The event was delivered to a mouse grabber; the press is likely to
       
   625         // have set a cursor, and we must not change it.
       
   626         return;
       
   627     }
       
   628 
       
   629 #ifndef QT_NO_CURSOR
       
   630     // If all the items ignore hover events, we don't look-up any items
       
   631     // in QGraphicsScenePrivate::dispatchHoverEvent, hence the
       
   632     // cachedItemsUnderMouse list will be empty. We therefore do the look-up
       
   633     // for cursor items here if not all items use the default cursor.
       
   634     if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
       
   635         && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
       
   636         scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
       
   637                                                                                   mouseEvent.scenePos(),
       
   638                                                                                   mouseEvent.widget());
       
   639     }
       
   640     // Find the topmost item under the mouse with a cursor.
       
   641     foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
       
   642         if (item->hasCursor()) {
       
   643             _q_setViewportCursor(item->cursor());
       
   644             return;
       
   645         }
       
   646     }
       
   647 
       
   648     // No items with cursors found; revert to the view cursor.
       
   649     if (hasStoredOriginalCursor) {
       
   650         // Restore the original viewport cursor.
       
   651         hasStoredOriginalCursor = false;
       
   652         viewport->setCursor(originalCursor);
       
   653     }
       
   654 #endif
       
   655 }
       
   656 
       
   657 /*!
       
   658     \internal
       
   659 */
       
   660 #ifndef QT_NO_RUBBERBAND
       
   661 QRegion QGraphicsViewPrivate::rubberBandRegion(const QWidget *widget, const QRect &rect) const
       
   662 {
       
   663     QStyleHintReturnMask mask;
       
   664     QStyleOptionRubberBand option;
       
   665     option.initFrom(widget);
       
   666     option.rect = rect;
       
   667     option.opaque = false;
       
   668     option.shape = QRubberBand::Rectangle;
       
   669 
       
   670     QRegion tmp;
       
   671     tmp += rect;
       
   672     if (widget->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, widget, &mask))
       
   673         tmp &= mask.region;
       
   674     return tmp;
       
   675 }
       
   676 #endif
       
   677 
       
   678 /*!
       
   679     \internal
       
   680 */
       
   681 #ifndef QT_NO_CURSOR
       
   682 void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
       
   683 {
       
   684     if (!hasStoredOriginalCursor) {
       
   685         hasStoredOriginalCursor = true;
       
   686         originalCursor = viewport->cursor();
       
   687     }
       
   688     viewport->setCursor(cursor);
       
   689 }
       
   690 #endif
       
   691 
       
   692 /*!
       
   693     \internal
       
   694 */
       
   695 #ifndef QT_NO_CURSOR
       
   696 void QGraphicsViewPrivate::_q_unsetViewportCursor()
       
   697 {
       
   698     Q_Q(QGraphicsView);
       
   699     foreach (QGraphicsItem *item, q->items(lastMouseEvent.pos())) {
       
   700         if (item->hasCursor()) {
       
   701             _q_setViewportCursor(item->cursor());
       
   702             return;
       
   703         }
       
   704     }
       
   705 
       
   706     // Restore the original viewport cursor.
       
   707     hasStoredOriginalCursor = false;
       
   708     if (dragMode == QGraphicsView::ScrollHandDrag)
       
   709         viewport->setCursor(Qt::OpenHandCursor);
       
   710     else
       
   711         viewport->setCursor(originalCursor);
       
   712 }
       
   713 #endif
       
   714 
       
   715 /*!
       
   716     \internal
       
   717 */
       
   718 void QGraphicsViewPrivate::storeDragDropEvent(const QGraphicsSceneDragDropEvent *event)
       
   719 {
       
   720     delete lastDragDropEvent;
       
   721     lastDragDropEvent = new QGraphicsSceneDragDropEvent(event->type());
       
   722     lastDragDropEvent->setScenePos(event->scenePos());
       
   723     lastDragDropEvent->setScreenPos(event->screenPos());
       
   724     lastDragDropEvent->setButtons(event->buttons());
       
   725     lastDragDropEvent->setModifiers(event->modifiers());
       
   726     lastDragDropEvent->setPossibleActions(event->possibleActions());
       
   727     lastDragDropEvent->setProposedAction(event->proposedAction());
       
   728     lastDragDropEvent->setDropAction(event->dropAction());
       
   729     lastDragDropEvent->setMimeData(event->mimeData());
       
   730     lastDragDropEvent->setWidget(event->widget());
       
   731     lastDragDropEvent->setSource(event->source());
       
   732 }
       
   733 
       
   734 /*!
       
   735     \internal
       
   736 */
       
   737 void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
       
   738                                                       QDropEvent *source)
       
   739 {
       
   740 #ifndef QT_NO_DRAGANDDROP
       
   741     Q_Q(QGraphicsView);
       
   742     dest->setScenePos(q->mapToScene(source->pos()));
       
   743     dest->setScreenPos(q->mapToGlobal(source->pos()));
       
   744     dest->setButtons(source->mouseButtons());
       
   745     dest->setModifiers(source->keyboardModifiers());
       
   746     dest->setPossibleActions(source->possibleActions());
       
   747     dest->setProposedAction(source->proposedAction());
       
   748     dest->setDropAction(source->dropAction());
       
   749     dest->setMimeData(source->mimeData());
       
   750     dest->setWidget(viewport);
       
   751     dest->setSource(source->source());
       
   752 #else
       
   753     Q_UNUSED(dest)
       
   754     Q_UNUSED(source)
       
   755 #endif
       
   756 }
       
   757 
       
   758 /*!
       
   759     \internal
       
   760 */
       
   761 QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const
       
   762 {
       
   763     Q_Q(const QGraphicsView);
       
   764     if (dirtyScroll)
       
   765         const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
       
   766 
       
   767     if (item->d_ptr->itemIsUntransformable()) {
       
   768         QTransform itv = item->deviceTransform(q->viewportTransform());
       
   769         return itv.mapRect(rect).toAlignedRect();
       
   770     }
       
   771 
       
   772     // Translate-only
       
   773     // COMBINE
       
   774     QPointF offset;
       
   775     const QGraphicsItem *parentItem = item;
       
   776     const QGraphicsItemPrivate *itemd;
       
   777     do {
       
   778         itemd = parentItem->d_ptr.data();
       
   779         if (itemd->transformData)
       
   780             break;
       
   781         offset += itemd->pos;
       
   782     } while ((parentItem = itemd->parent));
       
   783 
       
   784     QRectF baseRect = rect.translated(offset.x(), offset.y());
       
   785     if (!parentItem) {
       
   786         if (identityMatrix) {
       
   787             baseRect.translate(-scrollX, -scrollY);
       
   788             return baseRect.toAlignedRect();
       
   789         }
       
   790         return matrix.mapRect(baseRect).translated(-scrollX, -scrollY).toAlignedRect();
       
   791     }
       
   792 
       
   793     QTransform tr = parentItem->sceneTransform();
       
   794     if (!identityMatrix)
       
   795         tr *= matrix;
       
   796     QRectF r = tr.mapRect(baseRect);
       
   797     r.translate(-scrollX, -scrollY);
       
   798     return r.toAlignedRect();
       
   799 }
       
   800 
       
   801 /*!
       
   802     \internal
       
   803 */
       
   804 QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const
       
   805 {
       
   806     Q_Q(const QGraphicsView);
       
   807     if (dirtyScroll)
       
   808         const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
       
   809 
       
   810     // Accurate bounding region
       
   811     QTransform itv = item->deviceTransform(q->viewportTransform());
       
   812     return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
       
   813 }
       
   814 
       
   815 /*!
       
   816     \internal
       
   817 */
       
   818 void QGraphicsViewPrivate::processPendingUpdates()
       
   819 {
       
   820     if (!scene)
       
   821         return;
       
   822 
       
   823     if (fullUpdatePending) {
       
   824         viewport->update();
       
   825     } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
       
   826         if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
       
   827             viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
       
   828         else
       
   829             viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
       
   830     } else {
       
   831         viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
       
   832     }
       
   833 
       
   834     dirtyBoundingRect = QRect();
       
   835     dirtyRegion = QRegion();
       
   836 }
       
   837 
       
   838 static inline bool intersectsViewport(const QRect &r, int width, int height)
       
   839 { return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
       
   840 
       
   841 static inline bool containsViewport(const QRect &r, int width, int height)
       
   842 { return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
       
   843 
       
   844 static inline void QRect_unite(QRect *rect, const QRect &other)
       
   845 {
       
   846     if (rect->isEmpty()) {
       
   847         *rect = other;
       
   848     } else {
       
   849         rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
       
   850                         qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
       
   851     }
       
   852 }
       
   853 
       
   854 bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
       
   855 {
       
   856     if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
       
   857         return false;
       
   858 
       
   859     const QRect boundingRect = r.boundingRect();
       
   860     if (!intersectsViewport(boundingRect, viewport->width(), viewport->height()))
       
   861         return false; // Update region outside viewport.
       
   862 
       
   863     switch (viewportUpdateMode) {
       
   864     case QGraphicsView::FullViewportUpdate:
       
   865         fullUpdatePending = true;
       
   866         viewport->update();
       
   867         break;
       
   868     case QGraphicsView::BoundingRectViewportUpdate:
       
   869         QRect_unite(&dirtyBoundingRect, boundingRect);
       
   870         if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
       
   871             fullUpdatePending = true;
       
   872             viewport->update();
       
   873         }
       
   874         break;
       
   875     case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
       
   876     case QGraphicsView::MinimalViewportUpdate:
       
   877     {
       
   878         const QVector<QRect> &rects = r.rects();
       
   879         for (int i = 0; i < rects.size(); ++i) {
       
   880             if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
       
   881                 dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1);
       
   882             else
       
   883                 dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
       
   884         }
       
   885         break;
       
   886     }
       
   887     default:
       
   888         break;
       
   889     }
       
   890 
       
   891     return true;
       
   892 }
       
   893 
       
   894 bool QGraphicsViewPrivate::updateRect(const QRect &r)
       
   895 {
       
   896     if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
       
   897         || !intersectsViewport(r, viewport->width(), viewport->height())) {
       
   898         return false;
       
   899     }
       
   900 
       
   901     switch (viewportUpdateMode) {
       
   902     case QGraphicsView::FullViewportUpdate:
       
   903         fullUpdatePending = true;
       
   904         viewport->update();
       
   905         break;
       
   906     case QGraphicsView::BoundingRectViewportUpdate:
       
   907         QRect_unite(&dirtyBoundingRect, r);
       
   908         if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
       
   909             fullUpdatePending = true;
       
   910             viewport->update();
       
   911         }
       
   912         break;
       
   913     case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
       
   914     case QGraphicsView::MinimalViewportUpdate:
       
   915         if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
       
   916             dirtyRegion += r.adjusted(-1, -1, 1, 1);
       
   917         else
       
   918             dirtyRegion += r.adjusted(-2, -2, 2, 2);
       
   919         break;
       
   920     default:
       
   921         break;
       
   922     }
       
   923 
       
   924     return true;
       
   925 }
       
   926 
       
   927 QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems)
       
   928 {
       
   929     if (mustAllocateStyleOptions || (numItems > styleOptions.capacity()))
       
   930         // too many items, let's allocate on-the-fly
       
   931         return new QStyleOptionGraphicsItem[numItems];
       
   932 
       
   933     // expand only whenever necessary
       
   934     if (numItems > styleOptions.size())
       
   935         styleOptions.resize(numItems);
       
   936 
       
   937     mustAllocateStyleOptions = true;
       
   938     return styleOptions.data();
       
   939 }
       
   940 
       
   941 void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array)
       
   942 {
       
   943     mustAllocateStyleOptions = false;
       
   944     if (array != styleOptions.data())
       
   945         delete [] array;
       
   946 }
       
   947 
       
   948 extern QPainterPath qt_regionToPath(const QRegion &region);
       
   949 
       
   950 /*!
       
   951     ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the
       
   952     input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight()
       
   953     (etc) when mapping the rectangle to a polygon (which is _wrong_). In
       
   954     addition, as QGraphicsItem::boundingRect() is defined in logical space,
       
   955     but the default pen for QPainter is cosmetic with a width of 0, QPainter
       
   956     is at risk of painting 1 pixel outside the bounding rect. Therefore we
       
   957     must search for items with an adjustment of (-1, -1, 1, 1).
       
   958 */
       
   959 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems,
       
   960                                                        const QTransform &viewTransform) const
       
   961 {
       
   962     Q_Q(const QGraphicsView);
       
   963 
       
   964     // Step 1) If all items are contained within the expose region, then
       
   965     // return a list of all visible items. ### the scene's growing bounding
       
   966     // rect does not take into account untransformable items.
       
   967     const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
       
   968                                             .boundingRect();
       
   969     if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
       
   970         Q_ASSERT(allItems);
       
   971         *allItems = true;
       
   972 
       
   973         // All items are guaranteed within the exposed region.
       
   974         return scene->items(Qt::AscendingOrder);
       
   975     }
       
   976 
       
   977     // Step 2) If the expose region is a simple rect and the view is only
       
   978     // translated or scaled, search for items using
       
   979     // QGraphicsScene::items(QRectF).
       
   980     bool simpleRectLookup =  exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale;
       
   981     if (simpleRectLookup) {
       
   982         return scene->items(exposedRegionSceneBounds,
       
   983                             Qt::IntersectsItemBoundingRect,
       
   984                             Qt::AscendingOrder, viewTransform);
       
   985     }
       
   986 
       
   987     // If the region is complex or the view has a complex transform, adjust
       
   988     // the expose region, convert it to a path, and then search for items
       
   989     // using QGraphicsScene::items(QPainterPath);
       
   990     QRegion adjustedRegion;
       
   991     foreach (const QRect &r, exposedRegion.rects())
       
   992         adjustedRegion += r.adjusted(-1, -1, 1, 1);
       
   993 
       
   994     const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
       
   995     return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
       
   996                         Qt::AscendingOrder, viewTransform);
       
   997 }
       
   998 
       
   999 /*!
       
  1000     \internal
       
  1001 
       
  1002     Enables input methods for the view if and only if the current focus item of
       
  1003     the scene accepts input methods. Call function whenever that condition has
       
  1004     potentially changed.
       
  1005 */
       
  1006 void QGraphicsViewPrivate::updateInputMethodSensitivity()
       
  1007 {
       
  1008     Q_Q(QGraphicsView);
       
  1009     bool enabled = scene && scene->focusItem()
       
  1010                    && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
       
  1011     q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
       
  1012     q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
       
  1013 }
       
  1014 
       
  1015 /*!
       
  1016     Constructs a QGraphicsView. \a parent is passed to QWidget's constructor.
       
  1017 */
       
  1018 QGraphicsView::QGraphicsView(QWidget *parent)
       
  1019     : QAbstractScrollArea(*new QGraphicsViewPrivate, parent)
       
  1020 {
       
  1021     setViewport(0);
       
  1022     setAcceptDrops(true);
       
  1023     setBackgroundRole(QPalette::Base);
       
  1024     // Investigate leaving these disabled by default.
       
  1025     setAttribute(Qt::WA_InputMethodEnabled);
       
  1026     viewport()->setAttribute(Qt::WA_InputMethodEnabled);
       
  1027 }
       
  1028 
       
  1029 /*!
       
  1030     Constructs a QGraphicsView and sets the visualized scene to \a
       
  1031     scene. \a parent is passed to QWidget's constructor.
       
  1032 */
       
  1033 QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent)
       
  1034     : QAbstractScrollArea(*new QGraphicsViewPrivate, parent)
       
  1035 {
       
  1036     setScene(scene);
       
  1037     setViewport(0);
       
  1038     setAcceptDrops(true);
       
  1039     setBackgroundRole(QPalette::Base);
       
  1040     // Investigate leaving these disabled by default.
       
  1041     setAttribute(Qt::WA_InputMethodEnabled);
       
  1042     viewport()->setAttribute(Qt::WA_InputMethodEnabled);
       
  1043 }
       
  1044 
       
  1045 /*!
       
  1046   \internal
       
  1047  */
       
  1048 QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent)
       
  1049   : QAbstractScrollArea(dd, parent)
       
  1050 {
       
  1051     setViewport(0);
       
  1052     setAcceptDrops(true);
       
  1053     setBackgroundRole(QPalette::Base);
       
  1054     // Investigate leaving these disabled by default.
       
  1055     setAttribute(Qt::WA_InputMethodEnabled);
       
  1056     viewport()->setAttribute(Qt::WA_InputMethodEnabled);
       
  1057 }
       
  1058 
       
  1059 /*!
       
  1060     Destructs the QGraphicsView object.
       
  1061 */
       
  1062 QGraphicsView::~QGraphicsView()
       
  1063 {
       
  1064     Q_D(QGraphicsView);
       
  1065     if (d->scene)
       
  1066         d->scene->d_func()->views.removeAll(this);
       
  1067     delete d->lastDragDropEvent;
       
  1068 }
       
  1069 
       
  1070 /*!
       
  1071     \reimp
       
  1072 */
       
  1073 QSize QGraphicsView::sizeHint() const
       
  1074 {
       
  1075     Q_D(const QGraphicsView);
       
  1076     if (d->scene) {
       
  1077         QSizeF baseSize = d->matrix.mapRect(sceneRect()).size();
       
  1078         baseSize += QSizeF(d->frameWidth * 2, d->frameWidth * 2);
       
  1079         return baseSize.boundedTo((3 * QApplication::desktop()->size()) / 4).toSize();
       
  1080     }
       
  1081     return QAbstractScrollArea::sizeHint();
       
  1082 }
       
  1083 
       
  1084 /*!
       
  1085     \property QGraphicsView::renderHints
       
  1086     \brief the default render hints for the view
       
  1087 
       
  1088     These hints are
       
  1089     used to initialize QPainter before each visible item is drawn. QPainter
       
  1090     uses render hints to toggle rendering features such as antialiasing and
       
  1091     smooth pixmap transformation.
       
  1092 
       
  1093     QPainter::TextAntialiasing is enabled by default.
       
  1094 
       
  1095     Example:
       
  1096 
       
  1097     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 1
       
  1098 */
       
  1099 QPainter::RenderHints QGraphicsView::renderHints() const
       
  1100 {
       
  1101     Q_D(const QGraphicsView);
       
  1102     return d->renderHints;
       
  1103 }
       
  1104 void QGraphicsView::setRenderHints(QPainter::RenderHints hints)
       
  1105 {
       
  1106     Q_D(QGraphicsView);
       
  1107     if (hints == d->renderHints)
       
  1108         return;
       
  1109     d->renderHints = hints;
       
  1110     d->updateAll();
       
  1111 }
       
  1112 
       
  1113 /*!
       
  1114     If \a enabled is true, the render hint \a hint is enabled; otherwise it
       
  1115     is disabled.
       
  1116 
       
  1117     \sa renderHints
       
  1118 */
       
  1119 void QGraphicsView::setRenderHint(QPainter::RenderHint hint, bool enabled)
       
  1120 {
       
  1121     Q_D(QGraphicsView);
       
  1122     QPainter::RenderHints oldHints = d->renderHints;
       
  1123     if (enabled)
       
  1124         d->renderHints |= hint;
       
  1125     else
       
  1126         d->renderHints &= ~hint;
       
  1127     if (oldHints != d->renderHints)
       
  1128         d->updateAll();
       
  1129 }
       
  1130 
       
  1131 /*!
       
  1132     \property QGraphicsView::alignment
       
  1133     \brief the alignment of the scene in the view when the whole
       
  1134     scene is visible.
       
  1135 
       
  1136     If the whole scene is visible in the view, (i.e., there are no visible
       
  1137     scroll bars,) the view's alignment will decide where the scene will be
       
  1138     rendered in the view. For example, if the alignment is Qt::AlignCenter,
       
  1139     which is default, the scene will be centered in the view, and if the
       
  1140     alignment is (Qt::AlignLeft | Qt::AlignTop), the scene will be rendered in
       
  1141     the top-left corner of the view.
       
  1142 */
       
  1143 Qt::Alignment QGraphicsView::alignment() const
       
  1144 {
       
  1145     Q_D(const QGraphicsView);
       
  1146     return d->alignment;
       
  1147 }
       
  1148 void QGraphicsView::setAlignment(Qt::Alignment alignment)
       
  1149 {
       
  1150     Q_D(QGraphicsView);
       
  1151     if (d->alignment != alignment) {
       
  1152         d->alignment = alignment;
       
  1153         d->recalculateContentSize();
       
  1154     }
       
  1155 }
       
  1156 
       
  1157 /*!
       
  1158     \property QGraphicsView::transformationAnchor
       
  1159     \brief how the view should position the scene during transformations.
       
  1160 
       
  1161     QGraphicsView uses this property to decide how to position the scene in
       
  1162     the viewport when the transformation matrix changes, and the coordinate
       
  1163     system of the view is transformed. The default behavior, AnchorViewCenter,
       
  1164     ensures that the scene point at the center of the view remains unchanged
       
  1165     during transformations (e.g., when rotating, the scene will appear to
       
  1166     rotate around the center of the view).
       
  1167 
       
  1168     Note that the effect of this property is noticeable when only a part of the
       
  1169     scene is visible (i.e., when there are scroll bars). Otherwise, if the
       
  1170     whole scene fits in the view, QGraphicsScene uses the view \l alignment to
       
  1171     position the scene in the view.
       
  1172 
       
  1173     \sa alignment, resizeAnchor
       
  1174 */
       
  1175 QGraphicsView::ViewportAnchor QGraphicsView::transformationAnchor() const
       
  1176 {
       
  1177     Q_D(const QGraphicsView);
       
  1178     return d->transformationAnchor;
       
  1179 }
       
  1180 void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor)
       
  1181 {
       
  1182     Q_D(QGraphicsView);
       
  1183     d->transformationAnchor = anchor;
       
  1184 }
       
  1185 
       
  1186 /*!
       
  1187     \property QGraphicsView::resizeAnchor
       
  1188     \brief how the view should position the scene when the view is resized.
       
  1189 
       
  1190     QGraphicsView uses this property to decide how to position the scene in
       
  1191     the viewport when the viewport widget's size changes. The default
       
  1192     behavior, NoAnchor, leaves the scene's position unchanged during a resize;
       
  1193     the top-left corner of the view will appear to be anchored while resizing.
       
  1194 
       
  1195     Note that the effect of this property is noticeable when only a part of the
       
  1196     scene is visible (i.e., when there are scroll bars). Otherwise, if the
       
  1197     whole scene fits in the view, QGraphicsScene uses the view \l alignment to
       
  1198     position the scene in the view.
       
  1199 
       
  1200     \sa alignment, transformationAnchor, Qt::WNorthWestGravity
       
  1201 */
       
  1202 QGraphicsView::ViewportAnchor QGraphicsView::resizeAnchor() const
       
  1203 {
       
  1204     Q_D(const QGraphicsView);
       
  1205     return d->resizeAnchor;
       
  1206 }
       
  1207 void QGraphicsView::setResizeAnchor(ViewportAnchor anchor)
       
  1208 {
       
  1209     Q_D(QGraphicsView);
       
  1210     d->resizeAnchor = anchor;
       
  1211 }
       
  1212 
       
  1213 /*!
       
  1214     \property QGraphicsView::viewportUpdateMode
       
  1215     \brief how the viewport should update its contents.
       
  1216 
       
  1217     \since 4.3
       
  1218 
       
  1219     QGraphicsView uses this property to decide how to update areas of the
       
  1220     scene that have been reexposed or changed. Usually you do not need to
       
  1221     modify this property, but there are some cases where doing so can improve
       
  1222     rendering performance. See the ViewportUpdateMode documentation for
       
  1223     specific details.
       
  1224 
       
  1225     The default value is MinimalViewportUpdate, where QGraphicsView will
       
  1226     update as small an area of the viewport as possible when the contents
       
  1227     change.
       
  1228 
       
  1229     \sa ViewportUpdateMode, cacheMode
       
  1230 */
       
  1231 QGraphicsView::ViewportUpdateMode QGraphicsView::viewportUpdateMode() const
       
  1232 {
       
  1233     Q_D(const QGraphicsView);
       
  1234     return d->viewportUpdateMode;
       
  1235 }
       
  1236 void QGraphicsView::setViewportUpdateMode(ViewportUpdateMode mode)
       
  1237 {
       
  1238     Q_D(QGraphicsView);
       
  1239     d->viewportUpdateMode = mode;
       
  1240 }
       
  1241 
       
  1242 /*!
       
  1243     \property QGraphicsView::optimizationFlags
       
  1244     \brief flags that can be used to tune QGraphicsView's performance.
       
  1245 
       
  1246     \since 4.3
       
  1247 
       
  1248     QGraphicsView uses clipping, extra bounding rect adjustments, and certain
       
  1249     other aids to improve rendering quality and performance for the common
       
  1250     case graphics scene. However, depending on the target platform, the scene,
       
  1251     and the viewport in use, some of these operations can degrade performance.
       
  1252 
       
  1253     The effect varies from flag to flag; see the OptimizationFlags
       
  1254     documentation for details.
       
  1255 
       
  1256     By default, no optimization flags are enabled.
       
  1257 
       
  1258     \sa setOptimizationFlag()
       
  1259 */
       
  1260 QGraphicsView::OptimizationFlags QGraphicsView::optimizationFlags() const
       
  1261 {
       
  1262     Q_D(const QGraphicsView);
       
  1263     return d->optimizationFlags;
       
  1264 }
       
  1265 void QGraphicsView::setOptimizationFlags(OptimizationFlags flags)
       
  1266 {
       
  1267     Q_D(QGraphicsView);
       
  1268     d->optimizationFlags = flags;
       
  1269 }
       
  1270 
       
  1271 /*!
       
  1272     Enables \a flag if \a enabled is true; otherwise disables \a flag.
       
  1273 
       
  1274     \sa optimizationFlags
       
  1275 */
       
  1276 void QGraphicsView::setOptimizationFlag(OptimizationFlag flag, bool enabled)
       
  1277 {
       
  1278     Q_D(QGraphicsView);
       
  1279     if (enabled)
       
  1280         d->optimizationFlags |= flag;
       
  1281     else
       
  1282         d->optimizationFlags &= ~flag;
       
  1283 }
       
  1284 
       
  1285 /*!
       
  1286     \property QGraphicsView::dragMode
       
  1287     \brief the behavior for dragging the mouse over the scene while
       
  1288     the left mouse button is pressed.
       
  1289 
       
  1290     This property defines what should happen when the user clicks on the scene
       
  1291     background and drags the mouse (e.g., scrolling the viewport contents
       
  1292     using a pointing hand cursor, or selecting multiple items with a rubber
       
  1293     band). The default value, NoDrag, does nothing.
       
  1294 
       
  1295     This behavior only affects mouse clicks that are not handled by any item.
       
  1296     You can define a custom behavior by creating a subclass of QGraphicsView
       
  1297     and reimplementing mouseMoveEvent().
       
  1298 */
       
  1299 QGraphicsView::DragMode QGraphicsView::dragMode() const
       
  1300 {
       
  1301     Q_D(const QGraphicsView);
       
  1302     return d->dragMode;
       
  1303 }
       
  1304 void QGraphicsView::setDragMode(DragMode mode)
       
  1305 {
       
  1306     Q_D(QGraphicsView);
       
  1307     if (d->dragMode == mode)
       
  1308         return;
       
  1309 
       
  1310 #ifndef QT_NO_CURSOR
       
  1311     if (d->dragMode == ScrollHandDrag)
       
  1312         viewport()->unsetCursor();
       
  1313 #endif
       
  1314 
       
  1315     // If dragMode is unset while dragging, e.g. via a keyEvent, we
       
  1316     // don't unset the handScrolling state. When enabling scrolling
       
  1317     // again the mouseMoveEvent will automatically start scrolling,
       
  1318     // without a mousePress
       
  1319     if (d->dragMode == ScrollHandDrag && mode == NoDrag && d->handScrolling)
       
  1320         d->handScrolling = false;
       
  1321 
       
  1322     d->dragMode = mode;
       
  1323 
       
  1324 #ifndef QT_NO_CURSOR
       
  1325     if (d->dragMode == ScrollHandDrag) {
       
  1326         // Forget the stored viewport cursor when we enter scroll hand drag mode.
       
  1327         d->hasStoredOriginalCursor = false;
       
  1328         viewport()->setCursor(Qt::OpenHandCursor);
       
  1329     }
       
  1330 #endif
       
  1331 }
       
  1332 
       
  1333 #ifndef QT_NO_RUBBERBAND
       
  1334 /*!
       
  1335     \property QGraphicsView::rubberBandSelectionMode
       
  1336     \brief the behavior for selecting items with a rubber band selection rectangle.
       
  1337     \since 4.3
       
  1338 
       
  1339     This property defines how items are selected when using the RubberBandDrag
       
  1340     drag mode.
       
  1341 
       
  1342     The default value is Qt::IntersectsItemShape; all items whose shape
       
  1343     intersects with or is contained by the rubber band are selected.
       
  1344 
       
  1345     \sa dragMode, items()
       
  1346 */
       
  1347 Qt::ItemSelectionMode QGraphicsView::rubberBandSelectionMode() const
       
  1348 {
       
  1349     Q_D(const QGraphicsView);
       
  1350     return d->rubberBandSelectionMode;
       
  1351 }
       
  1352 void QGraphicsView::setRubberBandSelectionMode(Qt::ItemSelectionMode mode)
       
  1353 {
       
  1354     Q_D(QGraphicsView);
       
  1355     d->rubberBandSelectionMode = mode;
       
  1356 }
       
  1357 #endif
       
  1358 
       
  1359 /*!
       
  1360     \property QGraphicsView::cacheMode
       
  1361     \brief which parts of the view are cached
       
  1362 
       
  1363     QGraphicsView can cache pre-rendered content in a QPixmap, which is then
       
  1364     drawn onto the viewport. The purpose of such caching is to speed up the
       
  1365     total rendering time for areas that are slow to render.  Texture, gradient
       
  1366     and alpha blended backgrounds, for example, can be notibly slow to render;
       
  1367     especially with a transformed view. The CacheBackground flag enables
       
  1368     caching of the view's background. For example:
       
  1369 
       
  1370     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 2
       
  1371 
       
  1372     The cache is invalidated every time the view is transformed. However, when
       
  1373     scrolling, only partial invalidation is required.
       
  1374 
       
  1375     By default, nothing is cached.
       
  1376 
       
  1377     \sa resetCachedContent(), QPixmapCache
       
  1378 */
       
  1379 QGraphicsView::CacheMode QGraphicsView::cacheMode() const
       
  1380 {
       
  1381     Q_D(const QGraphicsView);
       
  1382     return d->cacheMode;
       
  1383 }
       
  1384 void QGraphicsView::setCacheMode(CacheMode mode)
       
  1385 {
       
  1386     Q_D(QGraphicsView);
       
  1387     if (mode == d->cacheMode)
       
  1388         return;
       
  1389     d->cacheMode = mode;
       
  1390     resetCachedContent();
       
  1391 }
       
  1392 
       
  1393 /*!
       
  1394     Resets any cached content. Calling this function will clear
       
  1395     QGraphicsView's cache. If the current cache mode is \l CacheNone, this
       
  1396     function does nothing.
       
  1397 
       
  1398     This function is called automatically for you when the backgroundBrush or
       
  1399     QGraphicsScene::backgroundBrush properties change; you only need to call
       
  1400     this function if you have reimplemented QGraphicsScene::drawBackground()
       
  1401     or QGraphicsView::drawBackground() to draw a custom background, and need
       
  1402     to trigger a full redraw.
       
  1403 
       
  1404     \sa cacheMode()
       
  1405 */
       
  1406 void QGraphicsView::resetCachedContent()
       
  1407 {
       
  1408     Q_D(QGraphicsView);
       
  1409     if (d->cacheMode == CacheNone)
       
  1410         return;
       
  1411 
       
  1412     if (d->cacheMode & CacheBackground) {
       
  1413         // Background caching is enabled.
       
  1414         d->mustResizeBackgroundPixmap = true;
       
  1415         d->updateAll();
       
  1416     } else if (d->mustResizeBackgroundPixmap) {
       
  1417         // Background caching is disabled.
       
  1418         // Cleanup, free some resources.
       
  1419         d->mustResizeBackgroundPixmap = false;
       
  1420         d->backgroundPixmap = QPixmap();
       
  1421         d->backgroundPixmapExposed = QRegion();
       
  1422     }
       
  1423 }
       
  1424 
       
  1425 /*!
       
  1426     Invalidates and schedules a redraw of \a layers inside \a rect. \a rect is
       
  1427     in scene coordinates. Any cached content for \a layers inside \a rect is
       
  1428     unconditionally invalidated and redrawn.
       
  1429 
       
  1430     You can call this function to notify QGraphicsView of changes to the
       
  1431     background or the foreground of the scene. It is commonly used for scenes
       
  1432     with tile-based backgrounds to notify changes when QGraphicsView has
       
  1433     enabled background caching.
       
  1434 
       
  1435     Note that QGraphicsView currently supports background caching only (see
       
  1436     QGraphicsView::CacheBackground). This function is equivalent to calling update() if any
       
  1437     layer but QGraphicsScene::BackgroundLayer is passed.
       
  1438 
       
  1439     \sa QGraphicsScene::invalidate(), update()
       
  1440 */
       
  1441 void QGraphicsView::invalidateScene(const QRectF &rect, QGraphicsScene::SceneLayers layers)
       
  1442 {
       
  1443     Q_D(QGraphicsView);
       
  1444     if ((layers & QGraphicsScene::BackgroundLayer) && !d->mustResizeBackgroundPixmap) {
       
  1445         QRect viewRect = mapFromScene(rect).boundingRect();
       
  1446         if (viewport()->rect().intersects(viewRect)) {
       
  1447             // The updated background area is exposed; schedule this area for
       
  1448             // redrawing.
       
  1449             d->backgroundPixmapExposed += viewRect;
       
  1450             if (d->scene)
       
  1451                 d->scene->update(rect);
       
  1452         }
       
  1453     }
       
  1454 }
       
  1455 
       
  1456 /*!
       
  1457     \property QGraphicsView::interactive
       
  1458     \brief whether the view allowed scene interaction.
       
  1459 
       
  1460     If enabled, this view is set to allow scene interaction. Otherwise, this
       
  1461     view will not allow interaction, and any mouse or key events are ignored
       
  1462     (i.e., it will act as a read-only view).
       
  1463 
       
  1464     By default, this property is true.
       
  1465 */
       
  1466 bool QGraphicsView::isInteractive() const
       
  1467 {
       
  1468     Q_D(const QGraphicsView);
       
  1469     return d->sceneInteractionAllowed;
       
  1470 }
       
  1471 void QGraphicsView::setInteractive(bool allowed)
       
  1472 {
       
  1473     Q_D(QGraphicsView);
       
  1474     d->sceneInteractionAllowed = allowed;
       
  1475 }
       
  1476 
       
  1477 /*!
       
  1478     Returns a pointer to the scene that is currently visualized in the
       
  1479     view. If no scene is currently visualized, 0 is returned.
       
  1480 
       
  1481     \sa setScene()
       
  1482 */
       
  1483 QGraphicsScene *QGraphicsView::scene() const
       
  1484 {
       
  1485     Q_D(const QGraphicsView);
       
  1486     return d->scene;
       
  1487 }
       
  1488 
       
  1489 /*!
       
  1490     Sets the current scene to \a scene. If \a scene is already being
       
  1491     viewed, this function does nothing.
       
  1492 
       
  1493     When a scene is set on a view, the QGraphicsScene::changed() signal
       
  1494     is automatically connected to this view's updateScene() slot, and the
       
  1495     view's scroll bars are adjusted to fit the size of the scene.
       
  1496 */
       
  1497 void QGraphicsView::setScene(QGraphicsScene *scene)
       
  1498 {
       
  1499     Q_D(QGraphicsView);
       
  1500     if (d->scene == scene)
       
  1501         return;
       
  1502 
       
  1503     // Always update the viewport when the scene changes.
       
  1504     d->updateAll();
       
  1505 
       
  1506     // Remove the previously assigned scene.
       
  1507     if (d->scene) {
       
  1508         disconnect(d->scene, SIGNAL(changed(QList<QRectF>)),
       
  1509                    this, SLOT(updateScene(QList<QRectF>)));
       
  1510         disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
       
  1511                    this, SLOT(updateSceneRect(QRectF)));
       
  1512         d->scene->d_func()->removeView(this);
       
  1513         d->connectedToScene = false;
       
  1514     }
       
  1515 
       
  1516     // Assign the new scene and update the contents (scrollbars, etc.)).
       
  1517     if ((d->scene = scene)) {
       
  1518         connect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
       
  1519                 this, SLOT(updateSceneRect(QRectF)));
       
  1520         d->updateSceneSlotReimplementedChecked = false;
       
  1521         d->scene->d_func()->addView(this);
       
  1522         d->recalculateContentSize();
       
  1523         d->lastCenterPoint = sceneRect().center();
       
  1524         d->keepLastCenterPoint = true;
       
  1525         // We are only interested in mouse tracking if items accept
       
  1526         // hover events or use non-default cursors.
       
  1527         if (!d->scene->d_func()->allItemsIgnoreHoverEvents
       
  1528             || !d->scene->d_func()->allItemsUseDefaultCursor) {
       
  1529             d->viewport->setMouseTracking(true);
       
  1530         }
       
  1531 
       
  1532         // enable touch events if any items is interested in them
       
  1533         if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
       
  1534             d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
       
  1535     } else {
       
  1536         d->recalculateContentSize();
       
  1537     }
       
  1538 
       
  1539     d->updateInputMethodSensitivity();
       
  1540 
       
  1541     if (d->scene && hasFocus())
       
  1542         d->scene->setFocus();
       
  1543 }
       
  1544 
       
  1545 /*!
       
  1546     \property QGraphicsView::sceneRect
       
  1547     \brief the area of the scene visualized by this view.
       
  1548 
       
  1549     The scene rectangle defines the extent of the scene, and in the view's case,
       
  1550     this means the area of the scene that you can navigate using the scroll
       
  1551     bars.
       
  1552 
       
  1553     If unset, or if a null QRectF is set, this property has the same value as
       
  1554     QGraphicsScene::sceneRect, and it changes with
       
  1555     QGraphicsScene::sceneRect. Otherwise, the view's scene rect is unaffected
       
  1556     by the scene.
       
  1557 
       
  1558     Note that, although the scene supports a virtually unlimited size, the
       
  1559     range of the scroll bars will never exceed the range of an integer
       
  1560     (INT_MIN, INT_MAX). When the scene is larger than the scroll bars' values,
       
  1561     you can choose to use translate() to navigate the scene instead.
       
  1562 
       
  1563     By default, this property contains a rectangle at the origin with zero
       
  1564     width and height.
       
  1565 
       
  1566     \sa QGraphicsScene::sceneRect
       
  1567 */
       
  1568 QRectF QGraphicsView::sceneRect() const
       
  1569 {
       
  1570     Q_D(const QGraphicsView);
       
  1571     if (d->hasSceneRect)
       
  1572         return d->sceneRect;
       
  1573     if (d->scene)
       
  1574         return d->scene->sceneRect();
       
  1575     return QRectF();
       
  1576 }
       
  1577 void QGraphicsView::setSceneRect(const QRectF &rect)
       
  1578 {
       
  1579     Q_D(QGraphicsView);
       
  1580     d->hasSceneRect = !rect.isNull();
       
  1581     d->sceneRect = rect;
       
  1582     d->recalculateContentSize();
       
  1583 }
       
  1584 
       
  1585 /*!
       
  1586     Returns the current transformation matrix for the view. If no current
       
  1587     transformation is set, the identity matrix is returned.
       
  1588 
       
  1589     \sa setMatrix(), transform(), rotate(), scale(), shear(), translate()
       
  1590 */
       
  1591 QMatrix QGraphicsView::matrix() const
       
  1592 {
       
  1593     Q_D(const QGraphicsView);
       
  1594     return d->matrix.toAffine();
       
  1595 }
       
  1596 
       
  1597 /*!
       
  1598     Sets the view's current transformation matrix to \a matrix.
       
  1599 
       
  1600     If \a combine is true, then \a matrix is combined with the current matrix;
       
  1601     otherwise, \a matrix \e replaces the current matrix. \a combine is false
       
  1602     by default.
       
  1603 
       
  1604     The transformation matrix tranforms the scene into view coordinates. Using
       
  1605     the default transformation, provided by the identity matrix, one pixel in
       
  1606     the view represents one unit in the scene (e.g., a 10x10 rectangular item
       
  1607     is drawn using 10x10 pixels in the view). If a 2x2 scaling matrix is
       
  1608     applied, the scene will be drawn in 1:2 (e.g., a 10x10 rectangular item is
       
  1609     then drawn using 20x20 pixels in the view).
       
  1610 
       
  1611     Example:
       
  1612 
       
  1613     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 3
       
  1614 
       
  1615     To simplify interation with items using a transformed view, QGraphicsView
       
  1616     provides mapTo... and mapFrom... functions that can translate between
       
  1617     scene and view coordinates. For example, you can call mapToScene() to map
       
  1618     a view coordinate to a floating point scene coordinate, or mapFromScene()
       
  1619     to map from floating point scene coordinates to view coordinates.
       
  1620 
       
  1621     \sa matrix(), setTransform(), rotate(), scale(), shear(), translate()
       
  1622 */
       
  1623 void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
       
  1624 {
       
  1625     setTransform(QTransform(matrix), combine);
       
  1626 }
       
  1627 
       
  1628 /*!
       
  1629     Resets the view transformation matrix to the identity matrix.
       
  1630 
       
  1631     \sa resetTransform()
       
  1632 */
       
  1633 void QGraphicsView::resetMatrix()
       
  1634 {
       
  1635     resetTransform();
       
  1636 }
       
  1637 
       
  1638 /*!
       
  1639     Rotates the current view transformation \a angle degrees clockwise.
       
  1640 
       
  1641     \sa setTransform(), transform(), scale(), shear(), translate()
       
  1642 */
       
  1643 void QGraphicsView::rotate(qreal angle)
       
  1644 {
       
  1645     Q_D(QGraphicsView);
       
  1646     QTransform matrix = d->matrix;
       
  1647     matrix.rotate(angle);
       
  1648     setTransform(matrix);
       
  1649 }
       
  1650 
       
  1651 /*!
       
  1652     Scales the current view transformation by (\a sx, \a sy).
       
  1653 
       
  1654     \sa setTransform(), transform(), rotate(), shear(), translate()
       
  1655 */
       
  1656 void QGraphicsView::scale(qreal sx, qreal sy)
       
  1657 {
       
  1658     Q_D(QGraphicsView);
       
  1659     QTransform matrix = d->matrix;
       
  1660     matrix.scale(sx, sy);
       
  1661     setTransform(matrix);
       
  1662 }
       
  1663 
       
  1664 /*!
       
  1665     Shears the current view transformation by (\a sh, \a sv).
       
  1666 
       
  1667     \sa setTransform(), transform(), rotate(), scale(), translate()
       
  1668 */
       
  1669 void QGraphicsView::shear(qreal sh, qreal sv)
       
  1670 {
       
  1671     Q_D(QGraphicsView);
       
  1672     QTransform matrix = d->matrix;
       
  1673     matrix.shear(sh, sv);
       
  1674     setTransform(matrix);
       
  1675 }
       
  1676 
       
  1677 /*!
       
  1678     Translates the current view transformation by (\a dx, \a dy).
       
  1679 
       
  1680     \sa setTransform(), transform(), rotate(), shear()
       
  1681 */
       
  1682 void QGraphicsView::translate(qreal dx, qreal dy)
       
  1683 {
       
  1684     Q_D(QGraphicsView);
       
  1685     QTransform matrix = d->matrix;
       
  1686     matrix.translate(dx, dy);
       
  1687     setTransform(matrix);
       
  1688 }
       
  1689 
       
  1690 /*!
       
  1691     Scrolls the contents of the viewport to ensure that the scene
       
  1692     coordinate \a pos, is centered in the view.
       
  1693 
       
  1694     Because \a pos is a floating point coordinate, and the scroll bars operate
       
  1695     on integer coordinates, the centering is only an approximation.
       
  1696 
       
  1697     \note If the item is close to or outside the border, it will be visible
       
  1698     in the view, but not centered.
       
  1699 
       
  1700     \sa ensureVisible()
       
  1701 */
       
  1702 void QGraphicsView::centerOn(const QPointF &pos)
       
  1703 {
       
  1704     Q_D(QGraphicsView);
       
  1705     qreal width = viewport()->width();
       
  1706     qreal height = viewport()->height();
       
  1707     QPointF viewPoint = d->matrix.map(pos);
       
  1708     QPointF oldCenterPoint = pos;
       
  1709 
       
  1710     if (!d->leftIndent) {
       
  1711         if (isRightToLeft()) {
       
  1712             qint64 horizontal = 0;
       
  1713             horizontal += horizontalScrollBar()->minimum();
       
  1714             horizontal += horizontalScrollBar()->maximum();
       
  1715             horizontal -= int(viewPoint.x() - width / 2.0);
       
  1716             horizontalScrollBar()->setValue(horizontal);
       
  1717         } else {
       
  1718             horizontalScrollBar()->setValue(int(viewPoint.x() - width / 2.0));
       
  1719         }
       
  1720     }
       
  1721     if (!d->topIndent)
       
  1722         verticalScrollBar()->setValue(int(viewPoint.y() - height / 2.0));
       
  1723     d->lastCenterPoint = oldCenterPoint;
       
  1724 }
       
  1725 
       
  1726 /*!
       
  1727     \fn QGraphicsView::centerOn(qreal x, qreal y)
       
  1728     \overload
       
  1729 
       
  1730     This function is provided for convenience. It's equivalent to calling
       
  1731     centerOn(QPointF(\a x, \a y)).
       
  1732 */
       
  1733 
       
  1734 /*!
       
  1735     \overload
       
  1736 
       
  1737     Scrolls the contents of the viewport to ensure that \a item
       
  1738     is centered in the view.
       
  1739 
       
  1740     \sa ensureVisible()
       
  1741 */
       
  1742 void QGraphicsView::centerOn(const QGraphicsItem *item)
       
  1743 {
       
  1744     centerOn(item->sceneBoundingRect().center());
       
  1745 }
       
  1746 
       
  1747 /*!
       
  1748     Scrolls the contents of the viewport so that the scene rectangle \a rect
       
  1749     is visible, with margins specified in pixels by \a xmargin and \a
       
  1750     ymargin. If the specified rect cannot be reached, the contents are
       
  1751     scrolled to the nearest valid position. The default value for both margins
       
  1752     is 50 pixels.
       
  1753 
       
  1754     \sa centerOn()
       
  1755 */
       
  1756 void QGraphicsView::ensureVisible(const QRectF &rect, int xmargin, int ymargin)
       
  1757 {
       
  1758     Q_D(QGraphicsView);
       
  1759     Q_UNUSED(xmargin);
       
  1760     Q_UNUSED(ymargin);
       
  1761     qreal width = viewport()->width();
       
  1762     qreal height = viewport()->height();
       
  1763     QRectF viewRect = d->matrix.mapRect(rect);
       
  1764 
       
  1765     qreal left = d->horizontalScroll();
       
  1766     qreal right = left + width;
       
  1767     qreal top = d->verticalScroll();
       
  1768     qreal bottom = top + height;
       
  1769 
       
  1770     if (viewRect.left() <= left + xmargin) {
       
  1771         // need to scroll from the left
       
  1772         if (!d->leftIndent)
       
  1773             horizontalScrollBar()->setValue(int(viewRect.left() - xmargin - 0.5));
       
  1774     }
       
  1775     if (viewRect.right() >= right - xmargin) {
       
  1776         // need to scroll from the right
       
  1777         if (!d->leftIndent)
       
  1778             horizontalScrollBar()->setValue(int(viewRect.right() - width + xmargin + 0.5));
       
  1779     }
       
  1780     if (viewRect.top() <= top + ymargin) {
       
  1781         // need to scroll from the top
       
  1782         if (!d->topIndent)
       
  1783             verticalScrollBar()->setValue(int(viewRect.top() - ymargin - 0.5));
       
  1784     }
       
  1785     if (viewRect.bottom() >= bottom - ymargin) {
       
  1786         // need to scroll from the bottom
       
  1787         if (!d->topIndent)
       
  1788             verticalScrollBar()->setValue(int(viewRect.bottom() - height + ymargin + 0.5));
       
  1789     }
       
  1790 }
       
  1791 
       
  1792 /*!
       
  1793     \fn QGraphicsView::ensureVisible(qreal x, qreal y, qreal w, qreal h,
       
  1794     int xmargin, int ymargin)
       
  1795     \overload
       
  1796 
       
  1797     This function is provided for convenience. It's equivalent to calling
       
  1798     ensureVisible(QRectF(\a x, \a y, \a w, \a h), \a xmargin, \a ymargin).
       
  1799 */
       
  1800 
       
  1801 /*!
       
  1802     \overload
       
  1803 
       
  1804     Scrolls the contents of the viewport so that the center of item \a item is
       
  1805     visible, with margins specified in pixels by \a xmargin and \a ymargin. If
       
  1806     the specified point cannot be reached, the contents are scrolled to the
       
  1807     nearest valid position. The default value for both margins is 50 pixels.
       
  1808 
       
  1809     \sa centerOn()
       
  1810 */
       
  1811 void QGraphicsView::ensureVisible(const QGraphicsItem *item, int xmargin, int ymargin)
       
  1812 {
       
  1813     ensureVisible(item->sceneBoundingRect(), xmargin, ymargin);
       
  1814 }
       
  1815 
       
  1816 /*!
       
  1817     Scales the view matrix and scrolls the scroll bars to ensure that the
       
  1818     scene rectangle \a rect fits inside the viewport. \a rect must be inside
       
  1819     the scene rect; otherwise, fitInView() cannot guarantee that the whole
       
  1820     rect is visible.
       
  1821 
       
  1822     This function keeps the view's rotation, translation, or shear. The view
       
  1823     is scaled according to \a aspectRatioMode. \a rect will be centered in the
       
  1824     view if it does not fit tightly.
       
  1825 
       
  1826     It's common to call fitInView() from inside a reimplementation of
       
  1827     resizeEvent(), to ensure that the whole scene, or parts of the scene,
       
  1828     scales automatically to fit the new size of the viewport as the view is
       
  1829     resized. Note though, that calling fitInView() from inside resizeEvent()
       
  1830     can lead to unwanted resize recursion, if the new transformation toggles
       
  1831     the automatic state of the scrollbars. You can toggle the scrollbar
       
  1832     policies to always on or always off to prevent this (see
       
  1833     horizontalScrollBarPolicy() and verticalScrollBarPolicy()).
       
  1834 
       
  1835     If \a rect is empty, or if the viewport is too small, this
       
  1836     function will do nothing.
       
  1837 
       
  1838     \sa setTransform(), ensureVisible(), centerOn()
       
  1839 */
       
  1840 void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
       
  1841 {
       
  1842     Q_D(QGraphicsView);
       
  1843     if (!d->scene || rect.isNull())
       
  1844         return;
       
  1845 
       
  1846     // Reset the view scale to 1:1.
       
  1847     QRectF unity = d->matrix.mapRect(QRectF(0, 0, 1, 1));
       
  1848     if (unity.isEmpty())
       
  1849         return;
       
  1850     scale(1 / unity.width(), 1 / unity.height());
       
  1851 
       
  1852     // Find the ideal x / y scaling ratio to fit \a rect in the view.
       
  1853     int margin = 2;
       
  1854     QRectF viewRect = viewport()->rect().adjusted(margin, margin, -margin, -margin);
       
  1855     if (viewRect.isEmpty())
       
  1856         return;
       
  1857     QRectF sceneRect = d->matrix.mapRect(rect);
       
  1858     if (sceneRect.isEmpty())
       
  1859         return;
       
  1860     qreal xratio = viewRect.width() / sceneRect.width();
       
  1861     qreal yratio = viewRect.height() / sceneRect.height();
       
  1862 
       
  1863     // Respect the aspect ratio mode.
       
  1864     switch (aspectRatioMode) {
       
  1865     case Qt::KeepAspectRatio:
       
  1866         xratio = yratio = qMin(xratio, yratio);
       
  1867         break;
       
  1868     case Qt::KeepAspectRatioByExpanding:
       
  1869         xratio = yratio = qMax(xratio, yratio);
       
  1870         break;
       
  1871     case Qt::IgnoreAspectRatio:
       
  1872         break;
       
  1873     }
       
  1874 
       
  1875     // Scale and center on the center of \a rect.
       
  1876     scale(xratio, yratio);
       
  1877     centerOn(rect.center());
       
  1878 }
       
  1879 
       
  1880 /*!
       
  1881     \fn void QGraphicsView::fitInView(qreal x, qreal y, qreal w, qreal h,
       
  1882     Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio)
       
  1883 
       
  1884     \overload
       
  1885 
       
  1886     This convenience function is equivalent to calling
       
  1887     fitInView(QRectF(\a x, \a y, \a w, \a h), \a aspectRatioMode).
       
  1888 
       
  1889     \sa ensureVisible(), centerOn()
       
  1890 */
       
  1891 
       
  1892 /*!
       
  1893     \overload
       
  1894 
       
  1895     Ensures that \a item fits tightly inside the view, scaling the view
       
  1896     according to \a aspectRatioMode.
       
  1897 
       
  1898     \sa ensureVisible(), centerOn()
       
  1899 */
       
  1900 void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode)
       
  1901 {
       
  1902     QPainterPath path = item->isClipped() ? item->clipPath() : item->shape();
       
  1903     if (item->d_ptr->hasTranslateOnlySceneTransform()) {
       
  1904         path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy());
       
  1905         fitInView(path.boundingRect(), aspectRatioMode);
       
  1906     } else {
       
  1907         fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode);
       
  1908     }
       
  1909 }
       
  1910 
       
  1911 /*!
       
  1912     Renders the \a source rect, which is in view coordinates, from the scene
       
  1913     into \a target, which is in paint device coordinates, using \a
       
  1914     painter. This function is useful for capturing the contents of the view
       
  1915     onto a paint device, such as a QImage (e.g., to take a screenshot), or for
       
  1916     printing to QPrinter. For example:
       
  1917 
       
  1918     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 4
       
  1919 
       
  1920     If \a source is a null rect, this function will use viewport()->rect() to
       
  1921     determine what to draw. If \a target is a null rect, the full dimensions
       
  1922     of \a painter's paint device (e.g., for a QPrinter, the page size) will be
       
  1923     used.
       
  1924 
       
  1925     The source rect contents will be transformed according to \a
       
  1926     aspectRatioMode to fit into the target rect. By default, the aspect ratio
       
  1927     is kept, and \a source is scaled to fit in \a target.
       
  1928 
       
  1929     \sa QGraphicsScene::render()
       
  1930 */
       
  1931 void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source,
       
  1932                            Qt::AspectRatioMode aspectRatioMode)
       
  1933 {
       
  1934     // ### Switch to using the recursive rendering algorithm instead.
       
  1935 
       
  1936     Q_D(QGraphicsView);
       
  1937     if (!d->scene || !(painter && painter->isActive()))
       
  1938         return;
       
  1939 
       
  1940     // Default source rect = viewport rect
       
  1941     QRect sourceRect = source;
       
  1942     if (source.isNull())
       
  1943         sourceRect = viewport()->rect();
       
  1944 
       
  1945     // Default target rect = device rect
       
  1946     QRectF targetRect = target;
       
  1947     if (target.isNull()) {
       
  1948         if (painter->device()->devType() == QInternal::Picture)
       
  1949             targetRect = sourceRect;
       
  1950         else
       
  1951             targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
       
  1952     }
       
  1953 
       
  1954     // Find the ideal x / y scaling ratio to fit \a source into \a target.
       
  1955     qreal xratio = targetRect.width() / sourceRect.width();
       
  1956     qreal yratio = targetRect.height() / sourceRect.height();
       
  1957 
       
  1958     // Scale according to the aspect ratio mode.
       
  1959     switch (aspectRatioMode) {
       
  1960     case Qt::KeepAspectRatio:
       
  1961         xratio = yratio = qMin(xratio, yratio);
       
  1962         break;
       
  1963     case Qt::KeepAspectRatioByExpanding:
       
  1964         xratio = yratio = qMax(xratio, yratio);
       
  1965         break;
       
  1966     case Qt::IgnoreAspectRatio:
       
  1967         break;
       
  1968     }
       
  1969 
       
  1970     // Find all items to draw, and reverse the list (we want to draw
       
  1971     // in reverse order).
       
  1972     QPolygonF sourceScenePoly = mapToScene(sourceRect.adjusted(-1, -1, 1, 1));
       
  1973     QList<QGraphicsItem *> itemList = d->scene->items(sourceScenePoly,
       
  1974                                                       Qt::IntersectsItemBoundingRect);
       
  1975     QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
       
  1976     int numItems = itemList.size();
       
  1977     for (int i = 0; i < numItems; ++i)
       
  1978         itemArray[numItems - i - 1] = itemList.at(i);
       
  1979     itemList.clear();
       
  1980 
       
  1981     // Setup painter matrix.
       
  1982     QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
       
  1983     QTransform painterMatrix = d->matrix * moveMatrix;
       
  1984     painterMatrix *= QTransform()
       
  1985                      .translate(targetRect.left(), targetRect.top())
       
  1986                      .scale(xratio, yratio)
       
  1987                      .translate(-sourceRect.left(), -sourceRect.top());
       
  1988 
       
  1989     // Generate the style options
       
  1990     QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
       
  1991     for (int i = 0; i < numItems; ++i)
       
  1992         itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
       
  1993 
       
  1994     painter->save();
       
  1995 
       
  1996     // Clip in device coordinates to avoid QRegion transformations.
       
  1997     painter->setClipRect(targetRect);
       
  1998     QPainterPath path;
       
  1999     path.addPolygon(sourceScenePoly);
       
  2000     path.closeSubpath();
       
  2001     painter->setClipPath(painterMatrix.map(path), Qt::IntersectClip);
       
  2002 
       
  2003     // Transform the painter.
       
  2004     painter->setTransform(painterMatrix, true);
       
  2005 
       
  2006     // Render the scene.
       
  2007     QRectF sourceSceneRect = sourceScenePoly.boundingRect();
       
  2008     drawBackground(painter, sourceSceneRect);
       
  2009     drawItems(painter, numItems, itemArray, styleOptionArray);
       
  2010     drawForeground(painter, sourceSceneRect);
       
  2011 
       
  2012     delete [] itemArray;
       
  2013     d->freeStyleOptionsArray(styleOptionArray);
       
  2014 
       
  2015     painter->restore();
       
  2016 }
       
  2017 
       
  2018 /*!
       
  2019     Returns a list of all the items in the associated scene, in descending
       
  2020     stacking order (i.e., the first item in the returned list is the uppermost
       
  2021     item).
       
  2022 
       
  2023     \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
       
  2024 */
       
  2025 QList<QGraphicsItem *> QGraphicsView::items() const
       
  2026 {
       
  2027     Q_D(const QGraphicsView);
       
  2028     if (!d->scene)
       
  2029         return QList<QGraphicsItem *>();
       
  2030     return d->scene->items();
       
  2031 }
       
  2032 
       
  2033 /*!
       
  2034     Returns a list of all the items at the position \a pos in the view. The
       
  2035     items are listed in descending stacking order (i.e., the first item in the
       
  2036     list is the uppermost item, and the last item is the lowermost item). \a
       
  2037     pos is in viewport coordinates.
       
  2038 
       
  2039     This function is most commonly called from within mouse event handlers in
       
  2040     a subclass in QGraphicsView. \a pos is in untransformed viewport
       
  2041     coordinates, just like QMouseEvent::pos().
       
  2042 
       
  2043     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5
       
  2044 
       
  2045     \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
       
  2046 */
       
  2047 QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
       
  2048 {
       
  2049     Q_D(const QGraphicsView);
       
  2050     if (!d->scene)
       
  2051         return QList<QGraphicsItem *>();
       
  2052     // ### Unify these two, and use the items(QPointF) version in
       
  2053     // QGraphicsScene instead. The scene items function could use the viewport
       
  2054     // transform to map the point to a rect/polygon.
       
  2055     if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
       
  2056         // Use the rect version
       
  2057         QTransform xinv = viewportTransform().inverted();
       
  2058         return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
       
  2059                                Qt::IntersectsItemShape,
       
  2060                                Qt::DescendingOrder,
       
  2061                                viewportTransform());
       
  2062     }
       
  2063     // Use the polygon version
       
  2064     return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
       
  2065                            Qt::IntersectsItemShape,
       
  2066                            Qt::DescendingOrder,
       
  2067                            viewportTransform());
       
  2068 }
       
  2069 
       
  2070 /*!
       
  2071     \fn QGraphicsView::items(int x, int y) const
       
  2072 
       
  2073     This function is provided for convenience. It's equivalent to calling
       
  2074     items(QPoint(\a x, \a y)).
       
  2075 */
       
  2076 
       
  2077 /*!
       
  2078     \overload
       
  2079 
       
  2080     Returns a list of all the items that, depending on \a mode, are either
       
  2081     contained by or intersect with \a rect. \a rect is in viewport
       
  2082     coordinates.
       
  2083 
       
  2084     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  2085     exact shape intersects with or is contained by \a rect are returned.
       
  2086 
       
  2087     The items are sorted in descending stacking order (i.e., the first item in
       
  2088     the returned list is the uppermost item).
       
  2089 
       
  2090     \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
       
  2091 */
       
  2092 QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const
       
  2093 {
       
  2094     Q_D(const QGraphicsView);
       
  2095     if (!d->scene)
       
  2096         return QList<QGraphicsItem *>();
       
  2097     return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform());
       
  2098 }
       
  2099 
       
  2100 /*!
       
  2101     \fn QList<QGraphicsItem *> QGraphicsView::items(int x, int y, int w, int h, Qt::ItemSelectionMode mode) const
       
  2102     \since 4.3
       
  2103 
       
  2104     This convenience function is equivalent to calling items(QRectF(\a x, \a
       
  2105     y, \a w, \a h), \a mode).
       
  2106 */
       
  2107 
       
  2108 /*!
       
  2109     \overload
       
  2110 
       
  2111     Returns a list of all the items that, depending on \a mode, are either
       
  2112     contained by or intersect with \a polygon. \a polygon is in viewport
       
  2113     coordinates.
       
  2114 
       
  2115     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  2116     exact shape intersects with or is contained by \a polygon are returned.
       
  2117 
       
  2118     The items are sorted by descending stacking order (i.e., the first item in
       
  2119     the returned list is the uppermost item).
       
  2120 
       
  2121     \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
       
  2122 */
       
  2123 QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const
       
  2124 {
       
  2125     Q_D(const QGraphicsView);
       
  2126     if (!d->scene)
       
  2127         return QList<QGraphicsItem *>();
       
  2128     return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform());
       
  2129 }
       
  2130 
       
  2131 /*!
       
  2132     \overload
       
  2133 
       
  2134     Returns a list of all the items that, depending on \a mode, are either
       
  2135     contained by or intersect with \a path. \a path is in viewport
       
  2136     coordinates.
       
  2137 
       
  2138     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  2139     exact shape intersects with or is contained by \a path are returned.
       
  2140 
       
  2141     \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
       
  2142 */
       
  2143 QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
       
  2144 {
       
  2145     Q_D(const QGraphicsView);
       
  2146     if (!d->scene)
       
  2147         return QList<QGraphicsItem *>();
       
  2148     return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform());
       
  2149 }
       
  2150 
       
  2151 /*!
       
  2152     Returns the item at position \a pos, which is in viewport coordinates.
       
  2153     If there are several items at this position, this function returns
       
  2154     the topmost item.
       
  2155 
       
  2156     Example:
       
  2157 
       
  2158     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6
       
  2159 
       
  2160     \sa items(), {QGraphicsItem#Sorting}{Sorting}
       
  2161 */
       
  2162 QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
       
  2163 {
       
  2164     Q_D(const QGraphicsView);
       
  2165     if (!d->scene)
       
  2166         return 0;
       
  2167     QList<QGraphicsItem *> itemsAtPos = items(pos);
       
  2168     return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first();
       
  2169 }
       
  2170 
       
  2171 /*!
       
  2172     \overload
       
  2173     \fn QGraphicsItem *QGraphicsView::itemAt(int x, int y) const
       
  2174 
       
  2175     This function is provided for convenience. It's equivalent to
       
  2176     calling itemAt(QPoint(\a x, \a y)).
       
  2177 */
       
  2178 
       
  2179 /*!
       
  2180     Returns the viewport coordinate \a point mapped to scene coordinates.
       
  2181 
       
  2182     Note: It can be useful to map the whole rectangle covered by the pixel at
       
  2183     \a point instead of the point itself. To do this, you can call
       
  2184     mapToScene(QRect(\a point, QSize(2, 2))).
       
  2185 
       
  2186     \sa mapFromScene()
       
  2187 */
       
  2188 QPointF QGraphicsView::mapToScene(const QPoint &point) const
       
  2189 {
       
  2190     Q_D(const QGraphicsView);
       
  2191     QPointF p = point;
       
  2192     p.rx() += d->horizontalScroll();
       
  2193     p.ry() += d->verticalScroll();
       
  2194     return d->identityMatrix ? p : d->matrix.inverted().map(p);
       
  2195 }
       
  2196 
       
  2197 /*!
       
  2198     \fn QGraphicsView::mapToScene(int x, int y) const
       
  2199 
       
  2200     This function is provided for convenience. It's equivalent to calling
       
  2201     mapToScene(QPoint(\a x, \a y)).
       
  2202 */
       
  2203 
       
  2204 /*!
       
  2205     Returns the viewport rectangle \a rect mapped to a scene coordinate
       
  2206     polygon.
       
  2207 
       
  2208     \sa mapFromScene()
       
  2209 */
       
  2210 QPolygonF QGraphicsView::mapToScene(const QRect &rect) const
       
  2211 {
       
  2212     Q_D(const QGraphicsView);
       
  2213     if (!rect.isValid())
       
  2214         return QPolygonF();
       
  2215 
       
  2216     QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
       
  2217     QRect r = rect.adjusted(0, 0, 1, 1);
       
  2218     QPointF tl = scrollOffset + r.topLeft();
       
  2219     QPointF tr = scrollOffset + r.topRight();
       
  2220     QPointF br = scrollOffset + r.bottomRight();
       
  2221     QPointF bl = scrollOffset + r.bottomLeft();
       
  2222 
       
  2223     QPolygonF poly(4);
       
  2224     if (!d->identityMatrix) {
       
  2225         QTransform x = d->matrix.inverted();
       
  2226         poly[0] = x.map(tl);
       
  2227         poly[1] = x.map(tr);
       
  2228         poly[2] = x.map(br);
       
  2229         poly[3] = x.map(bl);
       
  2230     } else {
       
  2231         poly[0] = tl;
       
  2232         poly[1] = tr;
       
  2233         poly[2] = br;
       
  2234         poly[3] = bl;
       
  2235     }
       
  2236     return poly;
       
  2237 }
       
  2238 
       
  2239 /*!
       
  2240     \fn QGraphicsView::mapToScene(int x, int y, int w, int h) const
       
  2241 
       
  2242     This function is provided for convenience. It's equivalent to calling
       
  2243     mapToScene(QRect(\a x, \a y, \a w, \a h)).
       
  2244 */
       
  2245 
       
  2246 /*!
       
  2247     Returns the viewport polygon \a polygon mapped to a scene coordinate
       
  2248     polygon.
       
  2249 
       
  2250     \sa mapFromScene()
       
  2251 */
       
  2252 QPolygonF QGraphicsView::mapToScene(const QPolygon &polygon) const
       
  2253 {
       
  2254     QPolygonF poly;
       
  2255     foreach (const QPoint &point, polygon)
       
  2256         poly << mapToScene(point);
       
  2257     return poly;
       
  2258 }
       
  2259 
       
  2260 /*!
       
  2261     Returns the viewport painter path \a path mapped to a scene coordinate
       
  2262     painter path.
       
  2263 
       
  2264     \sa mapFromScene()
       
  2265 */
       
  2266 QPainterPath QGraphicsView::mapToScene(const QPainterPath &path) const
       
  2267 {
       
  2268     Q_D(const QGraphicsView);
       
  2269     QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
       
  2270     matrix *= d->matrix.inverted();
       
  2271     return matrix.map(path);
       
  2272 }
       
  2273 
       
  2274 /*!
       
  2275     Returns the scene coordinate \a point to viewport coordinates.
       
  2276 
       
  2277     \sa mapToScene()
       
  2278 */
       
  2279 QPoint QGraphicsView::mapFromScene(const QPointF &point) const
       
  2280 {
       
  2281     Q_D(const QGraphicsView);
       
  2282     QPointF p = d->identityMatrix ? point : d->matrix.map(point);
       
  2283     p.rx() -= d->horizontalScroll();
       
  2284     p.ry() -= d->verticalScroll();
       
  2285     return p.toPoint();
       
  2286 }
       
  2287 
       
  2288 /*!
       
  2289     \fn QGraphicsView::mapFromScene(qreal x, qreal y) const
       
  2290 
       
  2291     This function is provided for convenience. It's equivalent to
       
  2292     calling mapFromScene(QPointF(\a x, \a y)).
       
  2293 */
       
  2294 
       
  2295 /*!
       
  2296     Returns the scene rectangle \a rect to a viewport coordinate
       
  2297     polygon.
       
  2298 
       
  2299     \sa mapToScene()
       
  2300 */
       
  2301 QPolygon QGraphicsView::mapFromScene(const QRectF &rect) const
       
  2302 {
       
  2303     Q_D(const QGraphicsView);
       
  2304     QPointF tl;
       
  2305     QPointF tr;
       
  2306     QPointF br;
       
  2307     QPointF bl;
       
  2308     if (!d->identityMatrix) {
       
  2309         const QTransform &x = d->matrix;
       
  2310         tl = x.map(rect.topLeft());
       
  2311         tr = x.map(rect.topRight());
       
  2312         br = x.map(rect.bottomRight());
       
  2313         bl = x.map(rect.bottomLeft());
       
  2314     } else {
       
  2315         tl = rect.topLeft();
       
  2316         tr = rect.topRight();
       
  2317         br = rect.bottomRight();
       
  2318         bl = rect.bottomLeft();
       
  2319     }
       
  2320     QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
       
  2321     tl -= scrollOffset;
       
  2322     tr -= scrollOffset;
       
  2323     br -= scrollOffset;
       
  2324     bl -= scrollOffset;
       
  2325 
       
  2326     QPolygon poly(4);
       
  2327     poly[0] = tl.toPoint();
       
  2328     poly[1] = tr.toPoint();
       
  2329     poly[2] = br.toPoint();
       
  2330     poly[3] = bl.toPoint();
       
  2331     return poly;
       
  2332 }
       
  2333 
       
  2334 /*!
       
  2335     \fn QGraphicsView::mapFromScene(qreal x, qreal y, qreal w, qreal h) const
       
  2336 
       
  2337     This function is provided for convenience. It's equivalent to
       
  2338     calling mapFromScene(QRectF(\a x, \a y, \a w, \a h)).
       
  2339 */
       
  2340 
       
  2341 /*!
       
  2342     Returns the scene coordinate polygon \a polygon to a viewport coordinate
       
  2343     polygon.
       
  2344 
       
  2345     \sa mapToScene()
       
  2346 */
       
  2347 QPolygon QGraphicsView::mapFromScene(const QPolygonF &polygon) const
       
  2348 {
       
  2349     QPolygon poly;
       
  2350     foreach (const QPointF &point, polygon)
       
  2351         poly << mapFromScene(point);
       
  2352     return poly;
       
  2353 }
       
  2354 
       
  2355 /*!
       
  2356     Returns the scene coordinate painter path \a path to a viewport coordinate
       
  2357     painter path.
       
  2358 
       
  2359     \sa mapToScene()
       
  2360 */
       
  2361 QPainterPath QGraphicsView::mapFromScene(const QPainterPath &path) const
       
  2362 {
       
  2363     Q_D(const QGraphicsView);
       
  2364     QTransform matrix = d->matrix;
       
  2365     matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
       
  2366     return matrix.map(path);
       
  2367 }
       
  2368 
       
  2369 /*!
       
  2370     \reimp
       
  2371 */
       
  2372 QVariant QGraphicsView::inputMethodQuery(Qt::InputMethodQuery query) const
       
  2373 {
       
  2374     Q_D(const QGraphicsView);
       
  2375     if (!d->scene)
       
  2376         return QVariant();
       
  2377 
       
  2378     QVariant value = d->scene->inputMethodQuery(query);
       
  2379     if (value.type() == QVariant::RectF)
       
  2380         value = mapFromScene(value.toRectF()).boundingRect();
       
  2381     else if (value.type() == QVariant::PointF)
       
  2382         value = mapFromScene(value.toPointF());
       
  2383     else if (value.type() == QVariant::Rect)
       
  2384         value = mapFromScene(value.toRect()).boundingRect();
       
  2385     else if (value.type() == QVariant::Point)
       
  2386         value = mapFromScene(value.toPoint());
       
  2387     return value;
       
  2388 }
       
  2389 
       
  2390 /*!
       
  2391     \property QGraphicsView::backgroundBrush
       
  2392     \brief the background brush of the scene.
       
  2393 
       
  2394     This property sets the background brush for the scene in this view. It is
       
  2395     used to override the scene's own background, and defines the behavior of
       
  2396     drawBackground(). To provide custom background drawing for this view, you
       
  2397     can reimplement drawBackground() instead.
       
  2398 
       
  2399     By default, this property contains a brush with the Qt::NoBrush pattern.
       
  2400 
       
  2401     \sa QGraphicsScene::backgroundBrush, foregroundBrush
       
  2402 */
       
  2403 QBrush QGraphicsView::backgroundBrush() const
       
  2404 {
       
  2405     Q_D(const QGraphicsView);
       
  2406     return d->backgroundBrush;
       
  2407 }
       
  2408 void QGraphicsView::setBackgroundBrush(const QBrush &brush)
       
  2409 {
       
  2410     Q_D(QGraphicsView);
       
  2411     d->backgroundBrush = brush;
       
  2412     d->updateAll();
       
  2413 
       
  2414     if (d->cacheMode & CacheBackground) {
       
  2415         // Invalidate the background pixmap
       
  2416         d->mustResizeBackgroundPixmap = true;
       
  2417     }
       
  2418 }
       
  2419 
       
  2420 /*!
       
  2421     \property QGraphicsView::foregroundBrush
       
  2422     \brief the foreground brush of the scene.
       
  2423 
       
  2424     This property sets the foreground brush for the scene in this view. It is
       
  2425     used to override the scene's own foreground, and defines the behavior of
       
  2426     drawForeground(). To provide custom foreground drawing for this view, you
       
  2427     can reimplement drawForeground() instead.
       
  2428 
       
  2429     By default, this property contains a brush with the Qt::NoBrush pattern.
       
  2430 
       
  2431     \sa QGraphicsScene::foregroundBrush, backgroundBrush
       
  2432 */
       
  2433 QBrush QGraphicsView::foregroundBrush() const
       
  2434 {
       
  2435     Q_D(const QGraphicsView);
       
  2436     return d->foregroundBrush;
       
  2437 }
       
  2438 void QGraphicsView::setForegroundBrush(const QBrush &brush)
       
  2439 {
       
  2440     Q_D(QGraphicsView);
       
  2441     d->foregroundBrush = brush;
       
  2442     d->updateAll();
       
  2443 }
       
  2444 
       
  2445 /*!
       
  2446     Schedules an update of the scene rectangles \a rects.
       
  2447 
       
  2448     \sa QGraphicsScene::changed()
       
  2449 */
       
  2450 void QGraphicsView::updateScene(const QList<QRectF> &rects)
       
  2451 {
       
  2452     // ### Note: Since 4.5, this slot is only called if the user explicitly
       
  2453     // establishes a connection between the scene and the view, as the scene
       
  2454     // and view are no longer connected. We need to keep it working (basically
       
  2455     // leave it as it is), but the new delivery path is through
       
  2456     // QGraphicsScenePrivate::itemUpdate().
       
  2457     Q_D(QGraphicsView);
       
  2458     if (d->fullUpdatePending || d->viewportUpdateMode == QGraphicsView::NoViewportUpdate)
       
  2459         return;
       
  2460 
       
  2461     // Extract and reset dirty scene rect info.
       
  2462     QVector<QRect> dirtyViewportRects;
       
  2463     const QVector<QRect> &dirtyRects = d->dirtyRegion.rects();
       
  2464     for (int i = 0; i < dirtyRects.size(); ++i)
       
  2465         dirtyViewportRects += dirtyRects.at(i);
       
  2466     d->dirtyRegion = QRegion();
       
  2467     d->dirtyBoundingRect = QRect();
       
  2468 
       
  2469     bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
       
  2470     bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
       
  2471                               || (d->viewportUpdateMode == QGraphicsView::SmartViewportUpdate
       
  2472                                   && ((dirtyViewportRects.size() + rects.size()) >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD));
       
  2473 
       
  2474     QRegion updateRegion;
       
  2475     QRect boundingRect;
       
  2476     QRect viewportRect = viewport()->rect();
       
  2477     bool redraw = false;
       
  2478     QTransform transform = viewportTransform();
       
  2479 
       
  2480     // Convert scene rects to viewport rects.
       
  2481     foreach (const QRectF &rect, rects) {
       
  2482         QRect xrect = transform.mapRect(rect).toRect();
       
  2483         if (!(d->optimizationFlags & DontAdjustForAntialiasing))
       
  2484             xrect.adjust(-2, -2, 2, 2);
       
  2485         if (!viewportRect.intersects(xrect))
       
  2486             continue;
       
  2487         dirtyViewportRects << xrect;
       
  2488     }
       
  2489 
       
  2490     foreach (const QRect &rect, dirtyViewportRects) {
       
  2491         // Add the exposed rect to the update region. In rect update
       
  2492         // mode, we only count the bounding rect of items.
       
  2493         if (!boundingRectUpdate) {
       
  2494             updateRegion += rect;
       
  2495         } else {
       
  2496             boundingRect |= rect;
       
  2497         }
       
  2498         redraw = true;
       
  2499         if (fullUpdate) {
       
  2500             // If fullUpdate is true and we found a visible dirty rect,
       
  2501             // we're done.
       
  2502             break;
       
  2503         }
       
  2504     }
       
  2505 
       
  2506     if (!redraw)
       
  2507         return;
       
  2508 
       
  2509     if (fullUpdate)
       
  2510         viewport()->update();
       
  2511     else if (boundingRectUpdate)
       
  2512         viewport()->update(boundingRect);
       
  2513     else
       
  2514         viewport()->update(updateRegion);
       
  2515 }
       
  2516 
       
  2517 /*!
       
  2518     Notifies QGraphicsView that the scene's scene rect has changed.  \a rect
       
  2519     is the new scene rect. If the view already has an explicitly set scene
       
  2520     rect, this function does nothing.
       
  2521 
       
  2522     \sa sceneRect, QGraphicsScene::sceneRectChanged()
       
  2523 */
       
  2524 void QGraphicsView::updateSceneRect(const QRectF &rect)
       
  2525 {
       
  2526     Q_D(QGraphicsView);
       
  2527     if (!d->hasSceneRect) {
       
  2528         d->sceneRect = rect;
       
  2529         d->recalculateContentSize();
       
  2530     }
       
  2531 }
       
  2532 
       
  2533 /*!
       
  2534     This slot is called by QAbstractScrollArea after setViewport() has been
       
  2535     called. Reimplement this function in a subclass of QGraphicsView to
       
  2536     initialize the new viewport \a widget before it is used.
       
  2537 
       
  2538     \sa setViewport()
       
  2539 */
       
  2540 void QGraphicsView::setupViewport(QWidget *widget)
       
  2541 {
       
  2542     Q_D(QGraphicsView);
       
  2543 
       
  2544     if (!widget) {
       
  2545         qWarning("QGraphicsView::setupViewport: cannot initialize null widget");
       
  2546         return;
       
  2547     }
       
  2548 
       
  2549     const bool isGLWidget = widget->inherits("QGLWidget");
       
  2550 
       
  2551     d->accelerateScrolling = !(isGLWidget);
       
  2552 
       
  2553     widget->setFocusPolicy(Qt::StrongFocus);
       
  2554 
       
  2555     if (!isGLWidget) {
       
  2556         // autoFillBackground enables scroll acceleration.
       
  2557         widget->setAutoFillBackground(true);
       
  2558     }
       
  2559 
       
  2560     // We are only interested in mouse tracking if items
       
  2561     // accept hover events or use non-default cursors.
       
  2562     if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
       
  2563                      || !d->scene->d_func()->allItemsUseDefaultCursor)) {
       
  2564         widget->setMouseTracking(true);
       
  2565     }
       
  2566 
       
  2567     // enable touch events if any items is interested in them
       
  2568     if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
       
  2569         widget->setAttribute(Qt::WA_AcceptTouchEvents);
       
  2570 
       
  2571     widget->setAcceptDrops(acceptDrops());
       
  2572 }
       
  2573 
       
  2574 /*!
       
  2575     \reimp
       
  2576 */
       
  2577 bool QGraphicsView::event(QEvent *event)
       
  2578 {
       
  2579     Q_D(QGraphicsView);
       
  2580 
       
  2581     if (d->sceneInteractionAllowed) {
       
  2582         switch (event->type()) {
       
  2583         case QEvent::ShortcutOverride:
       
  2584             if (d->scene)
       
  2585                 return QApplication::sendEvent(d->scene, event);
       
  2586             break;
       
  2587         case QEvent::KeyPress:
       
  2588             if (d->scene) {
       
  2589                 QKeyEvent *k = static_cast<QKeyEvent *>(event);
       
  2590                 if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
       
  2591                     // Send the key events to the scene. This will invoke the
       
  2592                     // scene's tab focus handling, and if the event is
       
  2593                     // accepted, we return (prevent further event delivery),
       
  2594                     // and the base implementation will call QGraphicsView's
       
  2595                     // focusNextPrevChild() function. If the event is ignored,
       
  2596                     // we fall back to standard tab focus handling.
       
  2597                     QApplication::sendEvent(d->scene, event);
       
  2598                     if (event->isAccepted())
       
  2599                         return true;
       
  2600                     // Ensure the event doesn't propagate just because the
       
  2601                     // scene ignored it. If the event propagates, then tab
       
  2602                     // handling will be called twice (this and parent).
       
  2603                     event->accept();
       
  2604                 }
       
  2605             }
       
  2606             break;
       
  2607         default:
       
  2608             break;
       
  2609         }
       
  2610     }
       
  2611 
       
  2612     return QAbstractScrollArea::event(event);
       
  2613 }
       
  2614 
       
  2615 /*!
       
  2616     \reimp
       
  2617 */
       
  2618 bool QGraphicsView::viewportEvent(QEvent *event)
       
  2619 {
       
  2620     Q_D(QGraphicsView);
       
  2621     if (!d->scene)
       
  2622         return QAbstractScrollArea::viewportEvent(event);
       
  2623 
       
  2624     switch (event->type()) {
       
  2625     case QEvent::Enter:
       
  2626         QApplication::sendEvent(d->scene, event);
       
  2627         break;
       
  2628     case QEvent::WindowActivate:
       
  2629         QApplication::sendEvent(d->scene, event);
       
  2630         break;
       
  2631     case QEvent::WindowDeactivate:
       
  2632         // ### This is a temporary fix for until we get proper mouse
       
  2633         // grab events. mouseGrabberItem should be set to 0 if we lose
       
  2634         // the mouse grab.
       
  2635         // Remove all popups when the scene loses focus.
       
  2636         if (!d->scene->d_func()->popupWidgets.isEmpty())
       
  2637             d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
       
  2638         QApplication::sendEvent(d->scene, event);
       
  2639         break;
       
  2640     case QEvent::Leave:
       
  2641         // ### This is a temporary fix for until we get proper mouse grab
       
  2642         // events. activeMouseGrabberItem should be set to 0 if we lose the
       
  2643         // mouse grab.
       
  2644         if ((QApplication::activePopupWidget() && QApplication::activePopupWidget() != window())
       
  2645             || (QApplication::activeModalWidget() && QApplication::activeModalWidget() != window())
       
  2646             || (QApplication::activeWindow() != window())) {
       
  2647             if (!d->scene->d_func()->popupWidgets.isEmpty())
       
  2648                 d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
       
  2649         }
       
  2650         d->useLastMouseEvent = false;
       
  2651         QApplication::sendEvent(d->scene, event);
       
  2652         break;
       
  2653 #ifndef QT_NO_TOOLTIP
       
  2654     case QEvent::ToolTip: {
       
  2655         QHelpEvent *toolTip = static_cast<QHelpEvent *>(event);
       
  2656         QGraphicsSceneHelpEvent helpEvent(QEvent::GraphicsSceneHelp);
       
  2657         helpEvent.setWidget(viewport());
       
  2658         helpEvent.setScreenPos(toolTip->globalPos());
       
  2659         helpEvent.setScenePos(mapToScene(toolTip->pos()));
       
  2660         QApplication::sendEvent(d->scene, &helpEvent);
       
  2661         toolTip->setAccepted(helpEvent.isAccepted());
       
  2662         return true;
       
  2663     }
       
  2664 #endif
       
  2665     case QEvent::Paint:
       
  2666         // Reset full update
       
  2667         d->fullUpdatePending = false;
       
  2668         d->dirtyScrollOffset = QPoint();
       
  2669         if (d->scene) {
       
  2670             // Check if this view reimplements the updateScene slot; if it
       
  2671             // does, we can't do direct update delivery and have to fall back
       
  2672             // to connecting the changed signal.
       
  2673             if (!d->updateSceneSlotReimplementedChecked) {
       
  2674                 d->updateSceneSlotReimplementedChecked = true;
       
  2675                 const QMetaObject *mo = metaObject();
       
  2676                 if (mo != &QGraphicsView::staticMetaObject) {
       
  2677                     if (mo->indexOfSlot("updateScene(QList<QRectF>)")
       
  2678                         != QGraphicsView::staticMetaObject.indexOfSlot("updateScene(QList<QRectF>)")) {
       
  2679                         connect(d->scene, SIGNAL(changed(QList<QRectF>)),
       
  2680                                 this, SLOT(updateScene(QList<QRectF>)));
       
  2681                     }
       
  2682                 }
       
  2683             }
       
  2684             d->scene->d_func()->updateAll = false;
       
  2685         }
       
  2686         break;
       
  2687     case QEvent::TouchBegin:
       
  2688     case QEvent::TouchUpdate:
       
  2689     case QEvent::TouchEnd:
       
  2690     {
       
  2691         if (!isEnabled())
       
  2692             return false;
       
  2693 
       
  2694         if (d->scene && d->sceneInteractionAllowed) {
       
  2695             // Convert and deliver the touch event to the scene.
       
  2696             QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
       
  2697             touchEvent->setWidget(viewport());
       
  2698             QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
       
  2699             (void) QApplication::sendEvent(d->scene, touchEvent);
       
  2700         }
       
  2701 
       
  2702         return true;
       
  2703     }
       
  2704     case QEvent::Gesture:
       
  2705     case QEvent::GestureOverride:
       
  2706     {
       
  2707         if (!isEnabled())
       
  2708             return false;
       
  2709 
       
  2710         if (d->scene && d->sceneInteractionAllowed) {
       
  2711             QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);
       
  2712             gestureEvent->setWidget(viewport());
       
  2713             (void) QApplication::sendEvent(d->scene, gestureEvent);
       
  2714         }
       
  2715         return true;
       
  2716     }
       
  2717     default:
       
  2718         break;
       
  2719     }
       
  2720 
       
  2721     return QAbstractScrollArea::viewportEvent(event);
       
  2722 }
       
  2723 
       
  2724 #ifndef QT_NO_CONTEXTMENU
       
  2725 /*!
       
  2726     \reimp
       
  2727 */
       
  2728 void QGraphicsView::contextMenuEvent(QContextMenuEvent *event)
       
  2729 {
       
  2730     Q_D(QGraphicsView);
       
  2731     if (!d->scene || !d->sceneInteractionAllowed)
       
  2732         return;
       
  2733 
       
  2734     d->mousePressViewPoint = event->pos();
       
  2735     d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
       
  2736     d->mousePressScreenPoint = event->globalPos();
       
  2737     d->lastMouseMoveScenePoint = d->mousePressScenePoint;
       
  2738     d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
       
  2739 
       
  2740     QGraphicsSceneContextMenuEvent contextEvent(QEvent::GraphicsSceneContextMenu);
       
  2741     contextEvent.setWidget(viewport());
       
  2742     contextEvent.setScenePos(d->mousePressScenePoint);
       
  2743     contextEvent.setScreenPos(d->mousePressScreenPoint);
       
  2744     contextEvent.setModifiers(event->modifiers());
       
  2745     contextEvent.setReason((QGraphicsSceneContextMenuEvent::Reason)(event->reason()));
       
  2746     contextEvent.setAccepted(event->isAccepted());
       
  2747     QApplication::sendEvent(d->scene, &contextEvent);
       
  2748     event->setAccepted(contextEvent.isAccepted());
       
  2749 }
       
  2750 #endif // QT_NO_CONTEXTMENU
       
  2751 
       
  2752 /*!
       
  2753     \reimp
       
  2754 */
       
  2755 void QGraphicsView::dropEvent(QDropEvent *event)
       
  2756 {
       
  2757 #ifndef QT_NO_DRAGANDDROP
       
  2758     Q_D(QGraphicsView);
       
  2759     if (!d->scene || !d->sceneInteractionAllowed)
       
  2760         return;
       
  2761 
       
  2762     // Generate a scene event.
       
  2763     QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDrop);
       
  2764     d->populateSceneDragDropEvent(&sceneEvent, event);
       
  2765 
       
  2766     // Send it to the scene.
       
  2767     QApplication::sendEvent(d->scene, &sceneEvent);
       
  2768 
       
  2769     // Accept the originating event if the scene accepted the scene event.
       
  2770     event->setAccepted(sceneEvent.isAccepted());
       
  2771     if (sceneEvent.isAccepted())
       
  2772         event->setDropAction(sceneEvent.dropAction());
       
  2773 
       
  2774     delete d->lastDragDropEvent;
       
  2775     d->lastDragDropEvent = 0;
       
  2776 
       
  2777 #else
       
  2778     Q_UNUSED(event)
       
  2779 #endif
       
  2780 }
       
  2781 
       
  2782 /*!
       
  2783     \reimp
       
  2784 */
       
  2785 void QGraphicsView::dragEnterEvent(QDragEnterEvent *event)
       
  2786 {
       
  2787 #ifndef QT_NO_DRAGANDDROP
       
  2788     Q_D(QGraphicsView);
       
  2789     if (!d->scene || !d->sceneInteractionAllowed)
       
  2790         return;
       
  2791 
       
  2792     // Disable replaying of mouse move events.
       
  2793     d->useLastMouseEvent = false;
       
  2794 
       
  2795     // Generate a scene event.
       
  2796     QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragEnter);
       
  2797     d->populateSceneDragDropEvent(&sceneEvent, event);
       
  2798 
       
  2799     // Store it for later use.
       
  2800     d->storeDragDropEvent(&sceneEvent);
       
  2801 
       
  2802     // Send it to the scene.
       
  2803     QApplication::sendEvent(d->scene, &sceneEvent);
       
  2804 
       
  2805     // Accept the originating event if the scene accepted the scene event.
       
  2806     if (sceneEvent.isAccepted()) {
       
  2807         event->setAccepted(true);
       
  2808         event->setDropAction(sceneEvent.dropAction());
       
  2809     }
       
  2810 #else
       
  2811     Q_UNUSED(event)
       
  2812 #endif
       
  2813 }
       
  2814 
       
  2815 /*!
       
  2816     \reimp
       
  2817 */
       
  2818 void QGraphicsView::dragLeaveEvent(QDragLeaveEvent *event)
       
  2819 {
       
  2820 #ifndef QT_NO_DRAGANDDROP
       
  2821     Q_D(QGraphicsView);
       
  2822     if (!d->scene || !d->sceneInteractionAllowed)
       
  2823         return;
       
  2824     if (!d->lastDragDropEvent) {
       
  2825         qWarning("QGraphicsView::dragLeaveEvent: drag leave received before drag enter");
       
  2826         return;
       
  2827     }
       
  2828 
       
  2829     // Generate a scene event.
       
  2830     QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragLeave);
       
  2831     sceneEvent.setScenePos(d->lastDragDropEvent->scenePos());
       
  2832     sceneEvent.setScreenPos(d->lastDragDropEvent->screenPos());
       
  2833     sceneEvent.setButtons(d->lastDragDropEvent->buttons());
       
  2834     sceneEvent.setModifiers(d->lastDragDropEvent->modifiers());
       
  2835     sceneEvent.setPossibleActions(d->lastDragDropEvent->possibleActions());
       
  2836     sceneEvent.setProposedAction(d->lastDragDropEvent->proposedAction());
       
  2837     sceneEvent.setDropAction(d->lastDragDropEvent->dropAction());
       
  2838     sceneEvent.setMimeData(d->lastDragDropEvent->mimeData());
       
  2839     sceneEvent.setWidget(d->lastDragDropEvent->widget());
       
  2840     sceneEvent.setSource(d->lastDragDropEvent->source());
       
  2841     delete d->lastDragDropEvent;
       
  2842     d->lastDragDropEvent = 0;
       
  2843 
       
  2844     // Send it to the scene.
       
  2845     QApplication::sendEvent(d->scene, &sceneEvent);
       
  2846 
       
  2847     // Accept the originating event if the scene accepted the scene event.
       
  2848     if (sceneEvent.isAccepted())
       
  2849         event->setAccepted(true);
       
  2850 #else
       
  2851     Q_UNUSED(event)
       
  2852 #endif
       
  2853 }
       
  2854 
       
  2855 /*!
       
  2856     \reimp
       
  2857 */
       
  2858 void QGraphicsView::dragMoveEvent(QDragMoveEvent *event)
       
  2859 {
       
  2860 #ifndef QT_NO_DRAGANDDROP
       
  2861     Q_D(QGraphicsView);
       
  2862     if (!d->scene || !d->sceneInteractionAllowed)
       
  2863         return;
       
  2864 
       
  2865     // Generate a scene event.
       
  2866     QGraphicsSceneDragDropEvent sceneEvent(QEvent::GraphicsSceneDragMove);
       
  2867     d->populateSceneDragDropEvent(&sceneEvent, event);
       
  2868 
       
  2869     // Store it for later use.
       
  2870     d->storeDragDropEvent(&sceneEvent);
       
  2871 
       
  2872     // Send it to the scene.
       
  2873     QApplication::sendEvent(d->scene, &sceneEvent);
       
  2874 
       
  2875     // Ignore the originating event if the scene ignored the scene event.
       
  2876     event->setAccepted(sceneEvent.isAccepted());
       
  2877     if (sceneEvent.isAccepted())
       
  2878         event->setDropAction(sceneEvent.dropAction());
       
  2879 #else
       
  2880     Q_UNUSED(event)
       
  2881 #endif
       
  2882 }
       
  2883 
       
  2884 /*!
       
  2885     \reimp
       
  2886 */
       
  2887 void QGraphicsView::focusInEvent(QFocusEvent *event)
       
  2888 {
       
  2889     Q_D(QGraphicsView);
       
  2890     d->updateInputMethodSensitivity();
       
  2891     QAbstractScrollArea::focusInEvent(event);
       
  2892     if (d->scene)
       
  2893         QApplication::sendEvent(d->scene, event);
       
  2894     // Pass focus on if the scene cannot accept focus.
       
  2895     if (!d->scene || !event->isAccepted())
       
  2896         QAbstractScrollArea::focusInEvent(event);
       
  2897 }
       
  2898 
       
  2899 /*!
       
  2900     \reimp
       
  2901 */
       
  2902 bool QGraphicsView::focusNextPrevChild(bool next)
       
  2903 {
       
  2904     return QAbstractScrollArea::focusNextPrevChild(next);
       
  2905 }
       
  2906 
       
  2907 /*!
       
  2908     \reimp
       
  2909 */
       
  2910 void QGraphicsView::focusOutEvent(QFocusEvent *event)
       
  2911 {
       
  2912     Q_D(QGraphicsView);
       
  2913     QAbstractScrollArea::focusOutEvent(event);
       
  2914     if (d->scene)
       
  2915         QApplication::sendEvent(d->scene, event);
       
  2916 }
       
  2917 
       
  2918 /*!
       
  2919     \reimp
       
  2920 */
       
  2921 void QGraphicsView::keyPressEvent(QKeyEvent *event)
       
  2922 {
       
  2923     Q_D(QGraphicsView);
       
  2924     if (!d->scene || !d->sceneInteractionAllowed) {
       
  2925         QAbstractScrollArea::keyPressEvent(event);
       
  2926         return;
       
  2927     }
       
  2928     QApplication::sendEvent(d->scene, event);
       
  2929     if (!event->isAccepted())
       
  2930         QAbstractScrollArea::keyPressEvent(event);
       
  2931 }
       
  2932 
       
  2933 /*!
       
  2934     \reimp
       
  2935 */
       
  2936 void QGraphicsView::keyReleaseEvent(QKeyEvent *event)
       
  2937 {
       
  2938     Q_D(QGraphicsView);
       
  2939     if (!d->scene || !d->sceneInteractionAllowed)
       
  2940         return;
       
  2941     QApplication::sendEvent(d->scene, event);
       
  2942     if (!event->isAccepted())
       
  2943         QAbstractScrollArea::keyReleaseEvent(event);
       
  2944 }
       
  2945 
       
  2946 /*!
       
  2947     \reimp
       
  2948 */
       
  2949 void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
       
  2950 {
       
  2951     Q_D(QGraphicsView);
       
  2952     if (!d->scene || !d->sceneInteractionAllowed)
       
  2953         return;
       
  2954 
       
  2955     d->storeMouseEvent(event);
       
  2956     d->mousePressViewPoint = event->pos();
       
  2957     d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
       
  2958     d->mousePressScreenPoint = event->globalPos();
       
  2959     d->lastMouseMoveScenePoint = d->mousePressScenePoint;
       
  2960     d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
       
  2961     d->mousePressButton = event->button();
       
  2962 
       
  2963     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseDoubleClick);
       
  2964     mouseEvent.setWidget(viewport());
       
  2965     mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
       
  2966     mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
       
  2967     mouseEvent.setScenePos(mapToScene(d->mousePressViewPoint));
       
  2968     mouseEvent.setScreenPos(d->mousePressScreenPoint);
       
  2969     mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
       
  2970     mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
       
  2971     mouseEvent.setButtons(event->buttons());
       
  2972     mouseEvent.setButtons(event->buttons());
       
  2973     mouseEvent.setAccepted(false);
       
  2974     mouseEvent.setButton(event->button());
       
  2975     mouseEvent.setModifiers(event->modifiers());
       
  2976     if (event->spontaneous())
       
  2977         qt_sendSpontaneousEvent(d->scene, &mouseEvent);
       
  2978     else
       
  2979         QApplication::sendEvent(d->scene, &mouseEvent);
       
  2980 }
       
  2981 
       
  2982 /*!
       
  2983     \reimp
       
  2984 */
       
  2985 void QGraphicsView::mousePressEvent(QMouseEvent *event)
       
  2986 {
       
  2987     Q_D(QGraphicsView);
       
  2988 
       
  2989     // Store this event for replaying, finding deltas, and for
       
  2990     // scroll-dragging; even in non-interactive mode, scroll hand dragging is
       
  2991     // allowed, so we store the event at the very top of this function.
       
  2992     d->storeMouseEvent(event);
       
  2993     d->lastMouseEvent.setAccepted(false);
       
  2994 
       
  2995     if (d->sceneInteractionAllowed) {
       
  2996         // Store some of the event's button-down data.
       
  2997         d->mousePressViewPoint = event->pos();
       
  2998         d->mousePressScenePoint = mapToScene(d->mousePressViewPoint);
       
  2999         d->mousePressScreenPoint = event->globalPos();
       
  3000         d->lastMouseMoveScenePoint = d->mousePressScenePoint;
       
  3001         d->lastMouseMoveScreenPoint = d->mousePressScreenPoint;
       
  3002         d->mousePressButton = event->button();
       
  3003 
       
  3004         if (d->scene) {
       
  3005             // Convert and deliver the mouse event to the scene.
       
  3006             QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
       
  3007             mouseEvent.setWidget(viewport());
       
  3008             mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
       
  3009             mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
       
  3010             mouseEvent.setScenePos(d->mousePressScenePoint);
       
  3011             mouseEvent.setScreenPos(d->mousePressScreenPoint);
       
  3012             mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
       
  3013             mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
       
  3014             mouseEvent.setButtons(event->buttons());
       
  3015             mouseEvent.setButton(event->button());
       
  3016             mouseEvent.setModifiers(event->modifiers());
       
  3017             mouseEvent.setAccepted(false);
       
  3018             if (event->spontaneous())
       
  3019                 qt_sendSpontaneousEvent(d->scene, &mouseEvent);
       
  3020             else
       
  3021                 QApplication::sendEvent(d->scene, &mouseEvent);
       
  3022 
       
  3023             // Update the original mouse event accepted state.
       
  3024             bool isAccepted = mouseEvent.isAccepted();
       
  3025             event->setAccepted(isAccepted);
       
  3026 
       
  3027             // Update the last mouse event accepted state.
       
  3028             d->lastMouseEvent.setAccepted(isAccepted);
       
  3029 
       
  3030             if (isAccepted)
       
  3031                 return;
       
  3032         }
       
  3033     }
       
  3034 
       
  3035 #ifndef QT_NO_RUBBERBAND
       
  3036     if (d->dragMode == QGraphicsView::RubberBandDrag && !d->rubberBanding) {
       
  3037         if (d->sceneInteractionAllowed) {
       
  3038             // Rubberbanding is only allowed in interactive mode.
       
  3039             event->accept();
       
  3040             d->rubberBanding = true;
       
  3041             d->rubberBandRect = QRect();
       
  3042             if (d->scene) {
       
  3043                 // Initiating a rubber band always clears the selection.
       
  3044                 d->scene->clearSelection();
       
  3045             }
       
  3046         }
       
  3047     } else
       
  3048 #endif
       
  3049         if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
       
  3050             // Left-button press in scroll hand mode initiates hand scrolling.
       
  3051             event->accept();
       
  3052             d->handScrolling = true;
       
  3053             d->handScrollMotions = 0;
       
  3054 #ifndef QT_NO_CURSOR
       
  3055             viewport()->setCursor(Qt::ClosedHandCursor);
       
  3056 #endif
       
  3057         }
       
  3058 }
       
  3059 
       
  3060 /*!
       
  3061     \reimp
       
  3062 */
       
  3063 void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
       
  3064 {
       
  3065     Q_D(QGraphicsView);
       
  3066 
       
  3067 #ifndef QT_NO_RUBBERBAND
       
  3068     if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed) {
       
  3069         d->storeMouseEvent(event);
       
  3070         if (d->rubberBanding) {
       
  3071             // Check for enough drag distance
       
  3072             if ((d->mousePressViewPoint - event->pos()).manhattanLength()
       
  3073                 < QApplication::startDragDistance()) {
       
  3074                 return;
       
  3075             }
       
  3076 
       
  3077             // Update old rubberband
       
  3078             if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isEmpty()) {
       
  3079                 if (d->viewportUpdateMode != FullViewportUpdate)
       
  3080                     viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
       
  3081                 else
       
  3082                     d->updateAll();
       
  3083             }
       
  3084 
       
  3085             // Stop rubber banding if the user has let go of all buttons (even
       
  3086             // if we didn't get the release events).
       
  3087             if (!event->buttons()) {
       
  3088                 d->rubberBanding = false;
       
  3089                 d->rubberBandRect = QRect();
       
  3090                 return;
       
  3091             }
       
  3092 
       
  3093             // Update rubberband position
       
  3094             const QPoint &mp = d->mousePressViewPoint;
       
  3095             QPoint ep = event->pos();
       
  3096             d->rubberBandRect = QRect(qMin(mp.x(), ep.x()), qMin(mp.y(), ep.y()),
       
  3097                                       qAbs(mp.x() - ep.x()) + 1, qAbs(mp.y() - ep.y()) + 1);
       
  3098 
       
  3099             // Update new rubberband
       
  3100             if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate){
       
  3101                 if (d->viewportUpdateMode != FullViewportUpdate)
       
  3102                     viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
       
  3103                 else
       
  3104                     d->updateAll();
       
  3105             }
       
  3106             // Set the new selection area
       
  3107             QPainterPath selectionArea;
       
  3108             selectionArea.addPolygon(mapToScene(d->rubberBandRect));
       
  3109             selectionArea.closeSubpath();
       
  3110             if (d->scene)
       
  3111                 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode,
       
  3112                                            viewportTransform());
       
  3113             return;
       
  3114         }
       
  3115     } else
       
  3116 #endif // QT_NO_RUBBERBAND
       
  3117     if (d->dragMode == QGraphicsView::ScrollHandDrag) {
       
  3118         if (d->handScrolling) {
       
  3119             QScrollBar *hBar = horizontalScrollBar();
       
  3120             QScrollBar *vBar = verticalScrollBar();
       
  3121             QPoint delta = event->pos() - d->lastMouseEvent.pos();
       
  3122             hBar->setValue(hBar->value() + (isRightToLeft() ? delta.x() : -delta.x()));
       
  3123             vBar->setValue(vBar->value() - delta.y());
       
  3124 
       
  3125             // Detect how much we've scrolled to disambiguate scrolling from
       
  3126             // clicking.
       
  3127             ++d->handScrollMotions;
       
  3128         }
       
  3129     }
       
  3130 
       
  3131     d->mouseMoveEventHandler(event);
       
  3132 }
       
  3133 
       
  3134 /*!
       
  3135     \reimp
       
  3136 */
       
  3137 void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
       
  3138 {
       
  3139     Q_D(QGraphicsView);
       
  3140 
       
  3141 #ifndef QT_NO_RUBBERBAND
       
  3142     if (d->dragMode == QGraphicsView::RubberBandDrag && d->sceneInteractionAllowed && !event->buttons()) {
       
  3143         if (d->rubberBanding) {
       
  3144             if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate){
       
  3145                 if (d->viewportUpdateMode != FullViewportUpdate)
       
  3146                     viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
       
  3147                 else
       
  3148                     d->updateAll();
       
  3149             }
       
  3150             d->rubberBanding = false;
       
  3151             d->rubberBandRect = QRect();
       
  3152         }
       
  3153     } else
       
  3154 #endif
       
  3155     if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
       
  3156 #ifndef QT_NO_CURSOR
       
  3157         // Restore the open hand cursor. ### There might be items
       
  3158         // under the mouse that have a valid cursor at this time, so
       
  3159         // we could repeat the steps from mouseMoveEvent().
       
  3160         viewport()->setCursor(Qt::OpenHandCursor);
       
  3161 #endif
       
  3162         d->handScrolling = false;
       
  3163 
       
  3164         if (d->scene && d->sceneInteractionAllowed && !d->lastMouseEvent.isAccepted() && d->handScrollMotions <= 6) {
       
  3165             // If we've detected very little motion during the hand drag, and
       
  3166             // no item accepted the last event, we'll interpret that as a
       
  3167             // click to the scene, and reset the selection.
       
  3168             d->scene->clearSelection();
       
  3169         }
       
  3170     }
       
  3171 
       
  3172     d->storeMouseEvent(event);
       
  3173 
       
  3174     if (!d->sceneInteractionAllowed)
       
  3175         return;
       
  3176 
       
  3177     if (!d->scene)
       
  3178         return;
       
  3179 
       
  3180     QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
       
  3181     mouseEvent.setWidget(viewport());
       
  3182     mouseEvent.setButtonDownScenePos(d->mousePressButton, d->mousePressScenePoint);
       
  3183     mouseEvent.setButtonDownScreenPos(d->mousePressButton, d->mousePressScreenPoint);
       
  3184     mouseEvent.setScenePos(mapToScene(event->pos()));
       
  3185     mouseEvent.setScreenPos(event->globalPos());
       
  3186     mouseEvent.setLastScenePos(d->lastMouseMoveScenePoint);
       
  3187     mouseEvent.setLastScreenPos(d->lastMouseMoveScreenPoint);
       
  3188     mouseEvent.setButtons(event->buttons());
       
  3189     mouseEvent.setButton(event->button());
       
  3190     mouseEvent.setModifiers(event->modifiers());
       
  3191     mouseEvent.setAccepted(false);
       
  3192     if (event->spontaneous())
       
  3193         qt_sendSpontaneousEvent(d->scene, &mouseEvent);
       
  3194     else
       
  3195         QApplication::sendEvent(d->scene, &mouseEvent);
       
  3196 
       
  3197     // Update the last mouse event selected state.
       
  3198     d->lastMouseEvent.setAccepted(mouseEvent.isAccepted());
       
  3199 
       
  3200 #ifndef QT_NO_CURSOR
       
  3201     if (mouseEvent.isAccepted() && mouseEvent.buttons() == 0 && viewport()->testAttribute(Qt::WA_SetCursor)) {
       
  3202         // The last mouse release on the viewport will trigger clearing the cursor.
       
  3203         d->_q_unsetViewportCursor();
       
  3204     }
       
  3205 #endif
       
  3206 }
       
  3207 
       
  3208 #ifndef QT_NO_WHEELEVENT
       
  3209 /*!
       
  3210     \reimp
       
  3211 */
       
  3212 void QGraphicsView::wheelEvent(QWheelEvent *event)
       
  3213 {
       
  3214     Q_D(QGraphicsView);
       
  3215     if (!d->scene || !d->sceneInteractionAllowed) {
       
  3216         QAbstractScrollArea::wheelEvent(event);
       
  3217         return;
       
  3218     }
       
  3219 
       
  3220     event->ignore();
       
  3221 
       
  3222     QGraphicsSceneWheelEvent wheelEvent(QEvent::GraphicsSceneWheel);
       
  3223     wheelEvent.setWidget(viewport());
       
  3224     wheelEvent.setScenePos(mapToScene(event->pos()));
       
  3225     wheelEvent.setScreenPos(event->globalPos());
       
  3226     wheelEvent.setButtons(event->buttons());
       
  3227     wheelEvent.setModifiers(event->modifiers());
       
  3228     wheelEvent.setDelta(event->delta());
       
  3229     wheelEvent.setOrientation(event->orientation());
       
  3230     wheelEvent.setAccepted(false);
       
  3231     QApplication::sendEvent(d->scene, &wheelEvent);
       
  3232     event->setAccepted(wheelEvent.isAccepted());
       
  3233     if (!event->isAccepted())
       
  3234         QAbstractScrollArea::wheelEvent(event);
       
  3235 }
       
  3236 #endif // QT_NO_WHEELEVENT
       
  3237 
       
  3238 /*!
       
  3239     \reimp
       
  3240 */
       
  3241 void QGraphicsView::paintEvent(QPaintEvent *event)
       
  3242 {
       
  3243     Q_D(QGraphicsView);
       
  3244     if (!d->scene) {
       
  3245         QAbstractScrollArea::paintEvent(event);
       
  3246         return;
       
  3247     }
       
  3248 
       
  3249     // Set up painter state protection.
       
  3250     d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
       
  3251 
       
  3252     // Determine the exposed region
       
  3253     d->exposedRegion = event->region();
       
  3254     QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
       
  3255 
       
  3256     // Set up the painter
       
  3257     QPainter painter(viewport());
       
  3258 #ifndef QT_NO_RUBBERBAND
       
  3259     if (d->rubberBanding && !d->rubberBandRect.isEmpty())
       
  3260         painter.save();
       
  3261 #endif
       
  3262     // Set up render hints
       
  3263     painter.setRenderHints(painter.renderHints(), false);
       
  3264     painter.setRenderHints(d->renderHints, true);
       
  3265 
       
  3266     // Set up viewport transform
       
  3267     const bool viewTransformed = isTransformed();
       
  3268     if (viewTransformed)
       
  3269         painter.setWorldTransform(viewportTransform());
       
  3270     const QTransform viewTransform = painter.worldTransform();
       
  3271 
       
  3272     // Draw background
       
  3273     if ((d->cacheMode & CacheBackground)
       
  3274 #ifdef Q_WS_X11
       
  3275         && X11->use_xrender
       
  3276 #endif
       
  3277         ) {
       
  3278         // Recreate the background pixmap, and flag the whole background as
       
  3279         // exposed.
       
  3280         if (d->mustResizeBackgroundPixmap) {
       
  3281             d->backgroundPixmap = QPixmap(viewport()->size());
       
  3282             QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
       
  3283             if (!bgBrush.isOpaque())
       
  3284                 d->backgroundPixmap.fill(Qt::transparent);
       
  3285             QPainter p(&d->backgroundPixmap);
       
  3286             p.fillRect(0, 0, d->backgroundPixmap.width(), d->backgroundPixmap.height(), bgBrush);
       
  3287             d->backgroundPixmapExposed = QRegion(viewport()->rect());
       
  3288             d->mustResizeBackgroundPixmap = false;
       
  3289         }
       
  3290 
       
  3291         // Redraw exposed areas
       
  3292         if (!d->backgroundPixmapExposed.isEmpty()) {
       
  3293             QPainter backgroundPainter(&d->backgroundPixmap);
       
  3294             backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
       
  3295             if (viewTransformed)
       
  3296                 backgroundPainter.setTransform(viewTransform);
       
  3297             backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
       
  3298             drawBackground(&backgroundPainter, exposedSceneRect);
       
  3299             d->backgroundPixmapExposed = QRegion();
       
  3300         }
       
  3301 
       
  3302         // Blit the background from the background pixmap
       
  3303         if (viewTransformed) {
       
  3304             painter.setWorldTransform(QTransform());
       
  3305             painter.drawPixmap(QPoint(), d->backgroundPixmap);
       
  3306             painter.setWorldTransform(viewTransform);
       
  3307         } else {
       
  3308             painter.drawPixmap(QPoint(), d->backgroundPixmap);
       
  3309         }
       
  3310     } else {
       
  3311         if (!(d->optimizationFlags & DontSavePainterState))
       
  3312             painter.save();
       
  3313         drawBackground(&painter, exposedSceneRect);
       
  3314         if (!(d->optimizationFlags & DontSavePainterState))
       
  3315             painter.restore();
       
  3316     }
       
  3317 
       
  3318     // Items
       
  3319     if (!(d->optimizationFlags & IndirectPainting)) {
       
  3320         d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
       
  3321                                       &d->exposedRegion, viewport());
       
  3322     } else {
       
  3323         // Find all exposed items
       
  3324         bool allItems = false;
       
  3325         QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
       
  3326         if (!itemList.isEmpty()) {
       
  3327             // Generate the style options.
       
  3328             const int numItems = itemList.size();
       
  3329             QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
       
  3330             QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
       
  3331             for (int i = 0; i < numItems; ++i) {
       
  3332                 itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform,
       
  3333                                                      d->exposedRegion, allItems);
       
  3334             }
       
  3335             // Draw the items.
       
  3336             drawItems(&painter, numItems, itemArray, styleOptionArray);
       
  3337             d->freeStyleOptionsArray(styleOptionArray);
       
  3338         }
       
  3339     }
       
  3340 
       
  3341     // Foreground
       
  3342     drawForeground(&painter, exposedSceneRect);
       
  3343 
       
  3344 #ifndef QT_NO_RUBBERBAND
       
  3345     // Rubberband
       
  3346     if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
       
  3347         painter.restore();
       
  3348         QStyleOptionRubberBand option;
       
  3349         option.initFrom(viewport());
       
  3350         option.rect = d->rubberBandRect;
       
  3351         option.shape = QRubberBand::Rectangle;
       
  3352 
       
  3353         QStyleHintReturnMask mask;
       
  3354         if (viewport()->style()->styleHint(QStyle::SH_RubberBand_Mask, &option, viewport(), &mask)) {
       
  3355             // painter clipping for masked rubberbands
       
  3356             painter.setClipRegion(mask.region, Qt::IntersectClip);
       
  3357         }
       
  3358 
       
  3359         viewport()->style()->drawControl(QStyle::CE_RubberBand, &option, &painter, viewport());
       
  3360     }
       
  3361 #endif
       
  3362 
       
  3363     painter.end();
       
  3364 
       
  3365     // Restore painter state protection.
       
  3366     d->scene->d_func()->painterStateProtection = true;
       
  3367 }
       
  3368 
       
  3369 /*!
       
  3370     \reimp
       
  3371 */
       
  3372 void QGraphicsView::resizeEvent(QResizeEvent *event)
       
  3373 {
       
  3374     Q_D(QGraphicsView);
       
  3375     // Save the last center point - the resize may scroll the view, which
       
  3376     // changes the center point.
       
  3377     QPointF oldLastCenterPoint = d->lastCenterPoint;
       
  3378 
       
  3379     QAbstractScrollArea::resizeEvent(event);
       
  3380     d->recalculateContentSize();
       
  3381 
       
  3382     // Restore the center point again.
       
  3383     if (d->resizeAnchor == NoAnchor && !d->keepLastCenterPoint) {
       
  3384         d->updateLastCenterPoint();
       
  3385     } else {
       
  3386         d->lastCenterPoint = oldLastCenterPoint;
       
  3387     }
       
  3388     d->centerView(d->resizeAnchor);
       
  3389     d->keepLastCenterPoint = false;
       
  3390 
       
  3391     if (d->cacheMode & CacheBackground) {
       
  3392         // Invalidate the background pixmap
       
  3393         d->mustResizeBackgroundPixmap = true;
       
  3394     }
       
  3395 }
       
  3396 
       
  3397 /*!
       
  3398     \reimp
       
  3399 */
       
  3400 void QGraphicsView::scrollContentsBy(int dx, int dy)
       
  3401 {
       
  3402     Q_D(QGraphicsView);
       
  3403     d->dirtyScroll = true;
       
  3404     if (d->transforming)
       
  3405         return;
       
  3406     if (isRightToLeft())
       
  3407         dx = -dx;
       
  3408 
       
  3409     if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
       
  3410         if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
       
  3411             if (d->accelerateScrolling) {
       
  3412 #ifndef QT_NO_RUBBERBAND
       
  3413                 // Update new and old rubberband regions
       
  3414                 if (!d->rubberBandRect.isEmpty()) {
       
  3415                     QRegion rubberBandRegion(d->rubberBandRegion(viewport(), d->rubberBandRect));
       
  3416                     rubberBandRegion += rubberBandRegion.translated(-dx, -dy);
       
  3417                     viewport()->update(rubberBandRegion);
       
  3418                 }
       
  3419 #endif
       
  3420                 d->dirtyScrollOffset.rx() += dx;
       
  3421                 d->dirtyScrollOffset.ry() += dy;
       
  3422                 d->dirtyRegion.translate(dx, dy);
       
  3423                 viewport()->scroll(dx, dy);
       
  3424             } else {
       
  3425                 d->updateAll();
       
  3426             }
       
  3427         } else {
       
  3428             d->updateAll();
       
  3429         }
       
  3430     }
       
  3431 
       
  3432     d->updateLastCenterPoint();
       
  3433 
       
  3434     if ((d->cacheMode & CacheBackground)
       
  3435 #ifdef Q_WS_X11
       
  3436         && X11->use_xrender
       
  3437 #endif
       
  3438         ) {
       
  3439         // Scroll the background pixmap
       
  3440         QRegion exposed;
       
  3441         if (!d->backgroundPixmap.isNull())
       
  3442             d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
       
  3443 
       
  3444         // Invalidate the background pixmap
       
  3445         d->backgroundPixmapExposed.translate(dx, dy);
       
  3446         d->backgroundPixmapExposed += exposed;
       
  3447     }
       
  3448 
       
  3449     // Always replay on scroll.
       
  3450     if (d->sceneInteractionAllowed)
       
  3451         d->replayLastMouseEvent();
       
  3452 }
       
  3453 
       
  3454 /*!
       
  3455     \reimp
       
  3456 */
       
  3457 void QGraphicsView::showEvent(QShowEvent *event)
       
  3458 {
       
  3459     Q_D(QGraphicsView);
       
  3460     d->recalculateContentSize();
       
  3461     d->centerView(d->transformationAnchor);
       
  3462     QAbstractScrollArea::showEvent(event);
       
  3463 }
       
  3464 
       
  3465 /*!
       
  3466     \reimp
       
  3467 */
       
  3468 void QGraphicsView::inputMethodEvent(QInputMethodEvent *event)
       
  3469 {
       
  3470     Q_D(QGraphicsView);
       
  3471     if (d->scene)
       
  3472         QApplication::sendEvent(d->scene, event);
       
  3473 }
       
  3474 
       
  3475 /*!
       
  3476     Draws the background of the scene using \a painter, before any items and
       
  3477     the foreground are drawn. Reimplement this function to provide a custom
       
  3478     background for this view.
       
  3479 
       
  3480     If all you want is to define a color, texture or gradient for the
       
  3481     background, you can call setBackgroundBrush() instead.
       
  3482 
       
  3483     All painting is done in \e scene coordinates. \a rect is the exposed
       
  3484     rectangle.
       
  3485 
       
  3486     The default implementation fills \a rect using the view's backgroundBrush.
       
  3487     If no such brush is defined (the default), the scene's drawBackground()
       
  3488     function is called instead.
       
  3489 
       
  3490     \sa drawForeground(), QGraphicsScene::drawBackground()
       
  3491 */
       
  3492 void QGraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
       
  3493 {
       
  3494     Q_D(QGraphicsView);
       
  3495     if (d->scene && d->backgroundBrush.style() == Qt::NoBrush) {
       
  3496         d->scene->drawBackground(painter, rect);
       
  3497         return;
       
  3498     }
       
  3499 
       
  3500     painter->fillRect(rect, d->backgroundBrush);
       
  3501 }
       
  3502 
       
  3503 /*!
       
  3504     Draws the foreground of the scene using \a painter, after the background
       
  3505     and all items are drawn. Reimplement this function to provide a custom
       
  3506     foreground for this view.
       
  3507 
       
  3508     If all you want is to define a color, texture or gradient for the
       
  3509     foreground, you can call setForegroundBrush() instead.
       
  3510 
       
  3511     All painting is done in \e scene coordinates. \a rect is the exposed
       
  3512     rectangle.
       
  3513 
       
  3514     The default implementation fills \a rect using the view's foregroundBrush.
       
  3515     If no such brush is defined (the default), the scene's drawForeground()
       
  3516     function is called instead.
       
  3517 
       
  3518     \sa drawBackground(), QGraphicsScene::drawForeground()
       
  3519 */
       
  3520 void QGraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
       
  3521 {
       
  3522     Q_D(QGraphicsView);
       
  3523     if (d->scene && d->foregroundBrush.style() == Qt::NoBrush) {
       
  3524         d->scene->drawForeground(painter, rect);
       
  3525         return;
       
  3526     }
       
  3527 
       
  3528     painter->fillRect(rect, d->foregroundBrush);
       
  3529 }
       
  3530 
       
  3531 /*!
       
  3532     Draws the items \a items in the scene using \a painter, after the
       
  3533     background and before the foreground are drawn. \a numItems is the number
       
  3534     of items in \a items and options in \a options. \a options is a list of
       
  3535     styleoptions; one for each item. Reimplement this function to provide
       
  3536     custom item drawing for this view.
       
  3537 
       
  3538     The default implementation calls the scene's drawItems() function.
       
  3539 
       
  3540     \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems()
       
  3541 */
       
  3542 void QGraphicsView::drawItems(QPainter *painter, int numItems,
       
  3543                               QGraphicsItem *items[],
       
  3544                               const QStyleOptionGraphicsItem options[])
       
  3545 {
       
  3546     Q_D(QGraphicsView);
       
  3547     if (d->scene) {
       
  3548         QWidget *widget = painter->device() == viewport() ? viewport() : 0;
       
  3549         d->scene->drawItems(painter, numItems, items, options, widget);
       
  3550     }
       
  3551 }
       
  3552 
       
  3553 /*!
       
  3554     Returns the current transformation matrix for the view. If no current
       
  3555     transformation is set, the identity matrix is returned.
       
  3556 
       
  3557     \sa setTransform(), rotate(), scale(), shear(), translate()
       
  3558 */
       
  3559 QTransform QGraphicsView::transform() const
       
  3560 {
       
  3561     Q_D(const QGraphicsView);
       
  3562     return d->matrix;
       
  3563 }
       
  3564 
       
  3565 /*!
       
  3566     Returns a matrix that maps viewport coordinates to scene coordinates.
       
  3567 
       
  3568     \sa mapToScene(), mapFromScene()
       
  3569 */
       
  3570 QTransform QGraphicsView::viewportTransform() const
       
  3571 {
       
  3572     Q_D(const QGraphicsView);
       
  3573     QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
       
  3574     return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
       
  3575 }
       
  3576 
       
  3577 /*!
       
  3578     \since 4.6
       
  3579 
       
  3580     Returns true if the view is transformed (i.e., a non-identity transform
       
  3581     has been assigned, or the scrollbars are adjusted).
       
  3582 
       
  3583     \sa setTransform(), horizontalScrollBar(), verticalScrollBar()
       
  3584 */
       
  3585 bool QGraphicsView::isTransformed() const
       
  3586 {
       
  3587     Q_D(const QGraphicsView);
       
  3588     return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
       
  3589 }
       
  3590 
       
  3591 /*!
       
  3592     Sets the view's current transformation matrix to \a matrix.
       
  3593 
       
  3594     If \a combine is true, then \a matrix is combined with the current matrix;
       
  3595     otherwise, \a matrix \e replaces the current matrix. \a combine is false
       
  3596     by default.
       
  3597 
       
  3598     The transformation matrix tranforms the scene into view coordinates. Using
       
  3599     the default transformation, provided by the identity matrix, one pixel in
       
  3600     the view represents one unit in the scene (e.g., a 10x10 rectangular item
       
  3601     is drawn using 10x10 pixels in the view). If a 2x2 scaling matrix is
       
  3602     applied, the scene will be drawn in 1:2 (e.g., a 10x10 rectangular item is
       
  3603     then drawn using 20x20 pixels in the view).
       
  3604 
       
  3605     Example:
       
  3606 
       
  3607     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 7
       
  3608 
       
  3609     To simplify interation with items using a transformed view, QGraphicsView
       
  3610     provides mapTo... and mapFrom... functions that can translate between
       
  3611     scene and view coordinates. For example, you can call mapToScene() to map
       
  3612     a view coordiate to a floating point scene coordinate, or mapFromScene()
       
  3613     to map from floating point scene coordinates to view coordinates.
       
  3614 
       
  3615     \sa transform(), rotate(), scale(), shear(), translate()
       
  3616 */
       
  3617 void QGraphicsView::setTransform(const QTransform &matrix, bool combine )
       
  3618 {
       
  3619     Q_D(QGraphicsView);
       
  3620     QTransform oldMatrix = d->matrix;
       
  3621     if (!combine)
       
  3622         d->matrix = matrix;
       
  3623     else
       
  3624         d->matrix = matrix * d->matrix;
       
  3625     if (oldMatrix == d->matrix)
       
  3626         return;
       
  3627 
       
  3628     d->identityMatrix = d->matrix.isIdentity();
       
  3629     d->transforming = true;
       
  3630     if (d->scene) {
       
  3631         d->recalculateContentSize();
       
  3632         d->centerView(d->transformationAnchor);
       
  3633     } else {
       
  3634         d->updateLastCenterPoint();
       
  3635     }
       
  3636 
       
  3637     if (d->sceneInteractionAllowed)
       
  3638         d->replayLastMouseEvent();
       
  3639     d->transforming = false;
       
  3640 
       
  3641     // Any matrix operation requires a full update.
       
  3642     d->updateAll();
       
  3643 }
       
  3644 
       
  3645 /*!
       
  3646     Resets the view transformation to the identity matrix.
       
  3647 
       
  3648     \sa transform(), setTransform()
       
  3649 */
       
  3650 void QGraphicsView::resetTransform()
       
  3651 {
       
  3652     setTransform(QTransform());
       
  3653 }
       
  3654 
       
  3655 QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const
       
  3656 {
       
  3657     QPointF p = point;
       
  3658     p.rx() += horizontalScroll();
       
  3659     p.ry() += verticalScroll();
       
  3660     return identityMatrix ? p : matrix.inverted().map(p);
       
  3661 }
       
  3662 
       
  3663 QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const
       
  3664 {
       
  3665     QPointF scrollOffset(horizontalScroll(), verticalScroll());
       
  3666     QPointF tl = scrollOffset + rect.topLeft();
       
  3667     QPointF tr = scrollOffset + rect.topRight();
       
  3668     QPointF br = scrollOffset + rect.bottomRight();
       
  3669     QPointF bl = scrollOffset + rect.bottomLeft();
       
  3670 
       
  3671     QPolygonF poly(4);
       
  3672     if (!identityMatrix) {
       
  3673         QTransform x = matrix.inverted();
       
  3674         poly[0] = x.map(tl);
       
  3675         poly[1] = x.map(tr);
       
  3676         poly[2] = x.map(br);
       
  3677         poly[3] = x.map(bl);
       
  3678     } else {
       
  3679         poly[0] = tl;
       
  3680         poly[1] = tr;
       
  3681         poly[2] = br;
       
  3682         poly[3] = bl;
       
  3683     }
       
  3684     return poly.boundingRect();
       
  3685 }
       
  3686 
       
  3687 QT_END_NAMESPACE
       
  3688 
       
  3689 #include "moc_qgraphicsview.cpp"
       
  3690 
       
  3691 #endif // QT_NO_GRAPHICSVIEW