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 static void deleteInOwnThread(QObject *object);
165
166 int signalIndex(const char *signalName, const QMetaObject **meta = nullptr) const;
167 bool isSignalConnected(uint signalIdx, bool checkDeclarative = true) const;
168 bool maybeSignalConnected(uint signalIndex) const;
169 inline bool isDeclarativeSignalConnected(uint signalIdx) const;
170
171 // To allow abitrary objects to call connectNotify()/disconnectNotify() without making
172 // the API public in QObject. This is used by QQmlNotifierEndpoint.
173 inline void connectNotify(const QMetaMethod &signal);
174 inline void disconnectNotify(const QMetaMethod &signal);
175
176 void reinitBindingStorageAfterThreadMove();
177
178 template <typename Func1, typename Func2>
179 static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
180 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
181 Qt::ConnectionType type = Qt::AutoConnection);
182
183 template <typename Func1, typename Func2>
184 static inline bool disconnect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
185 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot);
186
187 static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index,
188 const QObject *receiver, void **slot,
189 QtPrivate::QSlotObjectBase *slotObj, int type,
190 const int *types, const QMetaObject *senderMetaObject);
191 static QMetaObject::Connection connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type);
192 static QMetaObject::Connection connect(const QObject *sender, int signal_index,
193 const QObject *receiver,
194 QtPrivate::QSlotObjectBase *slotObj,
195 Qt::ConnectionType type);
196 static bool disconnect(const QObject *sender, int signal_index, void **slot);
197 static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver,
198 void **slot);
199
200 virtual std::string flagsForDumping() const;
201
202#ifndef QT_NO_DEBUG_STREAM
203 virtual void writeToDebugStream(QDebug &) const;
204#endif
205
206 QtPrivate::QPropertyAdaptorSlotObject *
207 getPropertyAdaptorSlotObject(const QMetaProperty &property);
208
209public:
210 mutable ExtraData *extraData; // extra data set by the user
211 // This atomic requires acquire/release semantics in a few places,
212 // e.g. QObject::moveToThread must synchronize with QCoreApplication::postEvent,
213 // because postEvent is thread-safe.
214 // However, most of the code paths involving QObject are only reentrant and
215 // not thread-safe, so synchronization should not be necessary there.
216 QAtomicPointer<QThreadData> threadData; // id of the thread that owns the object
217
218 using ConnectionDataPointer = QExplicitlySharedDataPointer<ConnectionData>;
219 QAtomicPointer<ConnectionData> connections;
220
221 union {
222 QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set
223 QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
224 };
225
226 // these objects are all used to indicate that a QObject was deleted
227 // plus QPointer, which keeps a separate list
228 QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
229};
230
231inline bool QObjectPrivate::isDeclarativeSignalConnected(uint signal_index) const
232{
233 return !isDeletingChildren && declarativeData && QAbstractDeclarativeData::isSignalConnected
234 && QAbstractDeclarativeData::isSignalConnected(declarativeData, q_func(), signal_index);
235}
236
237inline void QObjectPrivate::connectNotify(const QMetaMethod &signal)
238{
239 q_ptr->connectNotify(signal);
240}
241
242inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
243{
244 q_ptr->disconnectNotify(signal);
245}
246
247namespace QtPrivate {
248inline const QObject *getQObject(const QObjectPrivate *d) { return d->q_func(); }
249
250template <typename Func>
252
253template <typename ObjPrivate> inline void assertObjectType(QObjectPrivate *d)
254{
255 using Obj = std::remove_pointer_t<decltype(std::declval<ObjPrivate *>()->q_func())>;
257}
258
259template<typename Func, typename Args, typename R>
261{
262 typedef QtPrivate::FunctionPointer<Func> FuncType;
263#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
264 static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
265#else
266 static void impl(QSlotObjectBase *this_, QObject *r, void **a, int which, bool *ret)
267#endif
268 {
269 const auto that = static_cast<QPrivateSlotObject*>(this_);
270 switch (which) {
271 case Destroy:
272 delete that;
273 break;
274 case Call:
275 FuncType::template call<Args, R>(that->object(),
276 static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
277 break;
278 case Compare:
279 *ret = *reinterpret_cast<Func *>(a) == that->object();
280 break;
281 case NumOperations: ;
282 }
283 }
284public:
286};
287} //namespace QtPrivate
288
289template <typename Func1, typename Func2>
290inline QMetaObject::Connection QObjectPrivate::connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
291 const typename QtPrivate::FunctionPointer<Func2>::Object *receiverPrivate, Func2 slot,
292 Qt::ConnectionType type)
293{
294 typedef QtPrivate::FunctionPointer<Func1> SignalType;
295 typedef QtPrivate::FunctionPointer<Func2> SlotType;
296 static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
297 "No Q_OBJECT in the class with the signal");
298
299 //compilation error if the arguments does not match.
300 static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount),
301 "The slot requires more arguments than the signal provides.");
302 static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
303 "Signal and slot arguments are not compatible.");
304 static_assert((QtPrivate::AreArgumentsCompatible<typename SlotType::ReturnType, typename SignalType::ReturnType>::value),
305 "Return type of the slot is not compatible with the return type of the signal.");
306
307 const int *types = nullptr;
308 if (type == Qt::QueuedConnection || type == Qt::BlockingQueuedConnection)
309 types = QtPrivate::ConnectionTypes<typename SignalType::Arguments>::types();
310
311 return QObject::connectImpl(sender, reinterpret_cast<void **>(&signal),
312 QtPrivate::getQObject(receiverPrivate), reinterpret_cast<void **>(&slot),
313 new QtPrivate::QPrivateSlotObject<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
314 typename SignalType::ReturnType>(slot),
315 type, types, &SignalType::Object::staticMetaObject);
316}
317
318template <typename Func1, typename Func2>
319bool QObjectPrivate::disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object* sender, Func1 signal,
320 const typename QtPrivate::FunctionPointer< Func2 >::Object* receiverPrivate, Func2 slot)
321{
322 typedef QtPrivate::FunctionPointer<Func1> SignalType;
323 typedef QtPrivate::FunctionPointer<Func2> SlotType;
324 static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
325 "No Q_OBJECT in the class with the signal");
326 //compilation error if the arguments does not match.
327 static_assert((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
328 "Signal and slot arguments are not compatible.");
329 return QObject::disconnectImpl(sender, reinterpret_cast<void **>(&signal),
330 receiverPrivate->q_ptr, reinterpret_cast<void **>(&slot),
331 &SignalType::Object::staticMetaObject);
332}
333
334class QLatch;
335class Q_CORE_EXPORT QAbstractMetaCallEvent : public QEvent
336{
337public:
338 QAbstractMetaCallEvent(const QObject *sender, int signalId, QLatch *latch = nullptr)
339 : QEvent(MetaCall), signalId_(signalId), sender_(sender), latch(latch)
340 {}
341 ~QAbstractMetaCallEvent();
342
343 virtual void placeMetaCall(QObject *object) = 0;
344
345 inline const QObject *sender() const { return sender_; }
346 inline int signalId() const { return signalId_; }
347
348private:
349 int signalId_;
350 const QObject *sender_;
351 QLatch *latch;
352};
353
354class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
355{
356public:
357 // blocking queued with latch - arguments always remain owned by the caller
358 QMetaCallEvent(ushort method_offset, ushort method_relative,
359 QObjectPrivate::StaticMetaCallFunction callFunction,
360 const QObject *sender, int signalId,
361 void **args, QLatch *latch);
362 QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
363 const QObject *sender, int signalId,
364 void **args, QLatch *latch);
365 QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
366 const QObject *sender, int signalId,
367 void **args, QLatch *latch);
368
369 virtual void placeMetaCall(QObject *object) override;
370
371 int id() const { return d.method_offset_ + d.method_relative_; }
372
373protected:
374 struct Data {
375 QtPrivate::SlotObjUniquePtr slotObj_;
376 void **args_;
377 QObjectPrivate::StaticMetaCallFunction callFunction_;
378 int nargs_;
379 ushort method_offset_;
380 ushort method_relative_;
381 } d;
382
383 inline QMetaCallEvent(const QObject *sender, int signalId, Data &&data);
384};
385
386class Q_CORE_EXPORT QQueuedMetaCallEvent : public QMetaCallEvent
387{
388public:
389 // queued - arguments are allocated and copied from argValues by these constructors
390 QQueuedMetaCallEvent(ushort method_offset, ushort method_relative,
391 QObjectPrivate::StaticMetaCallFunction callFunction,
392 const QObject *sender, int signalId,
393 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
394 const void * const *argValues);
395 QQueuedMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
396 const QObject *sender, int signalId,
397 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
398 const void * const *argValues);
399 QQueuedMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
400 const QObject *sender, int signalId,
401 int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
402 const void * const *argValues);
403
404 ~QQueuedMetaCallEvent() override;
405
406private:
407 inline void allocArgs();
408 inline void copyArgValues(int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
409 const void * const *argValues);
410 static inline bool typeFitsInPlace(const QMetaType type);
411
412 // Space for 5 argument pointers and types (including 1 return arg).
413 // Contiguous so that we can make one calloc() for both the pointers and the types when necessary.
414 static constexpr size_t PtrAndTypeSize = sizeof(void *) + sizeof(QMetaType);
415 alignas(void *) char prealloc_[5 * PtrAndTypeSize];
416 struct ArgValueStorage { // size and alignment matching QString, QList, etc
417 static constexpr size_t MaxSize = 3 * sizeof(void *);
418 alignas(void *) char storage[MaxSize];
419 };
420 static constexpr int InplaceValuesCapacity = 3;
421 ArgValueStorage valuesPrealloc_[InplaceValuesCapacity];
422};
423// The total QQueuedMetaCallEvent size is 224 bytes which is a 32-byte multiple, efficient for memory allocators.
424
425struct QAbstractDynamicMetaObject;
426struct Q_CORE_EXPORT QDynamicMetaObjectData
427{
428 virtual ~QDynamicMetaObjectData();
429 virtual void objectDestroyed(QObject *) { delete this; }
430
431#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
432 virtual const QMetaObject *toDynamicMetaObject(QObject *) const = 0;
433#else
434 virtual QMetaObject *toDynamicMetaObject(QObject *) = 0;
435#endif
436 virtual int metaCall(QObject *, QMetaObject::Call, int _id, void **) = 0;
437};
438
439struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, public QMetaObject
440{
441 ~QAbstractDynamicMetaObject();
442
443#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
444 const QMetaObject *toDynamicMetaObject(QObject *) const override { return this; }
445#else
446 QMetaObject *toDynamicMetaObject(QObject *) override { return this; }
447#endif
448 virtual int createProperty(const char *, const char *) { return -1; }
449 int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override
450 { return metaCall(c, _id, a); }
451 virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload
452};
453
454inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate *o)
455{
456 return &o->bindingStorage;
457}
458inline QBindingStorage *qGetBindingStorage(QObjectPrivate *o)
459{
460 return &o->bindingStorage;
461}
462inline const QBindingStorage *qGetBindingStorage(const QObjectPrivate::ExtraData *ed)
463{
464 return &ed->parent->bindingStorage;
465}
466inline QBindingStorage *qGetBindingStorage(QObjectPrivate::ExtraData *ed)
467{
468 return &ed->parent->bindingStorage;
469}
470
471QT_END_NAMESPACE
472
473#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:253
const QObject * getQObject(const QObjectPrivate *d)
Definition qobject_p.h:248
#define QT_CONCAT(B, M, m, u)
Definition qobject_p.h:43
QBindingStorage * qGetBindingStorage(QObjectPrivate *o)
Definition qobject_p.h:458
QBindingStorage * qGetBindingStorage(QObjectPrivate::ExtraData *ed)
Definition qobject_p.h:466
const QBindingStorage * qGetBindingStorage(const QObjectPrivate *o)
Definition qobject_p.h:454
#define Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(...)
Definition qproperty.h:1356
#define Q_OBJECT_COMPUTED_PROPERTY(Class, Type, name, ...)
Definition qproperty.h:1445
#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