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->childItems().count(), model.count()+1); // assumes all are visible, including highlight
258 for (int i = 0; i < model.count(); ++i) {
259 QDeclarativeText *name = findItem<QDeclarativeText>(pathview, "textName", i);
261 QCOMPARE(name->text(), model.name(i));
262 QDeclarativeText *number = findItem<QDeclarativeText>(pathview, "textNumber", i);
263 QVERIFY(number != 0);
264 QCOMPARE(number->text(), model.number(i));
267 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
270 QVERIFY(pathview->highlightItem());
271 QPointF start = path->pointAt(0.0);
273 offset.setX(pathview->highlightItem()->width()/2);
274 offset.setY(pathview->highlightItem()->height()/2);
275 QCOMPARE(pathview->highlightItem()->pos() + offset, start);
280 void tst_QDeclarativePathView::pathview2()
282 QDeclarativeEngine engine;
283 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview2.qml"));
284 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
287 QVERIFY(obj->path() != 0);
288 QVERIFY(obj->delegate() != 0);
289 QVERIFY(obj->model() != QVariant());
290 QCOMPARE(obj->currentIndex(), 0);
291 QCOMPARE(obj->offset(), 0.);
292 QCOMPARE(obj->preferredHighlightBegin(), 0.);
293 QCOMPARE(obj->dragMargin(), 0.);
294 QCOMPARE(obj->count(), 8);
295 QCOMPARE(obj->pathItemCount(), 10);
298 void tst_QDeclarativePathView::pathview3()
300 QDeclarativeEngine engine;
301 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathview3.qml"));
302 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
305 QVERIFY(obj->path() != 0);
306 QVERIFY(obj->delegate() != 0);
307 QVERIFY(obj->model() != QVariant());
308 QCOMPARE(obj->currentIndex(), 0);
309 QCOMPARE(obj->offset(), 1.0);
310 QCOMPARE(obj->preferredHighlightBegin(), 0.5);
311 QCOMPARE(obj->dragMargin(), 24.);
312 QCOMPARE(obj->count(), 8);
313 QCOMPARE(obj->pathItemCount(), 4);
316 void tst_QDeclarativePathView::path()
318 QDeclarativeEngine engine;
319 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/pathtest.qml"));
320 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
323 QCOMPARE(obj->startX(), 120.);
324 QCOMPARE(obj->startY(), 100.);
325 QVERIFY(obj->path() != QPainterPath());
327 QDeclarativeListReference list(obj, "pathElements");
328 QCOMPARE(list.count(), 5);
330 QDeclarativePathAttribute* attr = qobject_cast<QDeclarativePathAttribute*>(list.at(0));
332 QCOMPARE(attr->name(), QString("scale"));
333 QCOMPARE(attr->value(), 1.0);
335 QDeclarativePathQuad* quad = qobject_cast<QDeclarativePathQuad*>(list.at(1));
337 QCOMPARE(quad->x(), 120.);
338 QCOMPARE(quad->y(), 25.);
339 QCOMPARE(quad->controlX(), 260.);
340 QCOMPARE(quad->controlY(), 75.);
342 QDeclarativePathPercent* perc = qobject_cast<QDeclarativePathPercent*>(list.at(2));
344 QCOMPARE(perc->value(), 0.3);
346 QDeclarativePathLine* line = qobject_cast<QDeclarativePathLine*>(list.at(3));
348 QCOMPARE(line->x(), 120.);
349 QCOMPARE(line->y(), 100.);
351 QDeclarativePathCubic* cubic = qobject_cast<QDeclarativePathCubic*>(list.at(4));
353 QCOMPARE(cubic->x(), 180.);
354 QCOMPARE(cubic->y(), 0.);
355 QCOMPARE(cubic->control1X(), -10.);
356 QCOMPARE(cubic->control1Y(), 90.);
357 QCOMPARE(cubic->control2X(), 210.);
358 QCOMPARE(cubic->control2Y(), 90.);
361 void tst_QDeclarativePathView::dataModel()
363 QDeclarativeView *canvas = createView();
365 QDeclarativeContext *ctxt = canvas->rootContext();
366 TestObject *testObject = new TestObject;
367 ctxt->setContextProperty("testObject", testObject);
370 model.addItem("red", "1");
371 model.addItem("green", "2");
372 model.addItem("blue", "3");
373 model.addItem("purple", "4");
374 model.addItem("gray", "5");
375 model.addItem("brown", "6");
376 model.addItem("yellow", "7");
377 model.addItem("thistle", "8");
378 model.addItem("cyan", "9");
379 model.addItem("peachpuff", "10");
380 model.addItem("powderblue", "11");
381 model.addItem("gold", "12");
382 model.addItem("sandybrown", "13");
384 ctxt->setContextProperty("testData", &model);
386 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/datamodel.qml"));
387 qApp->processEvents();
389 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
390 QVERIFY(pathview != 0);
392 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
393 QVERIFY(testObject->error() == false);
395 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathview, "wrapper", 0);
397 QCOMPARE(item->x(), 110.0);
398 QCOMPARE(item->y(), 10.0);
400 model.insertItem(4, "orange", "10");
403 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 14);
405 QVERIFY(pathview->currentIndex() == 0);
407 QDeclarativeText *text = findItem<QDeclarativeText>(pathview, "myText", 4);
409 QCOMPARE(text->text(), model.name(4));
412 text = findItem<QDeclarativeText>(pathview, "myText", 2);
414 QCOMPARE(text->text(), model.name(2));
416 testObject->setPathItemCount(5);
417 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
418 QVERIFY(testObject->error() == false);
420 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
422 QDeclarativeRectangle *testItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 4);
423 QVERIFY(testItem != 0);
424 testItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 5);
425 QVERIFY(testItem == 0);
427 pathview->setCurrentIndex(1);
429 model.insertItem(2, "pink", "2");
432 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
433 QVERIFY(pathview->currentIndex() == 1);
435 text = findItem<QDeclarativeText>(pathview, "myText", 2);
437 QCOMPARE(text->text(), model.name(2));
440 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
441 text = findItem<QDeclarativeText>(pathview, "myText", 3);
443 QCOMPARE(text->text(), model.name(3));
445 model.moveItem(3, 5);
446 QTRY_COMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
447 QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(pathview, "wrapper");
448 foreach (QDeclarativeItem *item, items) {
449 QVERIFY(item->property("onPath").toBool());
453 pathview->setOffset(7);
454 pathview->setOffset(0);
455 QCOMPARE(findItems<QDeclarativeItem>(pathview, "wrapper").count(), 5);
457 pathview->setCurrentIndex(model.count()-1);
458 model.removeItem(model.count()-1);
459 QCOMPARE(pathview->currentIndex(), model.count()-1);
462 // Confirm that the target offset is adjusted when removing items
463 pathview->setCurrentIndex(model.count()-1);
464 QTRY_COMPARE(pathview->offset(), 1.);
465 pathview->setCurrentIndex(model.count()-5);
466 model.removeItem(model.count()-1);
467 model.removeItem(model.count()-1);
468 model.removeItem(model.count()-1);
469 QTRY_COMPARE(pathview->offset(), 2.);
474 void tst_QDeclarativePathView::pathMoved()
476 QDeclarativeView *canvas = createView();
479 model.addItem("Ben", "12345");
480 model.addItem("Bohn", "2345");
481 model.addItem("Bob", "54321");
482 model.addItem("Bill", "4321");
484 QDeclarativeContext *ctxt = canvas->rootContext();
485 ctxt->setContextProperty("testModel", &model);
487 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview0.qml"));
488 qApp->processEvents();
490 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
491 QVERIFY(pathview != 0);
493 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
495 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
497 QPointF start = path->pointAt(0.0);
498 QPointF offset;//Center of item is at point, but pos is from corner
499 offset.setX(firstItem->width()/2);
500 offset.setY(firstItem->height()/2);
501 QCOMPARE(firstItem->pos() + offset, start);
502 pathview->setOffset(1.0);
504 for(int i=0; i<model.count(); i++){
505 QDeclarativeRectangle *curItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", i);
506 QPointF itemPos(path->pointAt(0.25 + i*0.25));
507 QCOMPARE(curItem->pos() + offset, QPointF(qRound(itemPos.x()), qRound(itemPos.y())));
510 pathview->setOffset(0.0);
511 QCOMPARE(firstItem->pos() + offset, start);
513 // Change delegate size
514 pathview->setOffset(0.1);
515 pathview->setOffset(0.0);
516 canvas->rootObject()->setProperty("delegateWidth", 30);
517 QCOMPARE(firstItem->width(), 30.0);
518 offset.setX(firstItem->width()/2);
519 QTRY_COMPARE(firstItem->pos() + offset, start);
521 // Change delegate scale
522 pathview->setOffset(0.1);
523 pathview->setOffset(0.0);
524 canvas->rootObject()->setProperty("delegateScale", 1.2);
525 QTRY_COMPARE(firstItem->pos() + offset, start);
530 void tst_QDeclarativePathView::setCurrentIndex()
532 QDeclarativeView *canvas = createView();
535 model.addItem("Ben", "12345");
536 model.addItem("Bohn", "2345");
537 model.addItem("Bob", "54321");
538 model.addItem("Bill", "4321");
540 QDeclarativeContext *ctxt = canvas->rootContext();
541 ctxt->setContextProperty("testModel", &model);
543 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview0.qml"));
544 qApp->processEvents();
546 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
547 QVERIFY(pathview != 0);
549 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
551 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
553 QPointF start = path->pointAt(0.0);
554 QPointF offset;//Center of item is at point, but pos is from corner
555 offset.setX(firstItem->width()/2);
556 offset.setY(firstItem->height()/2);
557 QCOMPARE(firstItem->pos() + offset, start);
558 QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 0);
559 QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 0);
561 pathview->setCurrentIndex(2);
563 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 2);
564 QTRY_COMPARE(firstItem->pos() + offset, start);
565 QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 2);
566 QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 2);
568 pathview->decrementCurrentIndex();
569 QTRY_COMPARE(pathview->currentIndex(), 1);
570 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 1);
572 QTRY_COMPARE(firstItem->pos() + offset, start);
574 pathview->decrementCurrentIndex();
575 QTRY_COMPARE(pathview->currentIndex(), 0);
576 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
578 QTRY_COMPARE(firstItem->pos() + offset, start);
580 pathview->decrementCurrentIndex();
581 QTRY_COMPARE(pathview->currentIndex(), 3);
582 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 3);
584 QTRY_COMPARE(firstItem->pos() + offset, start);
586 pathview->incrementCurrentIndex();
587 QTRY_COMPARE(pathview->currentIndex(), 0);
588 firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
590 QTRY_COMPARE(firstItem->pos() + offset, start);
595 void tst_QDeclarativePathView::resetModel()
597 QDeclarativeView *canvas = createView();
600 strings << "one" << "two" << "three";
601 QStringListModel model(strings);
603 QDeclarativeContext *ctxt = canvas->rootContext();
604 ctxt->setContextProperty("testModel", &model);
606 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaypath.qml"));
607 qApp->processEvents();
609 QDeclarativePathView *pathview = findItem<QDeclarativePathView>(canvas->rootObject(), "view");
610 QVERIFY(pathview != 0);
612 QCOMPARE(pathview->count(), model.rowCount());
614 for (int i = 0; i < model.rowCount(); ++i) {
615 QDeclarativeText *display = findItem<QDeclarativeText>(pathview, "displayText", i);
616 QVERIFY(display != 0);
617 QCOMPARE(display->text(), strings.at(i));
621 strings << "four" << "five" << "six" << "seven";
622 model.setStringList(strings);
624 QCOMPARE(pathview->count(), model.rowCount());
626 for (int i = 0; i < model.rowCount(); ++i) {
627 QDeclarativeText *display = findItem<QDeclarativeText>(pathview, "displayText", i);
628 QVERIFY(display != 0);
629 QCOMPARE(display->text(), strings.at(i));
633 void tst_QDeclarativePathView::propertyChanges()
635 QDeclarativeView *canvas = createView();
637 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
639 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
642 QSignalSpy snapPositionSpy(pathView, SIGNAL(preferredHighlightBeginChanged()));
643 QSignalSpy dragMarginSpy(pathView, SIGNAL(dragMarginChanged()));
645 QCOMPARE(pathView->preferredHighlightBegin(), 0.1);
646 QCOMPARE(pathView->dragMargin(), 5.0);
648 pathView->setPreferredHighlightBegin(0.4);
649 pathView->setPreferredHighlightEnd(0.4);
650 pathView->setDragMargin(20.0);
652 QCOMPARE(pathView->preferredHighlightBegin(), 0.4);
653 QCOMPARE(pathView->preferredHighlightEnd(), 0.4);
654 QCOMPARE(pathView->dragMargin(), 20.0);
656 QCOMPARE(snapPositionSpy.count(), 1);
657 QCOMPARE(dragMarginSpy.count(), 1);
659 pathView->setPreferredHighlightBegin(0.4);
660 pathView->setPreferredHighlightEnd(0.4);
661 pathView->setDragMargin(20.0);
663 QCOMPARE(snapPositionSpy.count(), 1);
664 QCOMPARE(dragMarginSpy.count(), 1);
668 void tst_QDeclarativePathView::pathChanges()
670 QDeclarativeView *canvas = createView();
672 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
674 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
677 QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
680 QSignalSpy startXSpy(path, SIGNAL(startXChanged()));
681 QSignalSpy startYSpy(path, SIGNAL(startYChanged()));
683 QCOMPARE(path->startX(), 220.0);
684 QCOMPARE(path->startY(), 200.0);
686 path->setStartX(240.0);
687 path->setStartY(220.0);
689 QCOMPARE(path->startX(), 240.0);
690 QCOMPARE(path->startY(), 220.0);
692 QCOMPARE(startXSpy.count(),1);
693 QCOMPARE(startYSpy.count(),1);
695 path->setStartX(240);
696 path->setStartY(220);
698 QCOMPARE(startXSpy.count(),1);
699 QCOMPARE(startYSpy.count(),1);
701 QDeclarativePath *alternatePath = canvas->rootObject()->findChild<QDeclarativePath*>("alternatePath");
702 QVERIFY(alternatePath);
704 QSignalSpy pathSpy(pathView, SIGNAL(pathChanged()));
706 QCOMPARE(pathView->path(), path);
708 pathView->setPath(alternatePath);
709 QCOMPARE(pathView->path(), alternatePath);
710 QCOMPARE(pathSpy.count(),1);
712 pathView->setPath(alternatePath);
713 QCOMPARE(pathSpy.count(),1);
715 QDeclarativePathAttribute *pathAttribute = canvas->rootObject()->findChild<QDeclarativePathAttribute*>("pathAttribute");
716 QVERIFY(pathAttribute);
718 QSignalSpy nameSpy(pathAttribute, SIGNAL(nameChanged()));
719 QCOMPARE(pathAttribute->name(), QString("opacity"));
721 pathAttribute->setName("scale");
722 QCOMPARE(pathAttribute->name(), QString("scale"));
723 QCOMPARE(nameSpy.count(),1);
725 pathAttribute->setName("scale");
726 QCOMPARE(nameSpy.count(),1);
730 void tst_QDeclarativePathView::componentChanges()
732 QDeclarativeView *canvas = createView();
734 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
736 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
739 QDeclarativeComponent delegateComponent(canvas->engine());
740 delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
742 QSignalSpy delegateSpy(pathView, SIGNAL(delegateChanged()));
744 pathView->setDelegate(&delegateComponent);
745 QCOMPARE(pathView->delegate(), &delegateComponent);
746 QCOMPARE(delegateSpy.count(),1);
748 pathView->setDelegate(&delegateComponent);
749 QCOMPARE(delegateSpy.count(),1);
753 void tst_QDeclarativePathView::modelChanges()
755 QDeclarativeView *canvas = createView();
757 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychanges.qml"));
759 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
762 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
763 QVERIFY(alternateModel);
764 QVariant modelVariant = QVariant::fromValue(alternateModel);
765 QSignalSpy modelSpy(pathView, SIGNAL(modelChanged()));
767 pathView->setModel(modelVariant);
768 QCOMPARE(pathView->model(), modelVariant);
769 QCOMPARE(modelSpy.count(),1);
771 pathView->setModel(modelVariant);
772 QCOMPARE(modelSpy.count(),1);
774 pathView->setModel(QVariant());
775 QCOMPARE(modelSpy.count(),2);
780 void tst_QDeclarativePathView::pathUpdateOnStartChanged()
782 QDeclarativeView *canvas = createView();
784 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathUpdateOnStartChanged.qml"));
786 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
789 QDeclarativePath *path = canvas->rootObject()->findChild<QDeclarativePath*>("path");
791 QCOMPARE(path->startX(), 400.0);
792 QCOMPARE(path->startY(), 300.0);
794 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "wrapper", 0);
796 QCOMPARE(item->x(), path->startX() - item->width() / 2.0);
797 QCOMPARE(item->y(), path->startY() - item->height() / 2.0);
802 void tst_QDeclarativePathView::package()
804 QDeclarativeView *canvas = createView();
806 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathview_package.qml"));
808 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("photoPathView");
811 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "pathItem");
813 QVERIFY(item->scale() != 1.0);
819 void tst_QDeclarativePathView::emptyModel()
821 QDeclarativeView *canvas = createView();
823 QStringListModel model;
825 QDeclarativeContext *ctxt = canvas->rootContext();
826 ctxt->setContextProperty("emptyModel", &model);
828 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/emptymodel.qml"));
829 qApp->processEvents();
831 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
832 QVERIFY(pathview != 0);
834 QCOMPARE(pathview->offset(), qreal(0.0));
839 void tst_QDeclarativePathView::closed()
841 QDeclarativeEngine engine;
844 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/openPath.qml"));
845 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
847 QCOMPARE(obj->isClosed(), false);
852 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/closedPath.qml"));
853 QDeclarativePath *obj = qobject_cast<QDeclarativePath*>(c.create());
855 QCOMPARE(obj->isClosed(), true);
861 void tst_QDeclarativePathView::pathUpdate()
863 QDeclarativeView *canvas = createView();
865 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pathUpdate.qml"));
867 QDeclarativePathView *pathView = canvas->rootObject()->findChild<QDeclarativePathView*>("pathView");
870 QDeclarativeItem *item = findItem<QDeclarativeItem>(pathView, "wrapper", 0);
872 QCOMPARE(item->x(), 150.0);
877 void tst_QDeclarativePathView::visualDataModel()
879 QDeclarativeEngine engine;
880 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/vdm.qml"));
882 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
885 QCOMPARE(obj->count(), 3);
890 void tst_QDeclarativePathView::undefinedPath()
892 QDeclarativeEngine engine;
893 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/undefinedpath.qml"));
895 QDeclarativePathView *obj = qobject_cast<QDeclarativePathView*>(c.create());
898 QCOMPARE(obj->count(), 3);
903 void tst_QDeclarativePathView::mouseDrag()
905 QDeclarativeView *canvas = createView();
906 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml"));
908 QApplication::setActiveWindow(canvas);
909 QTest::qWaitForWindowShown(canvas);
910 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
912 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
913 QVERIFY(pathview != 0);
915 int current = pathview->currentIndex();
917 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(10,100)));
920 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(30,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
921 QApplication::sendEvent(canvas->viewport(), &mv);
924 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(90,100)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
925 QApplication::sendEvent(canvas->viewport(), &mv);
928 QVERIFY(pathview->currentIndex() != current);
930 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(40,100)));
935 void tst_QDeclarativePathView::treeModel()
937 QDeclarativeView *canvas = createView();
939 QStandardItemModel model;
940 initStandardTreeModel(&model);
941 canvas->engine()->rootContext()->setContextProperty("myModel", &model);
943 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/treemodel.qml"));
945 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
946 QVERIFY(pathview != 0);
947 QCOMPARE(pathview->count(), 3);
949 QDeclarativeText *item = findItem<QDeclarativeText>(pathview, "wrapper", 0);
951 QCOMPARE(item->text(), QLatin1String("Row 1 Item"));
953 QVERIFY(QMetaObject::invokeMethod(pathview, "setRoot", Q_ARG(QVariant, 1)));
954 QCOMPARE(pathview->count(), 1);
956 QTRY_VERIFY(item = findItem<QDeclarativeText>(pathview, "wrapper", 0));
957 QTRY_COMPARE(item->text(), QLatin1String("Row 2 Child Item"));
962 void tst_QDeclarativePathView::changePreferredHighlight()
964 QDeclarativeView *canvas = createView();
965 canvas->setFixedSize(400,200);
966 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/dragpath.qml"));
968 QApplication::setActiveWindow(canvas);
969 QTest::qWaitForWindowShown(canvas);
970 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(canvas));
972 QDeclarativePathView *pathview = qobject_cast<QDeclarativePathView*>(canvas->rootObject());
973 QVERIFY(pathview != 0);
975 int current = pathview->currentIndex();
976 QCOMPARE(current, 0);
978 QDeclarativeRectangle *firstItem = findItem<QDeclarativeRectangle>(pathview, "wrapper", 0);
980 QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
982 QPointF start = path->pointAt(0.5);
983 start.setX(qRound(start.x()));
984 start.setY(qRound(start.y()));
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 QTRY_COMPARE(firstItem->pos() + offset, start);
990 pathview->setPreferredHighlightBegin(0.8);
991 pathview->setPreferredHighlightEnd(0.8);
992 start = path->pointAt(0.8);
993 start.setX(qRound(start.x()));
994 start.setY(qRound(start.y()));
995 QTRY_COMPARE(firstItem->pos() + offset, start);
996 QCOMPARE(pathview->currentIndex(), 0);
1001 QDeclarativeView *tst_QDeclarativePathView::createView()
1003 QDeclarativeView *canvas = new QDeclarativeView(0);
1004 canvas->setFixedSize(240,320);
1010 Find an item with the specified objectName. If index is supplied then the
1011 item must also evaluate the {index} expression equal to index
1013 template<typename T>
1014 T *tst_QDeclarativePathView::findItem(QGraphicsObject *parent, const QString &objectName, int index)
1016 const QMetaObject &mo = T::staticMetaObject;
1017 //qDebug() << parent->childItems().count() << "children";
1018 for (int i = 0; i < parent->childItems().count(); ++i) {
1019 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
1022 //qDebug() << "try" << item;
1023 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
1025 QDeclarativeExpression e(qmlContext(item), item, "index");
1026 if (e.evaluate().toInt() == index)
1027 return static_cast<T*>(item);
1029 return static_cast<T*>(item);
1032 item = findItem<T>(item, objectName, index);
1034 return static_cast<T*>(item);
1040 template<typename T>
1041 QList<T*> tst_QDeclarativePathView::findItems(QGraphicsObject *parent, const QString &objectName)
1044 const QMetaObject &mo = T::staticMetaObject;
1045 //qDebug() << parent->QGraphicsObject::children().count() << "children";
1046 for (int i = 0; i < parent->childItems().count(); ++i) {
1047 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
1050 //qDebug() << "try" << item;
1051 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
1052 items.append(static_cast<T*>(item));
1053 items += findItems<T>(item, objectName);
1059 QTEST_MAIN(tst_QDeclarativePathView)
1061 #include "tst_qdeclarativepathview.moc"