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
qobject_p.h
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#ifndef QOBJECT_P_H
7#define QOBJECT_P_H
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists for the convenience
14// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
15// file may change from version to version without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include <QtCore/private/qglobal_p.h>
21#include "QtCore/qcoreevent.h"
22#include <QtCore/qfunctionaltools_impl.h>
23#include "QtCore/qlist.h"
24#include "QtCore/qobject.h"
25#include "QtCore/qpointer.h"
26#include "QtCore/qvariant.h"
27#include "QtCore/qproperty.h"
28#include <QtCore/qshareddata.h>
29#include "QtCore/private/qproperty_p.h"
30
31#include <string>
32
33QT_BEGIN_NAMESPACE
34
35#ifdef Q_MOC_RUN
36#define QT_ANONYMOUS_PROPERTY(text) QT_ANONYMOUS_PROPERTY(text)
37#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANONYMOUS_PRIVATE_PROPERTY(d, text)
38#elif !defined QT_NO_META_MACROS
39#define QT_ANONYMOUS_PROPERTY(...) QT_ANNOTATE_CLASS(qt_anonymous_property, __VA_ARGS__)
40#define QT_ANONYMOUS_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_anonymous_private_property, d, text)
41#endif
42
43#define QT_CONCAT(B, M, m, u) QT_CONCAT2(B, M, m, u)
44#define QT_CONCAT2(B, M, m, u) B ## M ## _ ## m ## _ ## u
45#if defined(QT_BUILD_INTERNAL) && !QT_CONFIG(elf_private_full_version)
46// Don't check the version parameter in internal builds.
47// This allows incompatible versions to be loaded, possibly for testing.
48enum QObjectPrivateVersionEnum
49#else
50enum QT_CONCAT(QtPrivate_, QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH)
51#endif
52{ QObjectPrivateVersion = QT_VERSION };
53#undef QT_CONCAT
54#undef QT_CONCAT2
55
56class QVariant;
57class QThreadData;
58class QObjectConnectionListVector;
60
61/* for Qt Test */
63{
64 typedef void (*BeginCallback)(QObject *caller, int signal_or_method_index, void **argv);
65 typedef void (*EndCallback)(QObject *caller, int signal_or_method_index);
70};
71void Q_CORE_EXPORT qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set);
72
73extern Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set;
74
75class Q_CORE_EXPORT QAbstractDeclarativeData
76{
77public:
78 static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
79 static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **);
80 static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int);
81 static bool (*isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int);
82 static void (*setWidgetParent)(QObject *, QObject *); // Used by the QML engine to specify parents for widgets. Set by QtWidgets.
83};
84
85class Q_CORE_EXPORT QObjectPrivate : public QObjectData
86{
87public:
88 Q_DECLARE_PUBLIC(QObject)
89
90 struct ExtraData
91 {
92 ExtraData(QObjectPrivate *ptr) : parent(ptr) { }
93
94 inline void setObjectNameForwarder(const QString &name)
95 {
96 parent->q_func()->setObjectName(name);
97 }
98
99 inline void nameChangedForwarder(const QString &name)
100 {
101 Q_EMIT parent->q_func()->objectNameChanged(name, QObject::QPrivateSignal());
102 }
103
104 QList<QByteArray> propertyNames;
105 QList<QVariant> propertyValues;
106 QList<Qt::TimerId> runningTimers;
107 QList<QPointer<QObject>> eventFilters;
108 Q_OBJECT_COMPAT_PROPERTY(QObjectPrivate::ExtraData, QString, objectName,
109 &QObjectPrivate::ExtraData::setObjectNameForwarder,
110 &QObjectPrivate::ExtraData::nameChangedForwarder)
111 QObjectPrivate *parent;
112 };
113
114 void ensureExtraData()
115 {
116 if (!extraData)
117 extraData = new ExtraData(this);
118 }
119 void setObjectNameWithoutBindings(const QString &name);
120
121 typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
122 struct Connection;
123 struct ConnectionData;
124 struct ConnectionList;
125 struct ConnectionOrSignalVector;
126 struct SignalVector;
127 struct Sender;
128 struct TaggedSignalVector;
129
130 /*
131 This contains the all connections from and to an object.
132
133 The signalVector contains the lists of connections for a given signal. The index in the vector correspond
134 to the signal index. The signal index is the one returned by QObjectPrivate::signalIndex (not
135 QMetaObject::indexOfSignal). allsignals contains a list of special connections that will get invoked on
136 any signal emission. This is done by connecting to signal index -1.
137
138 This vector is protected by the object mutex (signalSlotLock())
139
140 Each Connection is also part of a 'senders' linked list. This one contains all connections connected
141 to a slot in this object. The mutex of the receiver must be locked when touching the pointers of this
142 linked list.
143 */
144
145 QObjectPrivate(decltype(QObjectPrivateVersion) version = QObjectPrivateVersion);
146 virtual ~QObjectPrivate();
147 void deleteChildren();
148 // used to clear binding storage early in ~QObject
149 void clearBindingStorage();
150
151 void setParent_helper(QObject *);
152 void moveToThread_helper();
153 void setThreadData_helper(QThreadData *currentData, QThreadData *targetData, QBindingStatus *status);
154
155 QObjectList receiverList(const char *signal) const;
156
157 inline void ensureConnectionData();
158 inline void addConnection(int signal, Connection *c);
159 static inline bool removeConnection(Connection *c);
160
161 static QObjectPrivate *get(QObject *o) { return o->d_func(); }
162 static const QObjectPrivate *get(const QObject *o) { return o->d_func(); }
163
164 int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const;
165 bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
166 bool maybeSignalConnected(uint signalIndex) const;
167 inline bool isDeclarativeSignalConnected(uint signalIdx) const;
168
169 // To allow abitrary objects to call connectNotify()/disconnectNotify() without making
170 // the API public in QObject. This is used by QQmlNotifierEndpoint.
171 inline void connectNotify(const QMetaMethod &signal);
172 inline void disconnectNotify(const QMetaMethod &signal);
173
174 void reinitBindingStorageAfterThreadMove();
175
176 template <typename Func1, typename Func2>
177 static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
178 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
179 Qt::ConnectionType type = Qt::AutoConnection);
180
181 template <typename Func1, typename Func2>
182 static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
183 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
184
185 static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
186 const QObject *receiver, void **slot,
187 QtPrivate::QSlotObjectBase *slotObj, int type,
188 const int *types, const QMetaObject *senderMetaObject);
189 static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
190 static QMetaObject::Connection connect(const QObject *sender, int signal_index,
191 const QObject *receiver,
192 QtPrivate::QSlotObjectBase *slotObj,
193 Qt::ConnectionType type);
194 static bool disconnect(const QObject *sender, int signal_index, void **slot);
195 static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver,
196 void **slot);
197
198 virtual std::string flagsForDumping() const;
199
200#ifndef QT_NO_DEBUG_STREAM
201 virtual void writeToDebugStream(QDebug &) const;
202#endif
203
204 QtPrivate::QPropertyAdaptorSlotObject *
205 getPropertyAdaptorSlotObject(const QMetaProperty &property);
206
207public:
208 mutable ExtraData *extraData; // extra data set by the user
209 // This atomic requires acquire/release semantics in a few places,
210 // e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent,
211 // because postEvent is thread-safe.
212 // However, most of the code paths involving QObject are only reentrant and
213 // not thread-safe, so synchronization should not be necessary there.
214 QAtomicPointer<QThreadData> threadData; // id of the thread that owns the object
215
216 using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>;
217 QAtomicPointer<ConnectionData> connections;
218
219 union {
220 QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set
221 QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
222 };
223
224 // these objects are all used to indicate that a QObject was deleted
225 // plus QPointer, which keeps a separate list
226 QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
227};
228
229inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
230{
231 return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
232 && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
233}
234
235inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
236{
237 q_ptr->connectNotify(signal);
238}
239
240inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
241{
242 q_ptr->disconnectNotify(signal);
243}
244
245namespace QtPrivate {
246inline const QObject *getQObject(const QObjectPrivate *d) { return d->q_func(); }
247
248template <typename Func>
250
251template <typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d)
252{
253 using Obj = std::remove_pointer_t<decltype(std::declval<ObjPrivate *>()->q_func())>;
255}
256
257template<typename Func, typename Args, typename R>
259{
260 typedef QtPrivate::FunctionPointer<Func> FuncType;
261#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
262 static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
263#else
264 static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret)
265#endif
266 {
267 const auto that = static_cast<QPrivateSlotObject*>(this_);
268 switch (which) {
269 case Destroy:
270 delete that;
271 break;
272 case Call:
273 FuncType::template call<Args, R>(that->object(),
274 static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
275 break;
276 case Compare:
277 *ret = *reinterpret_cast<Func *>(a) == that->object();
278 break;
279 case NumOperations: ;
280 }
281 }
282public:
284};
285} //namespace QtPrivate
286
287template <typename Func1, typename Func2>
288inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
289 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
290 Qt::ConnectionType type)
291{
292 typedef QtPrivate::FunctionPointer<Func1> SignalType;
293 typedef QtPrivate::FunctionPointer<Func2> SlotType;
294 static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
295 "No Q_OBJECT in the class with the signal");
296
297 //compilation error if the arguments does not match.
298 static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
299 "The slot requires more arguments than the signal provides.");
300 static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
301 "Signal and slot arguments are not compatible.");
302 static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
303 "Return type of the slot is not compatible with the return type of the signal.");
304
305 const int *types = nullptr;
306 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
307 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
308
309 return QObject::connectImpl(sender, reinterpret_cast<void **>(&signal),
310 QtPrivate::getQObject(receiverPrivate), reinterpret_cast<void **>(&slot),
311 new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
312 typename SignalType::ReturnType>(slot),
313 type, types, &SignalType::Object::staticMetaObject);
314}
315
316template <typename Func1, typename Func2>
317bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object* sender, Func1 signal,
318 const typename QtPrivate::FunctionPointer< Func2 >::Object* receiverPrivate, Func2 slot)
319{
320 typedef QtPrivate::FunctionPointer<Func1> SignalType;
321 typedef QtPrivate::FunctionPointer<Func2> SlotType;
322 static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
323 "No Q_OBJECT in the class with the signal");
324 //compilation error if the arguments does not match.
325 static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
326 "Signal and slot arguments are not compatible.");
327 return QObject::disconnectImpl(sender, reinterpret_cast<void **>(&signal),
328 receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
329 &SignalType::Object::staticMetaObject);
330}
331
332class QLatch;
333class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent
334{
335public:
336 QAbstractMetaCallEvent(const QObject *sender, int signalId, QLatch *latch = nullptr)
337 : QEvent(MetaCall), signalId_(signalId), sender_(sender), latch(latch)
338 {}
339 ~QAbstractMetaCallEvent();
340
341 virtual void placeMetaCall(QObject *object) = 0;
342
343 inline const QObject *sender() const { return sender_; }
344 inline int signalId() const { return signalId_; }
345
346private:
347 int signalId_;
348 const QObject *sender_;
349 QLatch *latch;
350};
351
352class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
353{
354public:
355 // blocking queued with latch - arguments always remain owned by the caller
356 QMetaCallEvent(ushort method_offset, ushort method_relative,
357 QObjectPrivate::StaticMetaCallFunction callFunction,
358 const QObject *sender, int signalId,
359 void **args, QLatch *latch);
360 QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
361 const QObject *sender, int signalId,
362 void **args, QLatch *latch);
363 QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
364 const QObject *sender, int signalId,
365 void **args, QLatch *latch);
366
367 virtual void placeMetaCall(QObject *object) override;
368
369protected:
370 struct Data {
371 QtPrivate::SlotObjUniquePtr slotObj_;
372 void **args_;
373 QObjectPrivate::StaticMetaCallFunction callFunction_;
374 int nargs_;
375 ushort method_offset_;
376 ushort method_relative_;
377 } d;
378
379 inline QMetaCallEvent(const QObject *sender, int signalId, Data &&data);
380};
381
382class Q_CORE_EXPORT QQueuedMetaCallEvent : public QMetaCallEvent
383{
384public:
385 // queued - arguments are allocated and copied from argValues by these constructors
386 QQueuedMetaCallEvent(ushort method_offset, ushort method_relative,
387 QObjectPrivate::StaticMetaCallFunction callFunction,
388 const QObject *sender, int signalId,
389 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
390 const void * const *argValues);
391 QQueuedMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
392 const QObject *sender, int signalId,
393 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
394 const void * const *argValues);
395 QQueuedMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
396 const QObject *sender, int signalId,
397 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
398 const void * const *argValues);
399
400 ~QQueuedMetaCallEvent() override;
401
402private:
403 inline void allocArgs();
404 inline void copyArgValues(int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
405 const void * const *argValues);
406 static inline bool typeFitsInPlace(const QMetaType type);
407
408 // Space for 5 argument pointers and types (including 1 return arg).
409 // Contiguous so that we can make one calloc() for both the pointers and the types when necessary.
410 static constexpr size_t PtrAndTypeSize = sizeof(void *) + sizeof(QMetaType);
411 alignas(void *) char prealloc_[5 * PtrAndTypeSize];
412 struct ArgValueStorage { // size and alignment matching QString, QList, etc
413 static constexpr size_t MaxSize = 3 * sizeof(void *);
414 alignas(void *) char storage[MaxSize];
415 };
416 static constexpr int InplaceValuesCapacity = 3;
417 ArgValueStorage valuesPrealloc_[InplaceValuesCapacity];
418};
419// The total QQueuedMetaCallEvent size is 224 bytes which is a 32-byte multiple, efficient for memory allocators.
420
421struct QAbstractDynamicMetaObject;
422struct Q_CORE_EXPORT QDynamicMetaObjectData
423{
424 virtual ~QDynamicMetaObjectData();
425 virtual void objectDestroyed(QObject *) { delete this; }
426
427#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
428 virtual const QMetaObject *toDynamicMetaObject(QObject *) const = 0;
429#else
430 virtual QMetaObject *toDynamicMetaObject(QObject *) = 0;
431#endif
432 virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;
433};
434
435struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject
436{
437 ~QAbstractDynamicMetaObject();
438
439#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
440 const QMetaObject *toDynamicMetaObject(QObject *) const override { return this; }
441#else
442 QMetaObject *toDynamicMetaObject(QObject *) override { return this; }
443#endif
444 virtual int createProperty(const char *, const char *) { return -1; }
445 int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override
446 { return metaCall(c, _id, a); }
447 virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
448};
449
450inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate *o)
451{
452 return &o->bindingStorage;
453}
454inline QBindingStorage *qGetBindingStorage(QObjectPrivate *o)
455{
456 return &o->bindingStorage;
457}
458inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate::ExtraData *ed)
459{
460 return &ed->parent->bindingStorage;
461}
462inline QBindingStorage *qGetBindingStorage(QObjectPrivate::ExtraData *ed)
463{
464 return &ed->parent->bindingStorage;
465}
466
467QT_END_NAMESPACE
468
469#endif // QOBJECT_P_H
\inmodule QtCore
~QTimerPrivate() override
QTimerPrivate(QTimer *qq)
Definition qtimer_p.h:28
void setIntervalDuration(std::chrono::nanoseconds nsec)
Definition qtimer_p.h:43
static constexpr int INV_TIMER
Definition qtimer_p.h:41
void setInterval(int msec)
Definition qtimer_p.h:53
bool isActive() const
Definition qtimer_p.h:59
const bool isQTimer
Definition qtimer_p.h:71
QTimerPrivate(std::chrono::nanoseconds nsec, QChronoTimer *qq)
Definition qtimer_p.h:33
Qt::TimerId id
Definition qtimer_p.h:61
\inmodule QtCore
Definition qtimer.h:21
Combined button and popup list for selecting options.
void assertObjectType(QObjectPrivate *d)
Definition qobject_p.h:251
const QObject * getQObject(const QObjectPrivate *d)
Definition qobject_p.h:246
#define QT_CONCAT(B, M, m, u)
Definition qobject_p.h:43
QBindingStorage * qGetBindingStorage(QObjectPrivate *o)
Definition qobject_p.h:454
QBindingStorage * qGetBindingStorage(QObjectPrivate::ExtraData *ed)
Definition qobject_p.h:462
const QBindingStorage * qGetBindingStorage(const QObjectPrivate *o)
Definition qobject_p.h:450
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...)
Definition qproperty.h:1336
#define Q_OBJECT_COMPUTED_PROPERTY(Class, Type, name, ...)
Definition qproperty.h:1425
#define Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(...)
void(* BeginCallback)(QObject *caller, int signal_or_method_index, void **argv)
Definition qobject_p.h:64
BeginCallback slot_begin_callback
Definition qobject_p.h:67
EndCallback slot_end_callback
Definition qobject_p.h:69
EndCallback signal_end_callback
Definition qobject_p.h:68
BeginCallback signal_begin_callback
Definition qobject_p.h:66
void(* EndCallback)(QObject *caller, int signal_or_method_index)
Definition qobject_p.h:65