summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsview.cpp
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-06-30 09:21:56 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-06-30 09:21:56 (GMT)
commit197df24edfe095a10e2bf65116796e027fea44e2 (patch)
tree4ffb08f614b550298663f90297c9e559ecb47a3c /src/gui/graphicsview/qgraphicsview.cpp
parent1e84894225e31adf80a7a33da7f655fb5c38ea0e (diff)
parente3c1039d4d10aa383a1f681e7dd9c1129d22d8ca (diff)
downloadQt-197df24edfe095a10e2bf65116796e027fea44e2.zip
Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.gz
Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.bz2
Merge commit 'qt/master-stable' into 4.6-merged
Conflicts: .gitignore configure.exe src/corelib/concurrent/qtconcurrentthreadengine.h src/corelib/global/qnamespace.h src/gui/graphicsview/qgraphicssceneevent.h src/gui/kernel/qapplication.cpp src/gui/kernel/qapplication.h src/gui/kernel/qapplication_p.h src/gui/kernel/qapplication_qws.cpp src/gui/kernel/qwidget.h src/gui/painting/qpaintengine_raster.cpp src/gui/text/qfontdatabase.cpp src/network/access/qnetworkaccesshttpbackend.cpp tests/auto/network-settings.h tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro tests/auto/qvariant/tst_qvariant.cpp
Diffstat (limited to 'src/gui/graphicsview/qgraphicsview.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp207
1 files changed, 161 insertions, 46 deletions
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index a3e2ebe..58bbdda 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
+** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
@@ -34,7 +34,7 @@
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
+** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -284,8 +284,12 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
#include <private/qt_x11_p.h>
#endif
+#include <private/qevent_p.h>
+
QT_BEGIN_NAMESPACE
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+
inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision
{
if (d <= (qreal) INT_MIN)
@@ -295,6 +299,23 @@ inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for sing
return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1);
}
+void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
+{
+ QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
+ for (int i = 0; i < touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
+ // the scene will set the item local pos, startPos, lastPos, and rect before delivering to
+ // an item, but for now those functions are returning the view's local coordinates
+ touchPoint.setSceneRect(d->mapToScene(touchPoint.rect()));
+ touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos()));
+ touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos()));
+
+ // screenPos, startScreenPos, lastScreenPos, and screenRect are already set
+ }
+
+ touchEvent->setTouchPoints(touchPoints);
+}
+
/*!
\internal
*/
@@ -591,7 +612,10 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
lastMouseMoveScenePoint = mouseEvent.scenePos();
lastMouseMoveScreenPoint = mouseEvent.screenPos();
mouseEvent.setAccepted(false);
- QApplication::sendEvent(scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(scene, &mouseEvent);
+ else
+ QApplication::sendEvent(scene, &mouseEvent);
// Remember whether the last event was accepted or not.
lastMouseEvent.setAccepted(mouseEvent.isAccepted());
@@ -825,19 +849,22 @@ void QGraphicsViewPrivate::processPendingUpdates()
dirtyRegion = QRegion();
}
-void QGraphicsViewPrivate::updateRegion(const QRegion &r)
+bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
- if (r.isEmpty() || fullUpdatePending)
- return;
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
+ return false;
+
+ const QRect boundingRect = r.boundingRect();
+ if (!boundingRect.intersects(viewport->rect()))
+ return false; // Update region outside viewport.
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
+ dirtyBoundingRect |= boundingRect;
if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
viewport->update();
@@ -855,18 +882,20 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r)
}
break;
}
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ default:
break;
}
+
+ return true;
}
-void QGraphicsViewPrivate::updateRect(const QRect &r)
+bool QGraphicsViewPrivate::updateRect(const QRect &r)
{
- if (r.isEmpty() || fullUpdatePending)
- return;
+ if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
+ || !r.intersects(viewport->rect())) {
+ return false;
+ }
- // Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
@@ -886,10 +915,11 @@ void QGraphicsViewPrivate::updateRect(const QRect &r)
else
dirtyRegion += r.adjusted(-2, -2, 2, 2);
break;
- case QGraphicsView::NoViewportUpdate:
- // Unreachable
+ default:
break;
}
+
+ return true;
}
QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems)
@@ -1497,7 +1527,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
this, SLOT(updateScene(QList<QRectF>)));
disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
this, SLOT(updateSceneRect(QRectF)));
- d->scene->d_func()->views.removeAll(this);
+ d->scene->d_func()->removeView(this);
d->connectedToScene = false;
}
@@ -1506,7 +1536,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
connect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
this, SLOT(updateSceneRect(QRectF)));
d->updateSceneSlotReimplementedChecked = false;
- d->scene->d_func()->views << this;
+ d->scene->d_func()->addView(this);
d->recalculateContentSize();
d->lastCenterPoint = sceneRect().center();
d->keepLastCenterPoint = true;
@@ -1516,6 +1546,10 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
|| !d->scene->d_func()->allItemsUseDefaultCursor) {
d->viewport->setMouseTracking(true);
}
+
+ // enable touch events if any items is interested in them
+ if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
+ d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
} else {
d->recalculateContentSize();
}
@@ -1949,8 +1983,7 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect
itemList.clear();
// Setup painter matrix.
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
+ QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
QTransform painterMatrix = d->matrix * moveMatrix;
painterMatrix *= QTransform()
.translate(targetRect.left(), targetRect.top())
@@ -2301,9 +2334,9 @@ QPolygonF QGraphicsView::mapToScene(const QPolygon &polygon) const
QPainterPath QGraphicsView::mapToScene(const QPainterPath &path) const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(d->horizontalScroll(), d->verticalScroll());
- return (moveMatrix * d->matrix.inverted()).map(path);
+ QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
+ matrix *= d->matrix.inverted();
+ return matrix.map(path);
}
/*!
@@ -2397,9 +2430,9 @@ QPolygon QGraphicsView::mapFromScene(const QPolygonF &polygon) const
QPainterPath QGraphicsView::mapFromScene(const QPainterPath &path) const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
- return (d->matrix * moveMatrix).map(path);
+ QTransform matrix = d->matrix;
+ matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
+ return matrix.map(path);
}
/*!
@@ -2599,6 +2632,11 @@ void QGraphicsView::setupViewport(QWidget *widget)
|| !d->scene->d_func()->allItemsUseDefaultCursor)) {
widget->setMouseTracking(true);
}
+
+ // enable touch events if any items is interested in them
+ if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
+ widget->setAttribute(Qt::WA_AcceptTouchEvents);
+
widget->setAcceptDrops(acceptDrops());
}
@@ -2635,6 +2673,9 @@ bool QGraphicsView::event(QEvent *event)
}
}
break;
+ case QEvent::Gesture:
+ viewportEvent(event);
+ return true;
default:
break;
}
@@ -2716,6 +2757,34 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->updateAll = false;
}
break;
+ case QEvent::Gesture: {
+ QGraphicsSceneGestureEvent gestureEvent;
+ gestureEvent.setWidget(this);
+ QGestureEvent *ev = static_cast<QGestureEvent*>(event);
+ gestureEvent.setGestures(ev->gestures());
+ gestureEvent.setCancelledGestures(ev->cancelledGestures());
+ QApplication::sendEvent(d->scene, &gestureEvent);
+ event->setAccepted(gestureEvent.isAccepted());
+ return true;
+ }
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ if (!isEnabled())
+ return false;
+
+ if (d->scene && d->sceneInteractionAllowed) {
+ // Convert and deliver the touch event to the scene.
+ QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
+ touchEvent->setWidget(viewport());
+ QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
+ (void) QApplication::sendEvent(d->scene, touchEvent);
+ }
+
+ return true;
+ }
default:
break;
}
@@ -2974,7 +3043,10 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
mouseEvent.setAccepted(false);
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
}
/*!
@@ -3013,7 +3085,10 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event)
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
mouseEvent.setAccepted(false);
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
// Update the original mouse event accepted state.
bool isAccepted = mouseEvent.isAccepted();
@@ -3183,7 +3258,10 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
mouseEvent.setButton(event->button());
mouseEvent.setModifiers(event->modifiers());
mouseEvent.setAccepted(false);
- QApplication::sendEvent(d->scene, &mouseEvent);
+ if (event->spontaneous())
+ qt_sendSpontaneousEvent(d->scene, &mouseEvent);
+ else
+ QApplication::sendEvent(d->scene, &mouseEvent);
// Update the last mouse event selected state.
d->lastMouseEvent.setAccepted(mouseEvent.isAccepted());
@@ -3242,10 +3320,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Determine the exposed region
d->exposedRegion = event->region();
- if (!d->accelerateScrolling)
- d->exposedRegion = viewport()->rect();
- else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
- d->exposedRegion = event->rect();
QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
@@ -3259,8 +3333,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.setRenderHints(d->renderHints, true);
// Set up viewport transform
- const QTransform viewTransform = viewportTransform();
- painter.setWorldTransform(viewTransform);
+ const bool viewTransformed = isTransformed();
+ if (viewTransformed)
+ painter.setWorldTransform(viewportTransform());
+ const QTransform viewTransform = painter.worldTransform();
// Draw background
if ((d->cacheMode & CacheBackground)
@@ -3285,16 +3361,21 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
if (!d->backgroundPixmapExposed.isEmpty()) {
QPainter backgroundPainter(&d->backgroundPixmap);
backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
- backgroundPainter.setTransform(viewportTransform());
+ if (viewTransformed)
+ backgroundPainter.setTransform(viewTransform);
backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
drawBackground(&backgroundPainter, exposedSceneRect);
d->backgroundPixmapExposed = QRegion();
}
// Blit the background from the background pixmap
- painter.setWorldTransform(QTransform());
- painter.drawPixmap(QPoint(), d->backgroundPixmap);
- painter.setWorldTransform(viewTransform);
+ if (viewTransformed) {
+ painter.setWorldTransform(QTransform());
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ painter.setWorldTransform(viewTransform);
+ } else {
+ painter.drawPixmap(QPoint(), d->backgroundPixmap);
+ }
} else {
if (!(d->optimizationFlags & DontSavePainterState))
painter.save();
@@ -3305,20 +3386,22 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Items
if (!(d->optimizationFlags & IndirectPainting)) {
- d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion,
- viewport(), 0);
+ d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
+ &d->exposedRegion, viewport());
} else {
// Find all exposed items
bool allItems = false;
QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems);
-
+
if (!itemList.isEmpty()) {
// Generate the style options.
const int numItems = itemList.size();
QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- for (int i = 0; i < numItems; ++i)
- itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
+ for (int i = 0; i < numItems; ++i) {
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform,
+ d->exposedRegion, allItems);
+ }
// Draw the items.
drawItems(&painter, numItems, itemArray, styleOptionArray);
d->freeStyleOptionsArray(styleOptionArray);
@@ -3557,8 +3640,7 @@ QTransform QGraphicsView::transform() const
QTransform QGraphicsView::viewportTransform() const
{
Q_D(const QGraphicsView);
- QTransform moveMatrix;
- moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
+ QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
}
@@ -3638,6 +3720,39 @@ void QGraphicsView::resetTransform()
setTransform(QTransform());
}
+QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const
+{
+ QPointF p = point;
+ p.rx() += horizontalScroll();
+ p.ry() += verticalScroll();
+ return identityMatrix ? p : matrix.inverted().map(p);
+}
+
+QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const
+{
+ QPointF scrollOffset(horizontalScroll(), verticalScroll());
+ QPointF tl = scrollOffset + rect.topLeft();
+ QPointF tr = scrollOffset + rect.topRight();
+ QPointF br = scrollOffset + rect.bottomRight();
+ QPointF bl = scrollOffset + rect.bottomLeft();
+
+ QPolygonF poly;
+ poly.resize(4);
+ if (!identityMatrix) {
+ QTransform x = matrix.inverted();
+ poly[0] = x.map(tl);
+ poly[1] = x.map(tr);
+ poly[2] = x.map(br);
+ poly[3] = x.map(bl);
+ } else {
+ poly[0] = tl;
+ poly[1] = tr;
+ poly[2] = br;
+ poly[3] = bl;
+ }
+ return poly.boundingRect();
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsview.cpp"