Change qml list interface
authorMarco Bubke <marco.bubke@digia.com>
Mon, 22 Oct 2012 15:57:05 +0000 (17:57 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 23 Oct 2012 11:24:54 +0000 (13:24 +0200)
Change-Id: I185c6f4cef6105544504324c1616b5995c219fe3
Reviewed-by: Christiaan Janssen <christiaan.janssen@digia.com>
src/particles/qquickparticlegroup.cpp
src/qml/qml/qqmllist.cpp
src/qml/qml/qqmllist.h
src/qml/qml/qqmlvme.cpp
src/qml/qml/v8/qv8contextwrapper.cpp
src/quick/items/qquickitem.cpp
src/quick/items/qquickvisualdatamodel.cpp
src/quick/items/qquickvisualitemmodel.cpp
tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
tests/auto/quick/qquickitem2/tst_qquickitem.cpp
tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp

index 63d54b0..cae5423 100644 (file)
@@ -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)
index 2aef3f2..e90633a 100644 (file)
@@ -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.
 */
 
 /*!
index bc2feaf..e772022 100644 (file)
@@ -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;
index 045869e..12de9ff 100644 (file)
@@ -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)
index b2c60fe..9f18afc 100644 (file)
@@ -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> >());
index 62fc81f..f213111 100644 (file)
@@ -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);
 
 }
 
index 6f7afd5..a297ec9 100644 (file)
@@ -597,7 +597,8 @@ QQmlListProperty<QQuickVisualDataGroup> QQuickVisualDataModel::groups()
             d,
             QQuickVisualDataModelPrivate::group_append,
             QQuickVisualDataModelPrivate::group_count,
-            QQuickVisualDataModelPrivate::group_at);
+            QQuickVisualDataModelPrivate::group_at,
+            0);
 }
 
 /*!
index 453b4a4..91f5269 100644 (file)
@@ -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);
 }
 
 /*!
index 028eb30..68f4553 100644 (file)
@@ -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;
index b3a78f6..8b445e3 100644 (file)
@@ -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);
index 78ff64d..bd2c964 100644 (file)
@@ -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)
     {