From: Marco Bubke Date: Mon, 22 Oct 2012 15:57:05 +0000 (+0200) Subject: Change qml list interface X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=3e9caba478695443669ff880334ea69db6f764eb;p=konrad%2Fqtdeclarative.git Change qml list interface Change-Id: I185c6f4cef6105544504324c1616b5995c219fe3 Reviewed-by: Christiaan Janssen --- diff --git a/src/particles/qquickparticlegroup.cpp b/src/particles/qquickparticlegroup.cpp index 63d54b0..cae5423 100644 --- a/src/particles/qquickparticlegroup.cpp +++ b/src/particles/qquickparticlegroup.cpp @@ -109,9 +109,9 @@ QQmlListProperty QQuickParticleGroup::particleChildren() { QQuickParticleSystem* system = qobject_cast(parent()); if (system) - return QQmlListProperty(this, 0, &QQuickParticleSystem::statePropertyRedirect); + return QQmlListProperty(this, 0, &QQuickParticleSystem::statePropertyRedirect, 0, 0, 0); else - return QQmlListProperty(this, 0, &delayedRedirect); + return QQmlListProperty(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 2aef3f2..e90633a 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -254,6 +254,32 @@ bool QQmlListReference::canCount() const } /*! + 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. \sa canAppend() @@ -366,16 +392,25 @@ 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 bc2feaf..e772022 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -69,10 +69,11 @@ public: QQmlListProperty(QObject *o, QList &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 045869e..12de9ff 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -941,7 +941,10 @@ QObject *QQmlVME::run(QList *errors, QObject *assign = objects.pop(); const List &list = lists.top(); - list.qListProperty.append((QQmlListProperty*)&list.qListProperty, assign); + if (list.qListProperty.append) + list.qListProperty.append((QQmlListProperty*)&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 *errors, if (!ptr) VME_EXCEPTION(tr("Cannot assign object to list"), instr.line); - - list.qListProperty.append((QQmlListProperty*)&list.qListProperty, ptr); + if (list.qListProperty.append) + list.qListProperty.append((QQmlListProperty*)&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 b2c60fe..9f18afc 100644 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ b/src/qml/qml/v8/qv8contextwrapper.cpp @@ -309,7 +309,6 @@ v8::Handle QV8ContextWrapper::Getter(v8::Local property, const QVariant &value = cp->propertyValues.at(propertyIdx); if (value.userType() == qMetaTypeId >()) { QQmlListProperty prop(context->asQQmlContext(), (void*) qintptr(propertyIdx), - 0, QQmlContextPrivate::context_count, QQmlContextPrivate::context_at); return engine->listWrapper()->newList(prop, qMetaTypeId >()); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 62fc81f..f213111 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2609,12 +2609,6 @@ void QQuickItemPrivate::children_clear(QQmlListProperty *prop) p->childItems.at(0)->setParentItem(0); } -void QQuickItemPrivate::visibleChildren_append(QQmlListProperty*, QQuickItem *self) -{ - // do nothing - qmlInfo(self) << "QQuickItem: visibleChildren property is readonly and cannot be assigned to."; -} - int QQuickItemPrivate::visibleChildren_count(QQmlListProperty *prop) { QQuickItemPrivate *p = QQuickItemPrivate::get(static_cast(prop->object)); @@ -3744,9 +3738,10 @@ QQmlListProperty QQuickItemPrivate::children() */ QQmlListProperty QQuickItemPrivate::visibleChildren() { - return QQmlListProperty(q_func(), 0, QQuickItemPrivate::visibleChildren_append, - QQuickItemPrivate::visibleChildren_count, - QQuickItemPrivate::visibleChildren_at); + return QQmlListProperty(q_func(), + 0, + QQuickItemPrivate::visibleChildren_count, + QQuickItemPrivate::visibleChildren_at); } diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp index 6f7afd5..a297ec9 100644 --- a/src/quick/items/qquickvisualdatamodel.cpp +++ b/src/quick/items/qquickvisualdatamodel.cpp @@ -597,7 +597,8 @@ QQmlListProperty 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 453b4a4..91f5269 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 *prop, QQuickItem *item) { @@ -78,6 +89,12 @@ public: return static_cast(prop->data)->children.at(index).item; } + static void children_clear(QQmlListProperty *prop) { + static_cast(prop->data)->itemCleared(static_cast(prop->data)->children); + static_cast(prop->data)->children.clear(); + static_cast(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 &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 children; }; @@ -168,8 +182,12 @@ QQuickVisualItemModel::QQuickVisualItemModel(QObject *parent) QQmlListProperty QQuickVisualItemModel::children() { Q_D(QQuickVisualItemModel); - return QQmlListProperty(this, d, d->children_append, - d->children_count, d->children_at); + return QQmlListProperty(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 028eb30..68f4553 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 b3a78f6..8b445e3 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 78ff64d..bd2c964 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 items READ items CONSTANT) Q_CLASSINFO("DefaultProperty", "items") public: - QQmlListProperty items() { return QQmlListProperty(this, 0, append); } + QQmlListProperty items() { return QQmlListProperty(this, 0, append, 0, 0, 0); } static void append(QQmlListProperty *property, StandardItem *item) {