summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/util/qscroller/tst_qscroller.cpp')
-rw-r--r--tests/auto/widgets/util/qscroller/tst_qscroller.cpp530
1 files changed, 530 insertions, 0 deletions
diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
new file mode 100644
index 0000000000..9ed4965d45
--- /dev/null
+++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtWidgets>
+#include <QtTest>
+// #include <QDebug>
+
+class tst_QScrollerWidget : public QWidget
+{
+public:
+ tst_QScrollerWidget()
+ : QWidget()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ receivedPrepare = false;
+ receivedScroll = false;
+ receivedFirst = false;
+ receivedLast = false;
+ receivedOvershoot = false;
+ }
+
+ bool event(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::Gesture:
+ e->setAccepted(false); // better reject the event or QGestureManager will make trouble
+ return false;
+
+ case QEvent::ScrollPrepare:
+ {
+ receivedPrepare = true;
+ QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
+ se->setViewportSize(QSizeF(100,100));
+ se->setContentPosRange(scrollArea);
+ se->setContentPos(scrollPosition);
+ se->accept();
+ return true;
+ }
+
+ case QEvent::Scroll:
+ {
+ receivedScroll = true;
+ QScrollEvent *se = static_cast<QScrollEvent *>(e);
+ // qDebug() << "Scroll for"<<this<<"pos"<<se->scrollPos()<<"ov"<<se->overshoot()<<"first"<<se->isFirst()<<"last"<<se->isLast();
+
+ if (se->scrollState() == QScrollEvent::ScrollStarted)
+ receivedFirst = true;
+ if (se->scrollState() == QScrollEvent::ScrollFinished)
+ receivedLast = true;
+
+ currentPos = se->contentPos();
+ overshoot = se->overshootDistance();
+ if (!qFuzzyCompare( overshoot.x() + 1.0, 1.0 ) ||
+ !qFuzzyCompare( overshoot.y() + 1.0, 1.0 ))
+ receivedOvershoot = true;
+ return true;
+ }
+
+ default:
+ return QObject::event(e);
+ }
+ }
+
+
+ QRectF scrollArea;
+ QPointF scrollPosition;
+
+ bool receivedPrepare;
+ bool receivedScroll;
+ bool receivedFirst;
+ bool receivedLast;
+ bool receivedOvershoot;
+
+ QPointF currentPos;
+ QPointF overshoot;
+};
+
+
+class tst_QScroller : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QScroller() { }
+ ~tst_QScroller() { }
+
+private:
+ void kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+ void kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+
+private slots:
+ void staticScrollers();
+ void scrollerProperties();
+ void scrollTo();
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+ void scroll();
+ void overshoot();
+#endif
+};
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ Tests some in between states but does not wait until scrolling is finished.
+*/
+void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos= from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = QScroller::scroller(sw)->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ QCOMPARE( s1->state(), QScroller::Pressed );
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QCOMPARE( s1->state(), QScroller::Dragging );
+ QCOMPARE( sw->receivedPrepare, true );
+
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // note that the scrolling goes in a different direction than the mouse move
+ QPoint calculatedPos = from.toPoint() - touchUpdate - touchStart;
+ QVERIFY(qAbs(sw->currentPos.x() - calculatedPos.x()) < 1.0);
+ QVERIFY(qAbs(sw->currentPos.y() - calculatedPos.y()) < 1.0);
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ This function does not have any in between tests, it does not expect the scroller to actually scroll.
+*/
+void tst_QScroller::kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos = from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = s1->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+
+void tst_QScroller::staticScrollers()
+{
+ // scrollers
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScroller *s1 = QScroller::scroller(o1);
+ QScroller *s2 = QScroller::scroller(o2);
+
+ QVERIFY(s1);
+ QVERIFY(s2);
+ QVERIFY(s1 != s2);
+
+ QVERIFY(!QScroller::scroller(static_cast<const QObject*>(0)));
+ QCOMPARE(QScroller::scroller(o1), s1);
+
+ delete o1;
+ delete o2;
+ }
+
+ // the same for properties
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+ QScrollerProperties sp2 = QScroller::scroller(o2)->scrollerProperties();
+
+ // default properties should be the same
+ QVERIFY(sp1 == sp2);
+
+ QCOMPARE(QScroller::scroller(o1)->scrollerProperties(), sp1);
+
+ delete o1;
+ delete o2;
+ }
+}
+
+void tst_QScroller::scrollerProperties()
+{
+ QObject *o1 = new QObject(this);
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+
+ QScrollerProperties::ScrollMetric metrics[] =
+ {
+ QScrollerProperties::MousePressEventDelay, // qreal [s]
+ QScrollerProperties::DragStartDistance, // qreal [m]
+ QScrollerProperties::DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
+ QScrollerProperties::AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|)
+
+ QScrollerProperties::DecelerationFactor, // slope of the curve
+
+ QScrollerProperties::MinimumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumClickThroughVelocity, // qreal [m/s]
+
+ QScrollerProperties::AcceleratingFlickMaximumTime, // qreal [s]
+ QScrollerProperties::AcceleratingFlickSpeedupFactor, // qreal [1..]
+
+ QScrollerProperties::SnapPositionRatio, // qreal [0..1]
+ QScrollerProperties::SnapTime, // qreal [s]
+
+ QScrollerProperties::OvershootDragResistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootDragDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollTime, // qreal [s]
+ };
+
+ for (unsigned int i = 0; i < sizeof(metrics) / sizeof(metrics[0]); i++) {
+ sp1.setScrollMetric(metrics[i], 0.9);
+ QCOMPARE(sp1.scrollMetric(metrics[i]).toDouble(), 0.9);
+ }
+ sp1.setScrollMetric(QScrollerProperties::ScrollingCurve, QEasingCurve(QEasingCurve::OutQuart));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::ScrollingCurve).toEasingCurve().type(), QEasingCurve::OutQuart);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::HorizontalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOff);
+
+ sp1.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::VerticalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOn);
+
+ sp1.setScrollMetric(QScrollerProperties::FrameRate, QVariant::fromValue(QScrollerProperties::Fps20));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::FrameRate).value<QScrollerProperties::FrameRates>(), QScrollerProperties::Fps20);
+}
+
+void tst_QScroller::scrollTo()
+{
+ {
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF( 0, 0, 1000, 1000 );
+ sw->scrollPosition = QPointF( 500, 500 );
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ // a normal scroll
+ s1->scrollTo(QPointF(100,100), 100);
+ QTest::qWait(200);
+
+ QCOMPARE( sw->receivedPrepare, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedLast, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 100 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 100 ));
+
+ delete sw;
+ }
+}
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::scroll()
+{
+ // -- good case. normal scroll
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ kineticScroll(sw, QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
+ // now we should be scrolling
+ QCOMPARE( s1->state(), QScroller::Scrolling );
+
+ // wait until finished, check that no further first scroll is send
+ sw->receivedFirst = false;
+ sw->receivedScroll = false;
+ while (s1->state() == QScroller::Scrolling)
+ QTest::qWait(100);
+
+ QCOMPARE( sw->receivedFirst, false );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedLast, true );
+ QVERIFY(sw->currentPos.x() < 400);
+ QVERIFY(sw->currentPos.y() < 400);
+
+ // -- try to scroll when nothing to scroll
+
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QCOMPARE(sw->currentPos.x(), 0.0);
+ QCOMPARE(sw->currentPos.y(), 500.0);
+
+ delete sw;
+}
+#endif
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::overshoot()
+{
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QScrollerProperties sp1 = s1->scrollerProperties();
+
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5);
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.2);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.2);
+
+ // -- try to scroll with overshoot (when scrollable good case)
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (when scrollable bad case)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (always off)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on but max overshoot = 0)
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.0);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0);
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ delete sw;
+}
+#endif
+
+QTEST_MAIN(tst_QScroller)
+
+#include "tst_qscroller.moc"