src/declarative/graphicsitems/qdeclarativeflickable.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp	Tue Jul 06 15:10:48 2010 +0300
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp	Wed Aug 18 10:37:55 2010 +0300
@@ -122,7 +122,7 @@
 
 
 QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate()
-  : viewport(new QDeclarativeItem)
+  : contentItem(new QDeclarativeItem)
     , hData(this, &QDeclarativeFlickablePrivate::setRoundedViewportX)
     , vData(this, &QDeclarativeFlickablePrivate::setRoundedViewportY)
     , flickingHorizontally(false), flickingVertically(false)
@@ -140,8 +140,8 @@
 void QDeclarativeFlickablePrivate::init()
 {
     Q_Q(QDeclarativeFlickable);
-    QDeclarative_setParent_noEvent(viewport, q);
-    viewport->setParentItem(q);
+    QDeclarative_setParent_noEvent(contentItem, q);
+    contentItem->setParentItem(q);
     static int timelineUpdatedIdx = -1;
     static int timelineCompletedIdx = -1;
     static int flickableTickedIdx = -1;
@@ -158,8 +158,9 @@
                          q, flickableMovementEndingIdx, Qt::DirectConnection);
     q->setAcceptedMouseButtons(Qt::LeftButton);
     q->setFiltersChildEvents(true);
-    QDeclarativeItemPrivate *viewportPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(viewport));
+    QDeclarativeItemPrivate *viewportPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(contentItem));
     viewportPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
+    lastPosTime.invalidate();
 }
 
 /*
@@ -181,7 +182,7 @@
 void QDeclarativeFlickablePrivate::itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeom, const QRectF &oldGeom)
 {
     Q_Q(QDeclarativeFlickable);
-    if (item == viewport) {
+    if (item == contentItem) {
         if (newGeom.x() != oldGeom.x())
             emit q->contentXChanged();
         if (newGeom.y() != oldGeom.y())
@@ -350,6 +351,8 @@
     Flickable places its children on a surface that can be dragged and flicked.
 
     \code
+    import Qt 4.7
+
     Flickable {
         width: 200; height: 200
         contentWidth: image.width; contentHeight: image.height
@@ -576,10 +579,28 @@
     viewportMoved();
 }
 
-QDeclarativeItem *QDeclarativeFlickable::viewport()
+/*!
+    \qmlproperty Item Flickable::contentItem
+
+    The internal item that contains the Items to be moved in the Flickable.
+
+    Items declared as children of a Flickable are automatically parented to the Flickable's contentItem.
+
+    Items created dynamically need to be explicitly parented to the \e contentItem:
+    \code
+    Flickable {
+        id: myFlickable
+        function addItem(file) {
+            var component = Qt.createComponent(file)
+            component.createObject(myFlickable.contentItem);
+        }
+    }
+    \endcode
+*/
+QDeclarativeItem *QDeclarativeFlickable::contentItem()
 {
     Q_D(QDeclarativeFlickable);
-    return d->viewport;
+    return d->contentItem;
 }
 
 QDeclarativeFlickableVisibleArea *QDeclarativeFlickable::visibleArea()
@@ -620,18 +641,6 @@
     }
 }
 
