aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2011-07-28 10:49:37 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-28 08:39:33 +0200
commit68ef13d7915fd86164b1819f7adeea22214a41b7 (patch)
tree161d8f5cd7719694694551f3adcc50d93a3a0980
parent02bf8f421d32ef7449b0fe2fe1ad62fea33bcc61 (diff)
Add dragging properties to Flickable
This allows the user to determine when a movement is due to the user dragging the view directly, i.e. excluding any flick that occurs after the touch is released. Change-Id: Idf4b699946f808da6fa34ec21a3d2cb2f0ec9de6 Fixes: QTBUG-19685 Reviewed-on: http://codereview.qt.nokia.com/2310 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Bea Lam <bea.lam@nokia.com>
-rw-r--r--doc/src/declarative/whatsnew.qdoc2
-rw-r--r--src/declarative/items/qsgflickable.cpp99
-rw-r--r--src/declarative/items/qsgflickable_p.h11
-rw-r--r--src/declarative/items/qsgflickable_p_p.h6
-rw-r--r--tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp111
5 files changed, 226 insertions, 3 deletions
diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc
index 0bf0fe6f59..f9b6683fa2 100644
--- a/doc/src/declarative/whatsnew.qdoc
+++ b/doc/src/declarative/whatsnew.qdoc
@@ -43,6 +43,8 @@ set binding when its \e when clause becomes false.
QDeclarativeExpression can now be directly (and more efficiently) constructed from a
QDeclarativeScriptString.
+Flickable: added dragging, draggingHorizontally and draggingVerically properties.
+
\section2 QtQuick 1 is now a separate library and module
Writing C++ applications using QtQuick 1 specific API, i.e. QDeclarativeView or QDeclarativeItem
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index f562a857bb..2c04ab09c6 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -428,6 +428,34 @@ void QSGFlickablePrivate::updateBeginningEnd()
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)
{
@@ -698,6 +726,7 @@ void QSGFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event)
}
if (hMoved || vMoved) {
+ draggingStarting();
q->movementStarting();
q->viewportMoved();
}
@@ -724,8 +753,6 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *even
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) {
@@ -736,6 +763,11 @@ void QSGFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *even
vData.velocity = 0.0;
}
+ draggingEnding();
+
+ if (!lastPosTime.isValid())
+ return;
+
vTime = timeline.time();
qreal velocity = vData.velocity;
@@ -1231,6 +1263,7 @@ void QSGFlickable::mouseUngrabEvent()
// if our mouse grab has been removed (probably by another Flickable),
// fix our state
d->pressed = false;
+ d->draggingEnding();
d->stealMouse = false;
setKeepMouseGrab(false);
}
@@ -1375,6 +1408,68 @@ bool QSGFlickable::isFlickingVertically() const
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);
diff --git a/src/declarative/items/qsgflickable_p.h b/src/declarative/items/qsgflickable_p.h
index e934b3a7da..7f12e8a63e 100644
--- a/src/declarative/items/qsgflickable_p.h
+++ b/src/declarative/items/qsgflickable_p.h
@@ -75,6 +75,9 @@ class Q_AUTOTEST_EXPORT QSGFlickable : public QSGItem
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)
@@ -123,6 +126,9 @@ public:
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);
@@ -164,6 +170,9 @@ Q_SIGNALS:
void flickingChanged();
void flickingHorizontallyChanged();
void flickingVerticallyChanged();
+ void draggingChanged();
+ void draggingHorizontallyChanged();
+ void draggingVerticallyChanged();
void horizontalVelocityChanged();
void verticalVelocityChanged();
void isAtBoundaryChanged();
@@ -177,6 +186,8 @@ Q_SIGNALS:
void movementEnded();
void flickStarted();
void flickEnded();
+ void dragStarted();
+ void dragEnded();
protected:
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
diff --git a/src/declarative/items/qsgflickable_p_p.h b/src/declarative/items/qsgflickable_p_p.h
index fd09b0efd4..9e854af62a 100644
--- a/src/declarative/items/qsgflickable_p_p.h
+++ b/src/declarative/items/qsgflickable_p_p.h
@@ -96,7 +96,7 @@ public:
struct AxisData {
AxisData(QSGFlickablePrivate *fp, void (QSGFlickablePrivate::*func)(qreal))
: move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true)
- , fixingUp(false), inOvershoot(false)
+ , fixingUp(false), inOvershoot(false), dragging(false)
{}
void reset() {
@@ -123,6 +123,7 @@ public:
bool atBeginning : 1;
bool fixingUp : 1;
bool inOvershoot : 1;
+ bool dragging : 1;
};
void flickX(qreal velocity);
@@ -147,6 +148,9 @@ public:
void itemGeometryChanged(QSGItem *, const QRectF &, const QRectF &);
+ void draggingStarting();
+ void draggingEnding();
+
public:
QSGItem *contentItem;
diff --git a/tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp b/tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp
index d1007819a4..b7c43ce5b0 100644
--- a/tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp
+++ b/tests/auto/declarative/qsgflickable/tst_qsgflickable.cpp
@@ -77,6 +77,7 @@ private slots:
void resizeContent();
void returnToBounds();
void wheel();
+ void movingAndDragging();
private:
QDeclarativeEngine engine;
@@ -400,6 +401,116 @@ void tst_qsgflickable::wheel()
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)