diff --git a/src/particles/qquickparticlegroup.cpp b/src/particles/qquickparticlegroup.cpp index 63d54b0e6c9fb7adadf1453ea1acdd9f56755579..cae5423379dd65e1cfe87f890b00370b38b98503 100644 --- a/src/particles/qquickparticlegroup.cpp +++ b/src/particles/qquickparticlegroup.cpp @@ -109,9 +109,9 @@ QQmlListProperty<QObject> QQuickParticleGroup::particleChildren() { QQuickParticleSystem* system = qobject_cast<QQuickParticleSystem*>(parent()); if (system) - return QQmlListProperty<QObject>(this, 0, &QQuickParticleSystem::statePropertyRedirect); + return QQmlListProperty<QObject>(this, 0, &QQuickParticleSystem::statePropertyRedirect, 0, 0, 0); else - return QQmlListProperty<QObject>(this, 0, &delayedRedirect); + return QQmlListProperty<QObject>(this, 0, &delayedRedirect, 0, 0, 0); } void QQuickParticleGroup::setSystem(QQuickParticleSystem* arg) diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 2aef3f2cd78b850f3de7f29e977596f7a2365765..e90633ac1a35d06257b957d486c4a1b5b9451241 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -253,6 +253,32 @@ bool QQmlListReference::canCount() const return (isValid() && d->property.count); } +/*! + Return true if at(), count(), append() and clear() are implemented, so you can manipulate + the list. + +\sa isReadable(), at(), count(), append(), clear() +*/ +bool QQmlListReference::isManipulable() const +{ + return (isValid() + && d->property.append + && d->property.count + && d->property.at + && d->property.clear); +} + + +/*! + Return true if at() and count() are implemented, so you can access the elements. + +\sa isManipulable(), at(), count() +*/ +bool QQmlListReference::isReadable() const +{ + return (isValid() && d->property.count && d->property.at); +} + /*! Appends \a object to the list. Returns true if the operation succeeded, otherwise false. @@ -365,17 +391,26 @@ writable QList violates QML's memory management rules. However, this constructo can very useful while prototyping. */ +/*! +\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, + CountFunction count, AtFunction at) + +Construct a readonly QQmlListProperty from a set of operation functions. An opaque \a data handle +may be passed which can be accessed from within the operation functions. The list property +remains valid while \a object exists. +*/ + /*! \fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, - CountFunction count = 0, AtFunction at = 0, - ClearFunction clear = 0) + CountFunction count, AtFunction at, + ClearFunction clear) Construct a QQmlListProperty from a set of operation functions. An opaque \a data handle may be passed which can be accessed from within the operation functions. The list property remains valid while \a object exists. -The \a append operation is compulsory and must be provided, while the \a count, \a at and -\a clear methods are optional. +You can pass a null pointer, but than the list will be not designable or changeable by the debugger. +So provide all function, except it is not possible. */ /*! diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h index bc2feaf22ff4e75636076b84536fac85316d1fb7..e7720226368f7c112b4cafc03b40c7e3615fb37f 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -69,10 +69,11 @@ public: QQmlListProperty(QObject *o, QList<T *> &list) : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), clear(qlist_clear), dummy1(0), dummy2(0) {} - QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0, - ClearFunction r = 0) + QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t, + ClearFunction r ) : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {} - + QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction t) + : object(o), data(d), append(0), count(c), at(t), clear(0), dummy1(0), dummy2(0) {} bool operator==(const QQmlListProperty &o) const { return object == o.object && data == o.data && @@ -132,6 +133,9 @@ public: bool canClear() const; bool canCount() const; + bool isManipulable() const; + bool isReadable() const; + bool append(QObject *) const; QObject *at(int) const; bool clear() const; diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 045869e15d1dd9f99889b7ce20902b1e49391853..12de9ffebd87540de38593cc275731f45c729e61 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -941,7 +941,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, QObject *assign = objects.pop(); const List &list = lists.top(); - list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, assign); + if (list.qListProperty.append) + list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, assign); + else + VME_EXCEPTION(tr("Cannot assign object to read only list"), -1); QML_END_INSTR(StoreObjectQList) QML_BEGIN_INSTR(AssignObjectList) @@ -959,8 +962,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors, if (!ptr) VME_EXCEPTION(tr("Cannot assign object to list"), instr.line); - - list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, ptr); + if (list.qListProperty.append) + list.qListProperty.append((QQmlListProperty<void>*)&list.qListProperty, ptr); + else + VME_EXCEPTION(tr("Cannot assign object to read only list"), -1); QML_END_INSTR(AssignObjectList) QML_BEGIN_INSTR(StoreInterface) diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp index b2c60fe7a893cb4875147725198cc0607f9ad058..9f18afc5cb711bb114776a27afb4e3ebeb072c11 100644 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ b/src/qml/qml/v8/qv8contextwrapper.cpp @@ -309,7 +309,6 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property, const QVariant &value = cp->propertyValues.at(propertyIdx); if (value.userType() == qMetaTypeId<QList<QObject*> >()) { QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx), - 0, QQmlContextPrivate::context_count, QQmlContextPrivate::context_at); return engine->listWrapper()->newList(prop, qMetaTypeId<QQmlListProperty<QObject> >()); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 62fc81fb674253df7f1735cc0ab8fb6712cb9bc9..f213111ccdd00fb462cd2623ea4736f18e2397bf 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2609,12 +2609,6 @@ void QQuickItemPrivate::children_clear(QQmlListProperty<QQuickItem> *prop) p->childItems.at(0)->setParentItem(0); } -void QQuickItemPrivate::visibleChildren_append(QQmlListProperty<QQuickItem>*, QQuickItem *self) -{ - // do nothing - qmlInfo(self) << "QQuickItem: visibleChildren property is readonly and cannot be assigned to."; -} - int QQuickItemPrivate::visibleChildren_count(QQmlListProperty<QQuickItem> *prop) { QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast<QQuickItem *>(prop->object)); @@ -3744,9 +3738,10 @@ QQmlListProperty<QQuickItem> QQuickItemPrivate::children() */ QQmlListProperty<QQuickItem> QQuickItemPrivate::visibleChildren() { - return QQmlListProperty<QQuickItem>(q_func(), 0, QQuickItemPrivate::visibleChildren_append, - QQuickItemPrivate::visibleChildren_count, - QQuickItemPrivate::visibleChildren_at); + return QQmlListProperty<QQuickItem>(q_func(), + 0, + QQuickItemPrivate::visibleChildren_count, + QQuickItemPrivate::visibleChildren_at); } diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 6f7afd51014bce39c1077fe04efee427e681aa95..a297ec90dfb9b098627980198587e0b9506f0708 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -597,7 +597,8 @@ QQmlListProperty<QQuickVisualDataGroup> QQuickVisualDataModel::groups() d, QQuickVisualDataModelPrivate::group_append, QQuickVisualDataModelPrivate::group_count, - QQuickVisualDataModelPrivate::group_at); + QQuickVisualDataModelPrivate::group_at, + 0); } /*! diff --git a/src/quick/items/qquickvisualitemmodel.cpp b/src/quick/items/qquickvisualitemmodel.cpp index 453b4a4b682cb76ae4677ab23a82a5a17dc42b24..91f52695ad91553647c39789ea171688cdf5d579 100644 --- a/src/quick/items/qquickvisualitemmodel.cpp +++ b/src/quick/items/qquickvisualitemmodel.cpp @@ -62,6 +62,17 @@ class QQuickVisualItemModelPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QQuickVisualItemModel) public: + class Item { + public: + Item(QQuickItem *i) : item(i), ref(0) {} + + void addRef() { ++ref; } + bool deref() { return --ref == 0; } + + QQuickItem *item; + int ref; + }; + QQuickVisualItemModelPrivate() : QObjectPrivate() {} static void children_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item) { @@ -78,6 +89,12 @@ public: return static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.at(index).item; } + static void children_clear(QQmlListProperty<QQuickItem> *prop) { + static_cast<QQuickVisualItemModelPrivate *>(prop->data)->itemCleared(static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children); + static_cast<QQuickVisualItemModelPrivate *>(prop->data)->children.clear(); + static_cast<QQuickVisualItemModelPrivate *>(prop->data)->emitChildrenChanged(); + } + void itemAppended() { Q_Q(QQuickVisualItemModel); QQuickVisualItemModelAttached *attached = QQuickVisualItemModelAttached::properties(children.last().item); @@ -88,6 +105,13 @@ public: emit q->countChanged(); } + void itemCleared(const QList<Item> &children) { + Q_Q(QQuickVisualItemModel); + foreach (const Item &child, children) + emit q->destroyingItem(child.item); + emit q->countChanged(); + } + void emitChildrenChanged() { Q_Q(QQuickVisualItemModel); emit q->childrenChanged(); @@ -100,16 +124,6 @@ public: return -1; } - class Item { - public: - Item(QQuickItem *i) : item(i), ref(0) {} - - void addRef() { ++ref; } - bool deref() { return --ref == 0; } - - QQuickItem *item; - int ref; - }; QList<Item> children; }; @@ -168,8 +182,12 @@ QQuickVisualItemModel::QQuickVisualItemModel(QObject *parent) QQmlListProperty<QQuickItem> QQuickVisualItemModel::children() { Q_D(QQuickVisualItemModel); - return QQmlListProperty<QQuickItem>(this, d, d->children_append, - d->children_count, d->children_at); + return QQmlListProperty<QQuickItem>(this, + d, + d->children_append, + d->children_count, + d->children_at, + d->children_clear); } /*! diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp index 028eb30f5373eb1b2f21bc166d96474c1865dc4b..68f4553921fbf407522f56a0dd7313a452e325f6 100644 --- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp +++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp @@ -68,6 +68,8 @@ private slots: void canAt(); void canClear(); void canCount(); + void isReadable(); + void isManipulable(); void append(); void at(); void clear(); @@ -128,6 +130,8 @@ void tst_qqmllistreference::qmllistreference_invalid() QVERIFY(r.at(10) == 0); QVERIFY(r.clear() == false); QVERIFY(r.count() == 0); + QVERIFY(r.isReadable() == false); + QVERIFY(r.isManipulable() == false); } // Non-property @@ -143,6 +147,8 @@ void tst_qqmllistreference::qmllistreference_invalid() QVERIFY(r.at(10) == 0); QVERIFY(r.clear() == false); QVERIFY(r.count() == 0); + QVERIFY(r.isReadable() == false); + QVERIFY(r.isManipulable() == false); } // Non-list property @@ -158,6 +164,8 @@ void tst_qqmllistreference::qmllistreference_invalid() QVERIFY(r.at(10) == 0); QVERIFY(r.clear() == false); QVERIFY(r.count() == 0); + QVERIFY(r.isReadable() == false); + QVERIFY(r.isManipulable() == false); } } @@ -343,6 +351,64 @@ void tst_qqmllistreference::canCount() } } +void tst_qqmllistreference::isReadable() +{ + TestType *tt = new TestType; + + { + QQmlListReference ref; + QVERIFY(ref.isReadable() == false); + } + + { + QQmlListReference ref(tt, "blah"); + QVERIFY(ref.isReadable() == false); + } + + { + QQmlListReference ref(tt, "data"); + QVERIFY(ref.isReadable() == true); + delete tt; + QVERIFY(ref.isReadable() == false); + } + + { + TestType tt; + tt.property.count = 0; + QQmlListReference ref(&tt, "data"); + QVERIFY(ref.isReadable() == false); + } +} + +void tst_qqmllistreference::isManipulable() +{ + TestType *tt = new TestType; + + { + QQmlListReference ref; + QVERIFY(ref.isManipulable() == false); + } + + { + QQmlListReference ref(tt, "blah"); + QVERIFY(ref.isManipulable() == false); + } + + { + QQmlListReference ref(tt, "data"); + QVERIFY(ref.isManipulable() == true); + delete tt; + QVERIFY(ref.isManipulable() == false); + } + + { + TestType tt; + tt.property.count = 0; + QQmlListReference ref(&tt, "data"); + QVERIFY(ref.isManipulable() == false); + } +} + void tst_qqmllistreference::append() { TestType *tt = new TestType; diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index b3a78f6a5ea87768cf54043c8d95aef949c4cdf4..8b445e38b95bbe8b034751ace6c5cbaf885a8b20 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -1551,10 +1551,9 @@ void tst_QQuickItem::visibleChildren() QCOMPARE(root->property("test4_3").toBool(), true); QCOMPARE(root->property("test4_4").toBool(), true); - QString warning1 = testFileUrl("visiblechildren.qml").toString() + ":96:32: QML Item: QQuickItem: visibleChildren property is readonly and cannot be assigned to."; + QString warning1 = testFileUrl("visiblechildren.qml").toString() + ":87: TypeError: Cannot read property 'visibleChildren' of null"; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); QMetaObject::invokeMethod(root, "tryWriteToReadonlyVisibleChildren"); - QCOMPARE(root->property("test5_1").toBool(), true); QMetaObject::invokeMethod(root, "reparentVisibleItem3"); QCOMPARE(root->property("test6_1").toBool(), true); diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp index 78ff64da076a06c664119e994a99bb0e7a60245e..bd2c964e1e11a5cc9365f7e82dc356be71be0c9b 100644 --- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp +++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp @@ -262,7 +262,7 @@ class StandardItemModel : public QStandardItemModel Q_PROPERTY(QQmlListProperty<StandardItem> items READ items CONSTANT) Q_CLASSINFO("DefaultProperty", "items") public: - QQmlListProperty<StandardItem> items() { return QQmlListProperty<StandardItem>(this, 0, append); } + QQmlListProperty<StandardItem> items() { return QQmlListProperty<StandardItem>(this, 0, append, 0, 0, 0); } static void append(QQmlListProperty<StandardItem> *property, StandardItem *item) {