diff options
16 files changed, 200 insertions, 65 deletions
diff --git a/doc/src/declarative/elements.qdoc b/doc/src/declarative/elements.qdoc index e62d546..8091f95 100644 --- a/doc/src/declarative/elements.qdoc +++ b/doc/src/declarative/elements.qdoc @@ -179,6 +179,7 @@ The following table lists the QML elements provided by the Qt Declarative module \o \l Column \o \l Row \o \l Grid +\o \l Flow \endlist \o diff --git a/doc/src/declarative/scope.qdoc b/doc/src/declarative/scope.qdoc index c588b45..964f7d5 100644 --- a/doc/src/declarative/scope.qdoc +++ b/doc/src/declarative/scope.qdoc @@ -160,7 +160,7 @@ Bindings have access to the scope object's properties without qualification. In the previous example, the binding accesses the \l Item's \c parent property directly, without needing any form of object prefix. QML introduces a more structured, object-oriented approach to JavaScript, and consequently does not -require (although it does support) use of the implicit \c this property. +require the use of the JavaScript \c this property. Care must be used when accessing \l {Attached Properties} from bindings due to their interaction with the scope object. Conceptually attached properties diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index 6ab77a7..847f1f5 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -62,7 +62,7 @@ MouseArea { becomes -Import “foo.js” as Foo +import “foo.js” as Foo MouseArea { onClicked: Foo.foo() } diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 611535c..e8f3652 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1438,10 +1438,6 @@ QDeclarativeItem::~QDeclarativeItem() */ void QDeclarativeItem::setParentItem(QDeclarativeItem *parent) { - QDeclarativeItem *oldParent = parentItem(); - if (parent == oldParent || !parent) return; - - QObject::setParent(parent); QGraphicsObject::setParentItem(parent); } diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 9b548d4..dd1edd6 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -501,6 +501,7 @@ void QDeclarativePathView::setCurrentIndex(int idx) } } } + d->currentItem = 0; d->moveReason = QDeclarativePathViewPrivate::SetIndex; d->currentIndex = idx; if (d->model->count()) { @@ -508,9 +509,9 @@ void QDeclarativePathView::setCurrentIndex(int idx) d->snapToCurrent(); int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count(); if (itemIndex < d->items.count()) { - QDeclarativeItem *item = d->items.at(itemIndex); - item->setFocus(true); - if (QDeclarativePathViewAttached *att = d->attached(item)) + d->currentItem = d->items.at(itemIndex); + d->currentItem->setFocus(true); + if (QDeclarativePathViewAttached *att = d->attached(d->currentItem)) att->setIsCurrentItem(true); } d->currentItemOffset = d->positionOfIndex(d->currentIndex); @@ -1083,6 +1084,7 @@ void QDeclarativePathView::refill() att->setIsCurrentItem(true); currentVisible = true; d->currentItemOffset = pos; + d->currentItem = item; } if (d->items.count() == 0) d->firstIndex = idx; @@ -1109,6 +1111,7 @@ void QDeclarativePathView::refill() att->setIsCurrentItem(true); currentVisible = true; d->currentItemOffset = pos; + d->currentItem = item; } d->items.prepend(item); d->updateItem(item, pos); @@ -1161,15 +1164,32 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count) if (!d->isValid() || !isComponentComplete()) return; + // fix current + bool currentChanged = false; + if (d->currentIndex >= modelIndex + count) { + d->currentIndex -= count; + currentChanged = true; + } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) { + // current item has been removed. + d->currentIndex = qMin(modelIndex, d->model->count()-1); + if (d->currentItem) { + if (QDeclarativePathViewAttached *att = d->attached(d->currentItem)) + att->setIsCurrentItem(true); + } + currentChanged = true; + } + QList<QDeclarativeItem *> removedItems = d->items; d->items.clear(); if (d->offset >= d->model->count()) d->offset = d->model->count() - 1; - //XXX update currentIndex + d->regenerate(); while (removedItems.count()) d->releaseItem(removedItems.takeLast()); d->updateCurrent(); + if (currentChanged) + emit currentIndexChanged(); emit countChanged(); } @@ -1181,10 +1201,17 @@ void QDeclarativePathView::itemsMoved(int from, int to, int count) QList<QDeclarativeItem *> removedItems = d->items; d->items.clear(); - //XXX update currentIndex d->regenerate(); while (removedItems.count()) d->releaseItem(removedItems.takeLast()); + + // Fix current index + if (d->currentIndex >= 0 && d->currentItem) { + int oldCurrent = d->currentIndex; + d->currentIndex = d->model->indexOf(d->currentItem, this); + if (oldCurrent != d->currentIndex) + emit currentIndexChanged(); + } d->updateCurrent(); } @@ -1247,11 +1274,12 @@ void QDeclarativePathViewPrivate::updateCurrent() } } currentIndex = idx; + currentItem = 0; itemIndex = (idx - firstIndex + model->count()) % model->count(); if (itemIndex < items.count()) { - QDeclarativeItem *item = items.at(itemIndex); - item->setFocus(true); - if (QDeclarativePathViewAttached *att = attached(item)) + currentItem = items.at(itemIndex); + currentItem->setFocus(true); + if (QDeclarativePathViewAttached *att = attached(currentItem)) att->setIsCurrentItem(true); } emit q->currentIndexChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index 90216c0..26ec4e5 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -124,6 +124,7 @@ public: QDeclarativePath *path; int currentIndex; + QDeclarativeGuard<QDeclarativeItem> currentItem; qreal currentItemOffset; qreal startPc; QPointF startPoint; diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 5e91224..b23b8c9 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -820,6 +820,9 @@ public: QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent) : QDeclarativeBasePositioner(*(new QDeclarativeFlowPrivate), Both, parent) { + Q_D(QDeclarativeFlow); + // Flow layout requires relayout if its own size changes too. + d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry); } /*! diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 2b8cf70..a9224ad 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -71,31 +71,30 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate() Contexts allow data to be exposed to the QML components instantiated by the QML engine. - Each QDeclarativeContext contains a set of properties, distinct from - its QObject properties, that allow data to be - explicitly bound to a context by name. The context properties are defined or - updated by calling QDeclarativeContext::setContextProperty(). The following example shows - a Qt model being bound to a context and then accessed from a QML file. + Each QDeclarativeContext contains a set of properties, distinct from its QObject + properties, that allow data to be explicitly bound to a context by name. The + context properties are defined and updated by calling + QDeclarativeContext::setContextProperty(). The following example shows a Qt model + being bound to a context and then accessed from a QML file. \code QDeclarativeEngine engine; - QDeclarativeContext context(engine.rootContext()); - context.setContextProperty("myModel", modelData); + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + context->setContextProperty("myModel", modelData); QDeclarativeComponent component(&engine, "ListView { model=myModel }"); - component.create(&context); + component.create(context); \endcode - To simplify binding and maintaining larger data sets, QObject's can be - added to a QDeclarativeContext. These objects are known as the context's default - objects. In this case all the properties of the QObject are - made available by name in the context, as though they were all individually - added by calling QDeclarativeContext::setContextProperty(). Changes to the property's - values are detected through the property's notify signal. This method is - also slightly more faster than manually adding property values. + To simplify binding and maintaining larger data sets, a context object can be set + on a QDeclarativeContext. All the properties of the context object are available + by name in the context, as though they were all individually added through calls + to QDeclarativeContext::setContextProperty(). Changes to the property's values are + detected through the property's notify signal. Setting a context object is both + faster and easier than manually adding and maintaing context property values. - The following example has the same effect as the one above, but it is - achieved using a default object. + The following example has the same effect as the previous one, but it uses a context + object. \code class MyDataSet : ... { @@ -104,46 +103,42 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate() ... }; - MyDataSet myDataSet; + MyDataSet *myDataSet = new MyDataSet; QDeclarativeEngine engine; - QDeclarativeContext context(engine.rootContext()); - context.setContextObject(&myDataSet); + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + context->setContextObject(myDataSet); QDeclarativeComponent component(&engine, "ListView { model=myModel }"); - component.create(&context); + component.create(context); \endcode - Default objects added first take precedence over those added later. All properties - added explicitly by QDeclarativeContext::setContextProperty() take precedence over default - object properties. + All properties added explicitly by QDeclarativeContext::setContextProperty() take + precedence over context object's properties. - Contexts are hierarchal, with the \l {QDeclarativeEngine::rootContext()}{root context} - being created by the QDeclarativeEngine. A component instantiated in a given context - has access to that context's data, as well as the data defined by its - ancestor contexts. Data values (including those added implicitly by the - default objects) in a context override those in ancestor contexts. Data - that should be available to all components instantiated by the QDeclarativeEngine - should be added to the \l {QDeclarativeEngine::rootContext()}{root context}. + Contexts form a hierarchy. The root of this heirarchy is the QDeclarativeEngine's + \l {QDeclarativeEngine::rootContext()}{root context}. A component instance can + access the data in its own context, as well as all its ancestor contexts. Data + can be made available to all instances by modifying the + \l {QDeclarativeEngine::rootContext()}{root context}. - In the following example, + The following example defines two contexts - \c context1 and \c context2. The + second context overrides the "b" context property inherited from the first with a + new value. \code QDeclarativeEngine engine; - QDeclarativeContext context1(engine.rootContext()); - QDeclarativeContext context2(&context1); - QDeclarativeContext context3(&context2); - - context1.setContextProperty("a", 12); - context2.setContextProperty("b", 13); - context3.setContextProperty("a", 14); - context3.setContextProperty("c", 14); + QDeclarativeContext *context1 = new QDeclarativeContext(engine.rootContext()); + QDeclarativeContext *context2 = new QDeclarativeContext(context1); + + context1->setContextProperty("a", 12); + context1->setContextProperty("b", 12); + + context2->setContextProperty("b", 15); \endcode - a QML component instantiated in context1 would have access to the "a" data, - a QML component instantiated in context2 would have access to the "a" and - "b" data, and a QML component instantiated in context3 would have access to - the "a", "b" and "c" data - although its "a" data would return 14, unlike - that in context1 or context2. + While QML objects instantiated in a context are not strictly owned by that + context, their bindings are. If a context is destroyed, the property bindings of + outstanding QML objects will stop evaluating. */ /*! \internal */ diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index 1d90bf8..fe5863f 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -114,6 +114,7 @@ private: QList<QDeclarativePixmapReply*> cancelled; QDeclarativeEngine *engine; QDeclarativeImageRequestHandler *handler; + QWaitCondition started; QMutex mutex; static QHash<QDeclarativeEngine *,QDeclarativeImageReader*> readers; @@ -370,8 +371,15 @@ QDeclarativeImageReader::~QDeclarativeImageReader() readers.remove(engine); readerMutex.unlock(); - quit(); - wait(); + if (isRunning()) { + quit(); + while (!wait(100)) { + // It is possible to for the quit to happen before exec() + // Need to wait until the event loop starts so that we + // can stop it. Particularly likely with an idle thread. + quit(); + } + } } QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *engine) @@ -380,6 +388,7 @@ QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *e QDeclarativeImageReader *reader = readers.value(engine); if (!reader) { reader = new QDeclarativeImageReader(engine); + reader->started.wait(&readerMutex); readers.insert(engine, reader); } readerMutex.unlock(); @@ -414,7 +423,10 @@ void QDeclarativeImageReader::cancel(QDeclarativePixmapReply *reply) void QDeclarativeImageReader::run() { + readerMutex.lock(); handler = new QDeclarativeImageRequestHandler(this, engine); + started.wakeAll(); + readerMutex.unlock(); exec(); diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml new file mode 100644 index 0000000..bd13bac --- /dev/null +++ b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml @@ -0,0 +1,39 @@ +import Qt 4.6 + +Item { + width: 90 + height: 480 + Flow { + anchors.fill: parent + Rectangle { + objectName: "one" + color: "red" + width: 50 + height: 50 + } + Rectangle { + objectName: "two" + color: "green" + width: 20 + height: 50 + } + Rectangle { + objectName: "three" + color: "blue" + width: 50 + height: 20 + } + Rectangle { + objectName: "four" + color: "cyan" + width: 50 + height: 50 + } + Rectangle { + objectName: "five" + color: "magenta" + width: 10 + height: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp index 0e1fee2..9026566 100644 --- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp +++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp @@ -65,6 +65,8 @@ private slots: void test_grid_animated(); void test_propertychanges(); void test_repeater(); + void test_flow(); + void test_flow_resize(); private: QDeclarativeView *createView(const QString &filename); }; @@ -441,6 +443,64 @@ void tst_QDeclarativePositioners::test_repeater() QCOMPARE(three->y(), 0.0); } +void tst_QDeclarativePositioners::test_flow() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 70.0); + QCOMPARE(five->x(), 50.0); + QCOMPARE(five->y(), 70.0); +} + +void tst_QDeclarativePositioners::test_flow_resize() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root); + root->setWidth(125); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild<QDeclarativeRectangle*>("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild<QDeclarativeRectangle*>("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild<QDeclarativeRectangle*>("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 70.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 50.0); + QCOMPARE(five->y(), 50.0); +} + QDeclarativeView *tst_QDeclarativePositioners::createView(const QString &filename) { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qmlvisual/animation/parentAnimation/data/parentAnimation.qml b/tests/auto/declarative/qmlvisual/animation/parentAnimation/data/parentAnimation-visual.qml index 5718560..5718560 100644 --- a/tests/auto/declarative/qmlvisual/animation/parentAnimation/data/parentAnimation.qml +++ b/tests/auto/declarative/qmlvisual/animation/parentAnimation/data/parentAnimation-visual.qml diff --git a/tests/auto/declarative/qmlvisual/animation/parentAnimation/parentAnimation.qml b/tests/auto/declarative/qmlvisual/animation/parentAnimation/parentAnimation-visual.qml index 8d0b375..8d0b375 100644 --- a/tests/auto/declarative/qmlvisual/animation/parentAnimation/parentAnimation.qml +++ b/tests/auto/declarative/qmlvisual/animation/parentAnimation/parentAnimation-visual.qml diff --git a/tests/auto/declarative/qmlvisual/animation/pauseAnimation/data/pauseAnimation.qml b/tests/auto/declarative/qmlvisual/animation/pauseAnimation/data/pauseAnimation-visual.qml index 73c6542..73c6542 100644 --- a/tests/auto/declarative/qmlvisual/animation/pauseAnimation/data/pauseAnimation.qml +++ b/tests/auto/declarative/qmlvisual/animation/pauseAnimation/data/pauseAnimation-visual.qml diff --git a/tests/auto/declarative/qmlvisual/animation/pauseAnimation/pauseAnimation.qml b/tests/auto/declarative/qmlvisual/animation/pauseAnimation/pauseAnimation-visual.qml index 8830170..8830170 100644 --- a/tests/auto/declarative/qmlvisual/animation/pauseAnimation/pauseAnimation.qml +++ b/tests/auto/declarative/qmlvisual/animation/pauseAnimation/pauseAnimation-visual.qml diff --git a/tests/auto/declarative/qmlvisual/tst_qmlvisual.cpp b/tests/auto/declarative/qmlvisual/tst_qmlvisual.cpp index f87fd29..8f1a406 100644 --- a/tests/auto/declarative/qmlvisual/tst_qmlvisual.cpp +++ b/tests/auto/declarative/qmlvisual/tst_qmlvisual.cpp @@ -97,12 +97,12 @@ void tst_qmlvisual::visual_data() QTest::addColumn<QString>("testdata"); QStringList files; - if (qgetenv("RUN_ALL") != "") + if (qgetenv("QMLVISUAL_ALL") != "") files << findQmlFiles(QDir(QT_TEST_SOURCE_DIR)); else { //these are tests we think are stable and useful enough to be run by the CI system - files << QT_TEST_SOURCE_DIR "/animation/pauseAnimation/pauseAnimation.qml"; - files << QT_TEST_SOURCE_DIR "/animation/parentAnimation/parentAnimation.qml"; + files << QT_TEST_SOURCE_DIR "/animation/pauseAnimation/pauseAnimation-visual.qml"; + files << QT_TEST_SOURCE_DIR "/animation/parentAnimation/parentAnimation-visual.qml"; files << QT_TEST_SOURCE_DIR "/animation/reanchor/reanchor.qml"; } @@ -124,7 +124,7 @@ void tst_qmlvisual::visual() QStringList arguments; arguments << "-script" << testdata << "-scriptopts" << "play,testimages,testerror,exitoncomplete,exitonfailure" - << file; + << file << "-graphicssystem" << "raster"; QProcess p; p.start(qmlruntime, arguments); QVERIFY(p.waitForFinished()); |