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>
This commit is contained in:
parent
02bf8f421d
commit
68ef13d791
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue