1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <QtDeclarative/qdeclarativeview.h>
44 #include <QtDeclarative/qdeclarativeengine.h>
45 #include <QtDeclarative/qdeclarativecomponent.h>
46 #include <QtDeclarative/qdeclarativecontext.h>
47 #include <QtDeclarative/qdeclarativeexpression.h>
48 #include <QtDeclarative/private/qdeclarativepathview_p.h>
49 #include <QtDeclarative/private/qdeclarativepath_p.h>
50 #include <QtDeclarative/private/qdeclarativetext_p.h>
51 #include <QtDeclarative/private/qdeclarativerectangle_p.h>
52 #include <QtDeclarative/private/qdeclarativelistmodel_p.h>
53 #include <QtDeclarative/private/qdeclarativevaluetype_p.h>
54 #include <QAbstractListModel>
55 #include <QStringListModel>
56 #include <QStandardItemModel>
59 #include "../../../shared/util.h"
62 // In Symbian OS test data is located in applications private dir
66 static void initStandardTreeModel(QStandardItemModel *model)
69 item = new QStandardItem(QLatin1String("Row 1 Item"));
70 model->insertRow(0, item);
72 item = new QStandardItem(QLatin1String("Row 2 Item"));
73 item->setCheckable(true);
74 model->insertRow(1, item);
76 QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
77 item->setChild(0, childItem);
79 item = new QStandardItem(QLatin1String("Row 3 Item"));
80 item->setIcon(QIcon());
81 model->insertRow(2, item);
85 class tst_QDeclarativePathView : public QObject
89 tst_QDeclarativePathView();
99 void setCurrentIndex();
101 void propertyChanges();
103 void componentChanges();
105 void pathUpdateOnStartChanged();
110 void visualDataModel();
111 void undefinedPath();
114 void changePreferredHighlight();
117 QDeclarativeView *createView();
119 T *findItem(QGraphicsObject *parent, const QString &objectName, int index=-1);
121 QList<T*> findItems(QGraphicsObject *parent, const QString &objectName);
124 class TestObject : public QObject
128 Q_PROPERTY(bool error READ error WRITE setError)
129 Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
130 Q_PROPERTY(int pathItemCount READ pathItemCount NOTIFY pathItemCountChanged)
133 TestObject() : QObject(), mError(true), mUseModel(true), mPathItemCount(-1) {}
135 bool error() const { return mError; }
136 void setError(bool err) { mError = err; }
138 bool useModel() const { return mUseModel; }
139 void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
141 int pathItemCount() const { return mPathItemCount; }
142 void setPathItemCount(int count) { mPathItemCount = count; emit pathItemCountChanged(); }
145 void useModelChanged();
146 void pathItemCountChanged();
154 class TestModel : public QAbstractListModel
157 enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
159 TestModel(QObject *parent=0) : QAbstractListModel(parent) {
160 QHash<int, QByteArray> roles;
161 roles[Name] = "name";
162 roles[Number] = "number";
166 int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
167 QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
170 rv = list.at(index.row()).first;
171 else if (role == Number)
172 rv = list.at(index.row()).second;
177 int count() const { return rowCount(); }
178 QString name(int index) const { return list.at(index).first; }
179 QString number(int index) const { return list.at(index).second; }
181 void addItem(const QString &name, const QString &number) {
182 beginInsertRows(QModelIndex(), list.count(), list.count());
183 list.append(QPair<QString,QString>(name, number));
187 void insertItem(int index, const QString &name, const QString &number) {
188 beginInsertRows(QModelIndex(), index, index);
189 list.insert(index, QPair<QString,QString>(name, number));
193 void removeItem(int index) {
194 beginRemoveRows(QModelIndex(), index, index);
195 list.removeAt(index);
199 void moveItem(int from, int to) {
200 beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
205 void modifyItem(int idx, const QString &name, const QString &number) {
206 list[idx] = QPair<QString,QString>(name, number);
207 emit dataChanged(index(idx,0), index(idx,0));
211 QList<QPair<QString,QString> > list;
215 tst_QDeclarativePathView::tst_QDeclarativePathView()
219 void tst_QDeclarativePathView::initValues()
221 QDeclarativeEngine engine;
222 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview1.qml"));
223 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
226 QVERIFY(obj->path() == 0);
227 QVERIFY(obj->delegate() == 0);
228 QCOMPARE(obj->model(), QVariant());
229 QCOMPARE(obj->currentIndex(), 0);
230 QCOMPARE(obj->offset(), 0.);
231 QCOMPARE(obj->preferredHighlightBegin(), 0.);
232 QCOMPARE(obj->dragMargin(), 0.);
233 QCOMPARE(obj->count(), 0);
234 QCOMPARE(obj->pathItemCount(), -1);
237 void tst_QDeclarativePathView::items()
239 QDeclarativeView *canvas = createView();
242 model.addItem("Fred", "12345");
243 model.addItem("John", "2345");
244 model.addItem("Bob", "54321");
245 model.addItem("Bill", "4321");
247 QDeclarativeContext *ctxt = canvas->rootContext();
248 ctxt->setContextProperty("testModel", &model);
250 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview0.qml"));
251 qApp->processEvents();
253 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
254 QVERIFY(pathview != 0);
256 QCOMPARE(pathview->count(), model.count());
257 QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
258 QCOMPARE(pathview->childItems().count(), model.count()+1); // assumes all are visible, including highlight
260 for (int i = 0; i < model.count(); ++i) {
261 QDeclarativeText *name = findItem<QDeclarativeText>(pathview, "textName", i);
263 QCOMPARE(name->text(), model.name(i));
264 QDeclarativeText *number = findItem<QDeclarativeText>(pathview, "textNumber", i);
265 QVERIFY(number != 0);
266 QCOMPARE(number->text(), model.number(i));
269 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
272 QVERIFY(pathview->highlightItem());
273 QPointF start = path->pointAt(0.0);
275 offset.setX(pathview->highlightItem()->width()/2);
276 offset.setY(pathview->highlightItem()->height()/2);
277 QCOMPARE(pathview->highlightItem()->pos() + offset, start);
282 void tst_QDeclarativePathView::pathview2()
284 QDeclarativeEngine engine;
285 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview2.qml"));
286 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
289 QVERIFY(obj->path() != 0);
290 QVERIFY(obj->delegate() != 0);
291 QVERIFY(obj->model() != QVariant());
292 QCOMPARE(obj->currentIndex(), 0);
293 QCOMPARE(obj->offset(), 0.);
294 QCOMPARE(obj->preferredHighlightBegin(), 0.);
295 QCOMPARE(obj->dragMargin(), 0.);
296 QCOMPARE(obj->count(), 8);
297 QCOMPARE(obj->pathItemCount(), 10);
300 void tst_QDeclarativePathView::pathview3()
302 QDeclarativeEngine engine;
303 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview3.qml"));
304 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
307 QVERIFY(obj->path() != 0);
308 QVERIFY(obj->delegate() != 0);
309 QVERIFY(obj->model() != QVariant());
310 QCOMPARE(obj->currentIndex(), 0);
311 QCOMPARE(obj->offset(), 1.0);
312 QCOMPARE(obj->preferredHighlightBegin(), 0.5);
313 QCOMPARE(obj->dragMargin(), 24.);
314 QCOMPARE(obj->count(), 8);
315 QCOMPARE(obj->pathItemCount(), 4);
318 void tst_QDeclarativePathView::path()
320 QDeclarativeEngine engine;
321 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathtest.qml"));
322 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
325 QCOMPARE(obj->startX(), 120.);
326 QCOMPARE(obj->startY(), 100.);
327 QVERIFY(obj->path() != QPainterPath());
329 QDeclarativeListReference list(obj, "pathElements");
330 QCOMPARE(list.count(), 5);
332 QDeclarativePathAttribute* attr = qobject_cast<QDeclarativePathAttribute*>(list.at(0));
334 QCOMPARE(attr->name(), QString("scale"));
335 QCOMPARE(attr->value(), 1.0);
337 QDeclarativePathQuad* quad = qobject_cast<QDeclarativePathQuad*>(list.at(1));
339 QCOMPARE(quad->x(), 120.);
340 QCOMPARE(quad->y(), 25.);
341 QCOMPARE(quad->controlX(), 260.);
342 QCOMPARE(quad->controlY(), 75.);
344 QDeclarativePathPercent* perc = qobject_cast<QDeclarativePathPercent*>(list.at(2));
346 QCOMPARE(perc->value(), 0.3);
348 QDeclarativePathLine* line = qobject_cast<QDeclarativePathLine*>(list.at(3));
350 QCOMPARE(line->x(), 120.);
351 QCOMPARE(line->y(), 100.);
353 QDeclarativePathCubic* cubic = qobject_cast<QDeclarativePathCubic*>(list.at(4));
355 QCOMPARE(cubic->x(), 180.);
356 QCOMPARE(cubic->y(), 0.);
357 QCOMPARE(cubic->control1X(), -10.);
358 QCOMPARE(cubic->control1Y(), 90.);
359 QCOMPARE(cubic->control2X(), 210.);
360 QCOMPARE(cubic->control2Y(), 90.);
363 void tst_QDeclarativePathView::dataModel()
365 QDeclarativeView *canvas = createView();
367 QDeclarativeContext *ctxt = canvas->rootContext();
368 TestObject *testObject = new TestObject;
369 ctxt->setContextProperty("testObject", testObject);
372 model.addItem("red", "1");
373 model.addItem("green", "2");
374 model.addItem("blue", "3");
375 model.addItem("purple", "4");
376 model.addItem("gray", "5");
377 model.addItem("brown", "6");
378 model.addItem("yellow", "7");
379 model.addItem("thistle", "8");
380 model.addItem("cyan", "9");
381 model.addItem("peachpuff", "10");
382 model.addItem("powderblue", "11");
383 model.addItem("gold", "12");
384 model.addItem("sandybrown", "13");
386 ctxt->setContextProperty("testData", &model);
388 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/datamodel.qml"));
389 qApp->processEvents();
391 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
392 QVERIFY(pathview != 0);
394 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
395 QVERIFY(testObject->error() == false);
397 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathview, "wrapper", 0);
399 QCOMPARE(item->x(), 110.0);
400 QCOMPARE(item->y(), 10.0);
402 model.insertItem(4, "orange", "10");
405 QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
406 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 14);
408 QVERIFY(pathview->currentIndex() == 0);
410 QDeclarativeText *text = findItem<QDeclarativeText>(pathview, "myText", 4);
412 QCOMPARE(text->text(), model.name(4));
415 QCOMPARE(canvas->rootObject()->property("viewCount").toInt(), model.count());
416 text = findItem<QDeclarativeText>(pathview, "myText", 2);
418 QCOMPARE(text->text(), model.name(2));
420 testObject->setPathItemCount(5);
421 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
422 QVERIFY(testObject->error() == false);
424 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
426 QDeclarativeRectangle *testItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 4);
427 QVERIFY(testItem != 0);
428 testItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 5);
429 QVERIFY(testItem == 0);
431 pathview->setCurrentIndex(1);
433 model.insertItem(2, "pink", "2");
436 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
437 QVERIFY(pathview->currentIndex() == 1);
439 text = findItem<QDeclarativeText>(pathview, "myText", 2);
441 QCOMPARE(text->text(), model.name(2));
444 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
445 text = findItem<QDeclarativeText>(pathview, "myText", 3);
447 QCOMPARE(text->text(), model.name(3));
449 model.moveItem(3, 5);
450 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
451 QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(pathview, "wrapper");
452 foreach (QDeclarativeItem *item, items) {
453 QVERIFY(item->property("onPath").toBool());
457 pathview->setOffset(7);
458 pathview->setOffset(0);
459 QCOMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
461 pathview->setCurrentIndex(model.count()-1);
462 model.removeItem(model.count()-1);
463 QCOMPARE(pathview->currentIndex(), model.count()-1);
466 // Confirm that the target offset is adjusted when removing items
467 pathview->setCurrentIndex(model.count()-1);
468 QTRY_COMPARE(pathview->offset(), 1.);
469 pathview->setCurrentIndex(model.count()-5);
470 model.removeItem(model.count()-1);
471 model.removeItem(model.count()-1);
472 model.removeItem(model.count()-1);
473 QTRY_COMPARE(pathview->offset(), 2.);
478 void tst_QDeclarativePathView::pathMoved()
480 QDeclarativeView *canvas = createView();
483 model.addItem("Ben", "12345");
484 model.addItem("Bohn", "2345");
485 model.addItem("Bob", "54321");
486 model.addItem("Bill", "4321");
488 QDeclarativeContext *ctxt = canvas->rootContext();
489 ctxt->setContextProperty("testModel", &model);
491 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview0.qml"));
492 qApp->processEvents();
494 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
495 QVERIFY(pathview != 0);
497 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
499 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
501 QPointF start = path->pointAt(0.0);
502 QPointF offset;//Center of item is at point, but pos is from corner
503 offset.setX(firstItem->width()/2);
504 offset.setY(firstItem->height()/2);
505 QCOMPARE(firstItem->pos() + offset, start);
506 pathview->setOffset(1.0);
508 for(int i=0; i<model.count(); i++){
509 QDeclarativeRectangle *curItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", i);
510 QPointF itemPos(path->pointAt(0.25 + i*0.25));
511 QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
514 pathview->setOffset(0.0);
515 QCOMPARE(firstItem->pos() + offset, start);
517 // Change delegate size
518 pathview->setOffset(0.1);
519 pathview->setOffset(0.0);
520 canvas->rootObject()->setProperty("delegateWidth", 30);
521 QCOMPARE(firstItem->width(), 30.0);
522 offset.setX(firstItem->width()/2);
523 QTRY_COMPARE(firstItem->pos() + offset, start);
525 // Change delegate scale
526 pathview->setOffset(0.1);
527 pathview->setOffset(0.0);
528 canvas->rootObject()->setProperty("delegateScale", 1.2);
529 QTRY_COMPARE(firstItem->pos() + offset, start);
534 void tst_QDeclarativePathView::setCurrentIndex()
536 QDeclarativeView *canvas = createView();
539 model.addItem("Ben", "12345");
540 model.addItem("Bohn", "2345");
541 model.addItem("Bob", "54321");
542 model.addItem("Bill", "4321");
544 QDeclarativeContext *ctxt = canvas->rootContext();
545 ctxt->setContextProperty("testModel", &model);
547 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview0.qml"));
548 qApp->processEvents();
550 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
551 QVERIFY(pathview != 0);
553 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
555 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
557 QPointF start = path->pointAt(0.0);
558 QPointF offset;//Center of item is at point, but pos is from corner
559 offset.setX(firstItem->width()/2);
560 offset.setY(firstItem->height()/2);
561 QCOMPARE(firstItem->pos() + offset, start);
562 QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 0);
563 QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 0);
565 pathview->setCurrentIndex(2);
567 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 2);
568 QTRY_COMPARE(firstItem->pos() + offset, start);
569 QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 2);
570 QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 2);
572 pathview->decrementCurrentIndex();
573 QTRY_COMPARE(pathview->currentIndex(), 1);
574 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 1);
576 QTRY_COMPARE(firstItem->pos() + offset, start);
578 pathview->decrementCurrentIndex();
579 QTRY_COMPARE(pathview->currentIndex(), 0);
580 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
582 QTRY_COMPARE(firstItem->pos() + offset, start);
584 pathview->decrementCurrentIndex();
585 QTRY_COMPARE(pathview->currentIndex(), 3);
586 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 3);
588 QTRY_COMPARE(firstItem->pos() + offset, start);
590 pathview->incrementCurrentIndex();
591 QTRY_COMPARE(pathview->currentIndex(), 0);
592 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
594 QTRY_COMPARE(firstItem->pos() + offset, start);
599 void tst_QDeclarativePathView::resetModel()
601 QDeclarativeView *canvas = createView();
604 strings << "one" << "two" << "three";
605 QStringListModel model(strings);
607 QDeclarativeContext *ctxt = canvas->rootContext();
608 ctxt->setContextProperty("testModel", &model);
610 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaypath.qml"));
611 qApp->processEvents();
613 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
614 QVERIFY(pathview != 0);
616 QCOMPARE(pathview->count(), model.rowCount());
618 for (int i = 0; i < model.rowCount(); ++i) {
619 QDeclarativeText *display = findItem<QDeclarativeText>(pathview, "displayText", i);
620 QVERIFY(display != 0);
621 QCOMPARE(display->text(), strings.at(i));
625 strings << "four" << "five" << "six" << "seven";
626 model.setStringList(strings);
628 QCOMPARE(pathview->count(), model.rowCount());
630 for (int i = 0; i < model.rowCount(); ++i) {
631 QDeclarativeText *display = findItem<QDeclarativeText>(pathview, "displayText", i);
632 QVERIFY(display != 0);
633 QCOMPARE(display->text(), strings.at(i));
637 void tst_QDeclarativePathView::propertyChanges()
639 QDeclarativeView *canvas = createView();
641 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
643 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
646 QSignalSpy snapPositionSpy(pathView, SIGNAL(preferredHighlightBeginChanged()));
647 QSignalSpy dragMarginSpy(pathView, SIGNAL(dragMarginChanged()));
649 QCOMPARE(pathView->preferredHighlightBegin(), 0.1);
650 QCOMPARE(pathView->dragMargin(), 5.0);
652 pathView->setPreferredHighlightBegin(0.4);
653 pathView->setPreferredHighlightEnd(0.4);
654 pathView->setDragMargin(20.0);
656 QCOMPARE(pathView->preferredHighlightBegin(), 0.4);
657 QCOMPARE(pathView->preferredHighlightEnd(), 0.4);
658 QCOMPARE(pathView->dragMargin(), 20.0);
660 QCOMPARE(snapPositionSpy.count(), 1);
661 QCOMPARE(dragMarginSpy.count(), 1);
663 pathView->setPreferredHighlightBegin(0.4);
664 pathView->setPreferredHighlightEnd(0.4);
665 pathView->setDragMargin(20.0);
667 QCOMPARE(snapPositionSpy.count(), 1);
668 QCOMPARE(dragMarginSpy.count(), 1);
672 void tst_QDeclarativePathView::pathChanges()
674 QDeclarativeView *canvas = createView();
676 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
678 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
681 QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
684 QSignalSpy startXSpy(path, SIGNAL(startXChanged()));
685 QSignalSpy startYSpy(path, SIGNAL(startYChanged()));
687 QCOMPARE(path->startX(), 220.0);
688 QCOMPARE(path->startY(), 200.0);
690 path->setStartX(240.0);
691 path->setStartY(220.0);
693 QCOMPARE(path->startX(), 240.0);
694 QCOMPARE(path->startY(), 220.0);
696 QCOMPARE(startXSpy.count(),1);
697 QCOMPARE(startYSpy.count(),1);
699 path->setStartX(240);
700 path->setStartY(220);
702 QCOMPARE(startXSpy.count(),1);
703 QCOMPARE(startYSpy.count(),1);
705 QDeclarativePath *alternatePath = canvas->rootObject()->findChild<QDeclarativePath*>("alternatePath");
706 QVERIFY(alternatePath);
708 QSignalSpy pathSpy(pathView, SIGNAL(pathChanged()));
710 QCOMPARE(pathView->path(), path);
712 pathView->setPath(alternatePath);
713 QCOMPARE(pathView->path(), alternatePath);
714 QCOMPARE(pathSpy.count(),1);
716 pathView->setPath(alternatePath);
717 QCOMPARE(pathSpy.count(),1);
719 QDeclarativePathAttribute *pathAttribute = canvas->rootObject()->findChild<QDeclarativePathAttribute*>("pathAttribute");
720 QVERIFY(pathAttribute);
722 QSignalSpy nameSpy(pathAttribute, SIGNAL(nameChanged()));
723 QCOMPARE(pathAttribute->name(), QString("opacity"));
725 pathAttribute->setName("scale");
726 QCOMPARE(pathAttribute->name(), QString("scale"));
727 QCOMPARE(nameSpy.count(),1);
729 pathAttribute->setName("scale");
730 QCOMPARE(nameSpy.count(),1);
734 void tst_QDeclarativePathView::componentChanges()
736 QDeclarativeView *canvas = createView();
738 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
740 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
743 QDeclarativeComponent delegateComponent(canvas->engine());
744 delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
746 QSignalSpy delegateSpy(pathView, SIGNAL(delegateChanged()));
748 pathView->setDelegate(&delegateComponent);
749 QCOMPARE(pathView->delegate(), &delegateComponent);
750 QCOMPARE(delegateSpy.count(),1);
752 pathView->setDelegate(&delegateComponent);
753 QCOMPARE(delegateSpy.count(),1);
757 void tst_QDeclarativePathView::modelChanges()
759 QDeclarativeView *canvas = createView();
761 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
763 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
766 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
767 QVERIFY(alternateModel);
768 QVariant modelVariant = QVariant::fromValue(alternateModel);
769 QSignalSpy modelSpy(pathView, SIGNAL(modelChanged()));
771 pathView->setModel(modelVariant);
772 QCOMPARE(pathView->model(), modelVariant);
773 QCOMPARE(modelSpy.count(),1);
775 pathView->setModel(modelVariant);
776 QCOMPARE(modelSpy.count(),1);
778 pathView->setModel(QVariant());
779 QCOMPARE(modelSpy.count(),2);
784 void tst_QDeclarativePathView::pathUpdateOnStartChanged()
786 QDeclarativeView *canvas = createView();
788 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathUpdateOnStartChanged.qml"));
790 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
793 QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
795 QCOMPARE(path->startX(), 400.0);
796 QCOMPARE(path->startY(), 300.0);
798 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "wrapper", 0);
800 QCOMPARE(item->x(), path->startX() - item->width() / 2.0);
801 QCOMPARE(item->y(), path->startY() - item->height() / 2.0);
806 void tst_QDeclarativePathView::package()
808 QDeclarativeView *canvas = createView();
810 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview_package.qml"));
812 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("photoPathView");
815 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "pathItem");
817 QVERIFY(item->scale() != 1.0);
823 void tst_QDeclarativePathView::emptyModel()
825 QDeclarativeView *canvas = createView();
827 QStringListModel model;
829 QDeclarativeContext *ctxt = canvas->rootContext();
830 ctxt->setContextProperty("emptyModel", &model);
832 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/emptymodel.qml"));
833 qApp->processEvents();
835 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
836 QVERIFY(pathview != 0);
838 QCOMPARE(pathview->offset(), qreal(0.0));
843 void tst_QDeclarativePathView::closed()
845 QDeclarativeEngine engine;
848 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/openPath.qml"));
849 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
851 QCOMPARE(obj->isClosed(), false);
856 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/closedPath.qml"));
857 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
859 QCOMPARE(obj->isClosed(), true);
865 void tst_QDeclarativePathView::pathUpdate()
867 QDeclarativeView *canvas = createView();
869 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathUpdate.qml"));
871 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
874 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "wrapper", 0);
876 QCOMPARE(item->x(), 150.0);
881 void tst_QDeclarativePathView::visualDataModel()
883 QDeclarativeEngine engine;
884 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/vdm.qml"));
886 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
889 QCOMPARE(obj->count(), 3);
894 void tst_QDeclarativePathView::undefinedPath()
896 QDeclarativeEngine engine;
897 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/undefinedpath.qml"));
899 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
902 QCOMPARE(obj->count(), 3);
907 void tst_QDeclarativePathView::mouseDrag()
909 QDeclarativeView *canvas = createView();
910 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml"));
912 QApplication::setActiveWindow(canvas);
913 QTest::qWaitForWindowShown(canvas);
914 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
916 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
917 QVERIFY(pathview != 0);
919 int current = pathview->currentIndex();
921 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(10,100)));
924 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(30,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
925 QApplication::sendEvent(canvas->viewport(), &mv);
928 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
929 QApplication::sendEvent(canvas->viewport(), &mv);
932 QVERIFY(pathview->currentIndex() != current);
934 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(40,100)));
939 void tst_QDeclarativePathView::treeModel()
941 QDeclarativeView *canvas = createView();
943 QStandardItemModel model;
944 initStandardTreeModel(&model);
945 canvas->engine()->rootContext()->setContextProperty("myModel", &model);
947 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/treemodel.qml"));
949 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
950 QVERIFY(pathview != 0);
951 QCOMPARE(pathview->count(), 3);
953 QDeclarativeText *item = findItem<QDeclarativeText>(pathview, "wrapper", 0);
955 QCOMPARE(item->text(), QLatin1String("Row 1 Item"));
957 QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1)));
958 QCOMPARE(pathview->count(), 1);
960 QTRY_VERIFY(item = findItem<QDeclarativeText>(pathview, "wrapper", 0));
961 QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item"));
966 void tst_QDeclarativePathView::changePreferredHighlight()
968 QDeclarativeView *canvas = createView();
969 canvas->setFixedSize(400,200);
970 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml"));
972 QApplication::setActiveWindow(canvas);
973 QTest::qWaitForWindowShown(canvas);
974 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
976 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
977 QVERIFY(pathview != 0);
979 int current = pathview->currentIndex();
980 QCOMPARE(current, 0);
982 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
984 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
986 QPointF start = path->pointAt(0.5);
987 start.setX(qRound(start.x()));
988 start.setY(qRound(start.y()));
989 QPointF offset;//Center of item is at point, but pos is from corner
990 offset.setX(firstItem->width()/2);
991 offset.setY(firstItem->height()/2);
992 QTRY_COMPARE(firstItem->pos() + offset, start);
994 pathview->setPreferredHighlightBegin(0.8);
995 pathview->setPreferredHighlightEnd(0.8);
996 start = path->pointAt(0.8);
997 start.setX(qRound(start.x()));
998 start.setY(qRound(start.y()));
999 QTRY_COMPARE(firstItem->pos() + offset, start);
1000 QCOMPARE(pathview->currentIndex(), 0);
1005 QDeclarativeView *tst_QDeclarativePathView::createView()
1007 QDeclarativeView *canvas = new QDeclarativeView(0);
1008 canvas->setFixedSize(240,320);
1014 Find an item with the specified objectName. If index is supplied then the
1015 item must also evaluate the {index} expression equal to index
1017 template<typename T>
1018 T *tst_QDeclarativePathView::findItem(QGraphicsObject *parent, const QString &objectName, int index)
1020 const QMetaObject &mo = T::staticMetaObject;
1021 //qDebug() << parent->childItems().count() << "children";
1022 for (int i = 0; i < parent->childItems().count(); ++i) {
1023 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
1026 //qDebug() << "try" << item;
1027 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
1029 QDeclarativeExpression e(qmlContext(item), item, "index");
1030 if (e.evaluate().toInt() == index)
1031 return static_cast<T*>(item);
1033 return static_cast<T*>(item);
1036 item = findItem<T>(item, objectName, index);
1038 return static_cast<T*>(item);
1044 template<typename T>
1045 QList<T*> tst_QDeclarativePathView::findItems(QGraphicsObject *parent, const QString &objectName)
1048 const QMetaObject &mo = T::staticMetaObject;
1049 //qDebug() << parent->QGraphicsObject::children().count() << "children";
1050 for (int i = 0; i < parent->childItems().count(); ++i) {
1051 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
1054 //qDebug() << "try" << item;
1055 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
1056 items.append(static_cast<T*>(item));
1057 items += findItems<T>(item, objectName);
1063 QTEST_MAIN(tst_QDeclarativePathView)
1065 #include "tst_qdeclarativepathview.moc"