diff options
author | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-09-22 11:46:36 -0500 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-01-25 16:22:51 +0000 |
commit | bf74a908cb0591c2adc024a6f93d566c7348c125 (patch) | |
tree | 71e749e71e8dcd4b159303526e7343dcd968e920 /src/quick/items | |
parent | f6222f825831202c084835412a3c217a9420cad7 (diff) |
Support masking of QQuickItems
Adding a new property, containsMask, to QQuickItem, that can be set
to any QObject defining a
Q_INVOKABLE bool contains(const QPointF &point).
When this property is set, the mask object contains method is used in
place of the item own contains method.
[ChangeLog][QtQuick][QQuickItem] Added containsMask property.
Task-number: QTBUG-20524
Change-Id: I5b0696e2cddc6ae3e217ce149c5f44980fdb69aa
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 72 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 4 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 7 | ||||
-rw-r--r-- | src/quick/items/qquickitemsmodule.cpp | 1 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea_p_p.h | 2 |
5 files changed, 83 insertions, 3 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index f1f6f97356..f4d11e32bd 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -7568,9 +7568,75 @@ void QQuickItem::setKeepTouchGrab(bool keep) bool QQuickItem::contains(const QPointF &point) const { Q_D(const QQuickItem); - qreal x = point.x(); - qreal y = point.y(); - return x >= 0 && y >= 0 && x <= d->width && y <= d->height; + if (d->mask) { + bool res = false; + d->extra->maskContains.invoke(d->mask, + Qt::DirectConnection, + Q_RETURN_ARG(bool, res), + Q_ARG(QPointF, point)); + return res; + } else { + qreal x = point.x(); + qreal y = point.y(); + return x >= 0 && y >= 0 && x <= d->width && y <= d->height; + } +} + +/*! + \qmlproperty QObject * QtQuick::Item::containsMask + \since 5.11 + This property holds an optional mask for the Item to be used in the + QtQuick::Item::contains method. + QtQuick::Item::contains main use is currently to determine whether + an input event has landed into the item or not. + + By default the \l contains method will return true for any point + within the Item's bounding box. \c containsMask allows for a + more fine-grained control. For example, the developer could + define and use an AnotherItem element as containsMask, + which has a specialized contains method, like: + + \code + Item { id: item; containsMask: AnotherItem { id: anotherItem } } + \endcode + + \e{item}'s contains method would then return true only if + \e{anotherItem}'s contains implementation returns true. +*/ +QObject *QQuickItem::containsMask() const +{ + Q_D(const QQuickItem); + return d->mask.data(); +} + +void QQuickItem::setContainsMask(QObject *mask) +{ + Q_D(QQuickItem); + // an Item can't mask itself (to prevent infinite loop in contains()) + if (d->mask.data() == mask || mask == static_cast<QObject *>(this)) + return; + + QQuickItem *quickMask = qobject_cast<QQuickItem *>(d->mask); + if (quickMask) { + QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask); + maskPrivate->registerAsContainsMask(this, false); // removed from use as my mask + } + + if (mask) { + int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)")); + if (methodIndex < 0) { + qmlWarning(this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it."); + return; + } + d->extra.value().maskContains = mask->metaObject()->method(methodIndex); + } + d->mask = mask; + quickMask = qobject_cast<QQuickItem *>(mask); + if (quickMask) { + QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask); + maskPrivate->registerAsContainsMask(this, true); // telling maskPrivate that "this" is using it as mask + } + emit containsMaskChanged(); } /*! diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index f6ee54e94d..e38c276b9f 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -144,6 +144,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QQmlParserStatus Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing NOTIFY antialiasingChanged RESET resetAntialiasing) Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged) Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged) + Q_PROPERTY(QObject *containsMask READ containsMask WRITE setContainsMask NOTIFY containsMaskChanged REVISION 11) Q_PRIVATE_PROPERTY(QQuickItem::d_func(), QQuickItemLayer *layer READ layer DESIGNABLE false CONSTANT FINAL) @@ -320,6 +321,8 @@ public: QSharedPointer<QQuickItemGrabResult> grabToImage(const QSize &targetSize = QSize()); Q_INVOKABLE virtual bool contains(const QPointF &point) const; + QObject *containsMask() const; + void setContainsMask(QObject *mask); QTransform itemTransform(QQuickItem *, bool *) const; QPointF mapToItem(const QQuickItem *item, const QPointF &point) const; @@ -390,6 +393,7 @@ Q_SIGNALS: void zChanged(); void implicitWidthChanged(); void implicitHeightChanged(); + Q_REVISION(11) void containsMaskChanged(); protected: bool event(QEvent *) override; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 9ed5286f22..0c02c66ef2 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -368,6 +368,9 @@ public: QQuickDefaultClipNode *clipNode; QSGRootNode *rootNode; + // Mask contains() method + QMetaMethod maskContains; + QObjectList resourcesList; // Although acceptedMouseButtons is inside ExtraData, we actually store @@ -382,6 +385,10 @@ public: // 26 bits padding }; QLazilyAllocated<ExtraData> extra; + // Contains mask + QPointer<QObject> mask; + // If the mask is an Item, inform it that it's being used as a mask (true) or is no longer being used (false) + virtual void registerAsContainsMask(QQuickItem * /* maskedItem */, bool /* set */) { } QQuickAnchors *anchors() const; mutable QQuickAnchors *_anchors; diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 4839b4dd4f..f03942ecee 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -415,6 +415,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #if QT_CONFIG(quick_animatedimage) qmlRegisterType<QQuickAnimatedImage, 11>(uri, 2, 11,"AnimatedImage"); #endif + qmlRegisterType<QQuickItem, 11>(uri, 2, 11,"Item"); } static void initResources() diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index 34cda9e193..0dd2690d43 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QQuickMouseEvent; class QQuickMouseArea; +class QQuickPointerMask; class QQuickMouseAreaPrivate : public QQuickItemPrivate { Q_DECLARE_PUBLIC(QQuickMouseArea) @@ -99,6 +100,7 @@ public: #if QT_CONFIG(draganddrop) QQuickDrag *drag; #endif + QPointer<QQuickPointerMask> mask; QPointF startScene; QPointF targetStartPos; QPointF lastPos; |