aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2017-09-22 22:48:25 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2018-01-25 16:23:08 +0000
commitbf5f171db212b7e57493f31f41e05e2d68ade791 (patch)
tree5b9b1c0796c5910e8a1cb918fd685bffc0a2d8ec
parentbf74a908cb0591c2adc024a6f93d566c7348c125 (diff)
QQuickShape: override contains(QPointF); demonstrate in examples
QQuickItem::contains() only checks the Item's bounding box by default. In the case of Shapes, that can be comically imprecise, but it's fast. So we add a containsMode property to control whether we will do that (the default) or actually check each of the QPainterPaths within to see whether they contain the point (FillContains). FillContains could be optimized later: use QRegion perhaps, or download the rendered texture from the GPU and test whether the pixel at the point is transparent. It may also be appropriate to add a StrokeContains option. The main motivation is to detect mouse (or touch) interaction within a shaped area. QQuickSinglePointHandler::wantsEventPoint() already checks whether its parent Item contains the event point. So if a Shape has a TapHandler for example, it will respond only within the visible bounds of the Shape rather than within the entire rectangular bounding box as long as containsMode is set to FillContains. Examples quick/shapes/content/tapableTriangle.qml and tiger.qml are modified to react when a press occurs inside, and the former is fixed to be able to run standalone via the qml runtime. The latter has an offset issue when run standalone but is OK within the shape gallery example. As a drive-by optimization, QQuickShapePrivate's variables are re-ordered by type so that the compiler can place the bools and enums into bitfields; and to facilitate reordering, the initialization is done C++11-style, in the header. [ChangeLog][QtQuick][Shape] A containsMode property is added. If it is set to FillContains, then Shape.contains() returns true only within the visible bounds, so its Pointer Handlers also respond only within those bounds. Change-Id: I31c85a9b08aa6945c58dc07febfe89ffef21274b Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
-rw-r--r--examples/quick/shapes/content/shapegallery.qml2
-rw-r--r--examples/quick/shapes/content/tapableTriangle.qml (renamed from examples/quick/shapes/content/item1.qml)14
-rw-r--r--examples/quick/shapes/content/tiger.qml106
-rw-r--r--examples/quick/shapes/shapes.pro2
-rw-r--r--examples/quick/shapes/shapes.qrc2
-rw-r--r--src/imports/shapes/plugin.cpp6
-rw-r--r--src/imports/shapes/plugins.qmltypes15
-rw-r--r--src/imports/shapes/qquickshape.cpp61
-rw-r--r--src/imports/shapes/qquickshape_p.h13
-rw-r--r--src/imports/shapes/qquickshape_p_p.h1
-rw-r--r--src/imports/shapes/shapes.pro2
11 files changed, 206 insertions, 18 deletions
diff --git a/examples/quick/shapes/content/shapegallery.qml b/examples/quick/shapes/content/shapegallery.qml
index 4096743833..86445e25c2 100644
--- a/examples/quick/shapes/content/shapegallery.qml
+++ b/examples/quick/shapes/content/shapegallery.qml
@@ -68,7 +68,7 @@ Rectangle {
id: pathGalleryModel
ListElement {
name: "Stroke and fill"
- shapeUrl: "item1.qml"
+ shapeUrl: "tapableTriangle.qml"
}
ListElement {
name: "Stroke or fill only"
diff --git a/examples/quick/shapes/content/item1.qml b/examples/quick/shapes/content/tapableTriangle.qml
index 9328979324..ba1fa1e460 100644
--- a/examples/quick/shapes/content/item1.qml
+++ b/examples/quick/shapes/content/tapableTriangle.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -48,15 +48,21 @@
**
****************************************************************************/
-import QtQuick 2.9
-import QtQuick.Shapes 1.0
+import QtQuick 2.11
+import QtQuick.Shapes 1.11
+import Qt.labs.handlers 1.0
Rectangle {
- color: "lightGray"
+ width: 120
+ height: 120
+ color: th.pressed ? "steelBlue" : "lightGray"
Shape {
id: ctr
anchors.fill: parent
+ containsMode: Shape.FillContains
+
+ TapHandler { id: th }
ShapePath {
strokeColor: "red"
diff --git a/examples/quick/shapes/content/tiger.qml b/examples/quick/shapes/content/tiger.qml
index 50cb103d50..7fa6ca2706 100644
--- a/examples/quick/shapes/content/tiger.qml
+++ b/examples/quick/shapes/content/tiger.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -48,13 +48,13 @@
**
****************************************************************************/
-import QtQuick 2.9
-import QtQuick.Shapes 1.0
+import QtQuick 2.11
+import QtQuick.Shapes 1.11
+import Qt.labs.handlers 1.0
Shape {
asynchronous: true
-
- anchors.fill: parent
+ width: 494; height: 510
ShapePath {
fillColor: "#ffffff"
@@ -3616,4 +3616,100 @@ Shape {
PathMove { x: 20.5; y: 344.5 }
PathCubic { control1X: 20.5; control1Y: 344.5; control2X: 22; control2Y: 333.5; x: 10.5; y: 346.5 }
}
+
+ Shape {
+ x: -184; y: -144; width: parent.width; height: parent.height
+ opacity: tapHandler.pressed ? 1 : 0
+ containsMode: Shape.FillContains
+
+ TapHandler { id: tapHandler }
+
+ ShapePath {
+ strokeColor: "red"
+ strokeWidth: 4
+ fillColor: "transparent"
+ PathSvg { path: "m 325.03711,0.5
+ c -26.61408,6.4494547 -49.95197,2.1018066 -76.21132,1.0771669
+ -22.26577,7.6817151 -47.96405,9.3627181 -65.67832,25.8497861
+ -15.74718,12.80008 -41.1564,19.605644 -45.74903,40.600391
+ -12.46933,17.76181 -25.36105,35.720146 -29.20117,57.999996
+ -18.709864,3.10961 -16.347355,30.83801 -22.385143,46.675
+ -6.848711,11.2677 11.07278,24.69174 -8.514666,27.97383
+ -10.266901,5.61543 -12.859313,28.96588 -13.732346,5.78143
+ 0.940083,-11.53398 -13.486195,-38.30626 -16.81701,-34.20231
+ 14.608079,7.8234 21.299281,50.52979 11.380052,48.14418
+ -3.406456,-15.12428 -26.181106,-38.29457 -31.849471,-35.62945
+ 16.851912,6.41472 35.569884,31.75215 28.172486,47.93115
+ -7.906485,-15.42757 -37.758959,-35.53783 -44.275447,-31.28685
+ 18.975831,1.7428 37.986009,20.68109 42.87115,37.14427 C
+ 42.279655,225.774 9.879724,213.57795 4.7080253,219.04989
+ 20.780803,212.57418 55.055919,239.88547 49.602579,241.25683
+ 38.186641,230.40078 6.6930104,222.77983 2.5752529,228.41774 c
+ 13.6045481,-8.33065 49.4437901,14.89041 43.5525671,14.2358
+ -9.759981,-7.96123 -43.5842921,7.36937 -17.554974,-1.20248
+ 9.464499,-3.73452 40.555672,12.80659 16.398749,5.14121
+ -9.1987,-7.28225 -39.0013156,3.37352 -14.121965,-2.12828
+ 13.244874,-0.0206 35.758428,14.62706 10.562447,6.42228
+ -10.780465,-8.4873 -47.8282254,11.10651 -21.027329,-0.003
+ 11.640859,-4.82877 52.615601,10.74471 24.234828,8.2659
+ -10.695834,-7.03902 -42.9384162,8.93905 -34.227854,5.58373
+ 9.077539,-8.56443 49.068801,-5.28097 43.06838,0.45546
+ -10.900893,-0.7118 -27.449619,17.27258 -10.00187,3.46526
+ 15.705191,-9.18198 18.344231,9.31645 1.10807,8.73907
+ -9.908444,1.77856 -21.108189,20.66671 -7.974821,4.92019
+ 15.750746,-14.10374 34.01348,2.07267 9.796961,8.69337
+ -8.17128,5.49929 -12.642664,19.13654 -3.994573,4.19708
+ 9.044753,-8.7077 23.850399,-13.64552 21.404959,4.02329
+ 12.509737,17.12562 51.158782,11.0442 45.106112,43.34009
+ -0.65006,10.05318 -3.79228,13.95389 1.62128,14.30064
+ -4.30913,8.82737 -14.652714,37.9591 2.92144,17.46024
+ 7.37972,-3.68333 -7.62399,16.24161 -7.98007,23.83761
+ -9.336865,18.77418 19.74873,-18.55943 6.62229,5.46195
+ 5.46464,-3.7389 36.23886,-19.41901 14.78167,0.58987
+ -8.59505,4.55644 29.29441,-2.99423 8.95489,6.47134 -9.22562,5.54437
+ -24.09765,26.79976 -11.73274,22.20385 -0.81685,5.4936
+ -1.58629,21.47626 2.34158,9.14886 1.61237,14.67029
+ -2.38384,25.22225 12.26908,15.1741 -4.40761,8.01039
+ -8.23679,36.91214 5.12235,17.92578 1.53454,2.99551 9.37569,3.1726
+ 7.15304,14.93579 3.51234,-11.31873 18.4607,-29.83809
+ 12.36869,-6.48005 -0.22629,16.26174 5.44303,-7.24791
+ 6.56926,10.49819 12.45412,28.9931 3.40908,-41.89883
+ 17.52051,-9.19238 3.23093,11.1924 6.53006,29.46941 7.55984,5.1249
+ 15.37236,-19.52583 4.09776,20.07416 12.64063,1.48215
+ 18.11247,-24.55068 -8.92586,38.39355 6.73828,6.62225
+ 4.55353,-6.91007 15.35028,-38.88977 12.55806,-13.78666
+ 1.05309,27.02664 11.54743,-24.40259 12.40657,6.86306
+ -1.72561,13.28253 11.85393,-24.15909 13.85568,-1.38002
+ 3.12455,8.33539 8.76536,26.46432 8.73882,5.09231 3.57025,-10.37352
+ -16.025,-37.75672 0.20707,-22.5788 -1.2458,-14.17213
+ -2.38918,-16.90145 10.85489,-6.71468 -16.57629,-17.22152
+ 0.19706,-26.08949 5.7751,-19.14889 -14.91681,-16.1674
+ 19.74174,7.19334 2.31875,-9.86869 -4.32508,-15.23278
+ 27.25228,29.12341 20.27514,18.81172 -11.97527,-18.92603
+ -17.96305,-45.80333 11.70099,-51.52566 17.19069,-9.57351
+ 31.17452,21.93154 38.50541,1.56304 16.26048,-4.6633
+ 22.3749,38.26516 24.86349,9.11316 5.94153,-9.9731 30.14313,6.97379
+ 36.34294,4.75012 7.07435,18.27732 8.06778,14.78971 11.04264,3.86016
+ 2.73754,-15.85945 28.7269,10.06391 28.09146,25.96561 3.00672,2.4754
+ 6.55025,-22.10264 11.23552,-14.43872 2.84155,-11.4823
+ -3.28976,-27.88574 4.24895,-25.5189 -0.61494,-11.53957
+ 22.83611,0.11011 10.64648,-15.28756 -6.5587,-21.38598
+ 9.32959,-3.0159 13.5107,-4.69375 -1.38592,-16.74533
+ -8.66673,-31.83316 -1.90087,-41.0875 2.39623,-15.14303
+ -12.50533,-44.45478 -4.70573,-48.49375 15.08472,3.42779
+ -20.39159,-42.17451 -1.69776,-40.85728 24.07272,21.63552
+ -3.65989,-30.10299 2.27233,-33.17152 16.90643,17.53071
+ -12.7383,-38.42821 6.79531,-21.57013 -4.50946,-21.08135
+ -2.53357,-37.43561 -15.5535,-55.59527 -11.0035,-12.40086
+ -1.87775,-7.12745 1.34831,-8.11755 C 468.27562,118.9774
+ 451.40746,102.656 430.98897,92.119168 439.06192,78.203836
+ 455.88012,60.123881 457.38638,40.337815 463.2373,23.183067
+ 450.82861,4.7342783 435.04883,22.626367 409.5188,28.206712
+ 386.3569,24.131269 365.63904,8.0954152 352.788,2.8857182
+ 338.88892,0.40735091 325.03711,0.5 Z m -219.0625,357.04297
+ -0.97656,0.88476 z"
+ }
+ }
+ }
}
+
diff --git a/examples/quick/shapes/shapes.pro b/examples/quick/shapes/shapes.pro
index c28359b13c..ff6fa422fb 100644
--- a/examples/quick/shapes/shapes.pro
+++ b/examples/quick/shapes/shapes.pro
@@ -9,7 +9,7 @@ OTHER_FILES += content/main.qml \
content/sampling.qml \
content/clippedtigers.qml \
content/tiger.qml \
- content/item1.qml \
+ content/tapableTriangle.qml \
content/item2.qml \
content/item3.qml \
content/item4.qml \
diff --git a/examples/quick/shapes/shapes.qrc b/examples/quick/shapes/shapes.qrc
index 5a0edd9f8f..e03c0e8a0a 100644
--- a/examples/quick/shapes/shapes.qrc
+++ b/examples/quick/shapes/shapes.qrc
@@ -12,7 +12,7 @@
<file alias="sampling.qml">content/sampling.qml</file>
<file alias="clippedtigers.qml">content/clippedtigers.qml</file>
<file alias="tiger.qml">content/tiger.qml</file>
- <file alias="item1.qml">content/item1.qml</file>
+ <file alias="tapableTriangle.qml">content/tapableTriangle.qml</file>
<file alias="item2.qml">content/item2.qml</file>
<file alias="item3.qml">content/item3.qml</file>
<file alias="item4.qml">content/item4.qml</file>
diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp
index e24826ee55..74731aa35f 100644
--- a/src/imports/shapes/plugin.cpp
+++ b/src/imports/shapes/plugin.cpp
@@ -68,6 +68,12 @@ public:
qmlRegisterType<QQuickShapeLinearGradient>(uri, 1, 0, "LinearGradient");
qmlRegisterType<QQuickShapeRadialGradient>(uri, 1, 0, "RadialGradient");
qmlRegisterType<QQuickShapeConicalGradient>(uri, 1, 0, "ConicalGradient");
+
+ // Auto-increment the import to stay in sync with ALL future QtQuick minor versions
+ qmlRegisterModule(uri, 1, QT_VERSION_MINOR);
+
+ // revision in Qt 5.11: added containsMode property
+ qmlRegisterType<QQuickShape, 11>(uri, 1, 11, "Shape");
}
};
diff --git a/src/imports/shapes/plugins.qmltypes b/src/imports/shapes/plugins.qmltypes
index 39aab42401..a140644d6d 100644
--- a/src/imports/shapes/plugins.qmltypes
+++ b/src/imports/shapes/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtQuick.Shapes 1.0'
+// 'qmlplugindump -nonrelocatable QtQuick.Shapes 1.11'
Module {
dependencies: ["QtQuick 2.8"]
@@ -12,8 +12,8 @@ Module {
name: "QQuickShape"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtQuick.Shapes/Shape 1.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick.Shapes/Shape 1.0", "QtQuick.Shapes/Shape 1.11"]
+ exportMetaObjectRevisions: [0, 11]
Enum {
name: "RendererType"
values: {
@@ -31,12 +31,21 @@ Module {
"Processing": 2
}
}
+ Enum {
+ name: "ContainsMode"
+ values: {
+ "BoundingRectContains": 0,
+ "FillContains": 1
+ }
+ }
Property { name: "rendererType"; type: "RendererType"; isReadonly: true }
Property { name: "asynchronous"; type: "bool" }
Property { name: "vendorExtensionsEnabled"; type: "bool" }
Property { name: "status"; type: "Status"; isReadonly: true }
+ Property { name: "containsMode"; revision: 11; type: "ContainsMode" }
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
Signal { name: "rendererChanged" }
+ Signal { name: "containsModeChanged"; revision: 11 }
}
Component {
name: "QQuickShapeConicalGradient"
diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp
index 518f7a08cf..54a0a3d402 100644
--- a/src/imports/shapes/qquickshape.cpp
+++ b/src/imports/shapes/qquickshape.cpp
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QQSHAPE_LOG_TIME_DIRTY_SYNC, "qt.shape.time.sync")
/*!
- \qmlmodule QtQuick.Shapes 1.0
+ \qmlmodule QtQuick.Shapes 1.11
\title Qt Quick Shapes QML Types
\ingroup qmlmodules
\brief Provides QML types for drawing stroked and filled shapes.
@@ -61,7 +61,7 @@ Q_LOGGING_CATEGORY(QQSHAPE_LOG_TIME_DIRTY_SYNC, "qt.shape.time.sync")
To use the types in this module, import the module with the following line:
\badcode
- import QtQuick.Shapes 1.0
+ import QtQuick.Shapes 1.11
\endcode
*/
@@ -778,6 +778,63 @@ QQuickShape::Status QQuickShape::status() const
return d->status;
}
+/*!
+ \qmlproperty enumeration QtQuick.Shapes::Shape::containsMode
+ \since QtQuick.Shapes 1.11
+
+ This property determines the definition of \l {QQuickItem::contains()}{contains()}
+ for the Shape. It is useful in case you add
+ \l {Qt Quick Pointer Handlers QML Types}{Pointer Handlers} and you
+ want to react only when the mouse or touchpoint is fully inside the Shape.
+
+ \value Shape.BoundingRectContains
+ The default implementation of \l QQuickItem::contains() checks only
+ whether the given point is inside the rectangular bounding box. This is
+ the most efficient implementation, which is why it's the default.
+
+ \value Shape.FillContains
+ Check whether the interior (the part that would be filled if you are
+ rendering it with fill) of any \l ShapePath that makes up this Shape
+ contains the given point. The more complex and numerous ShapePaths you
+ add, the less efficient this is to check, which can potentially slow
+ down event delivery in your application. So it should be used with care.
+
+ One way to speed up the \c FillContains check is to generate an approximate
+ outline with as few points as possible, place that in a transparent Shape
+ on top, and add your Pointer Handlers to that, so that the containment
+ check is cheaper during event delivery.
+*/
+QQuickShape::ContainsMode QQuickShape::containsMode() const
+{
+ Q_D(const QQuickShape);
+ return d->containsMode;
+}
+
+void QQuickShape::setContainsMode(QQuickShape::ContainsMode containsMode)
+{
+ Q_D(QQuickShape);
+ if (d->containsMode == containsMode)
+ return;
+
+ d->containsMode = containsMode;
+ emit containsModeChanged();
+}
+
+bool QQuickShape::contains(const QPointF &point) const
+{
+ Q_D(const QQuickShape);
+ switch (d->containsMode) {
+ case BoundingRectContains:
+ return QQuickItem::contains(point);
+ case FillContains:
+ for (QQuickShapePath *path : d->sp) {
+ if (path->path().contains(point))
+ return true;
+ }
+ }
+ return false;
+}
+
static void vpe_append(QQmlListProperty<QObject> *property, QObject *obj)
{
QQuickShape *item = static_cast<QQuickShape *>(property->object);
diff --git a/src/imports/shapes/qquickshape_p.h b/src/imports/shapes/qquickshape_p.h
index 365d9644c7..1dfeaf9228 100644
--- a/src/imports/shapes/qquickshape_p.h
+++ b/src/imports/shapes/qquickshape_p.h
@@ -303,6 +303,7 @@ class QQuickShape : public QQuickItem
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
Q_PROPERTY(bool vendorExtensionsEnabled READ vendorExtensionsEnabled WRITE setVendorExtensionsEnabled NOTIFY vendorExtensionsEnabledChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(ContainsMode containsMode READ containsMode WRITE setContainsMode NOTIFY containsModeChanged REVISION 11)
Q_PROPERTY(QQmlListProperty<QObject> data READ data)
Q_CLASSINFO("DefaultProperty", "data")
@@ -322,6 +323,12 @@ public:
};
Q_ENUM(Status)
+ enum ContainsMode {
+ BoundingRectContains,
+ FillContains
+ };
+ Q_ENUM(ContainsMode)
+
QQuickShape(QQuickItem *parent = nullptr);
~QQuickShape();
@@ -335,6 +342,11 @@ public:
Status status() const;
+ ContainsMode containsMode() const;
+ void setContainsMode(ContainsMode containsMode);
+
+ bool contains(const QPointF &point) const override;
+
QQmlListProperty<QObject> data();
protected:
@@ -349,6 +361,7 @@ Q_SIGNALS:
void asynchronousChanged();
void vendorExtensionsEnabledChanged();
void statusChanged();
+ Q_REVISION(11) void containsModeChanged();
private:
Q_DISABLE_COPY(QQuickShape)
diff --git a/src/imports/shapes/qquickshape_p_p.h b/src/imports/shapes/qquickshape_p_p.h
index eb7fdc3bc8..c3d84b6353 100644
--- a/src/imports/shapes/qquickshape_p_p.h
+++ b/src/imports/shapes/qquickshape_p_p.h
@@ -177,6 +177,7 @@ public:
int syncTimeCounter = 0;
QQuickShape::Status status = QQuickShape::Null;
QQuickShape::RendererType rendererType = QQuickShape::UnknownRenderer;
+ QQuickShape::ContainsMode containsMode = QQuickShape::BoundingRectContains;
bool spChanged = false;
bool async = false;
bool enableVendorExts = true;
diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro
index fee950a529..4d6e9508af 100644
--- a/src/imports/shapes/shapes.pro
+++ b/src/imports/shapes/shapes.pro
@@ -1,7 +1,7 @@
CXX_MODULE = qml
TARGET = qmlshapesplugin
TARGETPATH = QtQuick/Shapes
-IMPORT_VERSION = 1.0
+IMPORT_VERSION = 1.11
QT = core gui-private qml quick-private