-QDeclarativeFlickable::FlickableDirection QDeclarativeFlickable::flickDirection() const
-{
-    qmlInfo(this) << "'flickDirection' is deprecated. Please use 'flickableDirection' instead.";
-    return flickableDirection();
-}
-
-void QDeclarativeFlickable::setFlickDirection(FlickableDirection direction)
-{
-    qmlInfo(this) << "'flickDirection' is deprecated. Please use 'flickableDirection' instead.";
-    setFlickableDirection(direction);
-}
-
 void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event)
 {
     if (interactive && timeline.isActive() && (qAbs(hData.velocity) > 10 || qAbs(vData.velocity) > 10))
@@ -656,7 +665,7 @@
 void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
 {
     Q_Q(QDeclarativeFlickable);
-    if (!interactive || lastPosTime.isNull())
+    if (!interactive || !lastPosTime.isValid())
         return;
     bool rejectY = false;
     bool rejectX = false;
@@ -752,7 +761,7 @@
     stealMouse = false;
     q->setKeepMouseGrab(false);
     pressed = false;
-    if (lastPosTime.isNull())
+    if (!lastPosTime.isValid())
         return;
 
     if (QDeclarativeItemPrivate::elapsed(lastPosTime) > 100) {
@@ -780,7 +789,7 @@
         fixupX();
     }
 
-    lastPosTime = QTime();
+    lastPosTime.invalidate();
 
     if (!timeline.isActive())
         q->movementEnding();
@@ -896,12 +905,12 @@
 
 void QDeclarativeFlickablePrivate::setRoundedViewportX(qreal x)
 {
-    viewport->setX(qRound(x));
+    contentItem->setX(qRound(x));
 }
 
 void QDeclarativeFlickablePrivate::setRoundedViewportY(qreal y)
 {
-    viewport->setY(qRound(y));
+    contentItem->setY(qRound(y));
 }
 
 void QDeclarativeFlickable::timerEvent(QTimerEvent *event)
@@ -911,8 +920,14 @@
         d->delayedPressTimer.stop();
         if (d->delayedPressEvent) {
             QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0;
-            if (!grabber || grabber != this)
-                scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+            if (!grabber || grabber != this) {
+                // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+                // so we reset the grabber
+                if (scene()->mouseGrabberItem() == d->delayedPressTarget)
+                    d->delayedPressTarget->ungrabMouse();
+                //Use the event handler that will take care of finding the proper item to propagate the event
+                QApplication::sendEvent(scene(), d->delayedPressEvent);
+            }
             delete d->delayedPressEvent;
             d->delayedPressEvent = 0;
         }
@@ -944,20 +959,19 @@
 {
     Q_D(QDeclarativeFlickable);
 
-    int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime);
-    if (!elapsed)
-        return;
-
     qreal prevY = d->lastFlickablePosition.x();
     qreal prevX = d->lastFlickablePosition.y();
     d->velocityTimeline.clear();
     if (d->pressed) {
-        qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
-        qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
-        d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
-        d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
-        d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
-        d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+        int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime);
+        if (elapsed > 0) {
+            qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed;
+            qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / elapsed;
+            d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing);
+            d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+            d->velocityTimeline.move(d->vData.smoothVelocity, verticalVelocity, d->reportedVelocitySmoothing);
+            d->velocityTimeline.move(d->vData.smoothVelocity, 0, d->reportedVelocitySmoothing);
+        }
     } else {
         if (d->timeline.time() > d->vTime) {
             qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime);
@@ -982,13 +996,13 @@
     bool changed = false;
     if (newGeometry.width() != oldGeometry.width()) {
         if (d->hData.viewSize < 0) {
-            d->viewport->setWidth(width());
+            d->contentItem->setWidth(width());
             emit contentWidthChanged();
         }
     }
     if (newGeometry.height() != oldGeometry.height()) {
         if (d->vData.viewSize < 0) {
-            d->viewport->setHeight(height());
+            d->contentItem->setHeight(height());
             emit contentHeightChanged();
         }
     }
@@ -1009,7 +1023,7 @@
 {
     QDeclarativeItem *i = qobject_cast<QDeclarativeItem *>(o);
     if (i)
-        i->setParentItem(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->viewport);
+        i->setParentItem(static_cast<QDeclarativeFlickablePrivate*>(prop->data)->contentItem);
     else
         o->setParent(prop->object);
 }
@@ -1023,25 +1037,7 @@
 QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren()
 {
     Q_D(QDeclarativeFlickable);
-    return QGraphicsItemPrivate::get(d->viewport)->childrenList();
-}
-
-bool QDeclarativeFlickable::overShoot() const
-{
-    Q_D(const QDeclarativeFlickable);
-    return d->boundsBehavior == DragAndOvershootBounds;
-}
-
-void QDeclarativeFlickable::setOverShoot(bool o)
-{
-    Q_D(QDeclarativeFlickable);
-    if ((o && d->boundsBehavior == DragAndOvershootBounds)
-        || (!o && d->boundsBehavior == StopAtBounds))
-        return;
-    qmlInfo(this) << "overshoot is deprecated and will be removed imminently - use boundsBehavior.";
-    d->boundsBehavior = o ? DragAndOvershootBounds : StopAtBounds;
-    emit boundsBehaviorChanged();
-    emit overShootChanged();
+    return QGraphicsItemPrivate::get(d->contentItem)->childrenList();
 }
 
 /*!
@@ -1056,11 +1052,11 @@
     The \c boundsBehavior can be one of:
 
     \list
-    \o \e Flickable.StopAtBounds - the contents can not be dragged beyond the boundary
+    \o Flickable.StopAtBounds - the contents can not be dragged beyond the boundary
     of the flickable, and flicks will not overshoot.
-    \o \e Flickable.DragOverBounds - the contents can be dragged beyond the boundary
+    \o Flickable.DragOverBounds - the contents can be dragged beyond the boundary
     of the Flickable, but flicks will not overshoot.
-    \o \e Flickable.DragAndOvershootBounds (default) - the contents can be dragged
+    \o Flickable.DragAndOvershootBounds (default) - the contents can be dragged
     beyond the boundary of the Flickable, and can overshoot the
     boundary when flicked.
     \endlist
@@ -1078,7 +1074,6 @@
         return;
     d->boundsBehavior = b;
     emit boundsBehaviorChanged();
-    emit overShootChanged();
 }
 
 /*!
@@ -1112,9 +1107,9 @@
         return;
     d->hData.viewSize = w;
     if (w < 0)
-        d->viewport->setWidth(width());
+        d->contentItem->setWidth(width());
     else
-        d->viewport->setWidth(w);
+        d->contentItem->setWidth(w);
     // Make sure that we're entirely in view.
     if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
         int oldDuration = d->fixupDuration;
@@ -1139,9 +1134,9 @@
         return;
     d->vData.viewSize = h;
     if (h < 0)
-        d->viewport->setHeight(height());
+        d->contentItem->setHeight(height());
     else
-        d->viewport->setHeight(h);
+        d->contentItem->setHeight(h);
     // Make sure that we're entirely in view.
     if (!d->pressed && !d->movingHorizontally && !d->movingVertically) {
         int oldDuration = d->fixupDuration;
@@ -1219,11 +1214,21 @@
 
             d->handleMousePressEvent(&mouseEvent);
             d->captureDelayedPress(event);
+            stealThisEvent = d->stealMouse;   // Update stealThisEvent in case changed by function call above
             break;
         case QEvent::GraphicsSceneMouseRelease:
             if (d->delayedPressEvent) {
-                scene()->sendEvent(d->delayedPressTarget, d->delayedPressEvent);
+                // We replay the mouse press but the grabber we had might not be interessted by the event (e.g. overlay)
+                // so we reset the grabber
+                if (s->mouseGrabberItem() == d->delayedPressTarget)
+                    d->delayedPressTarget->ungrabMouse();
+                //Use the event handler that will take care of finding the proper item to propagate the event
+                QApplication::sendEvent(scene(), d->delayedPressEvent);
                 d->clearDelayedPress();
+                // We send the release
+                scene()->sendEvent(s->mouseGrabberItem(), event);
+                // And the event has been consumed
+                return true;
             }
             d->handleMouseReleaseEvent(&mouseEvent);
             break;
@@ -1237,8 +1242,8 @@
         }
 
         return stealThisEvent || d->delayedPressEvent;
-    } else if (!d->lastPosTime.isNull()) {
-        d->lastPosTime = QTime();
+    } else if (d->lastPosTime.isValid()) {
+        d->lastPosTime.invalidate();
     }
     if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) {
         d->clearDelayedPress();
@@ -1337,7 +1342,7 @@
 
     This property holds the time to delay (ms) delivering a press to
     children of the Flickable.  This can be useful where reacting
-    to a press before a flicking action has undesireable effects.
+    to a press before a flicking action has undesirable effects.
 
     If the flickable is dragged/flicked before the delay times out
     the press event will not be delivered.  If the button is released