From a0bd8d2dc68fdf993821b5eb881769448b34dffd Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Mon, 27 Jun 2011 11:01:20 +0200 Subject: qmldump: Fix export comparison. Compare the full uri/name, not just the uri. Also QDeclarativeType::module was not available in 4.7.3. Mirrors http://codereview.qt.nokia.com/759 Reviewed-by: kkoehne --- tools/qmlplugindump/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index b414c3f..454f0f8 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -177,7 +177,7 @@ QSet collectReachableMetaObjects(const QString &importCode, foreach (const QDeclarativeType *baseExport, baseExports) { bool match = false; foreach (const QDeclarativeType *extensionExport, extensionExports) { - if (baseExport->module() == extensionExport->module() + if (baseExport->qmlTypeName() == extensionExport->qmlTypeName() && baseExport->majorVersion() == extensionExport->majorVersion() && baseExport->minorVersion() == extensionExport->minorVersion()) { match = true; -- cgit v0.12 From a2d97672bfaace677a4308db93f5802ba53af46e Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 28 Jun 2011 15:35:58 +1000 Subject: Velocities reported by Flickable in onFlickStarted can be 0 Ensure the smoothed velocity is set at the start of the flick. Ensure that the smoothed velocity animation isn't restarted unless there is new valid data. Change-Id: I00f8bbf1fe91faeea752b093c4658ad0f53ad06d Task-number: QTBUG-19676 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativeflickable.cpp | 30 +++++++--- .../tst_qdeclarativeflickable.cpp | 69 ++++++++++++++++++++++ 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index ce7566b..2fc2480 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -910,18 +910,24 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv qreal velocity = vData.velocity; if (vData.atBeginning || vData.atEnd) velocity /= 2; - if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) + if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) { + velocityTimeline.reset(vData.smoothVelocity); + vData.smoothVelocity.setValue(-velocity); flickY(velocity); - else + } else { fixupY(); + } velocity = hData.velocity; if (hData.atBeginning || hData.atEnd) velocity /= 2; - if (qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) + if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) { + velocityTimeline.reset(hData.smoothVelocity); + hData.smoothVelocity.setValue(-velocity); flickX(velocity); - else + } else { fixupX(); + } if (!timeline.isActive()) q->movementEnding(); @@ -1121,19 +1127,25 @@ void QDeclarativeFlickable::viewportMoved() qreal prevX = d->lastFlickablePosition.x(); qreal prevY = d->lastFlickablePosition.y(); - d->velocityTimeline.clear(); if (d->pressed || d->calcVelocity) { int elapsed = QDeclarativeItemPrivate::restart(d->velocityTime); if (elapsed > 0) { qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / elapsed; + if (qAbs(horizontalVelocity) > 0) { + d->velocityTimeline.reset(d->hData.smoothVelocity); + d->velocityTimeline.move(d->hData.smoothVelocity, horizontalVelocity, d->reportedVelocitySmoothing); + d->velocityTimeline.move(d->hData.smoothVelocity, 0, d->reportedVelocitySmoothing); + } 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); + if (qAbs(verticalVelocity) > 0) { + d->velocityTimeline.reset(d->vData.smoothVelocity); + 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) { + d->velocityTimeline.clear(); qreal horizontalVelocity = (prevX - d->hData.move.value()) * 1000 / (d->timeline.time() - d->vTime); qreal verticalVelocity = (prevY - d->vData.move.value()) * 1000 / (d->timeline.time() - d->vTime); d->hData.smoothVelocity.setValue(horizontalVelocity); diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index b077fdc..31a6b10 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -78,6 +78,7 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); void wheel(); + void flickVelocity(); private: QDeclarativeEngine engine; @@ -480,6 +481,74 @@ void tst_qdeclarativeflickable::wheel() delete canvas; } +void tst_qdeclarativeflickable::flickVelocity() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flickable = qobject_cast(canvas->rootObject()); + QVERIFY(flickable != 0); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 90))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,80)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,60)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 50))); + + QVERIFY(flickable->verticalVelocity() > 0.0); + QTRY_VERIFY(flickable->verticalVelocity() == 0.0); + + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 10))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,20)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,30)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,40)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::qWait(10); + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 50))); + + QVERIFY(flickable->verticalVelocity() < 0.0); + QTRY_VERIFY(flickable->verticalVelocity() == 0.0); + + delete canvas; +} + template T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) -- cgit v0.12 From 6fb7cdf8741ca924413dd7cbc09fad91ddc04823 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 29 Jun 2011 16:23:28 +1000 Subject: Reduce timing dependancy in flickable test Interval of 10ms between synthesized flick move events is too prone to timing difference on CI platforms. Change-Id: Id5da794a7294868c8f5e544fa71edeec967e31ca Task-number: QTBUG-19676 Reviewed-by: Bea Lam --- .../qdeclarativeflickable/data/flickable03.qml | 2 +- .../tst_qdeclarativeflickable.cpp | 69 +++++++--------------- 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/tests/auto/declarative/qdeclarativeflickable/data/flickable03.qml b/tests/auto/declarative/qdeclarativeflickable/data/flickable03.qml index a3e92fe..8359ad1 100644 --- a/tests/auto/declarative/qdeclarativeflickable/data/flickable03.qml +++ b/tests/auto/declarative/qdeclarativeflickable/data/flickable03.qml @@ -1,7 +1,7 @@ import QtQuick 1.0 Flickable { - width: 100; height: 100 + width: 100; height: 200 contentWidth: column.width; contentHeight: column.height Column { diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 31a6b10..05925cd 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -83,6 +83,7 @@ private slots: private: QDeclarativeEngine engine; + void flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration); template T *findItem(QGraphicsObject *parent, const QString &objectName); }; @@ -492,63 +493,35 @@ void tst_qdeclarativeflickable::flickVelocity() QDeclarativeFlickable *flickable = qobject_cast(canvas->rootObject()); QVERIFY(flickable != 0); - QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 90))); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,80)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,70)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,60)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - - QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 50))); - + // flick up + flick(canvas, QPoint(20,190), QPoint(20, 50), 100); QVERIFY(flickable->verticalVelocity() > 0.0); QTRY_VERIFY(flickable->verticalVelocity() == 0.0); - QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 10))); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,20)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,30)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,40)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - { - QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); - QApplication::sendEvent(canvas->viewport(), &mv); - } - QTest::qWait(10); - - QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20, 50))); - + // flick down + flick(canvas, QPoint(20,10), QPoint(20, 100), 100); QVERIFY(flickable->verticalVelocity() < 0.0); QTRY_VERIFY(flickable->verticalVelocity() == 0.0); delete canvas; } +void tst_qdeclarativeflickable::flick(QGraphicsView *canvas, const QPoint &from, const QPoint &to, int duration) +{ + const int pointCount = 5; + QPoint diff = to - from; + + // send press, five equally spaced moves, and release. + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(from)); + + for (int i = 0; i < pointCount; ++i) { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(from + (i+1)*diff/pointCount), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::qWait(duration/pointCount); + } + + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(to)); +} template T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) -- cgit v0.12 From 20f8357c8ee570f57091e20b9c0a9a1455dc1e8d Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 29 Jun 2011 16:33:04 +1000 Subject: Flickable is too sensitive. Drag, stop, release should result in a pan, which does not trigger a flick. The current flick threshold velocity is too low, leading to flicks when a pan gesture is more desireable. Change-Id: I3aa3bf28cc0ccbb043f3390ff4e044ea587ba3ff Task-number: QTBUG-19933 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativeflickable_p_p.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 46b2104..1c749cd 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -67,7 +67,11 @@ QT_BEGIN_NAMESPACE // Really slow flicks can be annoying. -const qreal MinimumFlickVelocity = 75.0; +#ifndef QML_FLICK_MINVELOCITY +#define QML_FLICK_MINVELOCITY 175 +#endif + +const qreal MinimumFlickVelocity = QML_FLICK_MINVELOCITY; class QDeclarativeFlickableVisibleArea; class QDeclarativeFlickablePrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener -- cgit v0.12 From a39e975465a5dc0548891ccd93c4ff04165b60cd Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 29 Jun 2011 10:06:39 +0200 Subject: qmlplugindump: Improve error message for misbehaving plugin components. Mirrors 6244008dcb43dde15dea3becbbec07d941b4759c in Qt Creator/2.3. Reviewed-by: Kai Koehne --- tools/qmlplugindump/main.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index 454f0f8..af291ee 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -68,6 +68,9 @@ QString pluginImportPath; bool verbose = false; +QString currentProperty; +QString inObjectInstantiation; + void collectReachableMetaObjects(const QMetaObject *meta, QSet *metas) { if (! meta || metas->contains(meta)) @@ -81,8 +84,6 @@ void collectReachableMetaObjects(const QMetaObject *meta, QSetsuperClass(), metas); } -QString currentProperty; - void collectReachableMetaObjects(QObject *object, QSet *metas) { if (! object) @@ -214,7 +215,10 @@ QSet collectReachableMetaObjects(const QString &importCode, QDeclarativeComponent c(engine); c.setData(code, QUrl::fromLocalFile(pluginImportPath + "/typeinstance.qml")); + inObjectInstantiation = tyName; QObject *object = c.create(); + inObjectInstantiation.clear(); + if (object) collectReachableMetaObjects(object, &metas); else @@ -433,6 +437,8 @@ void sigSegvHandler(int) { fprintf(stderr, "Error: SEGV\n"); if (!currentProperty.isEmpty()) fprintf(stderr, "While processing the property '%s', which probably has uninitialized data.\n", currentProperty.toLatin1().constData()); + if (!inObjectInstantiation.isEmpty()) + fprintf(stderr, "While instantiating the object '%s'.\n", inObjectInstantiation.toLatin1().constData()); exit(EXIT_SEGV); } #endif -- cgit v0.12 From d7ab0007d4b051f3cf12f01157b8b78d2fddf7c8 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 29 Jun 2011 14:00:34 +0200 Subject: qmlplugindump: Fix dumping with -path on Mac. If the current working directory was a direct parent of the qmldir path the exported modules had the path as the module URI on macs. Also changes the QtQuick export back to 1.0 to make it work with Qt 4.7.3. The version of that import statement does not actually matter as long as it's valid. Mirrors a change in Qt Creator: http://codereview.qt.nokia.com/896 Reviewed-by: Kai Koehne --- tools/qmlplugindump/main.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index af291ee..ae06d02 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -272,6 +272,9 @@ public: if (qmlTyName.startsWith(relocatableModuleUri + QLatin1Char('/'))) { qmlTyName.remove(0, relocatableModuleUri.size() + 1); } + if (qmlTyName.startsWith("./")) { + qmlTyName.remove(0, 2); + } exports += enquote(QString("%1 %2.%3").arg( qmlTyName, QString::number(qmlTy->majorVersion()), @@ -536,11 +539,16 @@ int main(int argc, char *argv[]) QDeclarativeView view; QDeclarativeEngine *engine = view.engine(); - if (!pluginImportPath.isEmpty()) + if (!pluginImportPath.isEmpty()) { + QDir cur = QDir::current(); + cur.cd(pluginImportPath); + pluginImportPath = cur.absolutePath(); + QDir::setCurrent(pluginImportPath); engine->addImportPath(pluginImportPath); + } // find all QMetaObjects reachable from the builtin module - QByteArray importCode("import QtQuick 1.1\n"); + QByteArray importCode("import QtQuick 1.0\n"); QSet defaultReachable = collectReachableMetaObjects(importCode, engine); // this will hold the meta objects we want to dump information of -- cgit v0.12 From 343069c7843321b33f06bfd42d476abae76dcece Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 30 Jun 2011 12:05:14 +1000 Subject: Try to fix Mac CI test failure Try slowing down the flick to give the slow CI machine a better chance of success. Change-Id: Id61473e73a38bb888b9bee47cffb913c936155b9 Task-number: QTBUG-19676 Reviewed-by: Bea Lam --- .../declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 05925cd..7cb7e6f 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -494,12 +494,12 @@ void tst_qdeclarativeflickable::flickVelocity() QVERIFY(flickable != 0); // flick up - flick(canvas, QPoint(20,190), QPoint(20, 50), 100); + flick(canvas, QPoint(20,190), QPoint(20, 50), 200); QVERIFY(flickable->verticalVelocity() > 0.0); QTRY_VERIFY(flickable->verticalVelocity() == 0.0); // flick down - flick(canvas, QPoint(20,10), QPoint(20, 100), 100); + flick(canvas, QPoint(20,10), QPoint(20, 140), 200); QVERIFY(flickable->verticalVelocity() < 0.0); QTRY_VERIFY(flickable->verticalVelocity() == 0.0); -- cgit v0.12 From 927b22b06ee2e749395e73f457fe3c16ea087864 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 30 Jun 2011 17:09:34 +1000 Subject: Try again to fix flickable velocity on Mac. Change-Id: Id2693a69739886f9a171f3f6438a5404dff8e901 Task-number: QTBUG-19676 Reviewed-by: Bea Lam --- .../auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 7cb7e6f..d3763a7 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -518,6 +518,7 @@ void tst_qdeclarativeflickable::flick(QGraphicsView *canvas, const QPoint &from, QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(from + (i+1)*diff/pointCount), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); QApplication::sendEvent(canvas->viewport(), &mv); QTest::qWait(duration/pointCount); + QCoreApplication::processEvents(); } QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(to)); -- cgit v0.12 From 8fbb802fa50d0a01c9c01d007a3e016c45fa863c Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 4 Jul 2011 09:52:15 +1000 Subject: Skip flick velocity test on Mac. Change-Id: Ib995961d7b1a939e5feb86d72a82408d1ceebe88 Task-number: QTBUG-19676 Reviewed-by: Bea Lam --- .../declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index d3763a7..4d4c30b 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -484,6 +484,10 @@ void tst_qdeclarativeflickable::wheel() void tst_qdeclarativeflickable::flickVelocity() { +#ifdef Q_WS_MAC + QSKIP("Producing flicks on Mac CI impossible due to timing problems", SkipAll); +#endif + QDeclarativeView *canvas = new QDeclarativeView; canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flickable03.qml")); canvas->show(); -- cgit v0.12 From e7bebcf0c59368340df524db4a53ae2595d057d7 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 4 Jul 2011 10:08:15 +1000 Subject: Flicking behaviour of ListView/GridView SnapOnItem is inconsistent Improve the response of the views when SnapOneItem/Row is enabled. In this case it is best to be much more reactive to the user input since even a small movement in a particular direction indicates a change to the next/previous item. Change-Id: I6a8eb689c3b12cdc67f24106032e36bba82d2846 Task-number: QTBUG-19874 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativeflickable.cpp | 106 ++++++++-------- .../graphicsitems/qdeclarativeflickable_p_p.h | 9 +- .../graphicsitems/qdeclarativegridview.cpp | 97 ++++++++++----- .../graphicsitems/qdeclarativelistview.cpp | 133 ++++++++++++--------- .../tst_qdeclarativegridview.cpp | 8 +- 5 files changed, 200 insertions(+), 153 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 2fc2480..1e04559 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -168,9 +168,7 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() : contentItem(new QDeclarativeItem) , hData(this, &QDeclarativeFlickablePrivate::setRoundedViewportX) , vData(this, &QDeclarativeFlickablePrivate::setRoundedViewportY) - , flickingHorizontally(false), flickingVertically(false) , hMoved(false), vMoved(false) - , movingHorizontally(false), movingVertically(false) , stealMouse(false), pressed(false), interactive(true), calcVelocity(false) , deceleration(QML_FLICK_DEFAULTDECELERATION) , maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100) @@ -294,18 +292,18 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal else timeline.accel(data.move, v, deceleration, maxDistance); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); - if (!flickingVertically) + if (!vData.flicking) emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); - if (!flickingHorizontally) + if (!hData.flicking) emit q->flickStarted(); } } else { @@ -614,11 +612,11 @@ void QDeclarativeFlickable::setInteractive(bool interactive) Q_D(QDeclarativeFlickable); if (interactive != d->interactive) { d->interactive = interactive; - if (!interactive && (d->flickingHorizontally || d->flickingVertically)) { + if (!interactive && (d->hData.flicking || d->vData.flicking)) { d->timeline.clear(); d->vTime = d->timeline.time(); - d->flickingHorizontally = false; - d->flickingVertically = false; + d->hData.flicking = false; + d->vData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); emit flickingVerticallyChanged(); @@ -771,8 +769,8 @@ void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEven pressPos = event->pos(); hData.pressPos = hData.move.value(); vData.pressPos = vData.move.value(); - flickingHorizontally = false; - flickingVertically = false; + hData.flicking = false; + vData.flicking = false; QDeclarativeItemPrivate::start(pressTime); QDeclarativeItemPrivate::start(velocityTime); } @@ -897,17 +895,13 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv return; // if we drag then pause before release we should not cause a flick. - if (QDeclarativeItemPrivate::elapsed(lastPosTime) < 100) { - vData.updateVelocity(); - hData.updateVelocity(); - } else { - hData.velocity = 0.0; - vData.velocity = 0.0; - } + qint64 elapsed = QDeclarativeItemPrivate::elapsed(lastPosTime); + vData.updateVelocity(); + hData.updateVelocity(); vTime = timeline.time(); - qreal velocity = vData.velocity; + qreal velocity = elapsed < 100 ? vData.velocity : 0; if (vData.atBeginning || vData.atEnd) velocity /= 2; if (q->yflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().y() - pressPos.y()) > FlickThreshold) { @@ -918,7 +912,7 @@ void QDeclarativeFlickablePrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEv fixupY(); } - velocity = hData.velocity; + velocity = elapsed < 100 ? hData.velocity : 0; if (hData.atBeginning || hData.atEnd) velocity /= 2; if (q->xflick() && qAbs(velocity) > MinimumFlickVelocity && qAbs(event->pos().x() - pressPos.x()) > FlickThreshold) { @@ -984,9 +978,9 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) valid = true; } if (valid) { - d->flickingVertically = false; + d->vData.flicking = false; d->flickY(d->vData.velocity); - if (d->flickingVertically) { + if (d->vData.flicking) { d->vMoved = true; movementStarting(); } @@ -1002,9 +996,9 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) valid = true; } if (valid) { - d->flickingHorizontally = false; + d->hData.flicking = false; d->flickX(d->hData.velocity); - if (d->flickingHorizontally) { + if (d->hData.flicking) { d->hMoved = true; movementStarting(); } @@ -1153,7 +1147,7 @@ void QDeclarativeFlickable::viewportMoved() } } - if (!d->vData.inOvershoot && !d->vData.fixingUp && d->flickingVertically + if (!d->vData.inOvershoot && !d->vData.fixingUp && d->vData.flicking && (d->vData.move.value() > minYExtent() || d->vData.move.value() < maxYExtent()) && qAbs(d->vData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1163,7 +1157,7 @@ void QDeclarativeFlickable::viewportMoved() d->timeline.accel(d->vData.move, -d->vData.smoothVelocity.value(), d->deceleration*QML_FLICK_OVERSHOOTFRICTION, maxDistance); d->timeline.callback(QDeclarativeTimeLineCallback(&d->vData.move, d->fixupY_callback, d)); } - if (!d->hData.inOvershoot && !d->hData.fixingUp && d->flickingHorizontally + if (!d->hData.inOvershoot && !d->hData.fixingUp && d->hData.flicking && (d->hData.move.value() > minXExtent() || d->hData.move.value() < maxXExtent()) && qAbs(d->hData.smoothVelocity.value()) > 100) { // Increase deceleration if we've passed a bound @@ -1195,7 +1189,7 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, emit contentWidthChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupX(); } @@ -1208,7 +1202,7 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, emit contentHeightChanged(); } // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupY(); } @@ -1363,7 +1357,7 @@ void QDeclarativeFlickable::setContentWidth(qreal w) else d->contentItem->setWidth(w); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupX(); } else if (!d->pressed && d->hData.fixingUp) { @@ -1391,7 +1385,7 @@ void QDeclarativeFlickable::setContentHeight(qreal h) else d->contentItem->setHeight(h); // Make sure that we're entirely in view. - if (!d->pressed && !d->movingHorizontally && !d->movingVertically) { + if (!d->pressed && !d->hData.moving && !d->vData.moving) { d->fixupMode = QDeclarativeFlickablePrivate::Immediate; d->fixupY(); } else if (!d->pressed && d->vData.fixingUp) { @@ -1647,7 +1641,7 @@ void QDeclarativeFlickable::setFlickDeceleration(qreal deceleration) bool QDeclarativeFlickable::isFlicking() const { Q_D(const QDeclarativeFlickable); - return d->flickingHorizontally || d->flickingVertically; + return d->hData.flicking || d->vData.flicking; } /*! @@ -1661,13 +1655,13 @@ bool QDeclarativeFlickable::isFlicking() const bool QDeclarativeFlickable::isFlickingHorizontally() const { Q_D(const QDeclarativeFlickable); - return d->flickingHorizontally; + return d->hData.flicking; } bool QDeclarativeFlickable::isFlickingVertically() const { Q_D(const QDeclarativeFlickable); - return d->flickingVertically; + return d->vData.flicking; } /*! @@ -1703,7 +1697,7 @@ void QDeclarativeFlickable::setPressDelay(int delay) bool QDeclarativeFlickable::isMoving() const { Q_D(const QDeclarativeFlickable); - return d->movingHorizontally || d->movingVertically; + return d->hData.moving || d->vData.moving; } /*! @@ -1718,30 +1712,30 @@ bool QDeclarativeFlickable::isMoving() const bool QDeclarativeFlickable::isMovingHorizontally() const { Q_D(const QDeclarativeFlickable); - return d->movingHorizontally; + return d->hData.moving; } bool QDeclarativeFlickable::isMovingVertically() const { Q_D(const QDeclarativeFlickable); - return d->movingVertically; + return d->vData.moving; } void QDeclarativeFlickable::movementStarting() { Q_D(QDeclarativeFlickable); - if (d->hMoved && !d->movingHorizontally) { - d->movingHorizontally = true; + if (d->hMoved && !d->hData.moving) { + d->hData.moving = true; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementStarted(); } - else if (d->vMoved && !d->movingVertically) { - d->movingVertically = true; + else if (d->vMoved && !d->vData.moving) { + d->vData.moving = true; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementStarted(); } } @@ -1758,20 +1752,20 @@ void QDeclarativeFlickable::movementEnding() void QDeclarativeFlickable::movementXEnding() { Q_D(QDeclarativeFlickable); - if (d->flickingHorizontally) { - d->flickingHorizontally = false; + if (d->hData.flicking) { + d->hData.flicking = false; emit flickingChanged(); emit flickingHorizontallyChanged(); - if (!d->flickingVertically) + if (!d->vData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingHorizontally) { - d->movingHorizontally = false; + if (d->hData.moving) { + d->hData.moving = false; d->hMoved = false; emit movingChanged(); emit movingHorizontallyChanged(); - if (!d->movingVertically) + if (!d->vData.moving) emit movementEnded(); } } @@ -1781,20 +1775,20 @@ void QDeclarativeFlickable::movementXEnding() void QDeclarativeFlickable::movementYEnding() { Q_D(QDeclarativeFlickable); - if (d->flickingVertically) { - d->flickingVertically = false; + if (d->vData.flicking) { + d->vData.flicking = false; emit flickingChanged(); emit flickingVerticallyChanged(); - if (!d->flickingHorizontally) + if (!d->hData.flicking) emit flickEnded(); } if (!d->pressed && !d->stealMouse) { - if (d->movingVertically) { - d->movingVertically = false; + if (d->vData.moving) { + d->vData.moving = false; d->vMoved = false; emit movingChanged(); emit movingVerticallyChanged(); - if (!d->movingHorizontally) + if (!d->hData.moving) emit movementEnded(); } } diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 1c749cd..d73a907 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -63,6 +63,7 @@ #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE @@ -98,7 +99,7 @@ public: struct AxisData { AxisData(QDeclarativeFlickablePrivate *fp, void (QDeclarativeFlickablePrivate::*func)(qreal)) : move(fp, func), viewSize(-1), smoothVelocity(fp), atEnd(false), atBeginning(true) - , fixingUp(false), inOvershoot(false) + , fixingUp(false), inOvershoot(false), moving(false), flicking(false) {} void reset() { @@ -125,6 +126,8 @@ public: bool atBeginning : 1; bool fixingUp : 1; bool inOvershoot : 1; + bool moving : 1; + bool flicking : 1; }; void flickX(qreal velocity); @@ -156,12 +159,8 @@ public: AxisData vData; QDeclarativeTimeLine timeline; - bool flickingHorizontally : 1; - bool flickingVertically : 1; bool hMoved : 1; bool vMoved : 1; - bool movingHorizontally : 1; - bool movingVertically : 1; bool stealMouse : 1; bool pressed : 1; bool interactive : 1; diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 36f6e29..2642800 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -52,9 +52,13 @@ #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif //---------------------------------------------------------------------------- @@ -345,9 +349,12 @@ public: Q_Q(const QDeclarativeGridView); qreal snapPos = 0; if (!visibleItems.isEmpty()) { + qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; + pos += highlightStart; pos += rowSize()/2; snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize(); snapPos = pos - fmodf(pos - snapPos, qreal(rowSize())); + snapPos -= highlightStart; qreal maxExtent; qreal minExtent; if (isRightToLeftTopToBottom()) { @@ -875,7 +882,7 @@ void QDeclarativeGridViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { + if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) { // auto-update highlight highlightXAnimator->to = currentItem->item->x(); highlightYAnimator->to = currentItem->item->y(); @@ -1062,6 +1069,18 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m if (snapMode != QDeclarativeGridView::NoSnap) { qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position(); + if (snapMode == QDeclarativeGridView::SnapOneRow && moveReason == Mouse) { + // if we've been dragged < rowSize()/2 then bias towards the next row + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2) + bias = rowSize()/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2) + bias = -rowSize()/2; + if (isRightToLeftTopToBottom()) + bias = -bias; + tempPosition -= bias; + } FxGridItem *topItem = snapItemAt(tempPosition+highlightStart); FxGridItem *bottomItem = snapItemAt(tempPosition+highlightEnd); qreal pos; @@ -1083,25 +1102,13 @@ void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } } else if (bottomItem) { if (isRightToLeftTopToBottom()) - pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent); } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); return; } - if (currentItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) { - updateHighlight(); - qreal currPos = currentItem->rowPos(); - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Transform Pos if required - if (pos < currPos + rowSize() - highlightEnd) - pos = currPos + rowSize() - highlightEnd; - if (pos > currPos - highlightStart) - pos = currPos - highlightStart; - if (isRightToLeftTopToBottom()) - pos = -pos-size(); // Untransform - } qreal dist = qAbs(data.move + pos); if (dist > 0) { timeline.reset(data.move); @@ -1158,9 +1165,14 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m if (velocity > 0) { if (data.move.value() < minExtent) { if (snapMode == QDeclarativeGridView::SnapOneRow) { - if (FxGridItem *item = firstVisibleItem()) { - maxDistance = qAbs(item->rowPos() + dataValue); - } + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue - bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -1170,8 +1182,14 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } else { if (data.move.value() > maxExtent) { if (snapMode == QDeclarativeGridView::SnapOneRow) { - qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize()); - maxDistance = qAbs(pos + dataValue); + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0; + if (isRightToLeftTopToBottom()) + bias = -bias; + data.flickTarget = -snapPosAt(-dataValue + bias); + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -1181,7 +1199,6 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // This mode requires the grid to stop exactly on a row boundary. @@ -1201,9 +1218,20 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m dist = qMin(dist, maxDistance); if (v > 0) dist = -dist; - qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QDeclarativeGridView::SnapOneRow) { + qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist; + data.flickTarget = -snapPosAt(-dataValue + distTemp); + } data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget; + if (overShoot) { + if (data.flickTarget >= minExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget += overshootDist; + } else if (data.flickTarget <= maxExtent) { + overshootDist = overShootDistance(vSize); + data.flickTarget -= overshootDist; + } + } qreal adjDist = -data.flickTarget + data.move.value(); if (qAbs(adjDist) > qAbs(dist)) { // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration @@ -1224,14 +1252,14 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -1555,6 +1583,8 @@ void QDeclarativeGridView::setCurrentIndex(int index) if (index == d->currentIndex) return; if (isComponentComplete() && d->isValid()) { + if (d->layoutScheduled) + d->layout(); d->moveReason = QDeclarativeGridViewPrivate::SetIndex; d->updateCurrent(index); } else { @@ -2108,7 +2138,8 @@ bool QDeclarativeGridView::event(QEvent *event) { Q_D(QDeclarativeGridView); if (event->type() == QEvent::User) { - d->layout(); + if (d->layoutScheduled) + d->layout(); return true; } @@ -2122,7 +2153,7 @@ void QDeclarativeGridView::viewportMoved() if (!d->itemCount) return; d->lazyRelease = true; - if (d->flickingHorizontally || d->flickingVertically) { + if (d->hData.flicking || d->vData.flicking) { if (yflick()) { if (d->vData.velocity > 0) d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore; @@ -2138,7 +2169,7 @@ void QDeclarativeGridView::viewportMoved() } } refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QDeclarativeGridViewPrivate::Mouse; if (d->moveReason != QDeclarativeGridViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2884,7 +2915,6 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) d->itemCount -= count; bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count; bool removedVisible = false; - // Remove the items from the visible list, skipping anything already marked for removal QList::Iterator it = d->visibleItems.begin(); while (it != d->visibleItems.end()) { @@ -2918,6 +2948,11 @@ void QDeclarativeGridView::itemsRemoved(int modelIndex, int count) } } + // If we removed items before visible items a layout may be + // required to ensure item 0 is in the first column. + if (!removedVisible && modelIndex < d->visibleIndex) + d->scheduleLayout(); + // fix current if (d->currentIndex >= modelIndex + count) { d->currentIndex -= count; diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 225b031..e0bee7e 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -53,9 +53,14 @@ #include #include #include +#include "qplatformdefs.h" QT_BEGIN_NAMESPACE +#ifndef QML_FLICK_SNAPONETHRESHOLD +#define QML_FLICK_SNAPONETHRESHOLD 30 +#endif + void QDeclarativeViewSection::setProperty(const QString &property) { if (property != m_property) { @@ -234,21 +239,6 @@ public: return visibleItems.count() ? visibleItems.first() : 0; } - FxListItem *nextVisibleItem() const { - const qreal pos = isRightToLeft() ? -position()-size() : position(); - bool foundFirst = false; - for (int i = 0; i < visibleItems.count(); ++i) { - FxListItem *item = visibleItems.at(i); - if (item->index != -1) { - if (foundFirst) - return item; - else if (item->position() < pos && item->endPosition() > pos) - foundFirst = true; - } - } - return 0; - } - // Returns the item before modelIndex, if created. // May return an item marked for removal. FxListItem *itemBefore(int modelIndex) const { @@ -1010,7 +1000,7 @@ void QDeclarativeListViewPrivate::updateHighlight() { if ((!currentItem && highlight) || (currentItem && !highlight)) createHighlight(); - if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) { + if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) { // auto-update highlight highlightPosAnimator->to = isRightToLeft() ? -currentItem->itemPosition()-currentItem->itemSize() @@ -1321,29 +1311,20 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m highlightEnd = highlightRangeEnd; } - if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange - && moveReason != QDeclarativeListViewPrivate::SetIndex) { - updateHighlight(); - qreal pos = currentItem->itemPosition(); - if (viewPos < pos + currentItem->itemSize() - highlightEnd) - viewPos = pos + currentItem->itemSize() - highlightEnd; - if (viewPos > pos - highlightStart) - viewPos = pos - highlightStart; - if (isRightToLeft()) - viewPos = -viewPos-size(); - - timeline.reset(data.move); - if (viewPos != position()) { - if (fixupMode != Immediate) { - timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - data.fixingUp = true; - } else { - timeline.set(data.move, -viewPos); - } - } - vTime = timeline.time(); - } else if (snapMode != QDeclarativeListView::NoSnap && moveReason != QDeclarativeListViewPrivate::SetIndex) { + if (snapMode != QDeclarativeListView::NoSnap && moveReason != QDeclarativeListViewPrivate::SetIndex) { qreal tempPosition = isRightToLeft() ? -position()-size() : position(); + if (snapMode == QDeclarativeListView::SnapOneItem && moveReason == Mouse) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = 0; + if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < averageSize/2) + bias = averageSize/2; + else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2) + bias = -averageSize/2; + if (isRightToLeft()) + bias = -bias; + tempPosition -= bias; + } FxListItem *topItem = snapItemAt(tempPosition+highlightStart); FxListItem *bottomItem = snapItemAt(tempPosition+highlightEnd); qreal pos; @@ -1359,9 +1340,9 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } } else if (bottomItem && isInBounds) { if (isRightToLeft()) - pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent); + pos = qMax(qMin(-bottomItem->position() + highlightEnd - size(), -maxExtent), -minExtent); else - pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent); + pos = qMax(qMin(bottomItem->position() - highlightEnd, -maxExtent), -minExtent); } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); return; @@ -1378,6 +1359,27 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m } vTime = timeline.time(); } + } else if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange + && moveReason != QDeclarativeListViewPrivate::SetIndex) { + updateHighlight(); + qreal pos = currentItem->itemPosition(); + if (viewPos < pos + currentItem->itemSize() - highlightEnd) + viewPos = pos + currentItem->itemSize() - highlightEnd; + if (viewPos > pos - highlightStart) + viewPos = pos - highlightStart; + if (isRightToLeft()) + viewPos = -viewPos-size(); + + timeline.reset(data.move); + if (viewPos != position()) { + if (fixupMode != Immediate) { + timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); + data.fixingUp = true; + } else { + timeline.set(data.move, -viewPos); + } + } + vTime = timeline.time(); } else { QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent); } @@ -1399,12 +1401,19 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } qreal maxDistance = 0; qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value(); + qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; // -ve velocity means list is moving up/left if (velocity > 0) { if (data.move.value() < minExtent) { - if (snapMode == QDeclarativeListView::SnapOneItem) { - if (FxListItem *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarativeListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) - bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = maxVelocity; } else { maxDistance = qAbs(minExtent - data.move.value()); } @@ -1413,9 +1422,15 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m data.flickTarget = minExtent; } else { if (data.move.value() > maxExtent) { - if (snapMode == QDeclarativeListView::SnapOneItem) { - if (FxListItem *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem()) - maxDistance = qAbs(item->position() + dataValue); + if (snapMode == QDeclarativeListView::SnapOneItem && !hData.flicking && !vData.flicking) { + // if we've been dragged < averageSize/2 then bias towards the next item + qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset); + qreal bias = -dist < averageSize/2 ? averageSize/2 : 0; + if (isRightToLeft()) + bias = -bias; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + bias) + highlightStart; + maxDistance = qAbs(data.flickTarget - data.move.value()); + velocity = -maxVelocity; } else { maxDistance = qAbs(maxExtent - data.move.value()); } @@ -1425,7 +1440,6 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m } bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; - qreal highlightStart = isRightToLeft() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; if (maxDistance > 0 || overShoot) { // These modes require the list to stop exactly on an item boundary. @@ -1439,7 +1453,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m else v = maxVelocity; } - if (!flickingHorizontally && !flickingVertically) { + if (!hData.flicking && !vData.flicking) { // the initial flick - estimate boundary qreal accel = deceleration; qreal v2 = v * v; @@ -1451,8 +1465,10 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m if (v > 0) dist = -dist; if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarativeListView::SnapOneItem) { - qreal distTemp = isRightToLeft() ? -dist : dist; - data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + if (snapMode != QDeclarativeListView::SnapOneItem) { + qreal distTemp = isRightToLeft() ? -dist : dist; + data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart; + } data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget; if (overShoot) { if (data.flickTarget >= minExtent) { @@ -1490,14 +1506,14 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m timeline.reset(data.move); timeline.accel(data.move, v, accel, maxDistance + overshootDist); timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this)); - if (!flickingHorizontally && q->xflick()) { - flickingHorizontally = true; + if (!hData.flicking && q->xflick()) { + hData.flicking = true; emit q->flickingChanged(); emit q->flickingHorizontallyChanged(); emit q->flickStarted(); } - if (!flickingVertically && q->yflick()) { - flickingVertically = true; + if (!vData.flicking && q->yflick()) { + vData.flicking = true; emit q->flickingChanged(); emit q->flickingVerticallyChanged(); emit q->flickStarted(); @@ -1873,6 +1889,8 @@ void QDeclarativeListView::setCurrentIndex(int index) if (index == d->currentIndex) return; if (isComponentComplete() && d->isValid()) { + if (d->layoutScheduled) + d->layout(); d->moveReason = QDeclarativeListViewPrivate::SetIndex; d->updateCurrent(index); } else if (d->currentIndex != index) { @@ -2565,7 +2583,8 @@ bool QDeclarativeListView::event(QEvent *event) { Q_D(QDeclarativeListView); if (event->type() == QEvent::User) { - d->layout(); + if (d->layoutScheduled) + d->layout(); return true; } @@ -2584,7 +2603,7 @@ void QDeclarativeListView::viewportMoved() d->inViewportMoved = true; d->lazyRelease = true; refill(); - if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically) + if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) d->moveReason = QDeclarativeListViewPrivate::Mouse; if (d->moveReason != QDeclarativeListViewPrivate::SetIndex) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { @@ -2618,7 +2637,7 @@ void QDeclarativeListView::viewportMoved() } } - if ((d->flickingHorizontally || d->flickingVertically) && d->correctFlick && !d->inFlickCorrection) { + if ((d->hData.flicking || d->vData.flicking) && d->correctFlick && !d->inFlickCorrection) { d->inFlickCorrection = true; // Near an end and it seems that the extent has changed? // Recalculate the flick so that we don't end up in an odd position. diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index e3f7980..4342ff3 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -450,12 +450,12 @@ void tst_QDeclarativeGridView::removed() model.removeItem(1); // Confirm items positioned correctly - for (int i = 6; i < 18; ++i) { + for (int i = 3; i < 15; ++i) { QDeclarativeItem *item = findItem(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_VERIFY(item->x() == (i%3)*80); - QTRY_VERIFY(item->y() == (i/3)*60); + QTRY_COMPARE(item->x(), (i%3)*80.0); + QTRY_COMPARE(item->y(), 60+(i/3)*60.0); } // Remove currentIndex @@ -476,7 +476,7 @@ void tst_QDeclarativeGridView::removed() if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); QTRY_VERIFY(item->x() == (i%3)*80); - QTRY_VERIFY(item->y() == (i/3)*60); + QTRY_VERIFY(item->y() == 60+(i/3)*60); } // remove item outside current view. -- cgit v0.12