Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickitemchangelistener_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QQUICKITEMCHANGELISTENER_P_H
6#define QQUICKITEMCHANGELISTENER_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qxptype_traits.h>
20#include <QtQml/private/qqmldata_p.h>
21#include <QtQuick/qquickitem.h>
22#include <QtQuick/private/qtquickglobal_p.h>
23
24QT_BEGIN_NAMESPACE
25
26class QRectF;
27class QQuickItem;
29
31{
32public:
33 enum Kind: int {
34 Nothing = 0x00,
35 X = 0x01,
36 Y = 0x02,
37 Width = 0x04,
38 Height = 0x08,
39
41 All = X | Y | Size
42 };
43
45 : kind(change)
46 {}
47
48 bool noChange() const { return kind == Nothing; }
49 bool anyChange() const { return !noChange(); }
50
51 bool xChange() const { return kind & X; }
52 bool yChange() const { return kind & Y; }
53 bool widthChange() const { return kind & Width; }
54 bool heightChange() const { return kind & Height; }
55
56 bool positionChange() const { return xChange() || yChange(); }
57 bool sizeChange() const { return widthChange() || heightChange(); }
58
59 bool horizontalChange() const { return xChange() || widthChange(); }
60 bool verticalChange() const { return yChange() || heightChange(); }
61
62 void setXChange(bool enabled) { set(X, enabled); }
63 void setYChange(bool enabled) { set(Y, enabled); }
64 void setWidthChange(bool enabled) { set(Width, enabled); }
65 void setHeightChange(bool enabled) { set(Height, enabled); }
66 void setSizeChange(bool enabled) { set(Size, enabled); }
67 void setAllChanged(bool enabled) { set(All, enabled); }
68 void setHorizontalChange(bool enabled) { set(X | Width, enabled); }
69 void setVerticalChange(bool enabled) { set(Y | Height, enabled); }
70
71 void set(int bits, bool enabled)
72 {
73 if (enabled) {
74 kind |= bits;
75 } else {
76 kind &= ~bits;
77 }
78 }
79
80 bool matches(QQuickGeometryChange other) const { return kind & other.kind; }
81
82private:
83 int kind;
84};
85
86#define QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING
87
88class Q_QUICK_EXPORT QQuickItemChangeListener
89{
90public:
91 virtual ~QQuickItemChangeListener();
92
93 virtual void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF & /* oldGeometry */) {}
94 virtual void itemSiblingOrderChanged(QQuickItem *) {}
95 virtual void itemVisibilityChanged(QQuickItem *) {}
96 virtual void itemEnabledChanged(QQuickItem *) {}
97 virtual void itemOpacityChanged(QQuickItem *) {}
98 virtual void itemDestroyed(QQuickItem *) {}
99 virtual void itemChildAdded(QQuickItem *, QQuickItem * /* child */ ) {}
100 virtual void itemChildRemoved(QQuickItem *, QQuickItem * /* child */ ) {}
101 virtual void itemParentChanged(QQuickItem *, QQuickItem * /* parent */ ) {}
102 virtual void itemRotationChanged(QQuickItem *) {}
103 virtual void itemImplicitWidthChanged(QQuickItem *) {}
104 virtual void itemImplicitHeightChanged(QQuickItem *) {}
105 virtual void itemFocusChanged(QQuickItem *, Qt::FocusReason /* reason */) {}
106 virtual void itemScaleChanged(QQuickItem *) {}
107 virtual void itemTransformChanged(QQuickItem *, QQuickItem * /* transformedItem */) {}
108
109 virtual QQuickAnchorsPrivate *anchorPrivate() { return nullptr; }
110 virtual bool baseDeleted(const QObject *caller) const
111 {
112 if (auto ptr = dynamic_cast<const QObjectPrivate *>(this))
113 return ptr->q_ptr != caller && QQmlData::wasDeleted(ptr);
114 return false;
115 }
116 virtual QString debugName() const {
117 return QStringLiteral("QQuickItemChangeListener(0x%1)").arg(quintptr(this), 0, 16);
118 }
119 virtual void addSourceItem(QQuickItem *) {}
120 virtual void removeSourceItem(QQuickItem *) {}
121};
122
123/*!
124 \internal
125
126 Helper class using CRTP to add tracking of listeners to a
127 QQuickItemChangeListener implementation. Instantiated with the
128 class that implements the QQuickItemChangeListener interface, like
129
130 \code
131 class QQuickThingPrivate : public QQuickItemPrivate,
132 public QSafeQuickItemChangeListener<QQuickThingPrivate>
133 \endcode
134
135 When destroyed, QSafeQuickItemChangeListener will emit warning messages
136 in \c{-developer-build} configurations when listeners are still registered.
137 As the listener is at this point partially destroyed, any call to the
138 listener interface might result in undefined behavior, such as use-after-free.
139
140 Notifications to registered listeners will in addition check if the listener
141 is already in the destructor, and warn if that's the case. The \c{baseDeleted}
142 override checks for an \c inDestructor or \c wasDeleted data member of the
143 class implementing the QSafeQuickItemChangeListener interface.
144*/
145template<typename Self>
147{
148public:
150 {
151#ifdef QT_BUILD_INTERNAL
152 for (const auto &sourceItem : std::as_const(m_sourceItems)) {
153 if (sourceItem)
154 qCritical() << "Change Listener is still registered with item" << sourceItem;
155 }
156#endif
157 }
158
159 template <typename T>
160 using InDestructorTest = decltype(T::inDestructor);
161 template <typename T>
162 using WasDeletedTest = decltype(T::wasDeleted);
163
164 bool baseDeleted(const QObject *caller) const override
165 {
166 Q_UNUSED(caller);
167 const Self *self = static_cast<const Self *>(this);
168 if constexpr (qxp::is_detected_v<InDestructorTest, Self>) {
169 bool same = false;
170 if constexpr (std::is_convertible_v<Self *, QObjectPrivate *>)
171 same = self->q_ptr == caller;
172 return !same && self->inDestructor;
173 } else if constexpr (qxp::is_detected_v<WasDeletedTest, Self>) {
174 bool same = false;
175 if constexpr (std::is_convertible_v<Self *, QObjectPrivate *>)
176 same = self->q_ptr == caller;
177 return !same && self->wasDeleted;
178 } else if constexpr (std::is_convertible_v<Self *, QQuickItem *>) {
179 return self != caller && QQmlData::wasDeleted(self);
180 } else if constexpr (std::is_convertible_v<Self *, QObject *>) {
181 return self != caller && QQmlData::wasDeleted(self);
182 } else {
183 static_assert(QtPrivate::type_dependent_false<Self>(),
184 "Don't know where destruction state is stored");
185 }
186 }
187
188 QString debugName() const override
189 {
190 QString result;
191 QDebug dbg(&result);
192 dbg.nospace().noquote();
193 const Self *self = static_cast<const Self *>(this);
194 if constexpr (std::is_convertible_v<Self *, QObject *>) {
195 dbg << self;
196 } else if constexpr (std::is_convertible_v<Self *, QObjectPrivate *>) {
197 dbg << self->q_ptr << "::d_ptr";
198 } else {
199 dbg << QMetaType::fromType<Self>().name() << '('
200 << reinterpret_cast<const void *>(self) << ')';
201 }
202 return result;
203 }
204
205#ifdef QT_BUILD_INTERNAL
208 }
211 }
212
214#endif
215};
216
217QT_END_NAMESPACE
218
219#endif // QQUICKITEMCHANGELISTENER_P_H
bool checkHAnchorValid(QQuickAnchorLine anchor) const
bool isItemComplete() const
void remDepend(QQuickItem *)
QQuickGeometryChange calculateDependency(QQuickItem *) const
bool checkVAnchorValid(QQuickAnchorLine anchor) const
void addDepend(QQuickItem *)
void setItemSize(const QSizeF &)
static QQuickAnchorsPrivate * get(QQuickAnchors *o)
void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override
bool isMirrored() const
QQuickItem * baselineAnchorItem
QQuickAnchorsPrivate * anchorPrivate() override
bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line, QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line, qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch) const
void setItemPos(const QPointF &)
bool matches(QQuickGeometryChange other) const
void set(int bits, bool enabled)
QQuickGeometryChange(int change=Nothing)
void setVerticalChange(bool enabled)
void setHorizontalChange(bool enabled)
bool baseDeleted(const QObject *caller) const override
decltype(T::inDestructor) InDestructorTest
static qreal hcenter(const QQuickItem *item)
static qreal vcenter(const QQuickItem *item)
static QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine)
static qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
bool operator==(const QQuickAnchorLine &a, const QQuickAnchorLine &b)