aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2017-06-06 15:51:14 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2017-06-08 13:59:50 +0000
commit123f698c5bbf23ad816bf2274620ab4f0a82ed2f (patch)
tree12bbb64f44a4110ab1f2d5124245fefdc845d509
parentf4f89858cffa1107af5139dfb1e1d7b16ca3a1a0 (diff)
Allow freely mixing non-ShapePath objects in Shape
The own list property must be kept. However, we can reuse QQuickItemPrivate's data accessors in order to start supporting code like: Shape { .. ShapePath { ... } ShapePath { ... } Rectangle { ... } Image { ... } // any other visual type // or non-visual: Timer { ... } } Change-Id: I6d502d697cae37bf16857770273a749cee1b3aa3 Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
-rw-r--r--examples/quick/shapes/content/item1.qml17
-rw-r--r--examples/quick/shapes/content/pathiteminteract.qml8
-rw-r--r--src/imports/shapes/qquickshape.cpp52
-rw-r--r--src/imports/shapes/qquickshape_p.h6
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp10
5 files changed, 55 insertions, 38 deletions
diff --git a/examples/quick/shapes/content/item1.qml b/examples/quick/shapes/content/item1.qml
index 584a310af4..9328979324 100644
--- a/examples/quick/shapes/content/item1.qml
+++ b/examples/quick/shapes/content/item1.qml
@@ -74,5 +74,22 @@ Rectangle {
PathLine { x: 30; y: ctr.height - 30 }
PathLine { x: 30; y: 30 }
}
+
+ // Besides ShapePath, Shape supports visual and non-visual objects too, allowing
+ // free mixing without going through extra hoops:
+ Rectangle {
+ id: testRect
+ color: "green"
+ opacity: 0.3
+ width: 20
+ height: 20
+ anchors.right: parent.right
+ }
+ Timer {
+ interval: 100
+ repeat: true
+ onTriggered: testRect.width = testRect.width > 1 ? testRect.width - 1 : 20
+ running: true
+ }
}
}
diff --git a/examples/quick/shapes/content/pathiteminteract.qml b/examples/quick/shapes/content/pathiteminteract.qml
index b1c9cdf123..55a1d16299 100644
--- a/examples/quick/shapes/content/pathiteminteract.qml
+++ b/examples/quick/shapes/content/pathiteminteract.qml
@@ -195,7 +195,7 @@ Rectangle {
'startX: ' + x + '; startY: ' + y + ';' +
'PathLine { x: ' + x + ' + 1; y: ' + y + ' + 1 } }',
root, "dynamic_visual_path");
- shape.elements.push(p);
+ shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
if (!activePath)
@@ -218,7 +218,7 @@ Rectangle {
'PathCubic { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
'control1X: ' + x + ' + 50; control1Y: ' + y + ' + 50; control2X: ' + x + ' + 150; control2Y: ' + y + ' + 50; } }',
root, "dynamic_visual_path");
- shape.elements.push(p);
+ shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
if (!activePath)
@@ -243,7 +243,7 @@ Rectangle {
'PathQuad { x: ' + x + ' + 1; y: ' + y + ' + 1;' +
'controlX: ' + x + ' + 50; controlY: ' + y + ' + 50 } }',
root, "dynamic_visual_path");
- shape.elements.push(p);
+ shape.data.push(p);
activePath = p;
}, "move": function(x, y) {
if (!activePath)
@@ -279,7 +279,7 @@ Rectangle {
id: shape
anchors.fill: parent
- elements: []
+ data: []
}
}
}
diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp
index 3c253eabd4..0d060242b4 100644
--- a/src/imports/shapes/qquickshape.cpp
+++ b/src/imports/shapes/qquickshape.cpp
@@ -588,6 +588,11 @@ void QQuickShapePath::resetFillGradient()
\image pathitem-code-example.png
+ Like \l Item, Shape also allows any visual or non-visual objects to be
+ declared as children. ShapePath objects are handled specially. This is
+ useful since it allows adding visual items, like \l Rectangle or \l Image,
+ and non-visual objects, like \l Timer directly as children of Shape.
+
\note It is important to be aware of performance implications, in particular
when the application is running on the generic Shape implementation due to
not having support for accelerated path rendering. The geometry generation
@@ -788,31 +793,23 @@ QQuickShape::Status QQuickShape::status() const
return d->status;
}
-static QQuickShapePath *vpe_at(QQmlListProperty<QQuickShapePath> *property, int index)
-{
- QQuickShapePrivate *d = QQuickShapePrivate::get(static_cast<QQuickShape *>(property->object));
- return d->qmlData.sp.at(index);
-}
-
-static void vpe_append(QQmlListProperty<QQuickShapePath> *property, QQuickShapePath *obj)
+static void vpe_append(QQmlListProperty<QObject> *property, QObject *obj)
{
QQuickShape *item = static_cast<QQuickShape *>(property->object);
QQuickShapePrivate *d = QQuickShapePrivate::get(item);
- d->qmlData.sp.append(obj);
+ QQuickShapePath *path = qobject_cast<QQuickShapePath *>(obj);
+ if (path)
+ d->qmlData.sp.append(path);
+
+ QQuickItemPrivate::data_append(property, obj);
- if (d->componentComplete) {
- QObject::connect(obj, SIGNAL(shapePathChanged()), item, SLOT(_q_shapePathChanged()));
+ if (path && d->componentComplete) {
+ QObject::connect(path, SIGNAL(shapePathChanged()), item, SLOT(_q_shapePathChanged()));
d->_q_shapePathChanged();
}
}
-static int vpe_count(QQmlListProperty<QQuickShapePath> *property)
-{
- QQuickShapePrivate *d = QQuickShapePrivate::get(static_cast<QQuickShape *>(property->object));
- return d->qmlData.sp.count();
-}
-
-static void vpe_clear(QQmlListProperty<QQuickShapePath> *property)
+static void vpe_clear(QQmlListProperty<QObject> *property)
{
QQuickShape *item = static_cast<QQuickShape *>(property->object);
QQuickShapePrivate *d = QQuickShapePrivate::get(item);
@@ -822,27 +819,30 @@ static void vpe_clear(QQmlListProperty<QQuickShapePath> *property)
d->qmlData.sp.clear();
+ QQuickItemPrivate::data_clear(property);
+
if (d->componentComplete)
d->_q_shapePathChanged();
}
/*!
- \qmlproperty list<ShapePath> QtQuick.Shapes::Shape::elements
+ \qmlproperty list<Object> QtQuick.Shapes::Shape::data
This property holds the ShapePath objects that define the contents of the
- Shape.
+ Shape. It can also contain any other type of objects, since Shape, like Item,
+ allows adding any visual or non-visual objects as children.
\default
*/
-QQmlListProperty<QQuickShapePath> QQuickShape::elements()
+QQmlListProperty<QObject> QQuickShape::data()
{
- return QQmlListProperty<QQuickShapePath>(this,
- nullptr,
- vpe_append,
- vpe_count,
- vpe_at,
- vpe_clear);
+ return QQmlListProperty<QObject>(this,
+ nullptr,
+ vpe_append,
+ QQuickItemPrivate::data_count,
+ QQuickItemPrivate::data_at,
+ vpe_clear);
}
void QQuickShape::classBegin()
diff --git a/src/imports/shapes/qquickshape_p.h b/src/imports/shapes/qquickshape_p.h
index 50b242e492..c5096be229 100644
--- a/src/imports/shapes/qquickshape_p.h
+++ b/src/imports/shapes/qquickshape_p.h
@@ -227,8 +227,8 @@ class QQuickShape : public QQuickItem
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
Q_PROPERTY(bool enableVendorExtensions READ enableVendorExtensions WRITE setEnableVendorExtensions NOTIFY enableVendorExtensionsChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
- Q_PROPERTY(QQmlListProperty<QQuickShapePath> elements READ elements)
- Q_CLASSINFO("DefaultProperty", "elements")
+ Q_PROPERTY(QQmlListProperty<QObject> data READ data)
+ Q_CLASSINFO("DefaultProperty", "data")
public:
enum RendererType {
@@ -259,7 +259,7 @@ public:
Status status() const;
- QQmlListProperty<QQuickShapePath> elements();
+ QQmlListProperty<QObject> data();
protected:
QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *) override;
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index a984c28732..4f220cf801 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -80,7 +80,7 @@ void tst_QQuickShape::initValues()
QVERIFY(!obj->asynchronous());
QVERIFY(obj->enableVendorExtensions());
QVERIFY(obj->status() == QQuickShape::Null);
- auto vps = obj->elements();
+ auto vps = obj->data();
QVERIFY(vps.count(&vps) == 0);
delete obj;
@@ -97,10 +97,10 @@ void tst_QQuickShape::vpInitValues()
QVERIFY(!obj->asynchronous());
QVERIFY(obj->enableVendorExtensions());
QVERIFY(obj->status() == QQuickShape::Null);
- auto vps = obj->elements();
+ auto vps = obj->data();
QVERIFY(vps.count(&vps) == 2);
- QQuickShapePath *vp = vps.at(&vps, 0);
+ QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(vps.at(&vps, 0));
QVERIFY(vp != nullptr);
QQmlListReference pathList(vp, "pathElements");
QCOMPARE(pathList.count(), 0);
@@ -128,7 +128,7 @@ void tst_QQuickShape::basicShape()
QQuickShape *obj = findItem<QQuickShape>(window->rootObject(), "pathItem");
QVERIFY(obj != nullptr);
- QQmlListReference list(obj, "elements");
+ QQmlListReference list(obj, "data");
QCOMPARE(list.count(), 1);
QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
QVERIFY(vp != nullptr);
@@ -168,7 +168,7 @@ void tst_QQuickShape::changeSignals()
obj->setAsynchronous(false);
QCOMPARE(asyncPropSpy.count(), 2);
- QQmlListReference list(obj, "elements");
+ QQmlListReference list(obj, "data");
QQuickShapePath *vp = qobject_cast<QQuickShapePath *>(list.at(0));
QVERIFY(vp != nullptr);