visibleArea->updateVisible();
}
+/*
+XXXTODO add docs describing moving, dragging, flicking properties, e.g.
+
+When the user starts dragging the Flickable, the dragging and moving properties
+will be true.
+
+If the velocity is sufficient when the drag is ended, flicking may begin.
+
+The moving properties will remain true until all dragging and flicking
+is finished.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onDragStarted()
+
+ This handler is called when the view starts to be dragged due to user
+ interaction.
+*/
+
+/*!
+ \qmlsignal QtQuick2::Flickable::onDragEnded()
+
+ This handler is called when the user stops dragging the view.
+
+ If the velocity of the drag is suffient at the time the
+ touch/mouse button is released then a flick will start.
+*/
+
QSGFlickable::QSGFlickable(QSGItem *parent)
: QSGItem(*(new QSGFlickablePrivate), parent)
{
}
if (hMoved || vMoved) {
+ draggingStarting();
q->movementStarting();
q->viewportMoved();
}
stealMouse = false;
q->setKeepMouseGrab(false);
pressed = false;
- if (!lastPosTime.isValid())
- return;
// if we drag then pause before release we should not cause a flick.
if (QSGItemPrivate::elapsed(lastPosTime) < 100) {
vData.velocity = 0.0;
}
+ draggingEnding();
+
+ if (!lastPosTime.isValid())
+ return;
+
vTime = timeline.time();
qreal velocity = vData.velocity;
// if our mouse grab has been removed (probably by another Flickable),
// fix our state
d->pressed = false;
+ d->draggingEnding();
d->stealMouse = false;
setKeepMouseGrab(false);
}
return d->flickingVertically;
}
+/*!
+ \qmlproperty bool QtQuick2::Flickable::dragging
+ \qmlproperty bool QtQuick2::Flickable::draggingHorizontally
+ \qmlproperty bool QtQuick2::Flickable::draggingVertically
+
+ These properties describe whether the view is currently moving horizontally,
+ vertically or in either direction, due to the user dragging the view.
+*/
+bool QSGFlickable::isDragging() const
+{
+ Q_D(const QSGFlickable);
+ return d->hData.dragging || d->vData.dragging;
+}
+
+bool QSGFlickable::isDraggingHorizontally() const
+{
+ Q_D(const QSGFlickable);
+ return d->hData.dragging;
+}
+
+bool QSGFlickable::isDraggingVertically() const
+{
+ Q_D(const QSGFlickable);
+ return d->vData.dragging;
+}
+
+void QSGFlickablePrivate::draggingStarting()
+{
+ Q_Q(QSGFlickable);
+ bool wasDragging = hData.dragging || vData.dragging;
+ if (hMoved && !hData.dragging) {
+ hData.dragging = true;
+ emit q->draggingHorizontallyChanged();
+ }
+ if (vMoved && !vData.dragging) {
+ vData.dragging = true;
+ emit q->draggingVerticallyChanged();
+ }
+ if (!wasDragging && (hData.dragging || vData.dragging)) {
+ emit q->draggingChanged();
+ emit q->dragStarted();
+ }
+}
+
+void QSGFlickablePrivate::draggingEnding()
+{
+ Q_Q(QSGFlickable);
+ bool wasDragging = hData.dragging || vData.dragging;
+ if (hData.dragging) {
+ hData.dragging = false;
+ emit q->draggingHorizontallyChanged();
+ }
+ if (vData.dragging) {
+ vData.dragging = false;
+ emit q->draggingVerticallyChanged();
+ }
+ if (wasDragging && !hData.dragging && !vData.dragging) {
+ emit q->draggingChanged();
+ emit q->dragEnded();
+ }
+}
+
int QSGFlickable::pressDelay() const
{
Q_D(const QSGFlickable);
Q_PROPERTY(bool flicking READ isFlicking NOTIFY flickingChanged)
Q_PROPERTY(bool flickingHorizontally READ isFlickingHorizontally NOTIFY flickingHorizontallyChanged)
Q_PROPERTY(bool flickingVertically READ isFlickingVertically NOTIFY flickingVerticallyChanged)
+ Q_PROPERTY(bool dragging READ isDragging NOTIFY draggingChanged)
+ Q_PROPERTY(bool draggingHorizontally READ isDraggingHorizontally NOTIFY draggingHorizontallyChanged)
+ Q_PROPERTY(bool draggingVertically READ isDraggingVertically NOTIFY draggingVerticallyChanged)
Q_PROPERTY(FlickableDirection flickableDirection READ flickableDirection WRITE setFlickableDirection NOTIFY flickableDirectionChanged)
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
bool isFlicking() const;
bool isFlickingHorizontally() const;
bool isFlickingVertically() const;
+ bool isDragging() const;
+ bool isDraggingHorizontally() const;
+ bool isDraggingVertically() const;
int pressDelay() const;
void setPressDelay(int delay);
void flickingChanged();
void flickingHorizontallyChanged();
void flickingVerticallyChanged();
+ void draggingChanged();
+ void draggingHorizontallyChanged();
+ void draggingVerticallyChanged();
void horizontalVelocityChanged();
void verticalVelocityChanged();
void isAtBoundaryChanged();
void movementEnded();
void flickStarted();
void flickEnded();
+ void dragStarted();
+ void dragEnded();
protected:
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
void resizeContent();
void returnToBounds();
void wheel();
+ void movingAndDragging();
private:
QDeclarativeEngine engine;
delete canvas;
}
+void tst_qsgflickable::movingAndDragging()
+{
+ QSGView *canvas = new QSGView;
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml"));
+ canvas->show();
+ canvas->setFocus();
+ QVERIFY(canvas->rootObject() != 0);
+
+ QSGFlickable *flickable = qobject_cast<QSGFlickable*>(canvas->rootObject());
+ QVERIFY(flickable != 0);
+
+ QSignalSpy vDragSpy(flickable, SIGNAL(draggingVerticallyChanged()));
+ QSignalSpy hDragSpy(flickable, SIGNAL(draggingHorizontallyChanged()));
+ QSignalSpy dragSpy(flickable, SIGNAL(draggingChanged()));
+ QSignalSpy vMoveSpy(flickable, SIGNAL(movingVerticallyChanged()));
+ QSignalSpy hMoveSpy(flickable, SIGNAL(movingHorizontallyChanged()));
+ QSignalSpy moveSpy(flickable, SIGNAL(movingChanged()));
+ QSignalSpy dragStartSpy(flickable, SIGNAL(dragStarted()));
+ QSignalSpy dragEndSpy(flickable, SIGNAL(dragEnded()));
+
+ //Vertical
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
+
+ QMouseEvent moveEvent(QEvent::MouseMove, QPoint(50, 80), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ moveEvent = QMouseEvent(QEvent::MouseMove, QPoint(50, 70), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ moveEvent = QMouseEvent(QEvent::MouseMove, QPoint(50, 60), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ QVERIFY(!flickable->isDraggingHorizontally());
+ QVERIFY(flickable->isDraggingVertically());
+ QVERIFY(flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 1);
+ QCOMPARE(dragSpy.count(), 1);
+ QCOMPARE(hDragSpy.count(), 0);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 0);
+
+ QVERIFY(!flickable->isMovingHorizontally());
+ QVERIFY(flickable->isMovingVertically());
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(vMoveSpy.count(), 1);
+ QCOMPARE(moveSpy.count(), 1);
+ QCOMPARE(hMoveSpy.count(), 0);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 60));
+
+ QVERIFY(!flickable->isDraggingVertically());
+ QVERIFY(!flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 2);
+ QCOMPARE(dragSpy.count(), 2);
+ QCOMPARE(hDragSpy.count(), 0);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 1);
+
+ // Don't test moving because a flick could occur
+
+ //Horizontal
+ vDragSpy.clear();
+ hDragSpy.clear();
+ dragSpy.clear();
+ vMoveSpy.clear();
+ hMoveSpy.clear();
+ moveSpy.clear();
+ dragStartSpy.clear();
+ dragEndSpy.clear();
+
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(90, 50));
+
+ moveEvent = QMouseEvent(QEvent::MouseMove, QPoint(80, 50), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ moveEvent = QMouseEvent(QEvent::MouseMove, QPoint(70, 50), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ moveEvent = QMouseEvent(QEvent::MouseMove, QPoint(60, 50), Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(canvas, &moveEvent);
+
+ QVERIFY(flickable->isDraggingHorizontally());
+ QVERIFY(flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 0);
+ QCOMPARE(dragSpy.count(), 1);
+ QCOMPARE(hDragSpy.count(), 1);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 0);
+
+ QVERIFY(!flickable->isMovingVertically());
+ QVERIFY(flickable->isMovingHorizontally());
+ QVERIFY(flickable->isMoving());
+ QCOMPARE(vMoveSpy.count(), 0);
+ QCOMPARE(moveSpy.count(), 1);
+ QCOMPARE(hMoveSpy.count(), 1);
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(60, 50));
+
+ QVERIFY(!flickable->isDraggingHorizontally());
+ QVERIFY(!flickable->isDragging());
+ QCOMPARE(vDragSpy.count(), 0);
+ QCOMPARE(dragSpy.count(), 2);
+ QCOMPARE(hDragSpy.count(), 2);
+ QCOMPARE(dragStartSpy.count(), 1);
+ QCOMPARE(dragEndSpy.count(), 1);
+
+ // Don't test moving because a flick could occur
+
+ delete canvas;
+}
template<typename T>
T *tst_qsgflickable::findItem(QSGItem *parent, const QString &objectName)