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
qqmlnotifierendpoint_p.h
Go to the documentation of this file.
1// Copyright (C) 2026 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
4
5#ifndef QQMLNOTIFIERENDPOINT_P_H
6#define QQMLNOTIFIERENDPOINT_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 <private/qmetaobject_p.h>
20#include <private/qobject_p.h>
21#include <private/qqmlproperty_p.h>
22#include <private/qthread_p.h>
23#include <private/qtqmlglobal_p.h>
24
25#include <QtCore/qmetaobject.h>
26#include <QtQml/qqmlengine.h>
27
28QT_BEGIN_NAMESPACE
29
30class QQmlNotifier;
31class QQmlNotifyList;
32
34{
37
38public:
39 // QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
40 // To add another callback, extend this enum and add the callback to the top
41 // of qqmlnotifier.cpp. Four bits are reserved for the callback, so there can
42 // be up to 15 of them (0 is reserved).
52
53 inline QQmlNotifierEndpoint(Callback callback);
54 inline ~QQmlNotifierEndpoint();
55
56 inline bool isConnected() const;
57 inline bool isConnected(QObject *source, int sourceSignal) const;
58 inline bool isConnected(QQmlNotifier *) const;
59
60 inline void disconnect();
61
62 inline bool isNotifying() const;
63 inline void startNotifying(qintptr *originalSenderPtr);
64 inline void stopNotifying(qintptr *originalSenderPtr);
65
66 inline void cancelNotify();
67
68 inline int signalIndex() const { return sourceSignal; }
69
70 inline Callback callbackType() const { return callback; }
71 inline QQmlNotifierEndpoint *nextEndpoint() const { return next; }
72
73 inline qintptr sender() const;
74 inline void setSender(qintptr sender);
75
76 inline QObject *senderAsObject() const;
77 inline QQmlNotifier *senderAsNotifier() const;
78
79private:
80 friend class QQmlData;
81 friend class QQmlNotifier;
82 friend class QQmlNotifyList;
83
84 // Contains either the QObject*, or the QQmlNotifier* that this
85 // endpoint is connected to. While the endpoint is notifying, the
86 // senderPtr points to another qintptr that contains this value.
87 qintptr senderPtr;
88
89 Callback callback : 4;
90 int needsConnectNotify : 1;
91 // The index is in the range returned by QObjectPrivate::signalIndex().
92 // This is different from QMetaMethod::methodIndex().
93 signed int sourceSignal : 27;
94};
95
97 : next(nullptr),
98 prev(nullptr),
99 senderPtr(0),
100 callback(callback),
101 needsConnectNotify(false),
102 sourceSignal(-1)
103{
104}
105
110
112{
113 return prev != nullptr;
114}
115
116/*! \internal
117 \a sourceSignal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
118 This is different from QMetaMethod::methodIndex().
119*/
120bool QQmlNotifierEndpoint::isConnected(QObject *source, int sourceSignal) const
121{
122 return this->sourceSignal != -1 && senderAsObject() == source
123 && this->sourceSignal == sourceSignal;
124}
125
126bool QQmlNotifierEndpoint::isConnected(QQmlNotifier *notifier) const
127{
128 return sourceSignal == -1 && senderAsNotifier() == notifier;
129}
130
132{
133 // Remove from notifier chain before calling disconnectNotify(), so that that
134 // QObject::receivers() returns the correct value in there
135 if (next)
136 next->prev = prev;
137 if (prev)
138 *prev = next;
139
140 if (sourceSignal != -1 && needsConnectNotify) {
141 QObject *const obj = senderAsObject();
142 Q_ASSERT(obj);
143 QObjectPrivate *const priv = QObjectPrivate::get(obj);
144
145 // In some degenerate cases an object being destructed might be unable
146 // to produce a metaObject(). Therefore we check here.
147 if (const QMetaObject *mo = obj->metaObject())
148 priv->disconnectNotify(QMetaObjectPrivate::signal(mo, sourceSignal));
149 }
150
151 setSender(0x0);
152 next = nullptr;
153 prev = nullptr;
154 sourceSignal = -1;
155}
156
157/*!
158Returns true if a notify is in progress. This means that the signal or QQmlNotifier
159that this endpoint is connected to has been triggered, but this endpoint's callback has not
160yet been called.
161
162An in progress notify can be cancelled by calling cancelNotify.
163*/
165{
166 return senderPtr & 0x1;
167}
168
169inline void QQmlNotifierEndpoint::startNotifying(qintptr *originalSenderPtr)
170{
171 Q_ASSERT(*originalSenderPtr == 0);
172 // Set the endpoint to notifying:
173 // - Save the original senderPtr,
174 *originalSenderPtr = senderPtr;
175 // - Take a pointer of it,
176 // - And assign that to the senderPtr, including a flag to signify "notifying".
177 senderPtr = qintptr(originalSenderPtr) | 0x1;
178}
179
180inline void QQmlNotifierEndpoint::stopNotifying(qintptr *originalSenderPtr)
181{
182 // End of notifying, restore values
183 Q_ASSERT((senderPtr & ~0x1) == qintptr(originalSenderPtr));
184 senderPtr = *originalSenderPtr;
185 *originalSenderPtr = 0;
186}
187
188/*!
189Cancel any notifies that are in progress.
190*/
192{
193 if (isNotifying()) {
194 auto *ptr = (qintptr *)(senderPtr & ~0x1);
195 Q_ASSERT(ptr);
196 senderPtr = *ptr;
197 *ptr = 0;
198 }
199}
200
202{
203 return isNotifying() ? *(qintptr *)(senderPtr & ~0x1) : senderPtr;
204}
205
206inline void QQmlNotifierEndpoint::setSender(qintptr sender)
207{
208 // If we're just notifying, we write through to the originalSenderPtr
209 if (isNotifying())
210 *(qintptr *)(senderPtr & ~0x1) = sender;
211 else
212 senderPtr = sender;
213}
214
216{
217 return (QObject *)(sender());
218}
219
220inline QQmlNotifier *QQmlNotifierEndpoint::senderAsNotifier() const
221{
222 return (QQmlNotifier *)(sender());
223}
224
225QT_END_NAMESPACE
226
227#endif // QQMLNOTIFIERENDPOINT_P_H
void setSender(qintptr sender)
void cancelNotify()
Cancel any notifies that are in progress.
bool isNotifying() const
Returns true if a notify is in progress.
QObject * senderAsObject() const
QQmlNotifier * senderAsNotifier() const
bool isConnected(QQmlNotifier *) const
void stopNotifying(qintptr *originalSenderPtr)
QQmlNotifierEndpoint * nextEndpoint() const
bool isConnected(QObject *source, int sourceSignal) const
void startNotifying(qintptr *originalSenderPtr)
QQmlNotifierEndpoint(Callback callback)