1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <QtQuick/qquickview.h>
44 #include <QtQml/qqmlengine.h>
45 #include <QtQml/qqmlcomponent.h>
46 #include <QtQml/qqmlcontext.h>
47 #include <QtQml/qqmlexpression.h>
48 #include <QtQml/qqmlincubator.h>
49 #include <QtQuick/private/qquickpathview_p.h>
50 #include <QtQuick/private/qquickpath_p.h>
51 #include <QtQuick/private/qquicktext_p.h>
52 #include <QtQuick/private/qquickrectangle_p.h>
53 #include <QtQml/private/qquicklistmodel_p.h>
54 #include <QtQml/private/qqmlvaluetype_p.h>
55 #include <QtGui/qstandarditemmodel.h>
56 #include <QStringListModel>
59 #include "../../shared/util.h"
60 #include "../shared/viewtestutil.h"
61 #include "../shared/visualtestutil.h"
63 using namespace QQuickViewTestUtil;
64 using namespace QQuickVisualTestUtil;
66 Q_DECLARE_METATYPE(QQuickPathView::HighlightRangeMode)
67 Q_DECLARE_METATYPE(QQuickPathView::PositionMode)
69 static void initStandardTreeModel(QStandardItemModel *model)
72 item = new QStandardItem(QLatin1String("Row 1 Item"));
73 model->insertRow(0, item);
75 item = new QStandardItem(QLatin1String("Row 2 Item"));
76 item->setCheckable(true);
77 model->insertRow(1, item);
79 QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
80 item->setChild(0, childItem);
82 item = new QStandardItem(QLatin1String("Row 3 Item"));
83 item->setIcon(QIcon());
84 model->insertRow(2, item);
87 class tst_QQuickPathView : public QQmlDataTest
99 void initialCurrentIndex();
100 void insertModel_data();
102 void removeModel_data();
104 void moveModel_data();
106 void consecutiveModelChanges_data();
107 void consecutiveModelChanges();
112 void setCurrentIndex();
114 void propertyChanges();
116 void componentChanges();
118 void pathUpdateOnStartChanged();
123 void visualDataModel();
124 void undefinedPath();
127 void changePreferredHighlight();
128 void missingPercent();
129 void creationContext();
130 void currentOffsetOnInsertion();
133 void maximumFlickVelocity();
135 void snapToItem_data();
137 void snapOneItem_data();
138 void positionViewAtIndex();
139 void positionViewAtIndex_data();
140 void indexAt_itemAt();
141 void indexAt_itemAt_data();
142 void cacheItemCount();
145 class TestObject : public QObject
149 Q_PROPERTY(bool error READ error WRITE setError)
150 Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
151 Q_PROPERTY(int pathItemCount READ pathItemCount NOTIFY pathItemCountChanged)
154 TestObject() : QObject(), mError(true), mUseModel(true), mPathItemCount(-1) {}
156 bool error() const { return mError; }
157 void setError(bool err) { mError = err; }
159 bool useModel() const { return mUseModel; }
160 void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
162 int pathItemCount() const { return mPathItemCount; }
163 void setPathItemCount(int count) { mPathItemCount = count; emit pathItemCountChanged(); }
166 void useModelChanged();
167 void pathItemCountChanged();
175 tst_QQuickPathView::tst_QQuickPathView()
179 void tst_QQuickPathView::initValues()
182 QQmlComponent c(&engine, testFileUrl("pathview1.qml"));
183 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
186 QVERIFY(obj->path() == 0);
187 QVERIFY(obj->delegate() == 0);
188 QCOMPARE(obj->model(), QVariant());
189 QCOMPARE(obj->currentIndex(), 0);
190 QCOMPARE(obj->offset(), 0.);
191 QCOMPARE(obj->preferredHighlightBegin(), 0.);
192 QCOMPARE(obj->dragMargin(), 0.);
193 QCOMPARE(obj->count(), 0);
194 QCOMPARE(obj->pathItemCount(), -1);
199 void tst_QQuickPathView::items()
201 QQuickView *window = createView();
204 model.addItem("Fred", "12345");
205 model.addItem("John", "2345");
206 model.addItem("Bob", "54321");
207 model.addItem("Bill", "4321");
209 QQmlContext *ctxt = window->rootContext();
210 ctxt->setContextProperty("testModel", &model);
212 window->setSource(testFileUrl("pathview0.qml"));
213 qApp->processEvents();
215 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
216 QVERIFY(pathview != 0);
218 QCOMPARE(pathview->count(), model.count());
219 QCOMPARE(window->rootObject()->property("count").toInt(), model.count());
220 QCOMPARE(pathview->childItems().count(), model.count()+1); // assumes all are visible, including highlight
222 for (int i = 0; i < model.count(); ++i) {
223 QQuickText *name = findItem<QQuickText>(pathview, "textName", i);
225 QCOMPARE(name->text(), model.name(i));
226 QQuickText *number = findItem<QQuickText>(pathview, "textNumber", i);
227 QVERIFY(number != 0);
228 QCOMPARE(number->text(), model.number(i));
231 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
234 QVERIFY(pathview->highlightItem());
235 QPointF start = path->pointAt(0.0);
237 offset.setX(pathview->highlightItem()->width()/2);
238 offset.setY(pathview->highlightItem()->height()/2);
239 QCOMPARE(pathview->highlightItem()->position() + offset, start);
244 void tst_QQuickPathView::pathview2()
247 QQmlComponent c(&engine, testFileUrl("pathview2.qml"));
248 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
251 QVERIFY(obj->path() != 0);
252 QVERIFY(obj->delegate() != 0);
253 QVERIFY(obj->model() != QVariant());
254 QCOMPARE(obj->currentIndex(), 0);
255 QCOMPARE(obj->offset(), 0.);
256 QCOMPARE(obj->preferredHighlightBegin(), 0.);
257 QCOMPARE(obj->dragMargin(), 0.);
258 QCOMPARE(obj->count(), 8);
259 QCOMPARE(obj->pathItemCount(), 10);
264 void tst_QQuickPathView::pathview3()
267 QQmlComponent c(&engine, testFileUrl("pathview3.qml"));
268 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
271 QVERIFY(obj->path() != 0);
272 QVERIFY(obj->delegate() != 0);
273 QVERIFY(obj->model() != QVariant());
274 QCOMPARE(obj->currentIndex(), 7);
275 QCOMPARE(obj->offset(), 1.0);
276 QCOMPARE(obj->preferredHighlightBegin(), 0.5);
277 QCOMPARE(obj->dragMargin(), 24.);
278 QCOMPARE(obj->count(), 8);
279 QCOMPARE(obj->pathItemCount(), 4);
284 void tst_QQuickPathView::initialCurrentIndex()
287 QQmlComponent c(&engine, testFileUrl("initialCurrentIndex.qml"));
288 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
291 QVERIFY(obj->path() != 0);
292 QVERIFY(obj->delegate() != 0);
293 QVERIFY(obj->model() != QVariant());
294 QCOMPARE(obj->currentIndex(), 3);
295 QCOMPARE(obj->offset(), 5.0);
296 QCOMPARE(obj->preferredHighlightBegin(), 0.5);
297 QCOMPARE(obj->dragMargin(), 24.);
298 QCOMPARE(obj->count(), 8);
299 QCOMPARE(obj->pathItemCount(), 4);
304 void tst_QQuickPathView::insertModel_data()
306 QTest::addColumn<int>("mode");
307 QTest::addColumn<int>("idx");
308 QTest::addColumn<int>("count");
309 QTest::addColumn<qreal>("offset");
310 QTest::addColumn<int>("currentIndex");
312 // We have 8 items, with currentIndex == 4
313 QTest::newRow("insert after current")
314 << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 5. << 4;
315 QTest::newRow("insert before current")
316 << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4. << 5;
317 QTest::newRow("insert multiple after current")
318 << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 6. << 4;
319 QTest::newRow("insert multiple before current")
320 << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4. << 6;
321 QTest::newRow("insert at end")
322 << int(QQuickPathView::StrictlyEnforceRange) << 8 << 1 << 5. << 4;
323 QTest::newRow("insert at beginning")
324 << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4. << 5;
325 QTest::newRow("insert at current")
326 << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 4. << 5;
328 QTest::newRow("no range - insert after current")
329 << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 5. << 4;
330 QTest::newRow("no range - insert before current")
331 << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4. << 5;
332 QTest::newRow("no range - insert multiple after current")
333 << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 6. << 4;
334 QTest::newRow("no range - insert multiple before current")
335 << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4. << 6;
336 QTest::newRow("no range - insert at end")
337 << int(QQuickPathView::NoHighlightRange) << 8 << 1 << 5. << 4;
338 QTest::newRow("no range - insert at beginning")
339 << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4. << 5;
340 QTest::newRow("no range - insert at current")
341 << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4. << 5;
344 void tst_QQuickPathView::insertModel()
349 QFETCH(qreal, offset);
350 QFETCH(int, currentIndex);
352 QQuickView *window = createView();
356 model.addItem("Ben", "12345");
357 model.addItem("Bohn", "2345");
358 model.addItem("Bob", "54321");
359 model.addItem("Bill", "4321");
360 model.addItem("Jinny", "679");
361 model.addItem("Milly", "73378");
362 model.addItem("Jimmy", "3535");
363 model.addItem("Barb", "9039");
365 QQmlContext *ctxt = window->rootContext();
366 ctxt->setContextProperty("testModel", &model);
368 window->setSource(testFileUrl("pathview0.qml"));
369 qApp->processEvents();
371 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
372 QVERIFY(pathview != 0);
374 pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
376 pathview->setCurrentIndex(4);
377 if (mode == QQuickPathView::StrictlyEnforceRange)
378 QTRY_COMPARE(pathview->offset(), 4.0);
380 pathview->setOffset(4);
382 QList<QPair<QString, QString> > items;
383 for (int i = 0; i < count; ++i)
384 items.append(qMakePair(QString("New"), QString::number(i)));
386 model.insertItems(idx, items);
387 QTRY_COMPARE(pathview->offset(), offset);
389 QCOMPARE(pathview->currentIndex(), currentIndex);
394 void tst_QQuickPathView::removeModel_data()
396 QTest::addColumn<int>("mode");
397 QTest::addColumn<int>("idx");
398 QTest::addColumn<int>("count");
399 QTest::addColumn<qreal>("offset");
400 QTest::addColumn<int>("currentIndex");
402 // We have 8 items, with currentIndex == 4
403 QTest::newRow("remove after current")
404 << int(QQuickPathView::StrictlyEnforceRange) << 6 << 1 << 3. << 4;
405 QTest::newRow("remove before current")
406 << int(QQuickPathView::StrictlyEnforceRange) << 2 << 1 << 4. << 3;
407 QTest::newRow("remove multiple after current")
408 << int(QQuickPathView::StrictlyEnforceRange) << 5 << 2 << 2. << 4;
409 QTest::newRow("remove multiple before current")
410 << int(QQuickPathView::StrictlyEnforceRange) << 1 << 2 << 4. << 2;
411 QTest::newRow("remove last")
412 << int(QQuickPathView::StrictlyEnforceRange) << 7 << 1 << 3. << 4;
413 QTest::newRow("remove first")
414 << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 4. << 3;
415 QTest::newRow("remove current")
416 << int(QQuickPathView::StrictlyEnforceRange) << 4 << 1 << 3. << 4;
417 QTest::newRow("remove all")
418 << int(QQuickPathView::StrictlyEnforceRange) << 0 << 8 << 0. << 0;
420 QTest::newRow("no range - remove after current")
421 << int(QQuickPathView::NoHighlightRange) << 6 << 1 << 3. << 4;
422 QTest::newRow("no range - remove before current")
423 << int(QQuickPathView::NoHighlightRange) << 2 << 1 << 4. << 3;
424 QTest::newRow("no range - remove multiple after current")
425 << int(QQuickPathView::NoHighlightRange) << 5 << 2 << 2. << 4;
426 QTest::newRow("no range - remove multiple before current")
427 << int(QQuickPathView::NoHighlightRange) << 1 << 2 << 4. << 2;
428 QTest::newRow("no range - remove last")
429 << int(QQuickPathView::NoHighlightRange) << 7 << 1 << 3. << 4;
430 QTest::newRow("no range - remove first")
431 << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 4. << 3;
432 QTest::newRow("no range - remove current offset")
433 << int(QQuickPathView::NoHighlightRange) << 4 << 1 << 4. << 4;
434 QTest::newRow("no range - remove all")
435 << int(QQuickPathView::NoHighlightRange) << 0 << 8 << 0. << 0;
438 void tst_QQuickPathView::removeModel()
443 QFETCH(qreal, offset);
444 QFETCH(int, currentIndex);
446 QQuickView *window = createView();
450 model.addItem("Ben", "12345");
451 model.addItem("Bohn", "2345");
452 model.addItem("Bob", "54321");
453 model.addItem("Bill", "4321");
454 model.addItem("Jinny", "679");
455 model.addItem("Milly", "73378");
456 model.addItem("Jimmy", "3535");
457 model.addItem("Barb", "9039");
459 QQmlContext *ctxt = window->rootContext();
460 ctxt->setContextProperty("testModel", &model);
462 window->setSource(testFileUrl("pathview0.qml"));
463 qApp->processEvents();
465 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
466 QVERIFY(pathview != 0);
468 pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
470 pathview->setCurrentIndex(4);
471 if (mode == QQuickPathView::StrictlyEnforceRange)
472 QTRY_COMPARE(pathview->offset(), 4.0);
474 pathview->setOffset(4);
476 model.removeItems(idx, count);
477 QTRY_COMPARE(pathview->offset(), offset);
479 QCOMPARE(pathview->currentIndex(), currentIndex);
485 void tst_QQuickPathView::moveModel_data()
487 QTest::addColumn<int>("mode");
488 QTest::addColumn<int>("from");
489 QTest::addColumn<int>("to");
490 QTest::addColumn<int>("count");
491 QTest::addColumn<qreal>("offset");
492 QTest::addColumn<int>("currentIndex");
494 // We have 8 items, with currentIndex == 4
495 QTest::newRow("move after current")
496 << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 1 << 4. << 4;
497 QTest::newRow("move before current")
498 << int(QQuickPathView::StrictlyEnforceRange) << 2 << 3 << 1 << 4. << 4;
499 QTest::newRow("move before current to after")
500 << int(QQuickPathView::StrictlyEnforceRange) << 2 << 6 << 1 << 5. << 3;
501 QTest::newRow("move multiple after current")
502 << int(QQuickPathView::StrictlyEnforceRange) << 5 << 6 << 2 << 4. << 4;
503 QTest::newRow("move multiple before current")
504 << int(QQuickPathView::StrictlyEnforceRange) << 0 << 1 << 2 << 4. << 4;
505 QTest::newRow("move before current to end")
506 << int(QQuickPathView::StrictlyEnforceRange) << 2 << 7 << 1 << 5. << 3;
507 QTest::newRow("move last to beginning")
508 << int(QQuickPathView::StrictlyEnforceRange) << 7 << 0 << 1 << 3. << 5;
509 QTest::newRow("move current")
510 << int(QQuickPathView::StrictlyEnforceRange) << 4 << 6 << 1 << 2. << 6;
512 QTest::newRow("no range - move after current")
513 << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 1 << 4. << 4;
514 QTest::newRow("no range - move before current")
515 << int(QQuickPathView::NoHighlightRange) << 2 << 3 << 1 << 4. << 4;
516 QTest::newRow("no range - move before current to after")
517 << int(QQuickPathView::NoHighlightRange) << 2 << 6 << 1 << 5. << 3;
518 QTest::newRow("no range - move multiple after current")
519 << int(QQuickPathView::NoHighlightRange) << 5 << 6 << 2 << 4. << 4;
520 QTest::newRow("no range - move multiple before current")
521 << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 2 << 4. << 4;
522 QTest::newRow("no range - move before current to end")
523 << int(QQuickPathView::NoHighlightRange) << 2 << 7 << 1 << 5. << 3;
524 QTest::newRow("no range - move last to beginning")
525 << int(QQuickPathView::NoHighlightRange) << 7 << 0 << 1 << 3. << 5;
526 QTest::newRow("no range - move current")
527 << int(QQuickPathView::NoHighlightRange) << 4 << 6 << 1 << 4. << 6;
528 QTest::newRow("no range - move multiple incl. current")
529 << int(QQuickPathView::NoHighlightRange) << 0 << 1 << 5 << 4. << 5;
532 void tst_QQuickPathView::moveModel()
538 QFETCH(qreal, offset);
539 QFETCH(int, currentIndex);
541 QQuickView *window = createView();
545 model.addItem("Ben", "12345");
546 model.addItem("Bohn", "2345");
547 model.addItem("Bob", "54321");
548 model.addItem("Bill", "4321");
549 model.addItem("Jinny", "679");
550 model.addItem("Milly", "73378");
551 model.addItem("Jimmy", "3535");
552 model.addItem("Barb", "9039");
554 QQmlContext *ctxt = window->rootContext();
555 ctxt->setContextProperty("testModel", &model);
557 window->setSource(testFileUrl("pathview0.qml"));
558 qApp->processEvents();
560 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
561 QVERIFY(pathview != 0);
563 pathview->setHighlightRangeMode((QQuickPathView::HighlightRangeMode)mode);
565 pathview->setCurrentIndex(4);
566 if (mode == QQuickPathView::StrictlyEnforceRange)
567 QTRY_COMPARE(pathview->offset(), 4.0);
569 pathview->setOffset(4);
571 model.moveItems(from, to, count);
572 QTRY_COMPARE(pathview->offset(), offset);
574 QCOMPARE(pathview->currentIndex(), currentIndex);
579 void tst_QQuickPathView::consecutiveModelChanges_data()
581 QTest::addColumn<QQuickPathView::HighlightRangeMode>("mode");
582 QTest::addColumn<QList<ListChange> >("changes");
583 QTest::addColumn<int>("count");
584 QTest::addColumn<qreal>("offset");
585 QTest::addColumn<int>("currentIndex");
587 QTest::newRow("no range - insert after, insert before")
588 << QQuickPathView::NoHighlightRange
589 << (QList<ListChange>()
590 << ListChange::insert(7, 2)
591 << ListChange::insert(1, 3))
595 QTest::newRow("no range - remove after, remove before")
596 << QQuickPathView::NoHighlightRange
597 << (QList<ListChange>()
598 << ListChange::remove(6, 2)
599 << ListChange::remove(1, 3))
604 QTest::newRow("no range - remove after, insert before")
605 << QQuickPathView::NoHighlightRange
606 << (QList<ListChange>()
607 << ListChange::remove(5, 2)
608 << ListChange::insert(1, 3))
613 QTest::newRow("no range - insert after, remove before")
614 << QQuickPathView::NoHighlightRange
615 << (QList<ListChange>()
616 << ListChange::insert(6, 2)
617 << ListChange::remove(1, 3))
622 QTest::newRow("no range - insert, remove all, polish, insert")
623 << QQuickPathView::NoHighlightRange
624 << (QList<ListChange>()
625 << ListChange::insert(3, 1)
626 << ListChange::remove(0, 9)
627 << ListChange::polish()
628 << ListChange::insert(0, 3))
634 void tst_QQuickPathView::consecutiveModelChanges()
636 QFETCH(QQuickPathView::HighlightRangeMode, mode);
637 QFETCH(QList<ListChange>, changes);
639 QFETCH(qreal, offset);
640 QFETCH(int, currentIndex);
642 QQuickView *window = createView();
646 model.addItem("Ben", "12345");
647 model.addItem("Bohn", "2345");
648 model.addItem("Bob", "54321");
649 model.addItem("Bill", "4321");
650 model.addItem("Jinny", "679");
651 model.addItem("Milly", "73378");
652 model.addItem("Jimmy", "3535");
653 model.addItem("Barb", "9039");
655 QQmlContext *ctxt = window->rootContext();
656 ctxt->setContextProperty("testModel", &model);
658 window->setSource(testFileUrl("pathview0.qml"));
659 qApp->processEvents();
661 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
662 QVERIFY(pathview != 0);
664 pathview->setHighlightRangeMode(mode);
666 pathview->setCurrentIndex(4);
667 if (mode == QQuickPathView::StrictlyEnforceRange)
668 QTRY_COMPARE(pathview->offset(), 4.0);
670 pathview->setOffset(4);
672 for (int i=0; i<changes.count(); i++) {
673 switch (changes[i].type) {
674 case ListChange::Inserted:
676 QList<QPair<QString, QString> > items;
677 for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
678 items << qMakePair(QString("new item %1").arg(j), QString::number(j));
679 model.insertItems(changes[i].index, items);
682 case ListChange::Removed:
683 model.removeItems(changes[i].index, changes[i].count);
685 case ListChange::Moved:
686 model.moveItems(changes[i].index, changes[i].to, changes[i].count);
688 case ListChange::SetCurrent:
689 pathview->setCurrentIndex(changes[i].index);
691 case ListChange::Polish:
692 QQUICK_VERIFY_POLISH(pathview);
698 QQUICK_VERIFY_POLISH(pathview);
700 QCOMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), count);
701 QCOMPARE(pathview->count(), count);
702 QTRY_COMPARE(pathview->offset(), offset);
704 QCOMPARE(pathview->currentIndex(), currentIndex);
709 void tst_QQuickPathView::path()
712 QQmlComponent c(&engine, testFileUrl("pathtest.qml"));
713 QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
716 QCOMPARE(obj->startX(), 120.);
717 QCOMPARE(obj->startY(), 100.);
718 QVERIFY(obj->path() != QPainterPath());
720 QQmlListReference list(obj, "pathElements");
721 QCOMPARE(list.count(), 5);
723 QQuickPathAttribute* attr = qobject_cast<QQuickPathAttribute*>(list.at(0));
725 QCOMPARE(attr->name(), QString("scale"));
726 QCOMPARE(attr->value(), 1.0);
728 QQuickPathQuad* quad = qobject_cast<QQuickPathQuad*>(list.at(1));
730 QCOMPARE(quad->x(), 120.);
731 QCOMPARE(quad->y(), 25.);
732 QCOMPARE(quad->controlX(), 260.);
733 QCOMPARE(quad->controlY(), 75.);
735 QQuickPathPercent* perc = qobject_cast<QQuickPathPercent*>(list.at(2));
737 QCOMPARE(perc->value(), 0.3);
739 QQuickPathLine* line = qobject_cast<QQuickPathLine*>(list.at(3));
741 QCOMPARE(line->x(), 120.);
742 QCOMPARE(line->y(), 100.);
744 QQuickPathCubic* cubic = qobject_cast<QQuickPathCubic*>(list.at(4));
746 QCOMPARE(cubic->x(), 180.);
747 QCOMPARE(cubic->y(), 0.);
748 QCOMPARE(cubic->control1X(), -10.);
749 QCOMPARE(cubic->control1Y(), 90.);
750 QCOMPARE(cubic->control2X(), 210.);
751 QCOMPARE(cubic->control2Y(), 90.);
756 void tst_QQuickPathView::dataModel()
758 QQuickView *window = createView();
761 QQmlContext *ctxt = window->rootContext();
762 TestObject *testObject = new TestObject;
763 ctxt->setContextProperty("testObject", testObject);
766 model.addItem("red", "1");
767 model.addItem("green", "2");
768 model.addItem("blue", "3");
769 model.addItem("purple", "4");
770 model.addItem("gray", "5");
771 model.addItem("brown", "6");
772 model.addItem("yellow", "7");
773 model.addItem("thistle", "8");
774 model.addItem("cyan", "9");
775 model.addItem("peachpuff", "10");
776 model.addItem("powderblue", "11");
777 model.addItem("gold", "12");
778 model.addItem("sandybrown", "13");
780 ctxt->setContextProperty("testData", &model);
782 window->setSource(testFileUrl("datamodel.qml"));
783 qApp->processEvents();
785 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
786 QVERIFY(pathview != 0);
788 QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
789 QVERIFY(testObject->error() == false);
791 QQuickItem *item = findItem<QQuickItem>(pathview, "wrapper", 0);
793 QCOMPARE(item->x(), 110.0);
794 QCOMPARE(item->y(), 10.0);
796 model.insertItem(4, "orange", "10");
799 QCOMPARE(window->rootObject()->property("viewCount").toInt(), model.count());
800 QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 14);
802 QVERIFY(pathview->currentIndex() == 0);
803 QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
805 QQuickText *text = findItem<QQuickText>(pathview, "myText", 4);
807 QCOMPARE(text->text(), model.name(4));
810 QCOMPARE(window->rootObject()->property("viewCount").toInt(), model.count());
811 text = findItem<QQuickText>(pathview, "myText", 2);
813 QCOMPARE(text->text(), model.name(2));
814 QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 0));
816 testObject->setPathItemCount(5);
817 QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
818 QVERIFY(testObject->error() == false);
820 QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
822 QQuickRectangle *testItem = findItem<QQuickRectangle>(pathview, "wrapper", 4);
823 QVERIFY(testItem != 0);
824 testItem = findItem<QQuickRectangle>(pathview, "wrapper", 5);
825 QVERIFY(testItem == 0);
827 pathview->setCurrentIndex(1);
828 QTRY_COMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
831 model.insertItem(2, "pink", "2");
834 QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
835 QVERIFY(pathview->currentIndex() == 1);
836 QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
838 text = findItem<QQuickText>(pathview, "myText", 2);
840 QCOMPARE(text->text(), model.name(2));
843 QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
844 text = findItem<QQuickText>(pathview, "myText", 3);
846 QCOMPARE(text->text(), model.name(3));
847 QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
849 model.moveItem(3, 5);
850 QTRY_COMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
851 QList<QQuickItem*> items = findItems<QQuickItem>(pathview, "wrapper");
852 foreach (QQuickItem *item, items) {
853 QVERIFY(item->property("onPath").toBool());
855 QCOMPARE(pathview->currentItem(), findItem<QQuickItem>(pathview, "wrapper", 1));
858 pathview->setOffset(7);
859 pathview->setOffset(0);
860 QCOMPARE(findItems<QQuickItem>(pathview, "wrapper").count(), 5);
862 pathview->setCurrentIndex(model.count()-1);
863 QTRY_COMPARE(pathview->offset(), 1.0);
864 model.removeItem(model.count()-1);
865 QCOMPARE(pathview->currentIndex(), model.count()-1);
871 void tst_QQuickPathView::pathMoved()
873 QQuickView *window = createView();
877 model.addItem("Ben", "12345");
878 model.addItem("Bohn", "2345");
879 model.addItem("Bob", "54321");
880 model.addItem("Bill", "4321");
882 QQmlContext *ctxt = window->rootContext();
883 ctxt->setContextProperty("testModel", &model);
885 window->setSource(testFileUrl("pathview0.qml"));
886 qApp->processEvents();
888 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
889 QVERIFY(pathview != 0);
891 QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
893 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
895 QPointF start = path->pointAt(0.0);
896 QPointF offset;//Center of item is at point, but pos is from corner
897 offset.setX(firstItem->width()/2);
898 offset.setY(firstItem->height()/2);
899 QTRY_COMPARE(firstItem->position() + offset, start);
900 pathview->setOffset(1.0);
902 for (int i=0; i<model.count(); i++) {
903 QQuickRectangle *curItem = findItem<QQuickRectangle>(pathview, "wrapper", i);
904 QPointF itemPos(path->pointAt(0.25 + i*0.25));
905 QCOMPARE(curItem->position() + offset, QPointF(itemPos.x(), itemPos.y()));
908 QCOMPARE(pathview->currentIndex(), 3);
910 pathview->setOffset(0.0);
911 QCOMPARE(firstItem->position() + offset, start);
912 QCOMPARE(pathview->currentIndex(), 0);
914 // Change delegate size
915 pathview->setOffset(0.1);
916 pathview->setOffset(0.0);
917 window->rootObject()->setProperty("delegateWidth", 30);
918 QCOMPARE(firstItem->width(), 30.0);
919 offset.setX(firstItem->width()/2);
920 QTRY_COMPARE(firstItem->position() + offset, start);
922 // Change delegate scale
923 pathview->setOffset(0.1);
924 pathview->setOffset(0.0);
925 window->rootObject()->setProperty("delegateScale", 1.2);
926 QTRY_COMPARE(firstItem->position() + offset, start);
931 void tst_QQuickPathView::offset_data()
933 QTest::addColumn<qreal>("offset");
934 QTest::addColumn<int>("currentIndex");
936 QTest::newRow("0.0") << 0.0 << 0;
937 QTest::newRow("1.0") << 7.0 << 1;
938 QTest::newRow("5.0") << 5.0 << 3;
939 QTest::newRow("4.6") << 4.6 << 3;
940 QTest::newRow("4.4") << 4.4 << 4;
941 QTest::newRow("5.4") << 5.4 << 3;
942 QTest::newRow("5.6") << 5.6 << 2;
945 void tst_QQuickPathView::offset()
947 QFETCH(qreal, offset);
948 QFETCH(int, currentIndex);
951 QQmlComponent c(&engine, testFileUrl("pathview3.qml"));
952 QQuickPathView *view = qobject_cast<QQuickPathView*>(c.create());
954 view->setOffset(offset);
955 QCOMPARE(view->currentIndex(), currentIndex);
960 void tst_QQuickPathView::setCurrentIndex()
962 QQuickView *window = createView();
966 model.addItem("Ben", "12345");
967 model.addItem("Bohn", "2345");
968 model.addItem("Bob", "54321");
969 model.addItem("Bill", "4321");
971 QQmlContext *ctxt = window->rootContext();
972 ctxt->setContextProperty("testModel", &model);
974 window->setSource(testFileUrl("pathview0.qml"));
975 qApp->processEvents();
977 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
978 QVERIFY(pathview != 0);
980 QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
982 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
984 QPointF start = path->pointAt(0.0);
985 QPointF offset;//Center of item is at point, but pos is from corner
986 offset.setX(firstItem->width()/2);
987 offset.setY(firstItem->height()/2);
988 QCOMPARE(firstItem->position() + offset, start);
989 QCOMPARE(window->rootObject()->property("currentA").toInt(), 0);
990 QCOMPARE(window->rootObject()->property("currentB").toInt(), 0);
992 pathview->setCurrentIndex(2);
994 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
995 QTRY_COMPARE(firstItem->position() + offset, start);
996 QCOMPARE(window->rootObject()->property("currentA").toInt(), 2);
997 QCOMPARE(window->rootObject()->property("currentB").toInt(), 2);
998 QCOMPARE(pathview->currentItem(), firstItem);
999 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1001 pathview->decrementCurrentIndex();
1002 QTRY_COMPARE(pathview->currentIndex(), 1);
1003 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
1005 QTRY_COMPARE(firstItem->position() + offset, start);
1006 QCOMPARE(pathview->currentItem(), firstItem);
1007 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1009 pathview->decrementCurrentIndex();
1010 QTRY_COMPARE(pathview->currentIndex(), 0);
1011 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1013 QTRY_COMPARE(firstItem->position() + offset, start);
1014 QCOMPARE(pathview->currentItem(), firstItem);
1015 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1017 pathview->decrementCurrentIndex();
1018 QTRY_COMPARE(pathview->currentIndex(), 3);
1019 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
1021 QTRY_COMPARE(firstItem->position() + offset, start);
1022 QCOMPARE(pathview->currentItem(), firstItem);
1023 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1025 pathview->incrementCurrentIndex();
1026 QTRY_COMPARE(pathview->currentIndex(), 0);
1027 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1029 QTRY_COMPARE(firstItem->position() + offset, start);
1030 QCOMPARE(pathview->currentItem(), firstItem);
1031 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1033 // Test positive indexes are wrapped.
1034 pathview->setCurrentIndex(6);
1035 QTRY_COMPARE(pathview->currentIndex(), 2);
1036 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
1038 QTRY_COMPARE(firstItem->position() + offset, start);
1039 QCOMPARE(pathview->currentItem(), firstItem);
1040 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1042 // Test negative indexes are wrapped.
1043 pathview->setCurrentIndex(-3);
1044 QTRY_COMPARE(pathview->currentIndex(), 1);
1045 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
1047 QTRY_COMPARE(firstItem->position() + offset, start);
1048 QCOMPARE(pathview->currentItem(), firstItem);
1049 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1051 // move an item, set move duration to 0, and change currentIndex to moved item. QTBUG-22786
1052 model.moveItem(0, 3);
1053 pathview->setHighlightMoveDuration(0);
1054 pathview->setCurrentIndex(3);
1055 QCOMPARE(pathview->currentIndex(), 3);
1056 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
1058 QCOMPARE(pathview->currentItem(), firstItem);
1059 QTRY_COMPARE(firstItem->position() + offset, start);
1060 model.moveItem(3, 0);
1061 pathview->setCurrentIndex(0);
1062 pathview->setHighlightMoveDuration(300);
1064 // Check the current item is still created when outside the bounds of pathItemCount.
1065 pathview->setPathItemCount(2);
1066 pathview->setHighlightRangeMode(QQuickPathView::NoHighlightRange);
1067 QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 0));
1068 QVERIFY(findItem<QQuickRectangle>(pathview, "wrapper", 1));
1069 QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 2));
1070 QVERIFY(!findItem<QQuickRectangle>(pathview, "wrapper", 3));
1072 pathview->setCurrentIndex(2);
1073 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 2);
1074 QCOMPARE(pathview->currentItem(), firstItem);
1075 QCOMPARE(firstItem->property("onPath"), QVariant(false));
1077 pathview->decrementCurrentIndex();
1078 QTRY_COMPARE(pathview->currentIndex(), 1);
1079 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 1);
1081 QCOMPARE(pathview->currentItem(), firstItem);
1082 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1084 pathview->decrementCurrentIndex();
1085 QTRY_COMPARE(pathview->currentIndex(), 0);
1086 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1088 QCOMPARE(pathview->currentItem(), firstItem);
1089 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1091 pathview->decrementCurrentIndex();
1092 QTRY_COMPARE(pathview->currentIndex(), 3);
1093 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 3);
1095 QCOMPARE(pathview->currentItem(), firstItem);
1096 QCOMPARE(firstItem->property("onPath"), QVariant(false));
1098 pathview->incrementCurrentIndex();
1099 QTRY_COMPARE(pathview->currentIndex(), 0);
1100 firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1102 QCOMPARE(pathview->currentItem(), firstItem);
1103 QCOMPARE(firstItem->property("onPath"), QVariant(true));
1108 void tst_QQuickPathView::resetModel()
1110 QQuickView *window = createView();
1112 QStringList strings;
1113 strings << "one" << "two" << "three";
1114 QStringListModel model(strings);
1116 QQmlContext *ctxt = window->rootContext();
1117 ctxt->setContextProperty("testModel", &model);
1119 window->setSource(testFileUrl("displaypath.qml"));
1120 qApp->processEvents();
1122 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
1123 QVERIFY(pathview != 0);
1125 QCOMPARE(pathview->count(), model.rowCount());
1127 for (int i = 0; i < model.rowCount(); ++i) {
1128 QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
1129 QVERIFY(display != 0);
1130 QCOMPARE(display->text(), strings.at(i));
1134 strings << "four" << "five" << "six" << "seven";
1135 model.setStringList(strings);
1137 QCOMPARE(pathview->count(), model.rowCount());
1139 for (int i = 0; i < model.rowCount(); ++i) {
1140 QQuickText *display = findItem<QQuickText>(pathview, "displayText", i);
1141 QVERIFY(display != 0);
1142 QCOMPARE(display->text(), strings.at(i));
1148 void tst_QQuickPathView::propertyChanges()
1150 QQuickView *window = createView();
1152 window->setSource(testFileUrl("propertychanges.qml"));
1154 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1157 QSignalSpy snapPositionSpy(pathView, SIGNAL(preferredHighlightBeginChanged()));
1158 QSignalSpy dragMarginSpy(pathView, SIGNAL(dragMarginChanged()));
1160 QCOMPARE(pathView->preferredHighlightBegin(), 0.1);
1161 QCOMPARE(pathView->dragMargin(), 5.0);
1163 pathView->setPreferredHighlightBegin(0.4);
1164 pathView->setPreferredHighlightEnd(0.4);
1165 pathView->setDragMargin(20.0);
1167 QCOMPARE(pathView->preferredHighlightBegin(), 0.4);
1168 QCOMPARE(pathView->preferredHighlightEnd(), 0.4);
1169 QCOMPARE(pathView->dragMargin(), 20.0);
1171 QCOMPARE(snapPositionSpy.count(), 1);
1172 QCOMPARE(dragMarginSpy.count(), 1);
1174 pathView->setPreferredHighlightBegin(0.4);
1175 pathView->setPreferredHighlightEnd(0.4);
1176 pathView->setDragMargin(20.0);
1178 QCOMPARE(snapPositionSpy.count(), 1);
1179 QCOMPARE(dragMarginSpy.count(), 1);
1181 QSignalSpy maximumFlickVelocitySpy(pathView, SIGNAL(maximumFlickVelocityChanged()));
1182 pathView->setMaximumFlickVelocity(1000);
1183 QCOMPARE(maximumFlickVelocitySpy.count(), 1);
1184 pathView->setMaximumFlickVelocity(1000);
1185 QCOMPARE(maximumFlickVelocitySpy.count(), 1);
1190 void tst_QQuickPathView::pathChanges()
1192 QQuickView *window = createView();
1194 window->setSource(testFileUrl("propertychanges.qml"));
1196 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1199 QQuickPath *path = window->rootObject()->findChild<QQuickPath*>("path");
1202 QSignalSpy startXSpy(path, SIGNAL(startXChanged()));
1203 QSignalSpy startYSpy(path, SIGNAL(startYChanged()));
1205 QCOMPARE(path->startX(), 220.0);
1206 QCOMPARE(path->startY(), 200.0);
1208 path->setStartX(240.0);
1209 path->setStartY(220.0);
1211 QCOMPARE(path->startX(), 240.0);
1212 QCOMPARE(path->startY(), 220.0);
1214 QCOMPARE(startXSpy.count(),1);
1215 QCOMPARE(startYSpy.count(),1);
1217 path->setStartX(240);
1218 path->setStartY(220);
1220 QCOMPARE(startXSpy.count(),1);
1221 QCOMPARE(startYSpy.count(),1);
1223 QQuickPath *alternatePath = window->rootObject()->findChild<QQuickPath*>("alternatePath");
1224 QVERIFY(alternatePath);
1226 QSignalSpy pathSpy(pathView, SIGNAL(pathChanged()));
1228 QCOMPARE(pathView->path(), path);
1230 pathView->setPath(alternatePath);
1231 QCOMPARE(pathView->path(), alternatePath);
1232 QCOMPARE(pathSpy.count(),1);
1234 pathView->setPath(alternatePath);
1235 QCOMPARE(pathSpy.count(),1);
1237 QQuickPathAttribute *pathAttribute = window->rootObject()->findChild<QQuickPathAttribute*>("pathAttribute");
1238 QVERIFY(pathAttribute);
1240 QSignalSpy nameSpy(pathAttribute, SIGNAL(nameChanged()));
1241 QCOMPARE(pathAttribute->name(), QString("opacity"));
1243 pathAttribute->setName("scale");
1244 QCOMPARE(pathAttribute->name(), QString("scale"));
1245 QCOMPARE(nameSpy.count(),1);
1247 pathAttribute->setName("scale");
1248 QCOMPARE(nameSpy.count(),1);
1252 void tst_QQuickPathView::componentChanges()
1254 QQuickView *window = createView();
1256 window->setSource(testFileUrl("propertychanges.qml"));
1258 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1261 QQmlComponent delegateComponent(window->engine());
1262 delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1264 QSignalSpy delegateSpy(pathView, SIGNAL(delegateChanged()));
1266 pathView->setDelegate(&delegateComponent);
1267 QCOMPARE(pathView->delegate(), &delegateComponent);
1268 QCOMPARE(delegateSpy.count(),1);
1270 pathView->setDelegate(&delegateComponent);
1271 QCOMPARE(delegateSpy.count(),1);
1275 void tst_QQuickPathView::modelChanges()
1277 QQuickView *window = createView();
1279 window->setSource(testFileUrl("propertychanges.qml"));
1281 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1283 pathView->setCurrentIndex(3);
1284 QTRY_COMPARE(pathView->offset(), 6.0);
1286 QQuickListModel *alternateModel = window->rootObject()->findChild<QQuickListModel*>("alternateModel");
1287 QVERIFY(alternateModel);
1288 QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
1289 QSignalSpy modelSpy(pathView, SIGNAL(modelChanged()));
1290 QSignalSpy currentIndexSpy(pathView, SIGNAL(currentIndexChanged()));
1292 QCOMPARE(pathView->currentIndex(), 3);
1293 pathView->setModel(modelVariant);
1294 QCOMPARE(pathView->model(), modelVariant);
1295 QCOMPARE(modelSpy.count(),1);
1296 QCOMPARE(pathView->currentIndex(), 0);
1297 QCOMPARE(currentIndexSpy.count(), 1);
1299 pathView->setModel(modelVariant);
1300 QCOMPARE(modelSpy.count(),1);
1302 pathView->setModel(QVariant());
1303 QCOMPARE(modelSpy.count(),2);
1304 QCOMPARE(pathView->currentIndex(), 0);
1305 QCOMPARE(currentIndexSpy.count(), 1);
1310 void tst_QQuickPathView::pathUpdateOnStartChanged()
1312 QQuickView *window = createView();
1314 window->setSource(testFileUrl("pathUpdateOnStartChanged.qml"));
1316 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1319 QQuickPath *path = window->rootObject()->findChild<QQuickPath*>("path");
1321 QCOMPARE(path->startX(), 400.0);
1322 QCOMPARE(path->startY(), 300.0);
1324 QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
1326 QCOMPARE(item->x(), path->startX() - item->width() / 2.0);
1327 QCOMPARE(item->y(), path->startY() - item->height() / 2.0);
1332 void tst_QQuickPathView::package()
1334 QQuickView *window = createView();
1336 window->setSource(testFileUrl("pathview_package.qml"));
1338 window->requestActivate();
1339 QVERIFY(QTest::qWaitForWindowActive(window));
1341 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("photoPathView");
1345 QSKIP("QTBUG-27170 view does not reliably receive polish without a running animation");
1348 QQuickItem *item = findItem<QQuickItem>(pathView, "pathItem");
1350 QVERIFY(item->scale() != 1.0);
1356 void tst_QQuickPathView::emptyModel()
1358 QQuickView *window = createView();
1360 QStringListModel model;
1362 QQmlContext *ctxt = window->rootContext();
1363 ctxt->setContextProperty("emptyModel", &model);
1365 window->setSource(testFileUrl("emptymodel.qml"));
1366 qApp->processEvents();
1368 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1369 QVERIFY(pathview != 0);
1371 QCOMPARE(pathview->offset(), qreal(0.0));
1376 void tst_QQuickPathView::closed()
1381 QQmlComponent c(&engine, testFileUrl("openPath.qml"));
1382 QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
1384 QCOMPARE(obj->isClosed(), false);
1389 QQmlComponent c(&engine, testFileUrl("closedPath.qml"));
1390 QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
1392 QCOMPARE(obj->isClosed(), true);
1398 void tst_QQuickPathView::pathUpdate()
1400 QQuickView *window = createView();
1402 window->setSource(testFileUrl("pathUpdate.qml"));
1404 QQuickPathView *pathView = window->rootObject()->findChild<QQuickPathView*>("pathView");
1407 QQuickItem *item = findItem<QQuickItem>(pathView, "wrapper", 0);
1409 QCOMPARE(item->x(), 150.0);
1414 void tst_QQuickPathView::visualDataModel()
1417 QQmlComponent c(&engine, testFileUrl("vdm.qml"));
1419 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
1422 QCOMPARE(obj->count(), 3);
1427 void tst_QQuickPathView::undefinedPath()
1431 // QPainterPath warnings are only received if QT_NO_DEBUG is not defined
1432 if (QLibraryInfo::isDebugBuild()) {
1433 QString warning1("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call");
1434 QTest::ignoreMessage(QtWarningMsg,qPrintable(warning1));
1436 QString warning2("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call");
1437 QTest::ignoreMessage(QtWarningMsg,qPrintable(warning2));
1440 QQmlComponent c(&engine, testFileUrl("undefinedpath.qml"));
1442 QQuickPathView *obj = qobject_cast<QQuickPathView*>(c.create());
1445 QCOMPARE(obj->count(), 3);
1450 void tst_QQuickPathView::mouseDrag()
1452 QQuickView *window = createView();
1453 window->setSource(testFileUrl("dragpath.qml"));
1455 window->requestActivate();
1456 QVERIFY(QTest::qWaitForWindowActive(window));
1457 QCOMPARE(window, qGuiApp->focusWindow());
1459 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1460 QVERIFY(pathview != 0);
1462 QSignalSpy movingSpy(pathview, SIGNAL(movingChanged()));
1463 QSignalSpy moveStartedSpy(pathview, SIGNAL(movementStarted()));
1464 QSignalSpy moveEndedSpy(pathview, SIGNAL(movementEnded()));
1465 QSignalSpy draggingSpy(pathview, SIGNAL(draggingChanged()));
1466 QSignalSpy dragStartedSpy(pathview, SIGNAL(dragStarted()));
1467 QSignalSpy dragEndedSpy(pathview, SIGNAL(dragEnded()));
1469 int current = pathview->currentIndex();
1471 QTest::mousePress(window, Qt::LeftButton, 0, QPoint(10,100));
1475 QMouseEvent mv(QEvent::MouseMove, QPoint(30,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1476 QGuiApplication::sendEvent(window, &mv);
1478 // first move beyond threshold does not trigger drag
1479 QVERIFY(!pathview->isMoving());
1480 QVERIFY(!pathview->isDragging());
1481 QCOMPARE(movingSpy.count(), 0);
1482 QCOMPARE(moveStartedSpy.count(), 0);
1483 QCOMPARE(moveEndedSpy.count(), 0);
1484 QCOMPARE(draggingSpy.count(), 0);
1485 QCOMPARE(dragStartedSpy.count(), 0);
1486 QCOMPARE(dragEndedSpy.count(), 0);
1489 QMouseEvent mv(QEvent::MouseMove, QPoint(90,100), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1490 QGuiApplication::sendEvent(window, &mv);
1492 // next move beyond threshold does trigger drag
1493 QVERIFY(pathview->isMoving());
1494 QVERIFY(pathview->isDragging());
1495 QCOMPARE(movingSpy.count(), 1);
1496 QCOMPARE(moveStartedSpy.count(), 1);
1497 QCOMPARE(moveEndedSpy.count(), 0);
1498 QCOMPARE(draggingSpy.count(), 1);
1499 QCOMPARE(dragStartedSpy.count(), 1);
1500 QCOMPARE(dragEndedSpy.count(), 0);
1502 QVERIFY(pathview->currentIndex() != current);
1504 QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(40,100));
1505 QVERIFY(!pathview->isDragging());
1506 QCOMPARE(draggingSpy.count(), 2);
1507 QCOMPARE(dragStartedSpy.count(), 1);
1508 QCOMPARE(dragEndedSpy.count(), 1);
1509 QTRY_COMPARE(movingSpy.count(), 2);
1510 QTRY_COMPARE(moveEndedSpy.count(), 1);
1511 QCOMPARE(moveStartedSpy.count(), 1);
1516 void tst_QQuickPathView::treeModel()
1518 QQuickView *window = createView();
1521 QStandardItemModel model;
1522 initStandardTreeModel(&model);
1523 window->engine()->rootContext()->setContextProperty("myModel", &model);
1525 window->setSource(testFileUrl("treemodel.qml"));
1527 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1528 QVERIFY(pathview != 0);
1529 QCOMPARE(pathview->count(), 3);
1531 QQuickText *item = findItem<QQuickText>(pathview, "wrapper", 0);
1533 QCOMPARE(item->text(), QLatin1String("Row 1 Item"));
1535 QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1)));
1536 QCOMPARE(pathview->count(), 1);
1538 QTRY_VERIFY(item = findItem<QQuickText>(pathview, "wrapper", 0));
1539 QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item"));
1544 void tst_QQuickPathView::changePreferredHighlight()
1546 QQuickView *window = createView();
1547 window->setGeometry(0,0,400,200);
1548 window->setSource(testFileUrl("dragpath.qml"));
1550 window->requestActivate();
1551 QVERIFY(QTest::qWaitForWindowActive(window));
1552 QCOMPARE(window, qGuiApp->focusWindow());
1554 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1555 QVERIFY(pathview != 0);
1557 int current = pathview->currentIndex();
1558 QCOMPARE(current, 0);
1560 QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1562 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
1564 QPointF start = path->pointAt(0.5);
1565 QPointF offset;//Center of item is at point, but pos is from corner
1566 offset.setX(firstItem->width()/2);
1567 offset.setY(firstItem->height()/2);
1568 QTRY_COMPARE(firstItem->position() + offset, start);
1570 pathview->setPreferredHighlightBegin(0.8);
1571 pathview->setPreferredHighlightEnd(0.8);
1572 start = path->pointAt(0.8);
1573 QTRY_COMPARE(firstItem->position() + offset, start);
1574 QCOMPARE(pathview->currentIndex(), 0);
1579 void tst_QQuickPathView::creationContext()
1582 window.setGeometry(0,0,240,320);
1583 window.setSource(testFileUrl("creationContext.qml"));
1585 QQuickItem *rootItem = qobject_cast<QQuickItem *>(window.rootObject());
1587 QVERIFY(rootItem->property("count").toInt() > 0);
1590 QVERIFY(item = findItem<QQuickItem>(rootItem, "listItem", 0));
1591 QCOMPARE(item->property("text").toString(), QString("Hello!"));
1595 void tst_QQuickPathView::currentOffsetOnInsertion()
1597 QQuickView *window = createView();
1602 QQmlContext *ctxt = window->rootContext();
1603 ctxt->setContextProperty("testModel", &model);
1605 window->setSource(testFileUrl("pathline.qml"));
1606 qApp->processEvents();
1608 QQuickPathView *pathview = findItem<QQuickPathView>(window->rootObject(), "view");
1609 QVERIFY(pathview != 0);
1611 pathview->setPreferredHighlightBegin(0.5);
1612 pathview->setPreferredHighlightEnd(0.5);
1614 QCOMPARE(pathview->count(), model.count());
1616 model.addItem("item0", "0");
1618 QCOMPARE(pathview->count(), model.count());
1620 QQuickRectangle *item = 0;
1621 QTRY_VERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 0));
1623 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
1626 QPointF start = path->pointAt(0.5);
1627 QPointF offset;//Center of item is at point, but pos is from corner
1628 offset.setX(item->width()/2);
1629 offset.setY(item->height()/2);
1630 QCOMPARE(item->position() + offset, start);
1632 QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged()));
1634 // insert an item at the beginning
1635 model.insertItem(0, "item1", "1");
1636 qApp->processEvents();
1638 QCOMPARE(currentIndexSpy.count(), 1);
1640 // currentIndex is now 1
1641 QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
1643 // verify that current item (item 1) is still at offset 0.5
1644 QCOMPARE(item->position() + offset, start);
1646 // insert another item at the beginning
1647 model.insertItem(0, "item2", "2");
1648 qApp->processEvents();
1650 QCOMPARE(currentIndexSpy.count(), 2);
1652 // currentIndex is now 2
1653 QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 2));
1655 // verify that current item (item 2) is still at offset 0.5
1656 QCOMPARE(item->position() + offset, start);
1658 // verify that remove before current maintains current item
1659 model.removeItem(0);
1660 qApp->processEvents();
1662 QCOMPARE(currentIndexSpy.count(), 3);
1664 // currentIndex is now 1
1665 QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
1667 // verify that current item (item 1) is still at offset 0.5
1668 QCOMPARE(item->position() + offset, start);
1673 void tst_QQuickPathView::asynchronous()
1675 QQuickView *window = createView();
1677 QQmlIncubationController controller;
1678 window->engine()->setIncubationController(&controller);
1680 window->setSource(testFileUrl("asyncloader.qml"));
1682 QQuickItem *rootObject = qobject_cast<QQuickItem*>(window->rootObject());
1683 QVERIFY(rootObject);
1685 QQuickPathView *pathview = 0;
1688 controller.incubateWhile(&b);
1689 pathview = rootObject->findChild<QQuickPathView*>("view");
1692 // items will be created one at a time
1693 for (int i = 0; i < 5; ++i) {
1694 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", i) == 0);
1695 QQuickItem *item = 0;
1698 controller.incubateWhile(&b);
1699 item = findItem<QQuickItem>(pathview, "wrapper", i);
1705 controller.incubateWhile(&b);
1708 // verify positioning
1709 QQuickRectangle *firstItem = findItem<QQuickRectangle>(pathview, "wrapper", 0);
1711 QQuickPath *path = qobject_cast<QQuickPath*>(pathview->path());
1713 QPointF start = path->pointAt(0.0);
1714 QPointF offset;//Center of item is at point, but pos is from corner
1715 offset.setX(firstItem->width()/2);
1716 offset.setY(firstItem->height()/2);
1717 QTRY_COMPARE(firstItem->position() + offset, start);
1718 pathview->setOffset(1.0);
1720 for (int i=0; i<5; i++) {
1721 QQuickItem *curItem = findItem<QQuickItem>(pathview, "wrapper", i);
1722 QPointF itemPos(path->pointAt(0.2 + i*0.2));
1723 QCOMPARE(curItem->position() + offset, itemPos);
1729 void tst_QQuickPathView::missingPercent()
1732 QQmlComponent c(&engine, testFileUrl("missingPercent.qml"));
1733 QQuickPath *obj = qobject_cast<QQuickPath*>(c.create());
1735 QCOMPARE(obj->attributeAt("_qfx_percent", 1.0), qreal(1.0));
1739 void tst_QQuickPathView::cancelDrag()
1741 QQuickView *window = createView();
1742 window->setSource(testFileUrl("dragpath.qml"));
1744 window->requestActivate();
1745 QVERIFY(QTest::qWaitForWindowActive(window));
1746 QCOMPARE(window, qGuiApp->focusWindow());
1748 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1749 QVERIFY(pathview != 0);
1751 QSignalSpy draggingSpy(pathview, SIGNAL(draggingChanged()));
1752 QSignalSpy dragStartedSpy(pathview, SIGNAL(dragStarted()));
1753 QSignalSpy dragEndedSpy(pathview, SIGNAL(dragEnded()));
1755 // drag between snap points
1756 QTest::mousePress(window, Qt::LeftButton, 0, QPoint(10,100));
1758 QTest::mouseMove(window, QPoint(30, 100));
1759 QTest::mouseMove(window, QPoint(85, 100));
1761 QTRY_VERIFY(pathview->offset() != qFloor(pathview->offset()));
1762 QTRY_VERIFY(pathview->isMoving());
1763 QVERIFY(pathview->isDragging());
1764 QCOMPARE(draggingSpy.count(), 1);
1765 QCOMPARE(dragStartedSpy.count(), 1);
1766 QCOMPARE(dragEndedSpy.count(), 0);
1768 // steal mouse grab - cancels PathView dragging
1769 QQuickItem *item = window->rootObject()->findChild<QQuickItem*>("text");
1772 // returns to a snap point.
1773 QTRY_VERIFY(pathview->offset() == qFloor(pathview->offset()));
1774 QTRY_VERIFY(!pathview->isMoving());
1775 QVERIFY(!pathview->isDragging());
1776 QCOMPARE(draggingSpy.count(), 2);
1777 QCOMPARE(dragStartedSpy.count(), 1);
1778 QCOMPARE(dragEndedSpy.count(), 1);
1780 QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(40,100));
1785 void tst_QQuickPathView::maximumFlickVelocity()
1787 QQuickView *window = createView();
1788 window->setSource(testFileUrl("dragpath.qml"));
1790 window->requestActivate();
1791 QVERIFY(QTest::qWaitForWindowActive(window));
1792 QCOMPARE(window, qGuiApp->focusWindow());
1794 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1795 QVERIFY(pathview != 0);
1797 pathview->setMaximumFlickVelocity(700);
1798 flick(window, QPoint(200,10), QPoint(10,10), 180);
1799 QVERIFY(pathview->isMoving());
1800 QVERIFY(pathview->isFlicking());
1801 QTRY_VERIFY(!pathview->isMoving());
1803 double dist1 = 100 - pathview->offset();
1805 pathview->setOffset(0.);
1806 pathview->setMaximumFlickVelocity(300);
1807 flick(window, QPoint(200,10), QPoint(10,10), 180);
1808 QVERIFY(pathview->isMoving());
1809 QVERIFY(pathview->isFlicking());
1810 QTRY_VERIFY(!pathview->isMoving());
1812 double dist2 = 100 - pathview->offset();
1814 pathview->setOffset(0.);
1815 pathview->setMaximumFlickVelocity(500);
1816 flick(window, QPoint(200,10), QPoint(10,10), 180);
1817 QVERIFY(pathview->isMoving());
1818 QVERIFY(pathview->isFlicking());
1819 QTRY_VERIFY(!pathview->isMoving());
1821 double dist3 = 100 - pathview->offset();
1823 QVERIFY(dist1 > dist2);
1824 QVERIFY(dist3 > dist2);
1825 QVERIFY(dist2 < dist1);
1830 void tst_QQuickPathView::snapToItem()
1832 QFETCH(bool, enforceRange);
1834 QQuickView *window = createView();
1835 window->setSource(testFileUrl("panels.qml"));
1836 QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
1837 QVERIFY(pathview != 0);
1839 window->rootObject()->setProperty("enforceRange", enforceRange);
1840 QTRY_VERIFY(!pathview->isMoving()); // ensure stable
1842 int currentIndex = pathview->currentIndex();
1844 QSignalSpy snapModeSpy(pathview, SIGNAL(snapModeChanged()));
1846 flick(window, QPoint(200,10), QPoint(10,10), 180);
1848 QVERIFY(pathview->isMoving());
1849 QTRY_VERIFY(!pathview->isMoving());
1851 QVERIFY(pathview->offset() == qFloor(pathview->offset()));
1854 QVERIFY(pathview->currentIndex() != currentIndex);
1856 QVERIFY(pathview->currentIndex() == currentIndex);
1861 void tst_QQuickPathView::snapToItem_data()
1863 QTest::addColumn<bool>("enforceRange");
1865 QTest::newRow("no enforce range") << false;
1866 QTest::newRow("enforce range") << true;
1869 void tst_QQuickPathView::snapOneItem()
1871 QFETCH(bool, enforceRange);
1873 QQuickView *window = createView();
1874 window->setSource(testFileUrl("panels.qml"));
1876 window->requestActivate();
1877 QVERIFY(QTest::qWaitForWindowActive(window));
1878 QCOMPARE(window, qGuiApp->focusWindow());
1880 QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
1881 QVERIFY(pathview != 0);
1883 window->rootObject()->setProperty("enforceRange", enforceRange);
1885 QSignalSpy snapModeSpy(pathview, SIGNAL(snapModeChanged()));
1887 window->rootObject()->setProperty("snapOne", true);
1888 QVERIFY(snapModeSpy.count() == 1);
1889 QTRY_VERIFY(!pathview->isMoving()); // ensure stable
1891 int currentIndex = pathview->currentIndex();
1893 double startOffset = pathview->offset();
1894 flick(window, QPoint(200,10), QPoint(10,10), 180);
1896 QVERIFY(pathview->isMoving());
1897 QTRY_VERIFY(!pathview->isMoving());
1899 // must have moved only one item
1900 QCOMPARE(pathview->offset(), fmodf(3.0 + startOffset - 1.0, 3.0));
1903 QVERIFY(pathview->currentIndex() == currentIndex+1);
1905 QVERIFY(pathview->currentIndex() == currentIndex);
1910 void tst_QQuickPathView::snapOneItem_data()
1912 QTest::addColumn<bool>("enforceRange");
1914 QTest::newRow("no enforce range") << false;
1915 QTest::newRow("enforce range") << true;
1918 void tst_QQuickPathView::positionViewAtIndex()
1920 QFETCH(bool, enforceRange);
1921 QFETCH(int, pathItemCount);
1922 QFETCH(qreal, initOffset);
1924 QFETCH(QQuickPathView::PositionMode, mode);
1925 QFETCH(qreal, offset);
1927 QQuickView *window = createView();
1928 window->setSource(testFileUrl("pathview3.qml"));
1930 window->requestActivate();
1931 QVERIFY(QTest::qWaitForWindowActive(window));
1932 QCOMPARE(window, qGuiApp->focusWindow());
1934 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1935 QVERIFY(pathview != 0);
1937 window->rootObject()->setProperty("enforceRange", enforceRange);
1938 if (pathItemCount == -1)
1939 pathview->resetPathItemCount();
1941 pathview->setPathItemCount(pathItemCount);
1942 pathview->setOffset(initOffset);
1944 pathview->positionViewAtIndex(index, mode);
1946 QCOMPARE(pathview->offset(), offset);
1951 void tst_QQuickPathView::positionViewAtIndex_data()
1953 QTest::addColumn<bool>("enforceRange");
1954 QTest::addColumn<int>("pathItemCount");
1955 QTest::addColumn<qreal>("initOffset");
1956 QTest::addColumn<int>("index");
1957 QTest::addColumn<QQuickPathView::PositionMode>("mode");
1958 QTest::addColumn<qreal>("offset");
1960 QTest::newRow("no range, all items, Beginning") << false << -1 << 0.0 << 3 << QQuickPathView::Beginning << 5.0;
1961 QTest::newRow("no range, all items, Center") << false << -1 << 0.0 << 3 << QQuickPathView::Center << 1.0;
1962 QTest::newRow("no range, all items, End") << false << -1 << 0.0 << 3 << QQuickPathView::End << 5.0;
1963 QTest::newRow("no range, 5 items, Beginning") << false << 5 << 0.0 << 3 << QQuickPathView::Beginning << 5.0;
1964 QTest::newRow("no range, 5 items, Center") << false << 5 << 0.0 << 3 << QQuickPathView::Center << 7.5;
1965 QTest::newRow("no range, 5 items, End") << false << 5 << 0.0 << 3 << QQuickPathView::End << 2.0;
1966 QTest::newRow("no range, 5 items, Contain") << false << 5 << 0.0 << 3 << QQuickPathView::Contain << 0.0;
1967 QTest::newRow("no range, 5 items, init offset 4.0, Contain") << false << 5 << 4.0 << 3 << QQuickPathView::Contain << 5.0;
1968 QTest::newRow("no range, 5 items, init offset 3.0, Contain") << false << 5 << 3.0 << 3 << QQuickPathView::Contain << 2.0;
1970 QTest::newRow("strict range, all items, Beginning") << true << -1 << 0.0 << 3 << QQuickPathView::Beginning << 1.0;
1971 QTest::newRow("strict range, all items, Center") << true << -1 << 0.0 << 3 << QQuickPathView::Center << 5.0;
1972 QTest::newRow("strict range, all items, End") << true << -1 << 0.0 << 3 << QQuickPathView::End << 0.0;
1973 QTest::newRow("strict range, all items, Contain") << true << -1 << 0.0 << 3 << QQuickPathView::Contain << 0.0;
1974 QTest::newRow("strict range, all items, init offset 1.0, Contain") << true << -1 << 1.0 << 3 << QQuickPathView::Contain << 1.0;
1975 QTest::newRow("strict range, all items, SnapPosition") << true << -1 << 0.0 << 3 << QQuickPathView::SnapPosition << 5.0;
1976 QTest::newRow("strict range, 5 items, Beginning") << true << 5 << 0.0 << 3 << QQuickPathView::Beginning << 3.0;
1977 QTest::newRow("strict range, 5 items, Center") << true << 5 << 0.0 << 3 << QQuickPathView::Center << 5.0;
1978 QTest::newRow("strict range, 5 items, End") << true << 5 << 0.0 << 3 << QQuickPathView::End << 7.0;
1979 QTest::newRow("strict range, 5 items, Contain") << true << 5 << 0.0 << 3 << QQuickPathView::Contain << 7.0;
1980 QTest::newRow("strict range, 5 items, init offset 1.0, Contain") << true << 5 << 1.0 << 3 << QQuickPathView::Contain << 7.0;
1981 QTest::newRow("strict range, 5 items, init offset 2.0, Contain") << true << 5 << 2.0 << 3 << QQuickPathView::Contain << 3.0;
1982 QTest::newRow("strict range, 5 items, SnapPosition") << true << 5 << 0.0 << 3 << QQuickPathView::SnapPosition << 5.0;
1985 void tst_QQuickPathView::indexAt_itemAt()
1991 QQuickView *window = createView();
1992 window->setSource(testFileUrl("pathview3.qml"));
1994 window->requestActivate();
1995 QVERIFY(QTest::qWaitForWindowActive(window));
1996 QCOMPARE(window, qGuiApp->focusWindow());
1998 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
1999 QVERIFY(pathview != 0);
2001 QQuickItem *item = 0;
2003 item = findItem<QQuickItem>(pathview, "wrapper", index);
2006 QCOMPARE(pathview->indexAt(x,y), index);
2007 QVERIFY(pathview->itemAt(x,y) == item);
2012 void tst_QQuickPathView::indexAt_itemAt_data()
2014 QTest::addColumn<qreal>("x");
2015 QTest::addColumn<qreal>("y");
2016 QTest::addColumn<int>("index");
2018 QTest::newRow("Item 0 - 585, 95") << 585. << 95. << 0;
2019 QTest::newRow("Item 0 - 660, 165") << 660. << 165. << 0;
2020 QTest::newRow("No Item a - 580, 95") << 580. << 95. << -1;
2021 QTest::newRow("No Item b - 585, 85") << 585. << 85. << -1;
2022 QTest::newRow("Item 7 - 360, 200") << 360. << 200. << 7;
2025 void tst_QQuickPathView::cacheItemCount()
2027 QQuickView *window = createView();
2029 window->setSource(testFileUrl("pathview3.qml"));
2031 qApp->processEvents();
2033 QQuickPathView *pathview = qobject_cast<QQuickPathView*>(window->rootObject());
2034 QVERIFY(pathview != 0);
2036 QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("orange")));
2037 QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("lightsteelblue")));
2038 QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("teal")));
2039 QMetaObject::invokeMethod(pathview, "addColor", Q_ARG(QVariant, QString("aqua")));
2041 pathview->setOffset(0);
2043 pathview->setCacheItemCount(3);
2044 QVERIFY(pathview->cacheItemCount() == 3);
2046 QQmlIncubationController controller;
2047 window->engine()->setIncubationController(&controller);
2049 // Items on the path are created immediately
2050 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 0));
2051 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 1));
2052 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 11));
2053 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 10));
2055 const int cached[] = { 2, 3, 9, -1 }; // two appended, one prepended
2058 while (cached[i] >= 0) {
2059 // items will be created one at a time
2060 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", cached[i]) == 0);
2061 QQuickItem *item = 0;
2064 controller.incubateWhile(&b);
2065 item = findItem<QQuickItem>(pathview, "wrapper", cached[i]);
2072 controller.incubateWhile(&b);
2075 // move view and confirm items in view are visible immediately and outside are created async
2076 pathview->setOffset(4);
2078 // Items on the path are created immediately
2079 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 6));
2080 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 7));
2081 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 8));
2082 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 9));
2083 // already created items within cache stay created
2084 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 10));
2085 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 11));
2087 // one item prepended async.
2088 QVERIFY(findItem<QQuickItem>(pathview, "wrapper", 5) == 0);
2089 QQuickItem *item = 0;
2092 controller.incubateWhile(&b);
2093 item = findItem<QQuickItem>(pathview, "wrapper", 5);
2098 controller.incubateWhile(&b);
2104 QTEST_MAIN(tst_QQuickPathView)
2106 #include "tst_qquickpathview.moc"