1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the QtCore module of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:LGPL$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU Lesser General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU Lesser
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
23 ** packaging of this file. Please review the following information to
24 ** ensure the GNU Lesser General Public License version 3 requirements
25 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26 **
27 ** GNU General Public License Usage
28 ** Alternatively, this file may be used under the terms of the GNU
29 ** General Public License version 2.0 or (at your option) the GNU General
30 ** Public license version 3 or any later version approved by the KDE Free
31 ** Qt Foundation. The licenses are as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33 ** included in the packaging of this file. Please review the following
34 ** information to ensure the GNU General Public License requirements will
35 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36 ** https://www.gnu.org/licenses/gpl-3.0.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qobject.h"
43 #include "qobject_p.h"
44 #include "qmetaobject_p.h"
45
46 #include "qabstracteventdispatcher.h"
47 #include "qabstracteventdispatcher_p.h"
48 #include "qcoreapplication.h"
49 #include "qcoreapplication_p.h"
50 #include "qloggingcategory.h"
51 #include "qvariant.h"
52 #include "qmetaobject.h"
53 #include <qregexp.h>
54 #if QT_CONFIG(regularexpression)
55 # include <qregularexpression.h>
56 #endif
57 #include <qthread.h>
58 #include <private/qthread_p.h>
59 #include <qdebug.h>
60 #include <qpair.h>
61 #include <qvarlengtharray.h>
62 #include <qscopeguard.h>
63 #include <qset.h>
64 #if QT_CONFIG(thread)
65 #include <qsemaphore.h>
66 #endif
67 #include <qsharedpointer.h>
68
69 #include <private/qorderedmutexlocker_p.h>
70 #include <private/qhooks_p.h>
71 #include <qtcore_tracepoints_p.h>
72
73 #include <new>
74
75 #include <ctype.h>
76 #include <limits.h>
77
78 QT_BEGIN_NAMESPACE
79
80 static int DIRECT_CONNECTION_ONLY = 0;
81
82 Q_LOGGING_CATEGORY(lcConnections, "qt.core.qmetaobject.connectslotsbyname")
83
84 Q_CORE_EXPORT QBasicAtomicPointer<QSignalSpyCallbackSet> qt_signal_spy_callback_set = Q_BASIC_ATOMIC_INITIALIZER(nullptr);
85
qt_register_signal_spy_callbacks(QSignalSpyCallbackSet * callback_set)86 void qt_register_signal_spy_callbacks(QSignalSpyCallbackSet *callback_set)
87 {
88 qt_signal_spy_callback_set.storeRelease(callback_set);
89 }
90
~QDynamicMetaObjectData()91 QDynamicMetaObjectData::~QDynamicMetaObjectData()
92 {
93 }
94
~QAbstractDynamicMetaObject()95 QAbstractDynamicMetaObject::~QAbstractDynamicMetaObject()
96 {
97 }
98
queuedConnectionTypes(const QList<QByteArray> & typeNames)99 static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
100 {
101 int *types = new int [typeNames.count() + 1];
102 Q_CHECK_PTR(types);
103 for (int i = 0; i < typeNames.count(); ++i) {
104 const QByteArray typeName = typeNames.at(i);
105 if (typeName.endsWith('*'))
106 types[i] = QMetaType::VoidStar;
107 else
108 types[i] = QMetaType::type(typeName);
109
110 if (!types[i]) {
111 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
112 "(Make sure '%s' is registered using qRegisterMetaType().)",
113 typeName.constData(), typeName.constData());
114 delete [] types;
115 return nullptr;
116 }
117 }
118 types[typeNames.count()] = 0;
119
120 return types;
121 }
122
queuedConnectionTypes(const QArgumentType * argumentTypes,int argc)123 static int *queuedConnectionTypes(const QArgumentType *argumentTypes, int argc)
124 {
125 QScopedArrayPointer<int> types(new int [argc + 1]);
126 for (int i = 0; i < argc; ++i) {
127 const QArgumentType &type = argumentTypes[i];
128 if (type.type())
129 types[i] = type.type();
130 else if (type.name().endsWith('*'))
131 types[i] = QMetaType::VoidStar;
132 else
133 types[i] = QMetaType::type(type.name());
134
135 if (!types[i]) {
136 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
137 "(Make sure '%s' is registered using qRegisterMetaType().)",
138 type.name().constData(), type.name().constData());
139 return nullptr;
140 }
141 }
142 types[argc] = 0;
143
144 return types.take();
145 }
146
147 static QBasicMutex _q_ObjectMutexPool[131];
148
149 /**
150 * \internal
151 * mutex to be locked when accessing the connection lists or the senders list
152 */
signalSlotLock(const QObject * o)153 static inline QBasicMutex *signalSlotLock(const QObject *o)
154 {
155 return &_q_ObjectMutexPool[uint(quintptr(o)) % sizeof(_q_ObjectMutexPool)/sizeof(QBasicMutex)];
156 }
157
158 #if QT_VERSION < 0x60000
qt_addObject(QObject *)159 extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
160 {}
161
qt_removeObject(QObject *)162 extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
163 {}
164 #endif
165
166 void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = nullptr;
167 void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = nullptr;
168 void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = nullptr;
169 void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = nullptr;
170 int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
171 bool (*QAbstractDeclarativeData::isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int) = nullptr;
172 void (*QAbstractDeclarativeData::setWidgetParent)(QObject *, QObject *) = nullptr;
173
174 /*!
175 \fn QObjectData::QObjectData()
176 \internal
177 */
178
179
~QObjectData()180 QObjectData::~QObjectData() {}
181
dynamicMetaObject() const182 QMetaObject *QObjectData::dynamicMetaObject() const
183 {
184 return metaObject->toDynamicMetaObject(q_ptr);
185 }
186
QObjectPrivate(int version)187 QObjectPrivate::QObjectPrivate(int version)
188 : threadData(nullptr), currentChildBeingDeleted(nullptr)
189 {
190 checkForIncompatibleLibraryVersion(version);
191
192 // QObjectData initialization
193 q_ptr = nullptr;
194 parent = nullptr; // no parent yet. It is set by setParent()
195 isWidget = false; // assume not a widget object
196 blockSig = false; // not blocking signals
197 wasDeleted = false; // double-delete catcher
198 isDeletingChildren = false; // set by deleteChildren()
199 sendChildEvents = true; // if we should send ChildAdded and ChildRemoved events to parent
200 receiveChildEvents = true;
201 postedEvents = 0;
202 extraData = nullptr;
203 metaObject = nullptr;
204 isWindow = false;
205 deleteLaterCalled = false;
206 }
207
~QObjectPrivate()208 QObjectPrivate::~QObjectPrivate()
209 {
210 auto thisThreadData = threadData.loadRelaxed();
211 if (extraData && !extraData->runningTimers.isEmpty()) {
212 if (Q_LIKELY(thisThreadData->thread.loadAcquire() == QThread::currentThread())) {
213 // unregister pending timers
214 if (thisThreadData->hasEventDispatcher())
215 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
216
217 // release the timer ids back to the pool
218 for (int i = 0; i < extraData->runningTimers.size(); ++i)
219 QAbstractEventDispatcherPrivate::releaseTimerId(extraData->runningTimers.at(i));
220 } else {
221 qWarning("QObject::~QObject: Timers cannot be stopped from another thread");
222 }
223 }
224
225 if (postedEvents)
226 QCoreApplication::removePostedEvents(q_ptr, 0);
227
228 thisThreadData->deref();
229
230 if (metaObject) metaObject->objectDestroyed(q_ptr);
231
232 #ifndef QT_NO_USERDATA
233 if (extraData)
234 qDeleteAll(extraData->userData);
235 #endif
236 delete extraData;
237 }
238
239 /*!
240 \internal
241 For a given metaobject, compute the signal offset, and the method offset (including signals)
242 */
computeOffsets(const QMetaObject * metaobject,int * signalOffset,int * methodOffset)243 static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
244 {
245 *signalOffset = *methodOffset = 0;
246 const QMetaObject *m = metaobject->d.superdata;
247 while (m) {
248 const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
249 *methodOffset += d->methodCount;
250 Q_ASSERT(d->revision >= 4);
251 *signalOffset += d->signalCount;
252 m = m->d.superdata;
253 }
254 }
255
256 // Used by QAccessibleWidget
isSender(const QObject * receiver,const char * signal) const257 bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
258 {
259 Q_Q(const QObject);
260 int signal_index = signalIndex(signal);
261 ConnectionData *cd = connections.loadRelaxed();
262 if (signal_index < 0 || !cd)
263 return false;
264 QBasicMutexLocker locker(signalSlotLock(q));
265 if (signal_index < cd->signalVectorCount()) {
266 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
267
268 while (c) {
269 if (c->receiver.loadRelaxed() == receiver)
270 return true;
271 c = c->nextConnectionList.loadRelaxed();
272 }
273 }
274 return false;
275 }
276
277 // Used by QAccessibleWidget
receiverList(const char * signal) const278 QObjectList QObjectPrivate::receiverList(const char *signal) const
279 {
280 QObjectList returnValue;
281 int signal_index = signalIndex(signal);
282 ConnectionData *cd = connections.loadRelaxed();
283 if (signal_index < 0 || !cd)
284 return returnValue;
285 if (signal_index < cd->signalVectorCount()) {
286 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
287
288 while (c) {
289 QObject *r = c->receiver.loadRelaxed();
290 if (r)
291 returnValue << r;
292 c = c->nextConnectionList.loadRelaxed();
293 }
294 }
295 return returnValue;
296 }
297
298 // Used by QAccessibleWidget
senderList() const299 QObjectList QObjectPrivate::senderList() const
300 {
301 QObjectList returnValue;
302 ConnectionData *cd = connections.loadRelaxed();
303 if (cd) {
304 QBasicMutexLocker locker(signalSlotLock(q_func()));
305 for (Connection *c = cd->senders; c; c = c->next)
306 returnValue << c->sender;
307 }
308 return returnValue;
309 }
310
311 /*!
312 \internal
313 Add the connection \a c to the list of connections of the sender's object
314 for the specified \a signal
315
316 The signalSlotLock() of the sender and receiver must be locked while calling
317 this function
318
319 Will also add the connection in the sender's list of the receiver.
320 */
addConnection(int signal,Connection * c)321 void QObjectPrivate::addConnection(int signal, Connection *c)
322 {
323 Q_ASSERT(c->sender == q_ptr);
324 ensureConnectionData();
325 ConnectionData *cd = connections.loadRelaxed();
326 cd->resizeSignalVector(signal + 1);
327
328 ConnectionList &connectionList = cd->connectionsForSignal(signal);
329 if (connectionList.last.loadRelaxed()) {
330 Q_ASSERT(connectionList.last.loadRelaxed()->receiver.loadRelaxed());
331 connectionList.last.loadRelaxed()->nextConnectionList.storeRelaxed(c);
332 } else {
333 connectionList.first.storeRelaxed(c);
334 }
335 c->id = ++cd->currentConnectionId;
336 c->prevConnectionList = connectionList.last.loadRelaxed();
337 connectionList.last.storeRelaxed(c);
338
339 QObjectPrivate *rd = QObjectPrivate::get(c->receiver.loadRelaxed());
340 rd->ensureConnectionData();
341
342 c->prev = &(rd->connections.loadRelaxed()->senders);
343 c->next = *c->prev;
344 *c->prev = c;
345 if (c->next)
346 c->next->prev = &c->next;
347 }
348
removeConnection(QObjectPrivate::Connection * c)349 void QObjectPrivate::ConnectionData::removeConnection(QObjectPrivate::Connection *c)
350 {
351 Q_ASSERT(c->receiver.loadRelaxed());
352 ConnectionList &connections = signalVector.loadRelaxed()->at(c->signal_index);
353 c->receiver.storeRelaxed(nullptr);
354 QThreadData *td = c->receiverThreadData.loadRelaxed();
355 if (td)
356 td->deref();
357 c->receiverThreadData.storeRelaxed(nullptr);
358
359 #ifndef QT_NO_DEBUG
360 bool found = false;
361 for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
362 if (cc == c) {
363 found = true;
364 break;
365 }
366 }
367 Q_ASSERT(found);
368 #endif
369
370 // remove from the senders linked list
371 *c->prev = c->next;
372 if (c->next)
373 c->next->prev = c->prev;
374 c->prev = nullptr;
375
376 if (connections.first.loadRelaxed() == c)
377 connections.first.storeRelaxed(c->nextConnectionList.loadRelaxed());
378 if (connections.last.loadRelaxed() == c)
379 connections.last.storeRelaxed(c->prevConnectionList);
380 Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).first.loadRelaxed() != c);
381 Q_ASSERT(signalVector.loadRelaxed()->at(c->signal_index).last.loadRelaxed() != c);
382
383 // keep c->nextConnectionList intact, as it might still get accessed by activate
384 Connection *n = c->nextConnectionList.loadRelaxed();
385 if (n)
386 n->prevConnectionList = c->prevConnectionList;
387 if (c->prevConnectionList)
388 c->prevConnectionList->nextConnectionList.storeRelaxed(n);
389 c->prevConnectionList = nullptr;
390
391 Q_ASSERT(c != orphaned.loadRelaxed());
392 // add c to orphanedConnections
393 c->nextInOrphanList = orphaned.loadRelaxed();
394 orphaned.storeRelaxed(c);
395
396 #ifndef QT_NO_DEBUG
397 found = false;
398 for (Connection *cc = connections.first.loadRelaxed(); cc; cc = cc->nextConnectionList.loadRelaxed()) {
399 if (cc == c) {
400 found = true;
401 break;
402 }
403 }
404 Q_ASSERT(!found);
405 #endif
406
407 }
408
cleanOrphanedConnectionsImpl(QObject * sender)409 void QObjectPrivate::ConnectionData::cleanOrphanedConnectionsImpl(QObject *sender)
410 {
411 ConnectionOrSignalVector *c = nullptr;
412 {
413 QBasicMutexLocker l(signalSlotLock(sender));
414 if (ref.loadAcquire() > 1)
415 return;
416
417 // Since ref == 1, no activate() is in process since we locked the mutex. That implies,
418 // that nothing can reference the orphaned connection objects anymore and they can
419 // be safely deleted
420 c = orphaned.loadRelaxed();
421 orphaned.storeRelaxed(nullptr);
422 }
423 deleteOrphaned(c);
424 }
425
deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector * o)426 void QObjectPrivate::ConnectionData::deleteOrphaned(QObjectPrivate::ConnectionOrSignalVector *o)
427 {
428 while (o) {
429 QObjectPrivate::ConnectionOrSignalVector *next = nullptr;
430 if (SignalVector *v = ConnectionOrSignalVector::asSignalVector(o)) {
431 next = v->nextInOrphanList;
432 free(v);
433 } else {
434 QObjectPrivate::Connection *c = static_cast<Connection *>(o);
435 next = c->nextInOrphanList;
436 Q_ASSERT(!c->receiver.loadRelaxed());
437 Q_ASSERT(!c->prev);
438 c->freeSlotObject();
439 c->deref();
440 }
441 o = next;
442 }
443 }
444
445 /*! \internal
446
447 Returns \c true if the signal with index \a signal_index from object \a sender is connected.
448
449 \a signal_index must be the index returned by QObjectPrivate::signalIndex;
450 */
isSignalConnected(uint signalIndex,bool checkDeclarative) const451 bool QObjectPrivate::isSignalConnected(uint signalIndex, bool checkDeclarative) const
452 {
453 if (checkDeclarative && isDeclarativeSignalConnected(signalIndex))
454 return true;
455
456 ConnectionData *cd = connections.loadRelaxed();
457 if (!cd)
458 return false;
459 SignalVector *signalVector = cd->signalVector.loadRelaxed();
460 if (!signalVector)
461 return false;
462
463 if (signalVector->at(-1).first.loadRelaxed())
464 return true;
465
466 if (signalIndex < uint(cd->signalVectorCount())) {
467 const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadRelaxed();
468 while (c) {
469 if (c->receiver.loadRelaxed())
470 return true;
471 c = c->nextConnectionList.loadRelaxed();
472 }
473 }
474 return false;
475 }
476
maybeSignalConnected(uint signalIndex) const477 bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
478 {
479 ConnectionData *cd = connections.loadRelaxed();
480 if (!cd)
481 return false;
482 SignalVector *signalVector = cd->signalVector.loadRelaxed();
483 if (!signalVector)
484 return false;
485
486 if (signalVector->at(-1).first.loadAcquire())
487 return true;
488
489 if (signalIndex < uint(cd->signalVectorCount())) {
490 const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadAcquire();
491 return c != nullptr;
492 }
493 return false;
494 }
495
496 /*!
497 \internal
498 */
~QAbstractMetaCallEvent()499 QAbstractMetaCallEvent::~QAbstractMetaCallEvent()
500 {
501 #if QT_CONFIG(thread)
502 if (semaphore_)
503 semaphore_->release();
504 #endif
505 }
506
507 /*!
508 \internal
509 */
allocArgs()510 inline void QMetaCallEvent::allocArgs()
511 {
512 if (!d.nargs_)
513 return;
514
515 constexpr size_t each = sizeof(void*) + sizeof(int);
516 void *const memory = d.nargs_ * each > sizeof(prealloc_) ?
517 calloc(d.nargs_, each) : prealloc_;
518
519 Q_CHECK_PTR(memory);
520 d.args_ = static_cast<void **>(memory);
521 }
522
523 /*!
524 \internal
525
526 Used for blocking queued connections, just passes \a args through without
527 allocating any memory.
528 */
QMetaCallEvent(ushort method_offset,ushort method_relative,QObjectPrivate::StaticMetaCallFunction callFunction,const QObject * sender,int signalId,void ** args,QSemaphore * semaphore)529 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
530 QObjectPrivate::StaticMetaCallFunction callFunction,
531 const QObject *sender, int signalId,
532 void **args, QSemaphore *semaphore)
533 : QAbstractMetaCallEvent(sender, signalId, semaphore),
534 d({nullptr, args, callFunction, 0, method_offset, method_relative}),
535 prealloc_()
536 {
537 }
538
539 /*!
540 \internal
541
542 Used for blocking queued connections, just passes \a args through without
543 allocating any memory.
544 */
QMetaCallEvent(QtPrivate::QSlotObjectBase * slotO,const QObject * sender,int signalId,void ** args,QSemaphore * semaphore)545 QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
546 const QObject *sender, int signalId,
547 void **args, QSemaphore *semaphore)
548 : QAbstractMetaCallEvent(sender, signalId, semaphore),
549 d({slotO, args, nullptr, 0, 0, ushort(-1)}),
550 prealloc_()
551 {
552 if (d.slotObj_)
553 d.slotObj_->ref();
554 }
555
556 /*!
557 \internal
558
559 Allocates memory for \a nargs; code creating an event needs to initialize
560 the void* and int arrays by accessing \a args() and \a types(), respectively.
561 */
QMetaCallEvent(ushort method_offset,ushort method_relative,QObjectPrivate::StaticMetaCallFunction callFunction,const QObject * sender,int signalId,int nargs)562 QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
563 QObjectPrivate::StaticMetaCallFunction callFunction,
564 const QObject *sender, int signalId,
565 int nargs)
566 : QAbstractMetaCallEvent(sender, signalId),
567 d({nullptr, nullptr, callFunction, nargs, method_offset, method_relative}),
568 prealloc_()
569 {
570 allocArgs();
571 }
572
573 /*!
574 \internal
575
576 Allocates memory for \a nargs; code creating an event needs to initialize
577 the void* and int arrays by accessing \a args() and \a types(), respectively.
578 */
QMetaCallEvent(QtPrivate::QSlotObjectBase * slotO,const QObject * sender,int signalId,int nargs)579 QMetaCallEvent::QMetaCallEvent(QtPrivate::QSlotObjectBase *slotO,
580 const QObject *sender, int signalId,
581 int nargs)
582 : QAbstractMetaCallEvent(sender, signalId),
583 d({slotO, nullptr, nullptr, nargs, 0, ushort(-1)}),
584 prealloc_()
585 {
586 if (d.slotObj_)
587 d.slotObj_->ref();
588 allocArgs();
589 }
590
591 /*!
592 \internal
593 */
~QMetaCallEvent()594 QMetaCallEvent::~QMetaCallEvent()
595 {
596 if (d.nargs_) {
597 int *typeIDs = types();
598 for (int i = 0; i < d.nargs_; ++i) {
599 if (typeIDs[i] && d.args_[i])
600 QMetaType::destroy(typeIDs[i], d.args_[i]);
601 }
602 if (reinterpret_cast<void*>(d.args_) != reinterpret_cast<void*>(prealloc_))
603 free(d.args_);
604 }
605 if (d.slotObj_)
606 d.slotObj_->destroyIfLastRef();
607 }
608
609 /*!
610 \internal
611 */
placeMetaCall(QObject * object)612 void QMetaCallEvent::placeMetaCall(QObject *object)
613 {
614 if (d.slotObj_) {
615 d.slotObj_->call(object, d.args_);
616 } else if (d.callFunction_ && d.method_offset_ <= object->metaObject()->methodOffset()) {
617 d.callFunction_(object, QMetaObject::InvokeMetaMethod, d.method_relative_, d.args_);
618 } else {
619 QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod,
620 d.method_offset_ + d.method_relative_, d.args_);
621 }
622 }
623
624 /*!
625 \class QSignalBlocker
626 \brief Exception-safe wrapper around QObject::blockSignals().
627 \since 5.3
628 \ingroup objectmodel
629 \inmodule QtCore
630
631 \reentrant
632
633 QSignalBlocker can be used wherever you would otherwise use a
634 pair of calls to blockSignals(). It blocks signals in its
635 constructor and in the destructor it resets the state to what
636 it was before the constructor ran.
637
638 \snippet code/src_corelib_kernel_qobject.cpp 53
639 is thus equivalent to
640 \snippet code/src_corelib_kernel_qobject.cpp 54
641
642 except the code using QSignalBlocker is safe in the face of
643 exceptions.
644
645 \sa QMutexLocker, QEventLoopLocker
646 */
647
648 /*!
649 \fn QSignalBlocker::QSignalBlocker(QObject *object)
650
651 Constructor. Calls \a{object}->blockSignals(true).
652 */
653
654 /*!
655 \fn QSignalBlocker::QSignalBlocker(QObject &object)
656 \overload
657
658 Calls \a{object}.blockSignals(true).
659 */
660
661 /*!
662 \fn QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
663
664 Move-constructs a signal blocker from \a other. \a other will have
665 a no-op destructor, while responsibility for restoring the
666 QObject::signalsBlocked() state is transferred to the new object.
667 */
668
669 /*!
670 \fn QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
671
672 Move-assigns this signal blocker from \a other. \a other will have
673 a no-op destructor, while responsibility for restoring the
674 QObject::signalsBlocked() state is transferred to this object.
675
676 The object's signals this signal blocker was blocking prior to
677 being moved to, if any, are unblocked \e except in the case where
678 both instances block the same object's signals and \c *this is
679 unblocked while \a other is not, at the time of the move.
680 */
681
682 /*!
683 \fn QSignalBlocker::~QSignalBlocker()
684
685 Destructor. Restores the QObject::signalsBlocked() state to what it
686 was before the constructor ran, unless unblock() has been called
687 without a following reblock(), in which case it does nothing.
688 */
689
690 /*!
691 \fn void QSignalBlocker::reblock()
692
693 Re-blocks signals after a previous unblock().
694
695 The numbers of reblock() and unblock() calls are not counted, so
696 every reblock() undoes any number of unblock() calls.
697 */
698
699 /*!
700 \fn void QSignalBlocker::unblock()
701
702 Temporarily restores the QObject::signalsBlocked() state to what
703 it was before this QSignalBlocker's constructor ran. To undo, use
704 reblock().
705
706 The numbers of reblock() and unblock() calls are not counted, so
707 every unblock() undoes any number of reblock() calls.
708 */
709
710 /*!
711 \class QObject
712 \inmodule QtCore
713 \brief The QObject class is the base class of all Qt objects.
714
715 \ingroup objectmodel
716
717 \reentrant
718
719 QObject is the heart of the Qt \l{Object Model}. The central
720 feature in this model is a very powerful mechanism for seamless
721 object communication called \l{signals and slots}. You can
722 connect a signal to a slot with connect() and destroy the
723 connection with disconnect(). To avoid never ending notification
724 loops you can temporarily block signals with blockSignals(). The
725 protected functions connectNotify() and disconnectNotify() make
726 it possible to track connections.
727
728 QObjects organize themselves in \l {Object Trees & Ownership}
729 {object trees}. When you create a QObject with another object as
730 parent, the object will automatically add itself to the parent's
731 children() list. The parent takes ownership of the object; i.e.,
732 it will automatically delete its children in its destructor. You
733 can look for an object by name and optionally type using
734 findChild() or findChildren().
735
736 Every object has an objectName() and its class name can be found
737 via the corresponding metaObject() (see QMetaObject::className()).
738 You can determine whether the object's class inherits another
739 class in the QObject inheritance hierarchy by using the
740 inherits() function.
741
742 When an object is deleted, it emits a destroyed() signal. You can
743 catch this signal to avoid dangling references to QObjects.
744
745 QObjects can receive events through event() and filter the events
746 of other objects. See installEventFilter() and eventFilter() for
747 details. A convenience handler, childEvent(), can be reimplemented
748 to catch child events.
749
750 Last but not least, QObject provides the basic timer support in
751 Qt; see QTimer for high-level support for timers.
752
753 Notice that the Q_OBJECT macro is mandatory for any object that
754 implements signals, slots or properties. You also need to run the
755 \l{moc}{Meta Object Compiler} on the source file. We strongly
756 recommend the use of this macro in all subclasses of QObject
757 regardless of whether or not they actually use signals, slots and
758 properties, since failure to do so may lead certain functions to
759 exhibit strange behavior.
760
761 All Qt widgets inherit QObject. The convenience function
762 isWidgetType() returns whether an object is actually a widget. It
763 is much faster than
764 \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
765 \e{obj}->\l{inherits()}{inherits}("QWidget").
766
767 Some QObject functions, e.g. children(), return a QObjectList.
768 QObjectList is a typedef for QList<QObject *>.
769
770 \section1 Thread Affinity
771
772 A QObject instance is said to have a \e{thread affinity}, or that
773 it \e{lives} in a certain thread. When a QObject receives a
774 \l{Qt::QueuedConnection}{queued signal} or a \l{The Event
775 System#Sending Events}{posted event}, the slot or event handler
776 will run in the thread that the object lives in.
777
778 \note If a QObject has no thread affinity (that is, if thread()
779 returns zero), or if it lives in a thread that has no running event
780 loop, then it cannot receive queued signals or posted events.
781
782 By default, a QObject lives in the thread in which it is created.
783 An object's thread affinity can be queried using thread() and
784 changed using moveToThread().
785
786 All QObjects must live in the same thread as their parent. Consequently:
787
788 \list
789 \li setParent() will fail if the two QObjects involved live in
790 different threads.
791 \li When a QObject is moved to another thread, all its children
792 will be automatically moved too.
793 \li moveToThread() will fail if the QObject has a parent.
794 \li If QObjects are created within QThread::run(), they cannot
795 become children of the QThread object because the QThread does
796 not live in the thread that calls QThread::run().
797 \endlist
798
799 \note A QObject's member variables \e{do not} automatically become
800 its children. The parent-child relationship must be set by either
801 passing a pointer to the child's \l{QObject()}{constructor}, or by
802 calling setParent(). Without this step, the object's member variables
803 will remain in the old thread when moveToThread() is called.
804
805 \target No copy constructor
806 \section1 No Copy Constructor or Assignment Operator
807
808 QObject has neither a copy constructor nor an assignment operator.
809 This is by design. Actually, they are declared, but in a
810 \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
811 Qt classes derived from QObject (direct or indirect) use this
812 macro to declare their copy constructor and assignment operator to
813 be private. The reasoning is found in the discussion on
814 \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
815 Model} page.
816
817 The main consequence is that you should use pointers to QObject
818 (or to your QObject subclass) where you might otherwise be tempted
819 to use your QObject subclass as a value. For example, without a
820 copy constructor, you can't use a subclass of QObject as the value
821 to be stored in one of the container classes. You must store
822 pointers.
823
824 \section1 Auto-Connection
825
826 Qt's meta-object system provides a mechanism to automatically connect
827 signals and slots between QObject subclasses and their children. As long
828 as objects are defined with suitable object names, and slots follow a
829 simple naming convention, this connection can be performed at run-time
830 by the QMetaObject::connectSlotsByName() function.
831
832 \l uic generates code that invokes this function to enable
833 auto-connection to be performed between widgets on forms created
834 with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
835 given in the \l{Using a Designer UI File in Your C++ Application} section of
836 the \e{Qt Designer} manual.
837
838 \section1 Dynamic Properties
839
840 From Qt 4.2, dynamic properties can be added to and removed from QObject
841 instances at run-time. Dynamic properties do not need to be declared at
842 compile-time, yet they provide the same advantages as static properties
843 and are manipulated using the same API - using property() to read them
844 and setProperty() to write them.
845
846 From Qt 4.3, dynamic properties are supported by
847 \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
848 and both standard Qt widgets and user-created forms can be given dynamic
849 properties.
850
851 \section1 Internationalization (I18n)
852
853 All QObject subclasses support Qt's translation features, making it possible
854 to translate an application's user interface into different languages.
855
856 To make user-visible text translatable, it must be wrapped in calls to
857 the tr() function. This is explained in detail in the
858 \l{Writing Source Code for Translation} document.
859
860 \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
861 \sa {Object Trees & Ownership}
862 */
863
864 /*****************************************************************************
865 QObject member functions
866 *****************************************************************************/
867
868 // check the constructor's parent thread argument
check_parent_thread(QObject * parent,QThreadData * parentThreadData,QThreadData * currentThreadData)869 static bool check_parent_thread(QObject *parent,
870 QThreadData *parentThreadData,
871 QThreadData *currentThreadData)
872 {
873 if (parent && parentThreadData != currentThreadData) {
874 QThread *parentThread = parentThreadData->thread.loadAcquire();
875 QThread *currentThread = currentThreadData->thread.loadAcquire();
876 qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
877 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
878 parent->metaObject()->className(),
879 parent,
880 parentThread ? parentThread->metaObject()->className() : "QThread",
881 parentThread,
882 currentThread ? currentThread->metaObject()->className() : "QThread",
883 currentThread);
884 return false;
885 }
886 return true;
887 }
888
889 /*!
890 Constructs an object with parent object \a parent.
891
892 The parent of an object may be viewed as the object's owner. For
893 instance, a \l{QDialog}{dialog box} is the parent of the \uicontrol{OK}
894 and \uicontrol{Cancel} buttons it contains.
895
896 The destructor of a parent object destroys all child objects.
897
898 Setting \a parent to \nullptr constructs an object with no parent. If the
899 object is a widget, it will become a top-level window.
900
901 \sa parent(), findChild(), findChildren()
902 */
903
QObject(QObject * parent)904 QObject::QObject(QObject *parent)
905 : QObject(*new QObjectPrivate, parent)
906 {
907 }
908
909 /*!
910 \internal
911 */
QObject(QObjectPrivate & dd,QObject * parent)912 QObject::QObject(QObjectPrivate &dd, QObject *parent)
913 : d_ptr(&dd)
914 {
915 Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QObject to itself");
916
917 Q_D(QObject);
918 d_ptr->q_ptr = this;
919 auto threadData = (parent && !parent->thread()) ? parent->d_func()->threadData.loadRelaxed() : QThreadData::current();
920 threadData->ref();
921 d->threadData.storeRelaxed(threadData);
922 if (parent) {
923 QT_TRY {
924 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData.loadRelaxed() : nullptr, threadData))
925 parent = nullptr;
926 if (d->isWidget) {
927 if (parent) {
928 d->parent = parent;
929 d->parent->d_func()->children.append(this);
930 }
931 // no events sent here, this is done at the end of the QWidget constructor
932 } else {
933 setParent(parent);
934 }
935 } QT_CATCH(...) {
936 threadData->deref();
937 QT_RETHROW;
938 }
939 }
940 #if QT_VERSION < 0x60000
941 qt_addObject(this);
942 #endif
943 if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
944 reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
945 Q_TRACE(QObject_ctor, this);
946 }
947
948 /*!
949 Destroys the object, deleting all its child objects.
950
951 All signals to and from the object are automatically disconnected, and
952 any pending posted events for the object are removed from the event
953 queue. However, it is often safer to use deleteLater() rather than
954 deleting a QObject subclass directly.
955
956 \warning All child objects are deleted. If any of these objects
957 are on the stack or global, sooner or later your program will
958 crash. We do not recommend holding pointers to child objects from
959 outside the parent. If you still do, the destroyed() signal gives
960 you an opportunity to detect when an object is destroyed.
961
962 \warning Deleting a QObject while pending events are waiting to
963 be delivered can cause a crash. You must not delete the QObject
964 directly if it exists in a different thread than the one currently
965 executing. Use deleteLater() instead, which will cause the event
966 loop to delete the object after all pending events have been
967 delivered to it.
968
969 \sa deleteLater()
970 */
971
~QObject()972 QObject::~QObject()
973 {
974 Q_D(QObject);
975 d->wasDeleted = true;
976 d->blockSig = 0; // unblock signals so we always emit destroyed()
977
978 QtSharedPointer::ExternalRefCountData *sharedRefcount = d->sharedRefcount.loadRelaxed();
979 if (sharedRefcount) {
980 if (sharedRefcount->strongref.loadRelaxed() > 0) {
981 qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
982 // but continue deleting, it's too late to stop anyway
983 }
984
985 // indicate to all QWeakPointers that this QObject has now been deleted
986 sharedRefcount->strongref.storeRelaxed(0);
987 if (!sharedRefcount->weakref.deref())
988 delete sharedRefcount;
989 }
990
991 if (!d->isWidget && d->isSignalConnected(0)) {
992 emit destroyed(this);
993 }
994
995 if (d->declarativeData) {
996 if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
997 if (QAbstractDeclarativeData::destroyed_qml1)
998 QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
999 } else {
1000 if (QAbstractDeclarativeData::destroyed)
1001 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
1002 }
1003 }
1004
1005 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
1006 if (cd) {
1007 if (cd->currentSender) {
1008 cd->currentSender->receiverDeleted();
1009 cd->currentSender = nullptr;
1010 }
1011
1012 QBasicMutex *signalSlotMutex = signalSlotLock(this);
1013 QBasicMutexLocker locker(signalSlotMutex);
1014
1015 // disconnect all receivers
1016 int receiverCount = cd->signalVectorCount();
1017 for (int signal = -1; signal < receiverCount; ++signal) {
1018 QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
1019
1020 while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
1021 Q_ASSERT(c->receiver.loadAcquire());
1022
1023 QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
1024 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
1025 if (c->receiver.loadAcquire()) {
1026 cd->removeConnection(c);
1027 Q_ASSERT(connectionList.first.loadRelaxed() != c);
1028 }
1029 if (needToUnlock)
1030 m->unlock();
1031 }
1032 }
1033
1034 /* Disconnect all senders:
1035 */
1036 while (QObjectPrivate::Connection *node = cd->senders) {
1037 Q_ASSERT(node->receiver.loadAcquire());
1038 QObject *sender = node->sender;
1039 // Send disconnectNotify before removing the connection from sender's connection list.
1040 // This ensures any eventual destructor of sender will block on getting receiver's lock
1041 // and not finish until we release it.
1042 sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index));
1043 QBasicMutex *m = signalSlotLock(sender);
1044 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
1045 //the node has maybe been removed while the mutex was unlocked in relock?
1046 if (node != cd->senders) {
1047 // We hold the wrong mutex
1048 Q_ASSERT(needToUnlock);
1049 m->unlock();
1050 continue;
1051 }
1052
1053 QObjectPrivate::ConnectionData *senderData = sender->d_func()->connections.loadRelaxed();
1054 Q_ASSERT(senderData);
1055
1056 QtPrivate::QSlotObjectBase *slotObj = nullptr;
1057 if (node->isSlotObject) {
1058 slotObj = node->slotObj;
1059 node->isSlotObject = false;
1060 }
1061
1062 senderData->removeConnection(node);
1063 if (needToUnlock)
1064 m->unlock();
1065
1066 if (slotObj) {
1067 locker.unlock();
1068 slotObj->destroyIfLastRef();
1069 locker.relock();
1070 }
1071 }
1072
1073 // invalidate all connections on the object and make sure
1074 // activate() will skip them
1075 cd->currentConnectionId.storeRelaxed(0);
1076 }
1077 if (cd && !cd->ref.deref())
1078 delete cd;
1079 d->connections.storeRelaxed(nullptr);
1080
1081 if (!d->children.isEmpty())
1082 d->deleteChildren();
1083
1084 #if QT_VERSION < 0x60000
1085 qt_removeObject(this);
1086 #endif
1087 if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
1088 reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
1089
1090 Q_TRACE(QObject_dtor, this);
1091
1092 if (d->parent) // remove it from parent object
1093 d->setParent_helper(nullptr);
1094 }
1095
~Connection()1096 QObjectPrivate::Connection::~Connection()
1097 {
1098 if (ownArgumentTypes) {
1099 const int *v = argumentTypes.loadRelaxed();
1100 if (v != &DIRECT_CONNECTION_ONLY)
1101 delete [] v;
1102 }
1103 if (isSlotObject)
1104 slotObj->destroyIfLastRef();
1105 }
1106
1107
1108 /*!
1109 \fn const QMetaObject *QObject::metaObject() const
1110
1111 Returns a pointer to the meta-object of this object.
1112
1113 A meta-object contains information about a class that inherits
1114 QObject, e.g. class name, superclass name, properties, signals and
1115 slots. Every QObject subclass that contains the Q_OBJECT macro will have a
1116 meta-object.
1117
1118 The meta-object information is required by the signal/slot
1119 connection mechanism and the property system. The inherits()
1120 function also makes use of the meta-object.
1121
1122 If you have no pointer to an actual object instance but still
1123 want to access the meta-object of a class, you can use \l
1124 staticMetaObject.
1125
1126 Example:
1127
1128 \snippet code/src_corelib_kernel_qobject.cpp 1
1129
1130 \sa staticMetaObject
1131 */
1132
1133 /*!
1134 \variable QObject::staticMetaObject
1135
1136 This variable stores the meta-object for the class.
1137
1138 A meta-object contains information about a class that inherits
1139 QObject, e.g. class name, superclass name, properties, signals and
1140 slots. Every class that contains the Q_OBJECT macro will also have
1141 a meta-object.
1142
1143 The meta-object information is required by the signal/slot
1144 connection mechanism and the property system. The inherits()
1145 function also makes use of the meta-object.
1146
1147 If you have a pointer to an object, you can use metaObject() to
1148 retrieve the meta-object associated with that object.
1149
1150 Example:
1151
1152 \snippet code/src_corelib_kernel_qobject.cpp 2
1153
1154 \sa metaObject()
1155 */
1156
1157 /*!
1158 \fn template <class T> T qobject_cast(QObject *object)
1159 \fn template <class T> T qobject_cast(const QObject *object)
1160 \relates QObject
1161
1162 Returns the given \a object cast to type T if the object is of type
1163 T (or of a subclass); otherwise returns \nullptr. If \a object is
1164 \nullptr then it will also return \nullptr.
1165
1166 The class T must inherit (directly or indirectly) QObject and be
1167 declared with the \l Q_OBJECT macro.
1168
1169 A class is considered to inherit itself.
1170
1171 Example:
1172
1173 \snippet code/src_corelib_kernel_qobject.cpp 3
1174
1175 The qobject_cast() function behaves similarly to the standard C++
1176 \c dynamic_cast(), with the advantages that it doesn't require
1177 RTTI support and it works across dynamic library boundaries.
1178
1179 qobject_cast() can also be used in conjunction with interfaces;
1180 see the \l{tools/plugandpaint/app}{Plug & Paint} example for details.
1181
1182 \warning If T isn't declared with the Q_OBJECT macro, this
1183 function's return value is undefined.
1184
1185 \sa QObject::inherits()
1186 */
1187
1188 /*!
1189 \fn bool QObject::inherits(const char *className) const
1190
1191 Returns \c true if this object is an instance of a class that
1192 inherits \a className or a QObject subclass that inherits \a
1193 className; otherwise returns \c false.
1194
1195 A class is considered to inherit itself.
1196
1197 Example:
1198
1199 \snippet code/src_corelib_kernel_qobject.cpp 4
1200
1201 If you need to determine whether an object is an instance of a particular
1202 class for the purpose of casting it, consider using qobject_cast<Type *>(object)
1203 instead.
1204
1205 \sa metaObject(), qobject_cast()
1206 */
1207
1208 /*!
1209 \property QObject::objectName
1210
1211 \brief the name of this object
1212
1213 You can find an object by name (and type) using findChild().
1214 You can find a set of objects with findChildren().
1215
1216 \snippet code/src_corelib_kernel_qobject.cpp 5
1217
1218 By default, this property contains an empty string.
1219
1220 \sa metaObject(), QMetaObject::className()
1221 */
1222
objectName() const1223 QString QObject::objectName() const
1224 {
1225 Q_D(const QObject);
1226 return d->extraData ? d->extraData->objectName : QString();
1227 }
1228
1229 /*
1230 Sets the object's name to \a name.
1231 */
setObjectName(const QString & name)1232 void QObject::setObjectName(const QString &name)
1233 {
1234 Q_D(QObject);
1235 if (!d->extraData)
1236 d->extraData = new QObjectPrivate::ExtraData;
1237
1238 if (d->extraData->objectName != name) {
1239 d->extraData->objectName = name;
1240 emit objectNameChanged(d->extraData->objectName, QPrivateSignal());
1241 }
1242 }
1243
1244 /*! \fn void QObject::objectNameChanged(const QString &objectName)
1245
1246 This signal is emitted after the object's name has been changed. The new object name is passed as \a objectName.
1247
1248 \sa QObject::objectName
1249 */
1250
1251 /*!
1252 \fn bool QObject::isWidgetType() const
1253
1254 Returns \c true if the object is a widget; otherwise returns \c false.
1255
1256 Calling this function is equivalent to calling
1257 \c{inherits("QWidget")}, except that it is much faster.
1258 */
1259
1260 /*!
1261 \fn bool QObject::isWindowType() const
1262
1263 Returns \c true if the object is a window; otherwise returns \c false.
1264
1265 Calling this function is equivalent to calling
1266 \c{inherits("QWindow")}, except that it is much faster.
1267 */
1268
1269 /*!
1270 This virtual function receives events to an object and should
1271 return true if the event \a e was recognized and processed.
1272
1273 The event() function can be reimplemented to customize the
1274 behavior of an object.
1275
1276 Make sure you call the parent event class implementation
1277 for all the events you did not handle.
1278
1279 Example:
1280
1281 \snippet code/src_corelib_kernel_qobject.cpp 52
1282
1283 \sa installEventFilter(), timerEvent(), QCoreApplication::sendEvent(),
1284 QCoreApplication::postEvent()
1285 */
1286
event(QEvent * e)1287 bool QObject::event(QEvent *e)
1288 {
1289 switch (e->type()) {
1290 case QEvent::Timer:
1291 timerEvent((QTimerEvent*)e);
1292 break;
1293
1294 case QEvent::ChildAdded:
1295 case QEvent::ChildPolished:
1296 case QEvent::ChildRemoved:
1297 childEvent((QChildEvent*)e);
1298 break;
1299
1300 case QEvent::DeferredDelete:
1301 qDeleteInEventHandler(this);
1302 break;
1303
1304 case QEvent::MetaCall:
1305 {
1306 QAbstractMetaCallEvent *mce = static_cast<QAbstractMetaCallEvent*>(e);
1307
1308 if (!d_func()->connections.loadRelaxed()) {
1309 QBasicMutexLocker locker(signalSlotLock(this));
1310 d_func()->ensureConnectionData();
1311 }
1312 QObjectPrivate::Sender sender(this, const_cast<QObject*>(mce->sender()), mce->signalId());
1313
1314 mce->placeMetaCall(this);
1315 break;
1316 }
1317
1318 case QEvent::ThreadChange: {
1319 Q_D(QObject);
1320 QThreadData *threadData = d->threadData.loadRelaxed();
1321 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.loadRelaxed();
1322 if (eventDispatcher) {
1323 QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
1324 if (!timers.isEmpty()) {
1325 // do not to release our timer ids back to the pool (since the timer ids are moving to a new thread).
1326 eventDispatcher->unregisterTimers(this);
1327 QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
1328 Q_ARG(void*, (new QList<QAbstractEventDispatcher::TimerInfo>(timers))));
1329 }
1330 }
1331 break;
1332 }
1333
1334 default:
1335 if (e->type() >= QEvent::User) {
1336 customEvent(e);
1337 break;
1338 }
1339 return false;
1340 }
1341 return true;
1342 }
1343
1344 /*!
1345 \fn void QObject::timerEvent(QTimerEvent *event)
1346
1347 This event handler can be reimplemented in a subclass to receive
1348 timer events for the object.
1349
1350 QTimer provides a higher-level interface to the timer
1351 functionality, and also more general information about timers. The
1352 timer event is passed in the \a event parameter.
1353
1354 \sa startTimer(), killTimer(), event()
1355 */
1356
timerEvent(QTimerEvent *)1357 void QObject::timerEvent(QTimerEvent *)
1358 {
1359 }
1360
1361
1362 /*!
1363 This event handler can be reimplemented in a subclass to receive
1364 child events. The event is passed in the \a event parameter.
1365
1366 QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1367 objects when children are added or removed. In both cases you can
1368 only rely on the child being a QObject, or if isWidgetType()
1369 returns \c true, a QWidget. (This is because, in the
1370 \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1371 fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1372 case it might have been destructed already).
1373
1374 QEvent::ChildPolished events are sent to widgets when children
1375 are polished, or when polished children are added. If you receive
1376 a child polished event, the child's construction is usually
1377 completed. However, this is not guaranteed, and multiple polish
1378 events may be delivered during the execution of a widget's
1379 constructor.
1380
1381 For every child widget, you receive one
1382 \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1383 \l{QEvent::ChildPolished}{ChildPolished} events, and one
1384 \l{QEvent::ChildRemoved}{ChildRemoved} event.
1385
1386 The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1387 a child is removed immediately after it is added. If a child is
1388 polished several times during construction and destruction, you
1389 may receive several child polished events for the same child,
1390 each time with a different virtual table.
1391
1392 \sa event()
1393 */
1394
childEvent(QChildEvent *)1395 void QObject::childEvent(QChildEvent * /* event */)
1396 {
1397 }
1398
1399
1400 /*!
1401 This event handler can be reimplemented in a subclass to receive
1402 custom events. Custom events are user-defined events with a type
1403 value at least as large as the QEvent::User item of the
1404 QEvent::Type enum, and is typically a QEvent subclass. The event
1405 is passed in the \a event parameter.
1406
1407 \sa event(), QEvent
1408 */
customEvent(QEvent *)1409 void QObject::customEvent(QEvent * /* event */)
1410 {
1411 }
1412
1413
1414
1415 /*!
1416 Filters events if this object has been installed as an event
1417 filter for the \a watched object.
1418
1419 In your reimplementation of this function, if you want to filter
1420 the \a event out, i.e. stop it being handled further, return
1421 true; otherwise return false.
1422
1423 Example:
1424 \snippet code/src_corelib_kernel_qobject.cpp 6
1425
1426 Notice in the example above that unhandled events are passed to
1427 the base class's eventFilter() function, since the base class
1428 might have reimplemented eventFilter() for its own internal
1429 purposes.
1430
1431 Some events, such as \l QEvent::ShortcutOverride must be explicitly
1432 accepted (by calling \l {QEvent::}{accept()} on them) in order to prevent
1433 propagation.
1434
1435 \warning If you delete the receiver object in this function, be
1436 sure to return true. Otherwise, Qt will forward the event to the
1437 deleted object and the program might crash.
1438
1439 \sa installEventFilter()
1440 */
1441
eventFilter(QObject *,QEvent *)1442 bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1443 {
1444 return false;
1445 }
1446
1447 /*!
1448 \fn bool QObject::signalsBlocked() const
1449
1450 Returns \c true if signals are blocked; otherwise returns \c false.
1451
1452 Signals are not blocked by default.
1453
1454 \sa blockSignals(), QSignalBlocker
1455 */
1456
1457 /*!
1458 If \a block is true, signals emitted by this object are blocked
1459 (i.e., emitting a signal will not invoke anything connected to it).
1460 If \a block is false, no such blocking will occur.
1461
1462 The return value is the previous value of signalsBlocked().
1463
1464 Note that the destroyed() signal will be emitted even if the signals
1465 for this object have been blocked.
1466
1467 Signals emitted while being blocked are not buffered.
1468
1469 \sa signalsBlocked(), QSignalBlocker
1470 */
1471
blockSignals(bool block)1472 bool QObject::blockSignals(bool block) noexcept
1473 {
1474 Q_D(QObject);
1475 bool previous = d->blockSig;
1476 d->blockSig = block;
1477 return previous;
1478 }
1479
1480 /*!
1481 Returns the thread in which the object lives.
1482
1483 \sa moveToThread()
1484 */
thread() const1485 QThread *QObject::thread() const
1486 {
1487 return d_func()->threadData.loadRelaxed()->thread.loadAcquire();
1488 }
1489
1490 /*!
1491 Changes the thread affinity for this object and its children. The
1492 object cannot be moved if it has a parent. Event processing will
1493 continue in the \a targetThread.
1494
1495 To move an object to the main thread, use QApplication::instance()
1496 to retrieve a pointer to the current application, and then use
1497 QApplication::thread() to retrieve the thread in which the
1498 application lives. For example:
1499
1500 \snippet code/src_corelib_kernel_qobject.cpp 7
1501
1502 If \a targetThread is \nullptr, all event processing for this object
1503 and its children stops, as they are no longer associated with any
1504 thread.
1505
1506 Note that all active timers for the object will be reset. The
1507 timers are first stopped in the current thread and restarted (with
1508 the same interval) in the \a targetThread. As a result, constantly
1509 moving an object between threads can postpone timer events
1510 indefinitely.
1511
1512 A QEvent::ThreadChange event is sent to this object just before
1513 the thread affinity is changed. You can handle this event to
1514 perform any special processing. Note that any new events that are
1515 posted to this object will be handled in the \a targetThread,
1516 provided it is not \nullptr: when it is \nullptr, no event processing
1517 for this object or its children can happen, as they are no longer
1518 associated with any thread.
1519
1520 \warning This function is \e not thread-safe; the current thread
1521 must be same as the current thread affinity. In other words, this
1522 function can only "push" an object from the current thread to
1523 another thread, it cannot "pull" an object from any arbitrary
1524 thread to the current thread. There is one exception to this rule
1525 however: objects with no thread affinity can be "pulled" to the
1526 current thread.
1527
1528 \sa thread()
1529 */
moveToThread(QThread * targetThread)1530 void QObject::moveToThread(QThread *targetThread)
1531 {
1532 Q_D(QObject);
1533
1534 if (d->threadData.loadRelaxed()->thread.loadAcquire() == targetThread) {
1535 // object is already in this thread
1536 return;
1537 }
1538
1539 if (d->parent != nullptr) {
1540 qWarning("QObject::moveToThread: Cannot move objects with a parent");
1541 return;
1542 }
1543 if (d->isWidget) {
1544 qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
1545 return;
1546 }
1547
1548 QThreadData *currentData = QThreadData::current();
1549 QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
1550 QThreadData *thisThreadData = d->threadData.loadRelaxed();
1551 if (!thisThreadData->thread.loadAcquire() && currentData == targetData) {
1552 // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1553 currentData = d->threadData;
1554 } else if (thisThreadData != currentData) {
1555 qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1556 "Cannot move to target thread (%p)\n",
1557 currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);
1558
1559 #ifdef Q_OS_MAC
1560 qWarning("You might be loading two sets of Qt binaries into the same process. "
1561 "Check that all plugins are compiled against the right Qt binaries. Export "
1562 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1563 #endif
1564
1565 return;
1566 }
1567
1568 // prepare to move
1569 d->moveToThread_helper();
1570
1571 if (!targetData)
1572 targetData = new QThreadData(0);
1573
1574 // make sure nobody adds/removes connections to this object while we're moving it
1575 QMutexLocker l(signalSlotLock(this));
1576
1577 QOrderedMutexLocker locker(¤tData->postEventList.mutex,
1578 &targetData->postEventList.mutex);
1579
1580 // keep currentData alive (since we've got it locked)
1581 currentData->ref();
1582
1583 // move the object
1584 d_func()->setThreadData_helper(currentData, targetData);
1585
1586 locker.unlock();
1587
1588 // now currentData can commit suicide if it wants to
1589 currentData->deref();
1590 }
1591
moveToThread_helper()1592 void QObjectPrivate::moveToThread_helper()
1593 {
1594 Q_Q(QObject);
1595 QEvent e(QEvent::ThreadChange);
1596 QCoreApplication::sendEvent(q, &e);
1597 for (int i = 0; i < children.size(); ++i) {
1598 QObject *child = children.at(i);
1599 child->d_func()->moveToThread_helper();
1600 }
1601 }
1602
setThreadData_helper(QThreadData * currentData,QThreadData * targetData)1603 void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1604 {
1605 Q_Q(QObject);
1606
1607 // move posted events
1608 int eventsMoved = 0;
1609 for (int i = 0; i < currentData->postEventList.size(); ++i) {
1610 const QPostEvent &pe = currentData->postEventList.at(i);
1611 if (!pe.event)
1612 continue;
1613 if (pe.receiver == q) {
1614 // move this post event to the targetList
1615 targetData->postEventList.addEvent(pe);
1616 const_cast<QPostEvent &>(pe).event = nullptr;
1617 ++eventsMoved;
1618 }
1619 }
1620 if (eventsMoved > 0 && targetData->hasEventDispatcher()) {
1621 targetData->canWait = false;
1622 targetData->eventDispatcher.loadRelaxed()->wakeUp();
1623 }
1624
1625 // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1626 ConnectionData *cd = connections.loadRelaxed();
1627 if (cd) {
1628 if (cd->currentSender) {
1629 cd->currentSender->receiverDeleted();
1630 cd->currentSender = nullptr;
1631 }
1632
1633 // adjust the receiverThreadId values in the Connections
1634 if (cd) {
1635 auto *c = cd->senders;
1636 while (c) {
1637 QObject *r = c->receiver.loadRelaxed();
1638 if (r) {
1639 Q_ASSERT(r == q);
1640 targetData->ref();
1641 QThreadData *old = c->receiverThreadData.loadRelaxed();
1642 if (old)
1643 old->deref();
1644 c->receiverThreadData.storeRelaxed(targetData);
1645 }
1646 c = c->next;
1647 }
1648 }
1649
1650 }
1651
1652 // set new thread data
1653 targetData->ref();
1654 threadData.loadRelaxed()->deref();
1655
1656 // synchronizes with loadAcquire e.g. in QCoreApplication::postEvent
1657 threadData.storeRelease(targetData);
1658
1659 for (int i = 0; i < children.size(); ++i) {
1660 QObject *child = children.at(i);
1661 child->d_func()->setThreadData_helper(currentData, targetData);
1662 }
1663 }
1664
_q_reregisterTimers(void * pointer)1665 void QObjectPrivate::_q_reregisterTimers(void *pointer)
1666 {
1667 Q_Q(QObject);
1668 QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
1669 QAbstractEventDispatcher *eventDispatcher = threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
1670 for (int i = 0; i < timerList->size(); ++i) {
1671 const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
1672 eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
1673 }
1674 delete timerList;
1675 }
1676
1677
1678 //
1679 // The timer flag hasTimer is set when startTimer is called.
1680 // It is not reset when killing the timer because more than
1681 // one timer might be active.
1682 //
1683
1684 /*!
1685 Starts a timer and returns a timer identifier, or returns zero if
1686 it could not start a timer.
1687
1688 A timer event will occur every \a interval milliseconds until
1689 killTimer() is called. If \a interval is 0, then the timer event
1690 occurs once every time there are no more window system events to
1691 process.
1692
1693 The virtual timerEvent() function is called with the QTimerEvent
1694 event parameter class when a timer event occurs. Reimplement this
1695 function to get timer events.
1696
1697 If multiple timers are running, the QTimerEvent::timerId() can be
1698 used to find out which timer was activated.
1699
1700 Example:
1701
1702 \snippet code/src_corelib_kernel_qobject.cpp 8
1703
1704 Note that QTimer's accuracy depends on the underlying operating system and
1705 hardware. The \a timerType argument allows you to customize the accuracy of
1706 the timer. See Qt::TimerType for information on the different timer types.
1707 Most platforms support an accuracy of 20 milliseconds; some provide more.
1708 If Qt is unable to deliver the requested number of timer events, it will
1709 silently discard some.
1710
1711 The QTimer class provides a high-level programming interface with
1712 single-shot timers and timer signals instead of events. There is
1713 also a QBasicTimer class that is more lightweight than QTimer and
1714 less clumsy than using timer IDs directly.
1715
1716 \sa timerEvent(), killTimer(), QTimer::singleShot()
1717 */
1718
startTimer(int interval,Qt::TimerType timerType)1719 int QObject::startTimer(int interval, Qt::TimerType timerType)
1720 {
1721 Q_D(QObject);
1722
1723 if (Q_UNLIKELY(interval < 0)) {
1724 qWarning("QObject::startTimer: Timers cannot have negative intervals");
1725 return 0;
1726 }
1727
1728 auto thisThreadData = d->threadData.loadRelaxed();
1729 if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) {
1730 qWarning("QObject::startTimer: Timers can only be used with threads started with QThread");
1731 return 0;
1732 }
1733 if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1734 qWarning("QObject::startTimer: Timers cannot be started from another thread");
1735 return 0;
1736 }
1737 int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this);
1738 if (!d->extraData)
1739 d->extraData = new QObjectPrivate::ExtraData;
1740 d->extraData->runningTimers.append(timerId);
1741 return timerId;
1742 }
1743
1744 /*!
1745 \since 5.9
1746 \overload
1747 \fn int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType)
1748
1749 Starts a timer and returns a timer identifier, or returns zero if
1750 it could not start a timer.
1751
1752 A timer event will occur every \a time interval until killTimer()
1753 is called. If \a time is equal to \c{std::chrono::duration::zero()},
1754 then the timer event occurs once every time there are no more window
1755 system events to process.
1756
1757 The virtual timerEvent() function is called with the QTimerEvent
1758 event parameter class when a timer event occurs. Reimplement this
1759 function to get timer events.
1760
1761 If multiple timers are running, the QTimerEvent::timerId() can be
1762 used to find out which timer was activated.
1763
1764 Example:
1765
1766 \snippet code/src_corelib_kernel_qobject.cpp 8
1767
1768 Note that QTimer's accuracy depends on the underlying operating system and
1769 hardware. The \a timerType argument allows you to customize the accuracy of
1770 the timer. See Qt::TimerType for information on the different timer types.
1771 Most platforms support an accuracy of 20 milliseconds; some provide more.
1772 If Qt is unable to deliver the requested number of timer events, it will
1773 silently discard some.
1774
1775 The QTimer class provides a high-level programming interface with
1776 single-shot timers and timer signals instead of events. There is
1777 also a QBasicTimer class that is more lightweight than QTimer and
1778 less clumsy than using timer IDs directly.
1779
1780 \sa timerEvent(), killTimer(), QTimer::singleShot()
1781 */
1782
1783 /*!
1784 Kills the timer with timer identifier, \a id.
1785
1786 The timer identifier is returned by startTimer() when a timer
1787 event is started.
1788
1789 \sa timerEvent(), startTimer()
1790 */
1791
killTimer(int id)1792 void QObject::killTimer(int id)
1793 {
1794 Q_D(QObject);
1795 if (Q_UNLIKELY(thread() != QThread::currentThread())) {
1796 qWarning("QObject::killTimer: Timers cannot be stopped from another thread");
1797 return;
1798 }
1799 if (id) {
1800 int at = d->extraData ? d->extraData->runningTimers.indexOf(id) : -1;
1801 if (at == -1) {
1802 // timer isn't owned by this object
1803 qWarning("QObject::killTimer(): Error: timer id %d is not valid for object %p (%s, %ls), timer has not been killed",
1804 id,
1805 this,
1806 metaObject()->className(),
1807 qUtf16Printable(objectName()));
1808 return;
1809 }
1810
1811 auto thisThreadData = d->threadData.loadRelaxed();
1812 if (thisThreadData->hasEventDispatcher())
1813 thisThreadData->eventDispatcher.loadRelaxed()->unregisterTimer(id);
1814
1815 d->extraData->runningTimers.remove(at);
1816 QAbstractEventDispatcherPrivate::releaseTimerId(id);
1817 }
1818 }
1819
1820
1821 /*!
1822 \fn QObject *QObject::parent() const
1823
1824 Returns a pointer to the parent object.
1825
1826 \sa children()
1827 */
1828
1829 /*!
1830 \fn const QObjectList &QObject::children() const
1831
1832 Returns a list of child objects.
1833 The QObjectList class is defined in the \c{<QObject>} header
1834 file as the following:
1835
1836 \quotefromfile kernel/qobject.h
1837 \skipto /typedef .*QObjectList/
1838 \printuntil QObjectList
1839
1840 The first child added is the \l{QList::first()}{first} object in
1841 the list and the last child added is the \l{QList::last()}{last}
1842 object in the list, i.e. new children are appended at the end.
1843
1844 Note that the list order changes when QWidget children are
1845 \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1846 widget that is raised becomes the last object in the list, and a
1847 widget that is lowered becomes the first object in the list.
1848
1849 \sa findChild(), findChildren(), parent(), setParent()
1850 */
1851
1852
1853 /*!
1854 \fn template<typename T> T *QObject::findChild(const QString &name, Qt::FindChildOptions options) const
1855
1856 Returns the child of this object that can be cast into type T and
1857 that is called \a name, or \nullptr if there is no such object.
1858 Omitting the \a name argument causes all object names to be matched.
1859 The search is performed recursively, unless \a options specifies the
1860 option FindDirectChildrenOnly.
1861
1862 If there is more than one child matching the search, the most
1863 direct ancestor is returned. If there are several direct
1864 ancestors, it is undefined which one will be returned. In that
1865 case, findChildren() should be used.
1866
1867 This example returns a child \c{QPushButton} of \c{parentWidget}
1868 named \c{"button1"}, even if the button isn't a direct child of
1869 the parent:
1870
1871 \snippet code/src_corelib_kernel_qobject.cpp 10
1872
1873 This example returns a \c{QListWidget} child of \c{parentWidget}:
1874
1875 \snippet code/src_corelib_kernel_qobject.cpp 11
1876
1877 This example returns a child \c{QPushButton} of \c{parentWidget}
1878 (its direct parent) named \c{"button1"}:
1879
1880 \snippet code/src_corelib_kernel_qobject.cpp 41
1881
1882 This example returns a \c{QListWidget} child of \c{parentWidget},
1883 its direct parent:
1884
1885 \snippet code/src_corelib_kernel_qobject.cpp 42
1886
1887 \sa findChildren()
1888 */
1889
1890 /*!
1891 \fn template<typename T> QList<T> QObject::findChildren(const QString &name, Qt::FindChildOptions options) const
1892
1893 Returns all children of this object with the given \a name that can be
1894 cast to type T, or an empty list if there are no such objects.
1895 Omitting the \a name argument causes all object names to be matched.
1896 The search is performed recursively, unless \a options specifies the
1897 option FindDirectChildrenOnly.
1898
1899 The following example shows how to find a list of child \c{QWidget}s of
1900 the specified \c{parentWidget} named \c{widgetname}:
1901
1902 \snippet code/src_corelib_kernel_qobject.cpp 12
1903
1904 This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1905
1906 \snippet code/src_corelib_kernel_qobject.cpp 13
1907
1908 This example returns all \c{QPushButton}s that are immediate children of \c{parentWidget}:
1909
1910 \snippet code/src_corelib_kernel_qobject.cpp 43
1911
1912 \sa findChild()
1913 */
1914
1915 /*!
1916 \fn template<typename T> QList<T> QObject::findChildren(const QRegExp ®Exp, Qt::FindChildOptions options) const
1917 \overload findChildren()
1918 \obsolete
1919
1920 Returns the children of this object that can be cast to type T
1921 and that have names matching the regular expression \a regExp,
1922 or an empty list if there are no such objects.
1923 The search is performed recursively, unless \a options specifies the
1924 option FindDirectChildrenOnly.
1925
1926 Use the findChildren overload taking a QRegularExpression instead.
1927 */
1928
1929 /*!
1930 \fn QList<T> QObject::findChildren(const QRegularExpression &re, Qt::FindChildOptions options) const
1931 \overload findChildren()
1932
1933 \since 5.0
1934
1935 Returns the children of this object that can be cast to type T
1936 and that have names matching the regular expression \a re,
1937 or an empty list if there are no such objects.
1938 The search is performed recursively, unless \a options specifies the
1939 option FindDirectChildrenOnly.
1940 */
1941
1942 /*!
1943 \fn template<typename T> T qFindChild(const QObject *obj, const QString &name)
1944 \relates QObject
1945 \overload qFindChildren()
1946 \obsolete
1947
1948 This function is equivalent to
1949 \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1950
1951 \note This function was provided as a workaround for MSVC 6
1952 which did not support member template functions. It is advised
1953 to use the other form in new code.
1954
1955 \sa QObject::findChild()
1956 */
1957
1958 /*!
1959 \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QString &name)
1960 \relates QObject
1961 \overload qFindChildren()
1962 \obsolete
1963
1964 This function is equivalent to
1965 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1966
1967 \note This function was provided as a workaround for MSVC 6
1968 which did not support member template functions. It is advised
1969 to use the other form in new code.
1970
1971 \sa QObject::findChildren()
1972 */
1973
1974 /*!
1975 \fn template<typename T> QList<T> qFindChildren(const QObject *obj, const QRegExp ®Exp)
1976 \relates QObject
1977 \overload qFindChildren()
1978
1979 This function is equivalent to
1980 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
1981
1982 \note This function was provided as a workaround for MSVC 6
1983 which did not support member template functions. It is advised
1984 to use the other form in new code.
1985
1986 \sa QObject::findChildren()
1987 */
1988
1989 /*!
1990 \internal
1991 */
qt_qFindChildren_helper(const QObject * parent,const QString & name,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)1992 void qt_qFindChildren_helper(const QObject *parent, const QString &name,
1993 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
1994 {
1995 if (!parent || !list)
1996 return;
1997 const QObjectList &children = parent->children();
1998 QObject *obj;
1999 for (int i = 0; i < children.size(); ++i) {
2000 obj = children.at(i);
2001 if (mo.cast(obj)) {
2002 if (name.isNull() || obj->objectName() == name)
2003 list->append(obj);
2004 }
2005 if (options & Qt::FindChildrenRecursively)
2006 qt_qFindChildren_helper(obj, name, mo, list, options);
2007 }
2008 }
2009
2010 #ifndef QT_NO_REGEXP
2011 /*!
2012 \internal
2013 */
qt_qFindChildren_helper(const QObject * parent,const QRegExp & re,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)2014 void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
2015 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2016 {
2017 if (!parent || !list)
2018 return;
2019 const QObjectList &children = parent->children();
2020 QRegExp reCopy = re;
2021 QObject *obj;
2022 for (int i = 0; i < children.size(); ++i) {
2023 obj = children.at(i);
2024 if (mo.cast(obj) && reCopy.indexIn(obj->objectName()) != -1)
2025 list->append(obj);
2026
2027 if (options & Qt::FindChildrenRecursively)
2028 qt_qFindChildren_helper(obj, re, mo, list, options);
2029 }
2030 }
2031 #endif // QT_NO_REGEXP
2032
2033 #if QT_CONFIG(regularexpression)
2034 /*!
2035 \internal
2036 */
qt_qFindChildren_helper(const QObject * parent,const QRegularExpression & re,const QMetaObject & mo,QList<void * > * list,Qt::FindChildOptions options)2037 void qt_qFindChildren_helper(const QObject *parent, const QRegularExpression &re,
2038 const QMetaObject &mo, QList<void*> *list, Qt::FindChildOptions options)
2039 {
2040 if (!parent || !list)
2041 return;
2042 const QObjectList &children = parent->children();
2043 QObject *obj;
2044 for (int i = 0; i < children.size(); ++i) {
2045 obj = children.at(i);
2046 if (mo.cast(obj)) {
2047 QRegularExpressionMatch m = re.match(obj->objectName());
2048 if (m.hasMatch())
2049 list->append(obj);
2050 }
2051 if (options & Qt::FindChildrenRecursively)
2052 qt_qFindChildren_helper(obj, re, mo, list, options);
2053 }
2054 }
2055 #endif // QT_CONFIG(regularexpression)
2056
2057 /*!
2058 \internal
2059 */
qt_qFindChild_helper(const QObject * parent,const QString & name,const QMetaObject & mo,Qt::FindChildOptions options)2060 QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo, Qt::FindChildOptions options)
2061 {
2062 if (!parent)
2063 return nullptr;
2064 const QObjectList &children = parent->children();
2065 QObject *obj;
2066 int i;
2067 for (i = 0; i < children.size(); ++i) {
2068 obj = children.at(i);
2069 if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
2070 return obj;
2071 }
2072 if (options & Qt::FindChildrenRecursively) {
2073 for (i = 0; i < children.size(); ++i) {
2074 obj = qt_qFindChild_helper(children.at(i), name, mo, options);
2075 if (obj)
2076 return obj;
2077 }
2078 }
2079 return nullptr;
2080 }
2081
2082 /*!
2083 Makes the object a child of \a parent.
2084
2085 \sa parent(), children()
2086 */
setParent(QObject * parent)2087 void QObject::setParent(QObject *parent)
2088 {
2089 Q_D(QObject);
2090 Q_ASSERT(!d->isWidget);
2091 d->setParent_helper(parent);
2092 }
2093
deleteChildren()2094 void QObjectPrivate::deleteChildren()
2095 {
2096 Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
2097 isDeletingChildren = true;
2098 // delete children objects
2099 // don't use qDeleteAll as the destructor of the child might
2100 // delete siblings
2101 for (int i = 0; i < children.count(); ++i) {
2102 currentChildBeingDeleted = children.at(i);
2103 children[i] = 0;
2104 delete currentChildBeingDeleted;
2105 }
2106 children.clear();
2107 currentChildBeingDeleted = nullptr;
2108 isDeletingChildren = false;
2109 }
2110
setParent_helper(QObject * o)2111 void QObjectPrivate::setParent_helper(QObject *o)
2112 {
2113 Q_Q(QObject);
2114 Q_ASSERT_X(q != o, Q_FUNC_INFO, "Cannot parent a QObject to itself");
2115 #ifdef QT_DEBUG
2116 const auto checkForParentChildLoops = qScopeGuard([&](){
2117 int depth = 0;
2118 auto p = parent;
2119 while (p) {
2120 if (++depth == CheckForParentChildLoopsWarnDepth) {
2121 qWarning("QObject %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; "
2122 "this is undefined behavior",
2123 q, q->metaObject()->className(), qPrintable(q->objectName()));
2124 }
2125 p = p->parent();
2126 }
2127 });
2128 #endif
2129
2130 if (o == parent)
2131 return;
2132
2133 if (parent) {
2134 QObjectPrivate *parentD = parent->d_func();
2135 if (parentD->isDeletingChildren && wasDeleted
2136 && parentD->currentChildBeingDeleted == q) {
2137 // don't do anything since QObjectPrivate::deleteChildren() already
2138 // cleared our entry in parentD->children.
2139 } else {
2140 const int index = parentD->children.indexOf(q);
2141 if (index < 0) {
2142 // we're probably recursing into setParent() from a ChildRemoved event, don't do anything
2143 } else if (parentD->isDeletingChildren) {
2144 parentD->children[index] = 0;
2145 } else {
2146 parentD->children.removeAt(index);
2147 if (sendChildEvents && parentD->receiveChildEvents) {
2148 QChildEvent e(QEvent::ChildRemoved, q);
2149 QCoreApplication::sendEvent(parent, &e);
2150 }
2151 }
2152 }
2153 }
2154 parent = o;
2155 if (parent) {
2156 // object hierarchies are constrained to a single thread
2157 if (threadData != parent->d_func()->threadData) {
2158 qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
2159 parent = nullptr;
2160 return;
2161 }
2162 parent->d_func()->children.append(q);
2163 if(sendChildEvents && parent->d_func()->receiveChildEvents) {
2164 if (!isWidget) {
2165 QChildEvent e(QEvent::ChildAdded, q);
2166 QCoreApplication::sendEvent(parent, &e);
2167 }
2168 }
2169 }
2170 if (!wasDeleted && !isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged)
2171 QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
2172 }
2173
2174 /*!
2175 \fn void QObject::installEventFilter(QObject *filterObj)
2176
2177 Installs an event filter \a filterObj on this object. For example:
2178 \snippet code/src_corelib_kernel_qobject.cpp 14
2179
2180 An event filter is an object that receives all events that are
2181 sent to this object. The filter can either stop the event or
2182 forward it to this object. The event filter \a filterObj receives
2183 events via its eventFilter() function. The eventFilter() function
2184 must return true if the event should be filtered, (i.e. stopped);
2185 otherwise it must return false.
2186
2187 If multiple event filters are installed on a single object, the
2188 filter that was installed last is activated first.
2189
2190 Here's a \c KeyPressEater class that eats the key presses of its
2191 monitored objects:
2192
2193 \snippet code/src_corelib_kernel_qobject.cpp 15
2194
2195 And here's how to install it on two widgets:
2196
2197 \snippet code/src_corelib_kernel_qobject.cpp 16
2198
2199 The QShortcut class, for example, uses this technique to intercept
2200 shortcut key presses.
2201
2202 \warning If you delete the receiver object in your eventFilter()
2203 function, be sure to return true. If you return false, Qt sends
2204 the event to the deleted object and the program will crash.
2205
2206 Note that the filtering object must be in the same thread as this
2207 object. If \a filterObj is in a different thread, this function does
2208 nothing. If either \a filterObj or this object are moved to a different
2209 thread after calling this function, the event filter will not be
2210 called until both objects have the same thread affinity again (it
2211 is \e not removed).
2212
2213 \sa removeEventFilter(), eventFilter(), event()
2214 */
2215
installEventFilter(QObject * obj)2216 void QObject::installEventFilter(QObject *obj)
2217 {
2218 Q_D(QObject);
2219 if (!obj)
2220 return;
2221 if (d->threadData != obj->d_func()->threadData) {
2222 qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2223 return;
2224 }
2225
2226 if (!d->extraData)
2227 d->extraData = new QObjectPrivate::ExtraData;
2228
2229 // clean up unused items in the list
2230 d->extraData->eventFilters.removeAll((QObject*)nullptr);
2231 d->extraData->eventFilters.removeAll(obj);
2232 d->extraData->eventFilters.prepend(obj);
2233 }
2234
2235 /*!
2236 Removes an event filter object \a obj from this object. The
2237 request is ignored if such an event filter has not been installed.
2238
2239 All event filters for this object are automatically removed when
2240 this object is destroyed.
2241
2242 It is always safe to remove an event filter, even during event
2243 filter activation (i.e. from the eventFilter() function).
2244
2245 \sa installEventFilter(), eventFilter(), event()
2246 */
2247
removeEventFilter(QObject * obj)2248 void QObject::removeEventFilter(QObject *obj)
2249 {
2250 Q_D(QObject);
2251 if (d->extraData) {
2252 for (int i = 0; i < d->extraData->eventFilters.count(); ++i) {
2253 if (d->extraData->eventFilters.at(i) == obj)
2254 d->extraData->eventFilters[i] = nullptr;
2255 }
2256 }
2257 }
2258
2259
2260 /*!
2261 \fn void QObject::destroyed(QObject *obj)
2262
2263 This signal is emitted immediately before the object \a obj is
2264 destroyed, after any instances of QPointer have been notified,
2265 and cannot be blocked.
2266
2267 All the objects's children are destroyed immediately after this
2268 signal is emitted.
2269
2270 \sa deleteLater(), QPointer
2271 */
2272
2273 /*!
2274 \threadsafe
2275
2276 Schedules this object for deletion.
2277
2278 The object will be deleted when control returns to the event
2279 loop. If the event loop is not running when this function is
2280 called (e.g. deleteLater() is called on an object before
2281 QCoreApplication::exec()), the object will be deleted once the
2282 event loop is started. If deleteLater() is called after the main event loop
2283 has stopped, the object will not be deleted.
2284 Since Qt 4.8, if deleteLater() is called on an object that lives in a
2285 thread with no running event loop, the object will be destroyed when the
2286 thread finishes.
2287
2288 Note that entering and leaving a new event loop (e.g., by opening a modal
2289 dialog) will \e not perform the deferred deletion; for the object to be
2290 deleted, the control must return to the event loop from which deleteLater()
2291 was called. This does not apply to objects deleted while a previous, nested
2292 event loop was still running: the Qt event loop will delete those objects
2293 as soon as the new nested event loop starts.
2294
2295 \b{Note:} It is safe to call this function more than once; when the
2296 first deferred deletion event is delivered, any pending events for the
2297 object are removed from the event queue.
2298
2299 \sa destroyed(), QPointer
2300 */
deleteLater()2301 void QObject::deleteLater()
2302 {
2303 QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
2304 }
2305
2306 /*!
2307 \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
2308 \reentrant
2309
2310 Returns a translated version of \a sourceText, optionally based on a
2311 \a disambiguation string and value of \a n for strings containing plurals;
2312 otherwise returns QString::fromUtf8(\a sourceText) if no appropriate
2313 translated string is available.
2314
2315 Example:
2316 \snippet ../widgets/mainwindows/sdi/mainwindow.cpp implicit tr context
2317 \dots
2318
2319 If the same \a sourceText is used in different roles within the
2320 same context, an additional identifying string may be passed in
2321 \a disambiguation (\nullptr by default). In Qt 4.4 and earlier, this was
2322 the preferred way to pass comments to translators.
2323
2324 Example:
2325
2326 \snippet code/src_corelib_kernel_qobject.cpp 17
2327 \dots
2328
2329 See \l{Writing Source Code for Translation} for a detailed description of
2330 Qt's translation mechanisms in general, and the
2331 \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
2332 section for information on disambiguation.
2333
2334 \warning This method is reentrant only if all translators are
2335 installed \e before calling this method. Installing or removing
2336 translators while performing translations is not supported. Doing
2337 so will probably result in crashes or other undesirable behavior.
2338
2339 \sa QCoreApplication::translate(), {Internationalization with Qt}
2340 */
2341
2342 /*!
2343 \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
2344 \reentrant
2345 \obsolete
2346
2347 Returns a translated version of \a sourceText, or
2348 QString::fromUtf8(\a sourceText) if there is no appropriate
2349 version. It is otherwise identical to tr(\a sourceText, \a
2350 disambiguation, \a n).
2351
2352 \warning This method is reentrant only if all translators are
2353 installed \e before calling this method. Installing or removing
2354 translators while performing translations is not supported. Doing
2355 so will probably result in crashes or other undesirable behavior.
2356
2357 \warning For portability reasons, we recommend that you use
2358 escape sequences for specifying non-ASCII characters in string
2359 literals to trUtf8(). For example:
2360
2361 \snippet code/src_corelib_kernel_qobject.cpp 20
2362
2363 \sa tr(), QCoreApplication::translate(), {Internationalization with Qt}
2364 */
2365
2366
2367
2368
2369 /*****************************************************************************
2370 Signals and slots
2371 *****************************************************************************/
2372
2373
qFlagLocation(const char * method)2374 const char *qFlagLocation(const char *method)
2375 {
2376 QThreadData *currentThreadData = QThreadData::current(false);
2377 if (currentThreadData != nullptr)
2378 currentThreadData->flaggedSignatures.store(method);
2379 return method;
2380 }
2381
extract_code(const char * member)2382 static int extract_code(const char *member)
2383 {
2384 // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
2385 return (((int)(*member) - '0') & 0x3);
2386 }
2387
extract_location(const char * member)2388 static const char * extract_location(const char *member)
2389 {
2390 if (QThreadData::current()->flaggedSignatures.contains(member)) {
2391 // signature includes location information after the first null-terminator
2392 const char *location = member + qstrlen(member) + 1;
2393 if (*location != '\0')
2394 return location;
2395 }
2396 return nullptr;
2397 }
2398
check_signal_macro(const QObject * sender,const char * signal,const char * func,const char * op)2399 static bool check_signal_macro(const QObject *sender, const char *signal,
2400 const char *func, const char *op)
2401 {
2402 int sigcode = extract_code(signal);
2403 if (sigcode != QSIGNAL_CODE) {
2404 if (sigcode == QSLOT_CODE)
2405 qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
2406 func, op, sender->metaObject()->className(), signal+1);
2407 else
2408 qWarning("QObject::%s: Use the SIGNAL macro to %s %s::%s",
2409 func, op, sender->metaObject()->className(), signal);
2410 return false;
2411 }
2412 return true;
2413 }
2414
check_method_code(int code,const QObject * object,const char * method,const char * func)2415 static bool check_method_code(int code, const QObject *object,
2416 const char *method, const char *func)
2417 {
2418 if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2419 qWarning("QObject::%s: Use the SLOT or SIGNAL macro to "
2420 "%s %s::%s", func, func, object->metaObject()->className(), method);
2421 return false;
2422 }
2423 return true;
2424 }
2425
err_method_notfound(const QObject * object,const char * method,const char * func)2426 static void err_method_notfound(const QObject *object,
2427 const char *method, const char *func)
2428 {
2429 const char *type = "method";
2430 switch (extract_code(method)) {
2431 case QSLOT_CODE: type = "slot"; break;
2432 case QSIGNAL_CODE: type = "signal"; break;
2433 }
2434 const char *loc = extract_location(method);
2435 if (strchr(method,')') == nullptr) // common typing mistake
2436 qWarning("QObject::%s: Parentheses expected, %s %s::%s%s%s",
2437 func, type, object->metaObject()->className(), method+1,
2438 loc ? " in ": "", loc ? loc : "");
2439 else
2440 qWarning("QObject::%s: No such %s %s::%s%s%s",
2441 func, type, object->metaObject()->className(), method+1,
2442 loc ? " in ": "", loc ? loc : "");
2443
2444 }
2445
2446
err_info_about_objects(const char * func,const QObject * sender,const QObject * receiver)2447 static void err_info_about_objects(const char * func,
2448 const QObject * sender,
2449 const QObject * receiver)
2450 {
2451 QString a = sender ? sender->objectName() : QString();
2452 QString b = receiver ? receiver->objectName() : QString();
2453 if (!a.isEmpty())
2454 qWarning("QObject::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
2455 if (!b.isEmpty())
2456 qWarning("QObject::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
2457 }
2458
2459 /*!
2460 Returns a pointer to the object that sent the signal, if called in
2461 a slot activated by a signal; otherwise it returns \nullptr. The pointer
2462 is valid only during the execution of the slot that calls this
2463 function from this object's thread context.
2464
2465 The pointer returned by this function becomes invalid if the
2466 sender is destroyed, or if the slot is disconnected from the
2467 sender's signal.
2468
2469 \warning This function violates the object-oriented principle of
2470 modularity. However, getting access to the sender might be useful
2471 when many signals are connected to a single slot.
2472
2473 \warning As mentioned above, the return value of this function is
2474 not valid when the slot is called via a Qt::DirectConnection from
2475 a thread different from this object's thread. Do not use this
2476 function in this type of scenario.
2477
2478 \sa senderSignalIndex()
2479 */
2480
sender() const2481 QObject *QObject::sender() const
2482 {
2483 Q_D(const QObject);
2484
2485 QBasicMutexLocker locker(signalSlotLock(this));
2486 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2487 if (!cd || !cd->currentSender)
2488 return nullptr;
2489
2490 for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2491 if (c->sender == cd->currentSender->sender)
2492 return cd->currentSender->sender;
2493 }
2494
2495 return nullptr;
2496 }
2497
2498 /*!
2499 \since 4.8
2500
2501 Returns the meta-method index of the signal that called the currently
2502 executing slot, which is a member of the class returned by sender().
2503 If called outside of a slot activated by a signal, -1 is returned.
2504
2505 For signals with default parameters, this function will always return
2506 the index with all parameters, regardless of which was used with
2507 connect(). For example, the signal \c {destroyed(QObject *obj = \nullptr)}
2508 will have two different indexes (with and without the parameter), but
2509 this function will always return the index with a parameter. This does
2510 not apply when overloading signals with different parameters.
2511
2512 \warning This function violates the object-oriented principle of
2513 modularity. However, getting access to the signal index might be useful
2514 when many signals are connected to a single slot.
2515
2516 \warning The return value of this function is not valid when the slot
2517 is called via a Qt::DirectConnection from a thread different from this
2518 object's thread. Do not use this function in this type of scenario.
2519
2520 \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2521 */
2522
senderSignalIndex() const2523 int QObject::senderSignalIndex() const
2524 {
2525 Q_D(const QObject);
2526
2527 QBasicMutexLocker locker(signalSlotLock(this));
2528 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2529 if (!cd || !cd->currentSender)
2530 return -1;
2531
2532 for (QObjectPrivate::Connection *c = cd->senders; c; c = c->next) {
2533 if (c->sender == cd->currentSender->sender) {
2534 // Convert from signal range to method range
2535 return QMetaObjectPrivate::signal(c->sender->metaObject(), cd->currentSender->signal).methodIndex();
2536 }
2537 }
2538
2539 return -1;
2540 }
2541
2542 /*!
2543 Returns the number of receivers connected to the \a signal.
2544
2545 Since both slots and signals can be used as receivers for signals,
2546 and the same connections can be made many times, the number of
2547 receivers is the same as the number of connections made from this
2548 signal.
2549
2550 When calling this function, you can use the \c SIGNAL() macro to
2551 pass a specific signal:
2552
2553 \snippet code/src_corelib_kernel_qobject.cpp 21
2554
2555 \warning This function violates the object-oriented principle of
2556 modularity. However, it might be useful when you need to perform
2557 expensive initialization only if something is connected to a
2558 signal.
2559
2560 \sa isSignalConnected()
2561 */
2562
receivers(const char * signal) const2563 int QObject::receivers(const char *signal) const
2564 {
2565 Q_D(const QObject);
2566 int receivers = 0;
2567 if (signal) {
2568 QByteArray signal_name = QMetaObject::normalizedSignature(signal);
2569 signal = signal_name;
2570 #ifndef QT_NO_DEBUG
2571 if (!check_signal_macro(this, signal, "receivers", "bind"))
2572 return 0;
2573 #endif
2574 signal++; // skip code
2575 int signal_index = d->signalIndex(signal);
2576 if (signal_index < 0) {
2577 #ifndef QT_NO_DEBUG
2578 err_method_notfound(this, signal-1, "receivers");
2579 #endif
2580 return 0;
2581 }
2582
2583 if (!d->isSignalConnected(signal_index))
2584 return receivers;
2585
2586 if (d->declarativeData && QAbstractDeclarativeData::receivers) {
2587 receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
2588 signal_index);
2589 }
2590
2591 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
2592 QBasicMutexLocker locker(signalSlotLock(this));
2593 if (cd && signal_index < cd->signalVectorCount()) {
2594 const QObjectPrivate::Connection *c = cd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
2595 while (c) {
2596 receivers += c->receiver.loadRelaxed() ? 1 : 0;
2597 c = c->nextConnectionList.loadRelaxed();
2598 }
2599 }
2600 }
2601 return receivers;
2602 }
2603
2604 /*!
2605 \since 5.0
2606 Returns \c true if the \a signal is connected to at least one receiver,
2607 otherwise returns \c false.
2608
2609 \a signal must be a signal member of this object, otherwise the behaviour
2610 is undefined.
2611
2612 \snippet code/src_corelib_kernel_qobject.cpp 49
2613
2614 As the code snippet above illustrates, you can use this function
2615 to avoid emitting a signal that nobody listens to.
2616
2617 \warning This function violates the object-oriented principle of
2618 modularity. However, it might be useful when you need to perform
2619 expensive initialization only if something is connected to a
2620 signal.
2621 */
isSignalConnected(const QMetaMethod & signal) const2622 bool QObject::isSignalConnected(const QMetaMethod &signal) const
2623 {
2624 Q_D(const QObject);
2625 if (!signal.mobj)
2626 return false;
2627
2628 Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
2629 "QObject::isSignalConnected" , "the parameter must be a signal member of the object");
2630 uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/5;
2631
2632 if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
2633 signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
2634
2635 signalIndex += QMetaObjectPrivate::signalOffset(signal.mobj);
2636
2637 QBasicMutexLocker locker(signalSlotLock(this));
2638 return d->isSignalConnected(signalIndex, true);
2639 }
2640
2641 /*!
2642 \internal
2643
2644 This helper function calculates signal and method index for the given
2645 member in the specified class.
2646
2647 \list
2648 \li If member.mobj is \nullptr then both signalIndex and methodIndex are set to -1.
2649
2650 \li If specified member is not a member of obj instance class (or one of
2651 its parent classes) then both signalIndex and methodIndex are set to -1.
2652 \endlist
2653
2654 This function is used by QObject::connect and QObject::disconnect which
2655 are working with QMetaMethod.
2656
2657 \a signalIndex is set to the signal index of member. If the member
2658 specified is not signal this variable is set to -1.
2659
2660 \a methodIndex is set to the method index of the member. If the
2661 member is not a method of the object specified by the \a obj argument this
2662 variable is set to -1.
2663 */
memberIndexes(const QObject * obj,const QMetaMethod & member,int * signalIndex,int * methodIndex)2664 void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2665 const QMetaMethod &member,
2666 int *signalIndex, int *methodIndex)
2667 {
2668 *signalIndex = -1;
2669 *methodIndex = -1;
2670 if (!obj || !member.mobj)
2671 return;
2672 const QMetaObject *m = obj->metaObject();
2673 // Check that member is member of obj class
2674 while (m != nullptr && m != member.mobj)
2675 m = m->d.superdata;
2676 if (!m)
2677 return;
2678 *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
2679
2680 int signalOffset;
2681 int methodOffset;
2682 computeOffsets(m, &signalOffset, &methodOffset);
2683
2684 *methodIndex += methodOffset;
2685 if (member.methodType() == QMetaMethod::Signal) {
2686 *signalIndex = originalClone(m, *signalIndex);
2687 *signalIndex += signalOffset;
2688 } else {
2689 *signalIndex = -1;
2690 }
2691 }
2692
2693 #ifndef QT_NO_DEBUG
check_and_warn_compat(const QMetaObject * sender,const QMetaMethod & signal,const QMetaObject * receiver,const QMetaMethod & method)2694 static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2695 const QMetaObject *receiver, const QMetaMethod &method)
2696 {
2697 if (signal.attributes() & QMetaMethod::Compatibility) {
2698 if (!(method.attributes() & QMetaMethod::Compatibility))
2699 qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
2700 sender->className(), signal.methodSignature().constData());
2701 } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2702 method.methodType() == QMetaMethod::Signal) {
2703 qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2704 sender->className(), signal.methodSignature().constData(),
2705 receiver->className(), method.methodSignature().constData());
2706 }
2707 }
2708 #endif
2709
2710 /*!
2711 \threadsafe
2712
2713 Creates a connection of the given \a type from the \a signal in
2714 the \a sender object to the \a method in the \a receiver object.
2715 Returns a handle to the connection that can be used to disconnect
2716 it later.
2717
2718 You must use the \c SIGNAL() and \c SLOT() macros when specifying
2719 the \a signal and the \a method, for example:
2720
2721 \snippet code/src_corelib_kernel_qobject.cpp 22
2722
2723 This example ensures that the label always displays the current
2724 scroll bar value. Note that the signal and slots parameters must not
2725 contain any variable names, only the type. E.g. the following would
2726 not work and return false:
2727
2728 \snippet code/src_corelib_kernel_qobject.cpp 23
2729
2730 A signal can also be connected to another signal:
2731
2732 \snippet code/src_corelib_kernel_qobject.cpp 24
2733
2734 In this example, the \c MyWidget constructor relays a signal from
2735 a private member variable, and makes it available under a name
2736 that relates to \c MyWidget.
2737
2738 A signal can be connected to many slots and signals. Many signals
2739 can be connected to one slot.
2740
2741 If a signal is connected to several slots, the slots are activated
2742 in the same order in which the connections were made, when the
2743 signal is emitted.
2744
2745 The function returns a QMetaObject::Connection that represents
2746 a handle to a connection if it successfully
2747 connects the signal to the slot. The connection handle will be invalid
2748 if it cannot create the connection, for example, if QObject is unable
2749 to verify the existence of either \a signal or \a method, or if their
2750 signatures aren't compatible.
2751 You can check if the handle is valid by casting it to a bool.
2752
2753 By default, a signal is emitted for every connection you make;
2754 two signals are emitted for duplicate connections. You can break
2755 all of these connections with a single disconnect() call.
2756 If you pass the Qt::UniqueConnection \a type, the connection will only
2757 be made if it is not a duplicate. If there is already a duplicate
2758 (exact same signal to the exact same slot on the same objects),
2759 the connection will fail and connect will return an invalid QMetaObject::Connection.
2760
2761 \note Qt::UniqueConnections do not work for lambdas, non-member functions
2762 and functors; they only apply to connecting to member functions.
2763
2764 The optional \a type parameter describes the type of connection
2765 to establish. In particular, it determines whether a particular
2766 signal is delivered to a slot immediately or queued for delivery
2767 at a later time. If the signal is queued, the parameters must be
2768 of types that are known to Qt's meta-object system, because Qt
2769 needs to copy the arguments to store them in an event behind the
2770 scenes. If you try to use a queued connection and get the error
2771 message
2772
2773 \snippet code/src_corelib_kernel_qobject.cpp 25
2774
2775 call qRegisterMetaType() to register the data type before you
2776 establish the connection.
2777
2778 \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE(),
2779 {Differences between String-Based and Functor-Based Connections}
2780 */
connect(const QObject * sender,const char * signal,const QObject * receiver,const char * method,Qt::ConnectionType type)2781 QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
2782 const QObject *receiver, const char *method,
2783 Qt::ConnectionType type)
2784 {
2785 if (sender == nullptr || receiver == nullptr || signal == nullptr || method == nullptr) {
2786 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2787 sender ? sender->metaObject()->className() : "(nullptr)",
2788 (signal && *signal) ? signal+1 : "(nullptr)",
2789 receiver ? receiver->metaObject()->className() : "(nullptr)",
2790 (method && *method) ? method+1 : "(nullptr)");
2791 return QMetaObject::Connection(nullptr);
2792 }
2793 QByteArray tmp_signal_name;
2794
2795 if (!check_signal_macro(sender, signal, "connect", "bind"))
2796 return QMetaObject::Connection(nullptr);
2797 const QMetaObject *smeta = sender->metaObject();
2798 const char *signal_arg = signal;
2799 ++signal; //skip code
2800 QArgumentTypeArray signalTypes;
2801 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
2802 QByteArray signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2803 int signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2804 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2805 if (signal_index < 0) {
2806 // check for normalized signatures
2807 tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
2808 signal = tmp_signal_name.constData() + 1;
2809
2810 signalTypes.clear();
2811 signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
2812 smeta = sender->metaObject();
2813 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
2814 &smeta, signalName, signalTypes.size(), signalTypes.constData());
2815 }
2816 if (signal_index < 0) {
2817 err_method_notfound(sender, signal_arg, "connect");
2818 err_info_about_objects("connect", sender, receiver);
2819 return QMetaObject::Connection(nullptr);
2820 }
2821 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2822 signal_index += QMetaObjectPrivate::signalOffset(smeta);
2823
2824 QByteArray tmp_method_name;
2825 int membcode = extract_code(method);
2826
2827 if (!check_method_code(membcode, receiver, method, "connect"))
2828 return QMetaObject::Connection(nullptr);
2829 const char *method_arg = method;
2830 ++method; // skip code
2831
2832 QArgumentTypeArray methodTypes;
2833 QByteArray methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2834 const QMetaObject *rmeta = receiver->metaObject();
2835 int method_index_relative = -1;
2836 Q_ASSERT(QMetaObjectPrivate::get(rmeta)->revision >= 7);
2837 switch (membcode) {
2838 case QSLOT_CODE:
2839 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2840 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2841 break;
2842 case QSIGNAL_CODE:
2843 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2844 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2845 break;
2846 }
2847 if (method_index_relative < 0) {
2848 // check for normalized methods
2849 tmp_method_name = QMetaObject::normalizedSignature(method);
2850 method = tmp_method_name.constData();
2851
2852 methodTypes.clear();
2853 methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
2854 // rmeta may have been modified above
2855 rmeta = receiver->metaObject();
2856 switch (membcode) {
2857 case QSLOT_CODE:
2858 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(
2859 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2860 break;
2861 case QSIGNAL_CODE:
2862 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(
2863 &rmeta, methodName, methodTypes.size(), methodTypes.constData());
2864 break;
2865 }
2866 }
2867
2868 if (method_index_relative < 0) {
2869 err_method_notfound(receiver, method_arg, "connect");
2870 err_info_about_objects("connect", sender, receiver);
2871 return QMetaObject::Connection(nullptr);
2872 }
2873
2874 if (!QMetaObjectPrivate::checkConnectArgs(signalTypes.size(), signalTypes.constData(),
2875 methodTypes.size(), methodTypes.constData())) {
2876 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2877 "\n %s::%s --> %s::%s",
2878 sender->metaObject()->className(), signal,
2879 receiver->metaObject()->className(), method);
2880 return QMetaObject::Connection(nullptr);
2881 }
2882
2883 int *types = nullptr;
2884 if ((type == Qt::QueuedConnection)
2885 && !(types = queuedConnectionTypes(signalTypes.constData(), signalTypes.size()))) {
2886 return QMetaObject::Connection(nullptr);
2887 }
2888
2889 #ifndef QT_NO_DEBUG
2890 QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
2891 QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
2892 check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2893 #endif
2894 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2895 sender, signal_index, smeta, receiver, method_index_relative, rmeta ,type, types));
2896 return handle;
2897 }
2898
2899 /*!
2900 \since 4.8
2901
2902 Creates a connection of the given \a type from the \a signal in
2903 the \a sender object to the \a method in the \a receiver object.
2904 Returns a handle to the connection that can be used to disconnect
2905 it later.
2906
2907 The Connection handle will be invalid if it cannot create the
2908 connection, for example, the parameters were invalid.
2909 You can check if the QMetaObject::Connection is valid by casting it to a bool.
2910
2911 This function works in the same way as
2912 \c {connect(const QObject *sender, const char *signal,
2913 const QObject *receiver, const char *method,
2914 Qt::ConnectionType type)}
2915 but it uses QMetaMethod to specify signal and method.
2916
2917 \sa connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
2918 */
connect(const QObject * sender,const QMetaMethod & signal,const QObject * receiver,const QMetaMethod & method,Qt::ConnectionType type)2919 QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,
2920 const QObject *receiver, const QMetaMethod &method,
2921 Qt::ConnectionType type)
2922 {
2923 if (sender == nullptr
2924 || receiver == nullptr
2925 || signal.methodType() != QMetaMethod::Signal
2926 || method.methodType() == QMetaMethod::Constructor) {
2927 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2928 sender ? sender->metaObject()->className() : "(nullptr)",
2929 signal.methodSignature().constData(),
2930 receiver ? receiver->metaObject()->className() : "(nullptr)",
2931 method.methodSignature().constData() );
2932 return QMetaObject::Connection(nullptr);
2933 }
2934
2935 int signal_index;
2936 int method_index;
2937 {
2938 int dummy;
2939 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2940 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2941 }
2942
2943 const QMetaObject *smeta = sender->metaObject();
2944 const QMetaObject *rmeta = receiver->metaObject();
2945 if (signal_index == -1) {
2946 qWarning("QObject::connect: Can't find signal %s on instance of class %s",
2947 signal.methodSignature().constData(), smeta->className());
2948 return QMetaObject::Connection(nullptr);
2949 }
2950 if (method_index == -1) {
2951 qWarning("QObject::connect: Can't find method %s on instance of class %s",
2952 method.methodSignature().constData(), rmeta->className());
2953 return QMetaObject::Connection(nullptr);
2954 }
2955
2956 if (!QMetaObject::checkConnectArgs(signal.methodSignature().constData(), method.methodSignature().constData())) {
2957 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2958 "\n %s::%s --> %s::%s",
2959 smeta->className(), signal.methodSignature().constData(),
2960 rmeta->className(), method.methodSignature().constData());
2961 return QMetaObject::Connection(nullptr);
2962 }
2963
2964 int *types = nullptr;
2965 if ((type == Qt::QueuedConnection)
2966 && !(types = queuedConnectionTypes(signal.parameterTypes())))
2967 return QMetaObject::Connection(nullptr);
2968
2969 #ifndef QT_NO_DEBUG
2970 check_and_warn_compat(smeta, signal, rmeta, method);
2971 #endif
2972 QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
2973 sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, nullptr, type, types));
2974 return handle;
2975 }
2976
2977 /*!
2978 \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
2979 \overload connect()
2980 \threadsafe
2981
2982 Connects \a signal from the \a sender object to this object's \a
2983 method.
2984
2985 Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
2986
2987 Every connection you make emits a signal, so duplicate connections emit
2988 two signals. You can break a connection using disconnect().
2989
2990 \sa disconnect()
2991 */
2992
2993 /*!
2994 \threadsafe
2995
2996 Disconnects \a signal in object \a sender from \a method in object
2997 \a receiver. Returns \c true if the connection is successfully broken;
2998 otherwise returns \c false.
2999
3000 A signal-slot connection is removed when either of the objects
3001 involved are destroyed.
3002
3003 disconnect() is typically used in three ways, as the following
3004 examples demonstrate.
3005 \list 1
3006 \li Disconnect everything connected to an object's signals:
3007
3008 \snippet code/src_corelib_kernel_qobject.cpp 26
3009
3010 equivalent to the non-static overloaded function
3011
3012 \snippet code/src_corelib_kernel_qobject.cpp 27
3013
3014 \li Disconnect everything connected to a specific signal:
3015
3016 \snippet code/src_corelib_kernel_qobject.cpp 28
3017
3018 equivalent to the non-static overloaded function
3019
3020 \snippet code/src_corelib_kernel_qobject.cpp 29
3021
3022 \li Disconnect a specific receiver:
3023
3024 \snippet code/src_corelib_kernel_qobject.cpp 30
3025
3026 equivalent to the non-static overloaded function
3027
3028 \snippet code/src_corelib_kernel_qobject.cpp 31
3029
3030 \endlist
3031
3032 \nullptr may be used as a wildcard, meaning "any signal", "any receiving
3033 object", or "any slot in the receiving object", respectively.
3034
3035 The \a sender may never be \nullptr. (You cannot disconnect signals
3036 from more than one object in a single call.)
3037
3038 If \a signal is \nullptr, it disconnects \a receiver and \a method from
3039 any signal. If not, only the specified signal is disconnected.
3040
3041 If \a receiver is \nullptr, it disconnects anything connected to \a
3042 signal. If not, slots in objects other than \a receiver are not
3043 disconnected.
3044
3045 If \a method is \nullptr, it disconnects anything that is connected to \a
3046 receiver. If not, only slots named \a method will be disconnected,
3047 and all other slots are left alone. The \a method must be \nullptr
3048 if \a receiver is left out, so you cannot disconnect a
3049 specifically-named slot on all objects.
3050
3051 \sa connect()
3052 */
disconnect(const QObject * sender,const char * signal,const QObject * receiver,const char * method)3053 bool QObject::disconnect(const QObject *sender, const char *signal,
3054 const QObject *receiver, const char *method)
3055 {
3056 if (sender == nullptr || (receiver == nullptr && method != nullptr)) {
3057 qWarning("QObject::disconnect: Unexpected nullptr parameter");
3058 return false;
3059 }
3060
3061 const char *signal_arg = signal;
3062 QByteArray signal_name;
3063 bool signal_found = false;
3064 if (signal) {
3065 QT_TRY {
3066 signal_name = QMetaObject::normalizedSignature(signal);
3067 signal = signal_name.constData();
3068 } QT_CATCH (const std::bad_alloc &) {
3069 // if the signal is already normalized, we can continue.
3070 if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
3071 QT_RETHROW;
3072 }
3073
3074 if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
3075 return false;
3076 signal++; // skip code
3077 }
3078
3079 QByteArray method_name;
3080 const char *method_arg = method;
3081 int membcode = -1;
3082 bool method_found = false;
3083 if (method) {
3084 QT_TRY {
3085 method_name = QMetaObject::normalizedSignature(method);
3086 method = method_name.constData();
3087 } QT_CATCH(const std::bad_alloc &) {
3088 // if the method is already normalized, we can continue.
3089 if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
3090 QT_RETHROW;
3091 }
3092
3093 membcode = extract_code(method);
3094 if (!check_method_code(membcode, receiver, method, "disconnect"))
3095 return false;
3096 method++; // skip code
3097 }
3098
3099 /* We now iterate through all the sender's and receiver's meta
3100 * objects in order to also disconnect possibly shadowed signals
3101 * and slots with the same signature.
3102 */
3103 bool res = false;
3104 const QMetaObject *smeta = sender->metaObject();
3105 QByteArray signalName;
3106 QArgumentTypeArray signalTypes;
3107 Q_ASSERT(QMetaObjectPrivate::get(smeta)->revision >= 7);
3108 if (signal)
3109 signalName = QMetaObjectPrivate::decodeMethodSignature(signal, signalTypes);
3110 QByteArray methodName;
3111 QArgumentTypeArray methodTypes;
3112 Q_ASSERT(!receiver || QMetaObjectPrivate::get(receiver->metaObject())->revision >= 7);
3113 if (method)
3114 methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodTypes);
3115 do {
3116 int signal_index = -1;
3117 if (signal) {
3118 signal_index = QMetaObjectPrivate::indexOfSignalRelative(
3119 &smeta, signalName, signalTypes.size(), signalTypes.constData());
3120 if (signal_index < 0)
3121 break;
3122 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
3123 signal_index += QMetaObjectPrivate::signalOffset(smeta);
3124 signal_found = true;
3125 }
3126
3127 if (!method) {
3128 res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, nullptr);
3129 } else {
3130 const QMetaObject *rmeta = receiver->metaObject();
3131 do {
3132 int method_index = QMetaObjectPrivate::indexOfMethod(
3133 rmeta, methodName, methodTypes.size(), methodTypes.constData());
3134 if (method_index >= 0)
3135 while (method_index < rmeta->methodOffset())
3136 rmeta = rmeta->superClass();
3137 if (method_index < 0)
3138 break;
3139 res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, nullptr);
3140 method_found = true;
3141 } while ((rmeta = rmeta->superClass()));
3142 }
3143 } while (signal && (smeta = smeta->superClass()));
3144
3145 if (signal && !signal_found) {
3146 err_method_notfound(sender, signal_arg, "disconnect");
3147 err_info_about_objects("disconnect", sender, receiver);
3148 } else if (method && !method_found) {
3149 err_method_notfound(receiver, method_arg, "disconnect");
3150 err_info_about_objects("disconnect", sender, receiver);
3151 }
3152 if (res) {
3153 if (!signal)
3154 const_cast<QObject*>(sender)->disconnectNotify(QMetaMethod());
3155 }
3156 return res;
3157 }
3158
3159 /*!
3160 \since 4.8
3161
3162 Disconnects \a signal in object \a sender from \a method in object
3163 \a receiver. Returns \c true if the connection is successfully broken;
3164 otherwise returns \c false.
3165
3166 This function provides the same possibilities like
3167 \c {disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) }
3168 but uses QMetaMethod to represent the signal and the method to be disconnected.
3169
3170 Additionally this function returns false and no signals and slots disconnected
3171 if:
3172 \list 1
3173
3174 \li \a signal is not a member of sender class or one of its parent classes.
3175
3176 \li \a method is not a member of receiver class or one of its parent classes.
3177
3178 \li \a signal instance represents not a signal.
3179
3180 \endlist
3181
3182 QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
3183 In the same way \nullptr can be used for \a receiver in the meaning "any receiving object".
3184 In this case method should also be QMetaMethod(). \a sender parameter should be never \nullptr.
3185
3186 \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
3187 */
disconnect(const QObject * sender,const QMetaMethod & signal,const QObject * receiver,const QMetaMethod & method)3188 bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
3189 const QObject *receiver, const QMetaMethod &method)
3190 {
3191 if (sender == nullptr || (receiver == nullptr && method.mobj != nullptr)) {
3192 qWarning("QObject::disconnect: Unexpected nullptr parameter");
3193 return false;
3194 }
3195 if (signal.mobj) {
3196 if(signal.methodType() != QMetaMethod::Signal) {
3197 qWarning("QObject::%s: Attempt to %s non-signal %s::%s",
3198 "disconnect","unbind",
3199 sender->metaObject()->className(), signal.methodSignature().constData());
3200 return false;
3201 }
3202 }
3203 if (method.mobj) {
3204 if(method.methodType() == QMetaMethod::Constructor) {
3205 qWarning("QObject::disconnect: cannot use constructor as argument %s::%s",
3206 receiver->metaObject()->className(), method.methodSignature().constData());
3207 return false;
3208 }
3209 }
3210
3211 // Reconstructing SIGNAL() macro result for signal.methodSignature() string
3212 QByteArray signalSignature;
3213 if (signal.mobj) {
3214 signalSignature.reserve(signal.methodSignature().size()+1);
3215 signalSignature.append((char)(QSIGNAL_CODE + '0'));
3216 signalSignature.append(signal.methodSignature());
3217 }
3218
3219 int signal_index;
3220 int method_index;
3221 {
3222 int dummy;
3223 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
3224 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
3225 }
3226 // If we are here sender is not nullptr. If signal is not nullptr while signal_index
3227 // is -1 then this signal is not a member of sender.
3228 if (signal.mobj && signal_index == -1) {
3229 qWarning("QObject::disconnect: signal %s not found on class %s",
3230 signal.methodSignature().constData(), sender->metaObject()->className());
3231 return false;
3232 }
3233 // If this condition is true then method is not a member of receiver.
3234 if (receiver && method.mobj && method_index == -1) {
3235 qWarning("QObject::disconnect: method %s not found on class %s",
3236 method.methodSignature().constData(), receiver->metaObject()->className());
3237 return false;
3238 }
3239
3240 if (!QMetaObjectPrivate::disconnect(sender, signal_index, signal.mobj, receiver, method_index, nullptr))
3241 return false;
3242
3243 if (!signal.isValid()) {
3244 // The signal is a wildcard, meaning all signals were disconnected.
3245 // QMetaObjectPrivate::disconnect() doesn't call disconnectNotify()
3246 // per connection in this case. Call it once now, with an invalid
3247 // QMetaMethod as argument, as documented.
3248 const_cast<QObject*>(sender)->disconnectNotify(signal);
3249 }
3250 return true;
3251 }
3252
3253 /*!
3254 \threadsafe
3255
3256 \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method) const
3257 \overload disconnect()
3258
3259 Disconnects \a signal from \a method of \a receiver.
3260
3261 A signal-slot connection is removed when either of the objects
3262 involved are destroyed.
3263 */
3264
3265 /*!
3266 \fn bool QObject::disconnect(const QObject *receiver, const char *method) const
3267 \overload disconnect()
3268
3269 Disconnects all signals in this object from \a receiver's \a
3270 method.
3271
3272 A signal-slot connection is removed when either of the objects
3273 involved are destroyed.
3274 */
3275
3276
3277 /*!
3278 \since 5.0
3279
3280 This virtual function is called when something has been connected
3281 to \a signal in this object.
3282
3283 If you want to compare \a signal with a specific signal, you can
3284 use QMetaMethod::fromSignal() as follows:
3285
3286 \snippet code/src_corelib_kernel_qobject.cpp 32
3287
3288 \warning This function violates the object-oriented principle of
3289 modularity. However, it might be useful when you need to perform
3290 expensive initialization only if something is connected to a
3291 signal.
3292
3293 \warning This function is called from the thread which performs the
3294 connection, which may be a different thread from the thread in
3295 which this object lives.
3296
3297 \sa connect(), disconnectNotify()
3298 */
3299
connectNotify(const QMetaMethod & signal)3300 void QObject::connectNotify(const QMetaMethod &signal)
3301 {
3302 Q_UNUSED(signal);
3303 }
3304
3305 /*!
3306 \since 5.0
3307
3308 This virtual function is called when something has been
3309 disconnected from \a signal in this object.
3310
3311 See connectNotify() for an example of how to compare
3312 \a signal with a specific signal.
3313
3314 If all signals were disconnected from this object (e.g., the
3315 signal argument to disconnect() was \nullptr), disconnectNotify()
3316 is only called once, and the \a signal will be an invalid
3317 QMetaMethod (QMetaMethod::isValid() returns \c false).
3318
3319 \warning This function violates the object-oriented principle of
3320 modularity. However, it might be useful for optimizing access to
3321 expensive resources.
3322
3323 \warning This function is called from the thread which performs the
3324 disconnection, which may be a different thread from the thread in
3325 which this object lives. This function may also be called with a QObject
3326 internal mutex locked. It is therefore not allowed to re-enter any
3327 of any QObject functions from your reimplementation and if you lock
3328 a mutex in your reimplementation, make sure that you don't call QObject
3329 functions with that mutex held in other places or it will result in
3330 a deadlock.
3331
3332 \sa disconnect(), connectNotify()
3333 */
3334
disconnectNotify(const QMetaMethod & signal)3335 void QObject::disconnectNotify(const QMetaMethod &signal)
3336 {
3337 Q_UNUSED(signal);
3338 }
3339
3340 /*
3341 \internal
3342 convert a signal index from the method range to the signal range
3343 */
methodIndexToSignalIndex(const QMetaObject ** base,int signal_index)3344 static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
3345 {
3346 if (signal_index < 0)
3347 return signal_index;
3348 const QMetaObject *metaObject = *base;
3349 while (metaObject && metaObject->methodOffset() > signal_index)
3350 metaObject = metaObject->superClass();
3351
3352 if (metaObject) {
3353 int signalOffset, methodOffset;
3354 computeOffsets(metaObject, &signalOffset, &methodOffset);
3355 if (signal_index < metaObject->methodCount())
3356 signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
3357 else
3358 signal_index = signal_index - methodOffset + signalOffset;
3359 *base = metaObject;
3360 }
3361 return signal_index;
3362 }
3363
3364 /*!
3365 \internal
3366 \a types is a 0-terminated vector of meta types for queued
3367 connections.
3368
3369 if \a signal_index is -1, then we effectively connect *all* signals
3370 from the sender to the receiver's slot
3371 */
connect(const QObject * sender,int signal_index,const QObject * receiver,int method_index,int type,int * types)3372 QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
3373 const QObject *receiver, int method_index, int type, int *types)
3374 {
3375 const QMetaObject *smeta = sender->metaObject();
3376 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3377 return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta,
3378 receiver, method_index,
3379 nullptr, //FIXME, we could speed this connection up by computing the relative index
3380 type, types));
3381 }
3382
3383 /*!
3384 \internal
3385 Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3386
3387 method_index is relative to the rmeta metaobject, if rmeta is \nullptr, then it is absolute index
3388
3389 the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
3390 */
connect(const QObject * sender,int signal_index,const QMetaObject * smeta,const QObject * receiver,int method_index,const QMetaObject * rmeta,int type,int * types)3391 QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
3392 int signal_index, const QMetaObject *smeta,
3393 const QObject *receiver, int method_index,
3394 const QMetaObject *rmeta, int type, int *types)
3395 {
3396 QObject *s = const_cast<QObject *>(sender);
3397 QObject *r = const_cast<QObject *>(receiver);
3398
3399 int method_offset = rmeta ? rmeta->methodOffset() : 0;
3400 Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
3401 QObjectPrivate::StaticMetaCallFunction callFunction = rmeta ? rmeta->d.static_metacall : nullptr;
3402
3403 QOrderedMutexLocker locker(signalSlotLock(sender),
3404 signalSlotLock(receiver));
3405
3406 QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
3407 if (type & Qt::UniqueConnection && scd) {
3408 if (scd->signalVectorCount() > signal_index) {
3409 const QObjectPrivate::Connection *c2 = scd->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
3410
3411 int method_index_absolute = method_index + method_offset;
3412
3413 while (c2) {
3414 if (!c2->isSlotObject && c2->receiver.loadRelaxed() == receiver && c2->method() == method_index_absolute)
3415 return nullptr;
3416 c2 = c2->nextConnectionList.loadRelaxed();
3417 }
3418 }
3419 type &= Qt::UniqueConnection - 1;
3420 }
3421
3422 std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
3423 c->sender = s;
3424 c->signal_index = signal_index;
3425 c->receiver.storeRelaxed(r);
3426 QThreadData *td = r->d_func()->threadData;
3427 td->ref();
3428 c->receiverThreadData.storeRelaxed(td);
3429 c->method_relative = method_index;
3430 c->method_offset = method_offset;
3431 c->connectionType = type;
3432 c->isSlotObject = false;
3433 c->argumentTypes.storeRelaxed(types);
3434 c->callFunction = callFunction;
3435
3436 QObjectPrivate::get(s)->addConnection(signal_index, c.get());
3437
3438 locker.unlock();
3439 QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
3440 if (smethod.isValid())
3441 s->connectNotify(smethod);
3442
3443 return c.release();
3444 }
3445
3446 /*!
3447 \internal
3448 */
disconnect(const QObject * sender,int signal_index,const QObject * receiver,int method_index)3449 bool QMetaObject::disconnect(const QObject *sender, int signal_index,
3450 const QObject *receiver, int method_index)
3451 {
3452 const QMetaObject *smeta = sender->metaObject();
3453 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3454 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3455 receiver, method_index, nullptr);
3456 }
3457
3458 /*!
3459 \internal
3460
3461 Disconnect a single signal connection. If QMetaObject::connect() has been called
3462 multiple times for the same sender, signal_index, receiver and method_index only
3463 one of these connections will be removed.
3464 */
disconnectOne(const QObject * sender,int signal_index,const QObject * receiver,int method_index)3465 bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
3466 const QObject *receiver, int method_index)
3467 {
3468 const QMetaObject *smeta = sender->metaObject();
3469 signal_index = methodIndexToSignalIndex(&smeta, signal_index);
3470 return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
3471 receiver, method_index, nullptr,
3472 QMetaObjectPrivate::DisconnectOne);
3473 }
3474
3475 /*!
3476 \internal
3477 Helper function to remove the connection from the senders list and set the receivers to \nullptr
3478 */
disconnectHelper(QObjectPrivate::ConnectionData * connections,int signalIndex,const QObject * receiver,int method_index,void ** slot,QBasicMutex * senderMutex,DisconnectType disconnectType)3479 bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::ConnectionData *connections, int signalIndex,
3480 const QObject *receiver, int method_index, void **slot,
3481 QBasicMutex *senderMutex, DisconnectType disconnectType)
3482 {
3483 bool success = false;
3484
3485 auto &connectionList = connections->connectionsForSignal(signalIndex);
3486 auto *c = connectionList.first.loadRelaxed();
3487 while (c) {
3488 QObject *r = c->receiver.loadRelaxed();
3489 if (r && (receiver == nullptr || (r == receiver
3490 && (method_index < 0 || (!c->isSlotObject && c->method() == method_index))
3491 && (slot == nullptr || (c->isSlotObject && c->slotObj->compare(slot)))))) {
3492 bool needToUnlock = false;
3493 QBasicMutex *receiverMutex = nullptr;
3494 if (r) {
3495 receiverMutex = signalSlotLock(r);
3496 // need to relock this receiver and sender in the correct order
3497 needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
3498 }
3499 if (c->receiver.loadRelaxed())
3500 connections->removeConnection(c);
3501
3502 if (needToUnlock)
3503 receiverMutex->unlock();
3504
3505 success = true;
3506
3507 if (disconnectType == DisconnectOne)
3508 return success;
3509 }
3510 c = c->nextConnectionList.loadRelaxed();
3511 }
3512 return success;
3513 }
3514
3515 /*!
3516 \internal
3517 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3518 */
disconnect(const QObject * sender,int signal_index,const QMetaObject * smeta,const QObject * receiver,int method_index,void ** slot,DisconnectType disconnectType)3519 bool QMetaObjectPrivate::disconnect(const QObject *sender,
3520 int signal_index, const QMetaObject *smeta,
3521 const QObject *receiver, int method_index, void **slot,
3522 DisconnectType disconnectType)
3523 {
3524 if (!sender)
3525 return false;
3526
3527 QObject *s = const_cast<QObject *>(sender);
3528
3529 QBasicMutex *senderMutex = signalSlotLock(sender);
3530 QBasicMutexLocker locker(senderMutex);
3531
3532 QObjectPrivate::ConnectionData *scd = QObjectPrivate::get(s)->connections.loadRelaxed();
3533 if (!scd)
3534 return false;
3535
3536 bool success = false;
3537 {
3538 // prevent incoming connections changing the connections->receivers while unlocked
3539 QObjectPrivate::ConnectionDataPointer connections(scd);
3540
3541 if (signal_index < 0) {
3542 // remove from all connection lists
3543 for (int sig_index = -1; sig_index < scd->signalVectorCount(); ++sig_index) {
3544 if (disconnectHelper(connections.data(), sig_index, receiver, method_index, slot, senderMutex, disconnectType))
3545 success = true;
3546 }
3547 } else if (signal_index < scd->signalVectorCount()) {
3548 if (disconnectHelper(connections.data(), signal_index, receiver, method_index, slot, senderMutex, disconnectType))
3549 success = true;
3550 }
3551 }
3552
3553 locker.unlock();
3554 if (success) {
3555 scd->cleanOrphanedConnections(s);
3556
3557 QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
3558 if (smethod.isValid())
3559 s->disconnectNotify(smethod);
3560 }
3561
3562 return success;
3563 }
3564
3565 // Helpers for formatting the connect statements of connectSlotsByName()'s debug mode
formatConnectionSignature(const char * className,const QMetaMethod & method)3566 static QByteArray formatConnectionSignature(const char *className, const QMetaMethod &method)
3567 {
3568 const auto signature = method.methodSignature();
3569 Q_ASSERT(signature.endsWith(')'));
3570 const int openParen = signature.indexOf('(');
3571 const bool hasParameters = openParen >= 0 && openParen < signature.size() - 2;
3572 QByteArray result;
3573 if (hasParameters) {
3574 result += "qOverload<"
3575 + signature.mid(openParen + 1, signature.size() - openParen - 2) + ">(";
3576 }
3577 result += '&';
3578 result += className + QByteArrayLiteral("::") + method.name();
3579 if (hasParameters)
3580 result += ')';
3581 return result;
3582 }
3583
msgConnect(const QMetaObject * senderMo,const QByteArray & senderName,const QMetaMethod & signal,const QObject * receiver,int receiverIndex)3584 static QByteArray msgConnect(const QMetaObject *senderMo, const QByteArray &senderName,
3585 const QMetaMethod &signal, const QObject *receiver, int receiverIndex)
3586 {
3587 const auto receiverMo = receiver->metaObject();
3588 const auto slot = receiverMo->method(receiverIndex);
3589 QByteArray message = QByteArrayLiteral("QObject::connect(")
3590 + senderName + ", " + formatConnectionSignature(senderMo->className(), signal)
3591 + ", " + receiver->objectName().toLatin1() + ", "
3592 + formatConnectionSignature(receiverMo->className(), slot) + ");";
3593 return message;
3594 }
3595
3596 /*!
3597 \fn void QMetaObject::connectSlotsByName(QObject *object)
3598
3599 Searches recursively for all child objects of the given \a object, and connects
3600 matching signals from them to slots of \a object that follow the following form:
3601
3602 \snippet code/src_corelib_kernel_qobject.cpp 33
3603
3604 Let's assume our object has a child object of type \c{QPushButton} with
3605 the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3606 button's \c{clicked()} signal would be:
3607
3608 \snippet code/src_corelib_kernel_qobject.cpp 34
3609
3610 If \a object itself has a properly set object name, its own signals are also
3611 connected to its respective slots.
3612
3613 \sa QObject::setObjectName()
3614 */
connectSlotsByName(QObject * o)3615 void QMetaObject::connectSlotsByName(QObject *o)
3616 {
3617 if (!o)
3618 return;
3619 const QMetaObject *mo = o->metaObject();
3620 Q_ASSERT(mo);
3621 const QObjectList list = // list of all objects to look for matching signals including...
3622 o->findChildren<QObject *>(QString()) // all children of 'o'...
3623 << o; // and the object 'o' itself
3624
3625 // for each method/slot of o ...
3626 for (int i = 0; i < mo->methodCount(); ++i) {
3627 const QByteArray slotSignature = mo->method(i).methodSignature();
3628 const char *slot = slotSignature.constData();
3629 Q_ASSERT(slot);
3630
3631 // ...that starts with "on_", ...
3632 if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3633 continue;
3634
3635 // ...we check each object in our list, ...
3636 bool foundIt = false;
3637 for(int j = 0; j < list.count(); ++j) {
3638 const QObject *co = list.at(j);
3639 const QByteArray coName = co->objectName().toLatin1();
3640
3641 // ...discarding those whose objectName is not fitting the pattern "on_<objectName>_...", ...
3642 if (coName.isEmpty() || qstrncmp(slot + 3, coName.constData(), coName.size()) || slot[coName.size()+3] != '_')
3643 continue;
3644
3645 const char *signal = slot + coName.size() + 4; // the 'signal' part of the slot name
3646
3647 // ...for the presence of a matching signal "on_<objectName>_<signal>".
3648 const QMetaObject *smeta;
3649 int sigIndex = co->d_func()->signalIndex(signal, &smeta);
3650 if (sigIndex < 0) {
3651 // if no exactly fitting signal (name + complete parameter type list) could be found
3652 // look for just any signal with the correct name and at least the slot's parameter list.
3653 // Note: if more than one of those signals exist, the one that gets connected is
3654 // chosen 'at random' (order of declaration in source file)
3655 QList<QByteArray> compatibleSignals;
3656 const QMetaObject *smo = co->metaObject();
3657 int sigLen = qstrlen(signal) - 1; // ignore the trailing ')'
3658 for (int k = QMetaObjectPrivate::absoluteSignalCount(smo)-1; k >= 0; --k) {
3659 const QMetaMethod method = QMetaObjectPrivate::signal(smo, k);
3660 if (!qstrncmp(method.methodSignature().constData(), signal, sigLen)) {
3661 smeta = method.enclosingMetaObject();
3662 sigIndex = k;
3663 compatibleSignals.prepend(method.methodSignature());
3664 }
3665 }
3666 if (compatibleSignals.size() > 1)
3667 qWarning() << "QMetaObject::connectSlotsByName: Connecting slot" << slot
3668 << "with the first of the following compatible signals:" << compatibleSignals;
3669 }
3670
3671 if (sigIndex < 0)
3672 continue;
3673
3674 // we connect it...
3675 if (Connection(QMetaObjectPrivate::connect(co, sigIndex, smeta, o, i))) {
3676 foundIt = true;
3677 qCDebug(lcConnections, "%s",
3678 msgConnect(smeta, coName, QMetaObjectPrivate::signal(smeta, sigIndex), o, i).constData());
3679 // ...and stop looking for further objects with the same name.
3680 // Note: the Designer will make sure each object name is unique in the above
3681 // 'list' but other code may create two child objects with the same name. In
3682 // this case one is chosen 'at random'.
3683 break;
3684 }
3685 }
3686 if (foundIt) {
3687 // we found our slot, now skip all overloads
3688 while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
3689 ++i;
3690 } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
3691 // check if the slot has the following signature: "on_..._...(..."
3692 int iParen = slotSignature.indexOf('(');
3693 int iLastUnderscore = slotSignature.lastIndexOf('_', iParen-1);
3694 if (iLastUnderscore > 3)
3695 qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3696 }
3697 }
3698 }
3699
3700 /*!
3701 \internal
3702
3703 \a signal must be in the signal index range (see QObjectPrivate::signalIndex()).
3704 */
queued_activate(QObject * sender,int signal,QObjectPrivate::Connection * c,void ** argv)3705 static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3706 {
3707 const int *argumentTypes = c->argumentTypes.loadRelaxed();
3708 if (!argumentTypes) {
3709 QMetaMethod m = QMetaObjectPrivate::signal(sender->metaObject(), signal);
3710 argumentTypes = queuedConnectionTypes(m.parameterTypes());
3711 if (!argumentTypes) // cannot queue arguments
3712 argumentTypes = &DIRECT_CONNECTION_ONLY;
3713 if (!c->argumentTypes.testAndSetOrdered(nullptr, argumentTypes)) {
3714 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
3715 delete [] argumentTypes;
3716 argumentTypes = c->argumentTypes.loadRelaxed();
3717 }
3718 }
3719 if (argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3720 return;
3721 int nargs = 1; // include return type
3722 while (argumentTypes[nargs-1])
3723 ++nargs;
3724
3725 QBasicMutexLocker locker(signalSlotLock(c->receiver.loadRelaxed()));
3726 if (!c->receiver.loadRelaxed()) {
3727 // the connection has been disconnected before we got the lock
3728 return;
3729 }
3730 if (c->isSlotObject)
3731 c->slotObj->ref();
3732 locker.unlock();
3733
3734 QMetaCallEvent *ev = c->isSlotObject ?
3735 new QMetaCallEvent(c->slotObj, sender, signal, nargs) :
3736 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
3737
3738 void **args = ev->args();
3739 int *types = ev->types();
3740
3741 types[0] = 0; // return type
3742 args[0] = nullptr; // return value
3743
3744 if (nargs > 1) {
3745 for (int n = 1; n < nargs; ++n)
3746 types[n] = argumentTypes[n-1];
3747
3748 for (int n = 1; n < nargs; ++n)
3749 args[n] = QMetaType::create(types[n], argv[n]);
3750 }
3751
3752 locker.relock();
3753 if (c->isSlotObject)
3754 c->slotObj->destroyIfLastRef();
3755 if (!c->receiver.loadRelaxed()) {
3756 // the connection has been disconnected while we were unlocked
3757 locker.unlock();
3758 delete ev;
3759 return;
3760 }
3761
3762 QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);
3763 }
3764
3765 template <bool callbacks_enabled>
doActivate(QObject * sender,int signal_index,void ** argv)3766 void doActivate(QObject *sender, int signal_index, void **argv)
3767 {
3768 QObjectPrivate *sp = QObjectPrivate::get(sender);
3769
3770 if (sp->blockSig)
3771 return;
3772
3773 Q_TRACE_SCOPE(QMetaObject_activate, sender, signal_index);
3774
3775 if (sp->isDeclarativeSignalConnected(signal_index)
3776 && QAbstractDeclarativeData::signalEmitted) {
3777 Q_TRACE_SCOPE(QMetaObject_activate_declarative_signal, sender, signal_index);
3778 QAbstractDeclarativeData::signalEmitted(sp->declarativeData, sender,
3779 signal_index, argv);
3780 }
3781
3782 const QSignalSpyCallbackSet *signal_spy_set = callbacks_enabled ? qt_signal_spy_callback_set.loadAcquire() : nullptr;
3783
3784 void *empty_argv[] = { nullptr };
3785 if (!argv)
3786 argv = empty_argv;
3787
3788 if (!sp->maybeSignalConnected(signal_index)) {
3789 // The possible declarative connection is done, and nothing else is connected
3790 if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3791 signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3792 if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3793 signal_spy_set->signal_end_callback(sender, signal_index);
3794 return;
3795 }
3796
3797 if (callbacks_enabled && signal_spy_set->signal_begin_callback != nullptr)
3798 signal_spy_set->signal_begin_callback(sender, signal_index, argv);
3799
3800 bool senderDeleted = false;
3801 {
3802 Q_ASSERT(sp->connections.loadAcquire());
3803 QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
3804 QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
3805
3806 const QObjectPrivate::ConnectionList *list;
3807 if (signal_index < signalVector->count())
3808 list = &signalVector->at(signal_index);
3809 else
3810 list = &signalVector->at(-1);
3811
3812 Qt::HANDLE currentThreadId = QThread::currentThreadId();
3813 bool inSenderThread = currentThreadId == QObjectPrivate::get(sender)->threadData.loadRelaxed()->threadId.loadRelaxed();
3814
3815 // We need to check against the highest connection id to ensure that signals added
3816 // during the signal emission are not emitted in this emission.
3817 uint highestConnectionId = connections->currentConnectionId.loadRelaxed();
3818 do {
3819 QObjectPrivate::Connection *c = list->first.loadRelaxed();
3820 if (!c)
3821 continue;
3822
3823 do {
3824 QObject * const receiver = c->receiver.loadRelaxed();
3825 if (!receiver)
3826 continue;
3827
3828 QThreadData *td = c->receiverThreadData.loadRelaxed();
3829 if (!td)
3830 continue;
3831
3832 bool receiverInSameThread;
3833 if (inSenderThread) {
3834 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3835 } else {
3836 // need to lock before reading the threadId, because moveToThread() could interfere
3837 QMutexLocker lock(signalSlotLock(receiver));
3838 receiverInSameThread = currentThreadId == td->threadId.loadRelaxed();
3839 }
3840
3841
3842 // determine if this connection should be sent immediately or
3843 // put into the event queue
3844 if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3845 || (c->connectionType == Qt::QueuedConnection)) {
3846 queued_activate(sender, signal_index, c, argv);
3847 continue;
3848 #if QT_CONFIG(thread)
3849 } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3850 if (receiverInSameThread) {
3851 qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3852 "Sender is %s(%p), receiver is %s(%p)",
3853 sender->metaObject()->className(), sender,
3854 receiver->metaObject()->className(), receiver);
3855 }
3856 QSemaphore semaphore;
3857 {
3858 QBasicMutexLocker locker(signalSlotLock(sender));
3859 if (!c->receiver.loadAcquire())
3860 continue;
3861 QMetaCallEvent *ev = c->isSlotObject ?
3862 new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :
3863 new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,
3864 sender, signal_index, argv, &semaphore);
3865 QCoreApplication::postEvent(receiver, ev);
3866 }
3867 semaphore.acquire();
3868 continue;
3869 #endif
3870 }
3871
3872 QObjectPrivate::Sender senderData(receiverInSameThread ? receiver : nullptr, sender, signal_index);
3873
3874 if (c->isSlotObject) {
3875 c->slotObj->ref();
3876
3877 struct Deleter {
3878 void operator()(QtPrivate::QSlotObjectBase *slot) const {
3879 if (slot) slot->destroyIfLastRef();
3880 }
3881 };
3882 const std::unique_ptr<QtPrivate::QSlotObjectBase, Deleter> obj{c->slotObj};
3883
3884 {
3885 Q_TRACE_SCOPE(QMetaObject_activate_slot_functor, obj.get());
3886 obj->call(receiver, argv);
3887 }
3888 } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
3889 //we compare the vtable to make sure we are not in the destructor of the object.
3890 const int method_relative = c->method_relative;
3891 const auto callFunction = c->callFunction;
3892 const int methodIndex = (Q_HAS_TRACEPOINTS || callbacks_enabled) ? c->method() : 0;
3893 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr)
3894 signal_spy_set->slot_begin_callback(receiver, methodIndex, argv);
3895
3896 {
3897 Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, methodIndex);
3898 callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
3899 }
3900
3901 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3902 signal_spy_set->slot_end_callback(receiver, methodIndex);
3903 } else {
3904 const int method = c->method_relative + c->method_offset;
3905
3906 if (callbacks_enabled && signal_spy_set->slot_begin_callback != nullptr) {
3907 signal_spy_set->slot_begin_callback(receiver, method, argv);
3908 }
3909
3910 {
3911 Q_TRACE_SCOPE(QMetaObject_activate_slot, receiver, method);
3912 QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
3913 }
3914
3915 if (callbacks_enabled && signal_spy_set->slot_end_callback != nullptr)
3916 signal_spy_set->slot_end_callback(receiver, method);
3917 }
3918 } while ((c = c->nextConnectionList.loadRelaxed()) != nullptr && c->id <= highestConnectionId);
3919
3920 } while (list != &signalVector->at(-1) &&
3921 //start over for all signals;
3922 ((list = &signalVector->at(-1)), true));
3923
3924 if (connections->currentConnectionId.loadRelaxed() == 0)
3925 senderDeleted = true;
3926 }
3927 if (!senderDeleted) {
3928 sp->connections.loadRelaxed()->cleanOrphanedConnections(sender);
3929
3930 if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr)
3931 signal_spy_set->signal_end_callback(sender, signal_index);
3932 }
3933 }
3934
3935 /*!
3936 \internal
3937 */
activate(QObject * sender,const QMetaObject * m,int local_signal_index,void ** argv)3938 void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3939 void **argv)
3940 {
3941 int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m);
3942
3943 if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3944 doActivate<true>(sender, signal_index, argv);
3945 else
3946 doActivate<false>(sender, signal_index, argv);
3947 }
3948
3949 /*!
3950 \internal
3951 */
activate(QObject * sender,int signalOffset,int local_signal_index,void ** argv)3952 void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
3953 {
3954 int signal_index = signalOffset + local_signal_index;
3955
3956 if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
3957 doActivate<true>(sender, signal_index, argv);
3958 else
3959 doActivate<false>(sender, signal_index, argv);
3960 }
3961
3962 /*!
3963 \internal
3964 signal_index comes from indexOfMethod()
3965 */
activate(QObject * sender,int signal_index,void ** argv)3966 void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
3967 {
3968 const QMetaObject *mo = sender->metaObject();
3969 while (mo->methodOffset() > signal_index)
3970 mo = mo->superClass();
3971 activate(sender, mo, signal_index - mo->methodOffset(), argv);
3972 }
3973
3974 /*!
3975 \internal
3976 Returns the signal index used in the internal connections->receivers vector.
3977
3978 It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
3979 while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
3980
3981 If \a meta is not \nullptr, it is set to the meta-object where the signal was found.
3982 */
signalIndex(const char * signalName,const QMetaObject ** meta) const3983 int QObjectPrivate::signalIndex(const char *signalName,
3984 const QMetaObject **meta) const
3985 {
3986 Q_Q(const QObject);
3987 const QMetaObject *base = q->metaObject();
3988 Q_ASSERT(QMetaObjectPrivate::get(base)->revision >= 7);
3989 QArgumentTypeArray types;
3990 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signalName, types);
3991 int relative_index = QMetaObjectPrivate::indexOfSignalRelative(
3992 &base, name, types.size(), types.constData());
3993 if (relative_index < 0)
3994 return relative_index;
3995 relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
3996 if (meta)
3997 *meta = base;
3998 return relative_index + QMetaObjectPrivate::signalOffset(base);
3999 }
4000
4001 /*****************************************************************************
4002 Properties
4003 *****************************************************************************/
4004
4005 #ifndef QT_NO_PROPERTIES
4006
4007 /*!
4008 Sets the value of the object's \a name property to \a value.
4009
4010 If the property is defined in the class using Q_PROPERTY then
4011 true is returned on success and false otherwise. If the property
4012 is not defined using Q_PROPERTY, and therefore not listed in the
4013 meta-object, it is added as a dynamic property and false is returned.
4014
4015 Information about all available properties is provided through the
4016 metaObject() and dynamicPropertyNames().
4017
4018 Dynamic properties can be queried again using property() and can be
4019 removed by setting the property value to an invalid QVariant.
4020 Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
4021 to be sent to the object.
4022
4023 \b{Note:} Dynamic properties starting with "_q_" are reserved for internal
4024 purposes.
4025
4026 \sa property(), metaObject(), dynamicPropertyNames(), QMetaProperty::write()
4027 */
setProperty(const char * name,const QVariant & value)4028 bool QObject::setProperty(const char *name, const QVariant &value)
4029 {
4030 Q_D(QObject);
4031 const QMetaObject* meta = metaObject();
4032 if (!name || !meta)
4033 return false;
4034
4035 int id = meta->indexOfProperty(name);
4036 if (id < 0) {
4037 if (!d->extraData)
4038 d->extraData = new QObjectPrivate::ExtraData;
4039
4040 const int idx = d->extraData->propertyNames.indexOf(name);
4041
4042 if (!value.isValid()) {
4043 if (idx == -1)
4044 return false;
4045 d->extraData->propertyNames.removeAt(idx);
4046 d->extraData->propertyValues.removeAt(idx);
4047 } else {
4048 if (idx == -1) {
4049 d->extraData->propertyNames.append(name);
4050 d->extraData->propertyValues.append(value);
4051 } else {
4052 if (value.userType() == d->extraData->propertyValues.at(idx).userType()
4053 && value == d->extraData->propertyValues.at(idx))
4054 return false;
4055 d->extraData->propertyValues[idx] = value;
4056 }
4057 }
4058
4059 QDynamicPropertyChangeEvent ev(name);
4060 QCoreApplication::sendEvent(this, &ev);
4061
4062 return false;
4063 }
4064 QMetaProperty p = meta->property(id);
4065 #ifndef QT_NO_DEBUG
4066 if (!p.isWritable())
4067 qWarning("%s::setProperty: Property \"%s\" invalid,"
4068 " read-only or does not exist", metaObject()->className(), name);
4069 #endif
4070 return p.write(this, value);
4071 }
4072
4073 /*!
4074 Returns the value of the object's \a name property.
4075
4076 If no such property exists, the returned variant is invalid.
4077
4078 Information about all available properties is provided through the
4079 metaObject() and dynamicPropertyNames().
4080
4081 \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
4082 */
property(const char * name) const4083 QVariant QObject::property(const char *name) const
4084 {
4085 Q_D(const QObject);
4086 const QMetaObject* meta = metaObject();
4087 if (!name || !meta)
4088 return QVariant();
4089
4090 int id = meta->indexOfProperty(name);
4091 if (id < 0) {
4092 if (!d->extraData)
4093 return QVariant();
4094 const int i = d->extraData->propertyNames.indexOf(name);
4095 return d->extraData->propertyValues.value(i);
4096 }
4097 QMetaProperty p = meta->property(id);
4098 #ifndef QT_NO_DEBUG
4099 if (!p.isReadable())
4100 qWarning("%s::property: Property \"%s\" invalid or does not exist",
4101 metaObject()->className(), name);
4102 #endif
4103 return p.read(this);
4104 }
4105
4106 /*!
4107 \since 4.2
4108
4109 Returns the names of all properties that were dynamically added to
4110 the object using setProperty().
4111 */
dynamicPropertyNames() const4112 QList<QByteArray> QObject::dynamicPropertyNames() const
4113 {
4114 Q_D(const QObject);
4115 if (d->extraData)
4116 return d->extraData->propertyNames;
4117 return QList<QByteArray>();
4118 }
4119
4120 #endif // QT_NO_PROPERTIES
4121
4122
4123 /*****************************************************************************
4124 QObject debugging output routines.
4125 *****************************************************************************/
4126
dumpRecursive(int level,const QObject * object)4127 static void dumpRecursive(int level, const QObject *object)
4128 {
4129 if (object) {
4130 QByteArray buf;
4131 buf.fill(' ', level / 2 * 8);
4132 if (level % 2)
4133 buf += " ";
4134 QString name = object->objectName();
4135 QString flags = QLatin1String("");
4136 #if 0
4137 if (qApp->focusWidget() == object)
4138 flags += 'F';
4139 if (object->isWidgetType()) {
4140 QWidget * w = (QWidget *)object;
4141 if (w->isVisible()) {
4142 QString t("<%1,%2,%3,%4>");
4143 flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
4144 } else {
4145 flags += 'I';
4146 }
4147 }
4148 #endif
4149 qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
4150 flags.toLatin1().data());
4151 QObjectList children = object->children();
4152 if (!children.isEmpty()) {
4153 for (int i = 0; i < children.size(); ++i)
4154 dumpRecursive(level+1, children.at(i));
4155 }
4156 }
4157 }
4158
4159 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4160 /*!
4161 \overload
4162 \obsolete
4163
4164 Dumps a tree of children to the debug output.
4165
4166 \sa dumpObjectInfo()
4167 */
4168
dumpObjectTree()4169 void QObject::dumpObjectTree()
4170 {
4171 const_cast<const QObject *>(this)->dumpObjectTree();
4172 }
4173 #endif
4174
4175 /*!
4176 Dumps a tree of children to the debug output.
4177
4178 \note before Qt 5.9, this function was not const.
4179
4180 \sa dumpObjectInfo()
4181 */
4182
dumpObjectTree() const4183 void QObject::dumpObjectTree() const
4184 {
4185 dumpRecursive(0, this);
4186 }
4187
4188 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
4189 /*!
4190 \overload
4191 \obsolete
4192
4193 Dumps information about signal connections, etc. for this object
4194 to the debug output.
4195
4196 \sa dumpObjectTree()
4197 */
4198
dumpObjectInfo()4199 void QObject::dumpObjectInfo()
4200 {
4201 const_cast<const QObject *>(this)->dumpObjectInfo();
4202 }
4203 #endif
4204
4205 /*!
4206 Dumps information about signal connections, etc. for this object
4207 to the debug output.
4208
4209 \note before Qt 5.9, this function was not const.
4210
4211 \sa dumpObjectTree()
4212 */
4213
dumpObjectInfo() const4214 void QObject::dumpObjectInfo() const
4215 {
4216 qDebug("OBJECT %s::%s", metaObject()->className(),
4217 objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
4218
4219 Q_D(const QObject);
4220 QBasicMutexLocker locker(signalSlotLock(this));
4221
4222 // first, look for connections where this object is the sender
4223 qDebug(" SIGNALS OUT");
4224
4225 QObjectPrivate::ConnectionData *cd = d->connections.loadRelaxed();
4226 if (cd && cd->signalVectorCount()) {
4227 QObjectPrivate::SignalVector *signalVector = cd->signalVector.loadRelaxed();
4228 for (int signal_index = 0; signal_index < signalVector->count(); ++signal_index) {
4229 const QObjectPrivate::Connection *c = signalVector->at(signal_index).first.loadRelaxed();
4230 if (!c)
4231 continue;
4232 const QMetaMethod signal = QMetaObjectPrivate::signal(metaObject(), signal_index);
4233 qDebug(" signal: %s", signal.methodSignature().constData());
4234
4235 // receivers
4236 while (c) {
4237 if (!c->receiver.loadRelaxed()) {
4238 qDebug(" <Disconnected receiver>");
4239 c = c->nextConnectionList.loadRelaxed();
4240 continue;
4241 }
4242 if (c->isSlotObject) {
4243 qDebug(" <functor or function pointer>");
4244 c = c->nextConnectionList.loadRelaxed();
4245 continue;
4246 }
4247 const QMetaObject *receiverMetaObject = c->receiver.loadRelaxed()->metaObject();
4248 const QMetaMethod method = receiverMetaObject->method(c->method());
4249 qDebug(" --> %s::%s %s",
4250 receiverMetaObject->className(),
4251 c->receiver.loadRelaxed()->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver.loadRelaxed()->objectName()),
4252 method.methodSignature().constData());
4253 c = c->nextConnectionList.loadRelaxed();
4254 }
4255 }
4256 } else {
4257 qDebug( " <None>" );
4258 }
4259
4260 // now look for connections where this object is the receiver
4261 qDebug(" SIGNALS IN");
4262
4263 if (cd && cd->senders) {
4264 for (QObjectPrivate::Connection *s = cd->senders; s; s = s->next) {
4265 QByteArray slotName = QByteArrayLiteral("<unknown>");
4266 if (!s->isSlotObject) {
4267 const QMetaMethod slot = metaObject()->method(s->method());
4268 slotName = slot.methodSignature();
4269 }
4270 qDebug(" <-- %s::%s %s",
4271 s->sender->metaObject()->className(),
4272 s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
4273 slotName.constData());
4274 }
4275 } else {
4276 qDebug(" <None>");
4277 }
4278 }
4279
4280 #ifndef QT_NO_USERDATA
4281 static QBasicAtomicInteger<uint> user_data_registration = Q_BASIC_ATOMIC_INITIALIZER(0);
4282
4283 /*!
4284 \internal
4285 */
registerUserData()4286 uint QObject::registerUserData()
4287 {
4288 return user_data_registration.fetchAndAddRelaxed(1);
4289 }
4290
4291 /*!
4292 \fn QObjectUserData::QObjectUserData()
4293 \internal
4294 */
4295
4296 /*!
4297 \internal
4298 */
~QObjectUserData()4299 QObjectUserData::~QObjectUserData()
4300 {
4301 }
4302
4303 /*!
4304 \internal
4305 */
setUserData(uint id,QObjectUserData * data)4306 void QObject::setUserData(uint id, QObjectUserData* data)
4307 {
4308 Q_D(QObject);
4309 if (!d->extraData)
4310 d->extraData = new QObjectPrivate::ExtraData;
4311
4312 if (d->extraData->userData.size() <= (int) id)
4313 d->extraData->userData.resize((int) id + 1);
4314 d->extraData->userData[id] = data;
4315 }
4316
4317 /*!
4318 \internal
4319 */
userData(uint id) const4320 QObjectUserData* QObject::userData(uint id) const
4321 {
4322 Q_D(const QObject);
4323 if (!d->extraData)
4324 return nullptr;
4325 if ((int)id < d->extraData->userData.size())
4326 return d->extraData->userData.at(id);
4327 return nullptr;
4328 }
4329
4330 #endif // QT_NO_USERDATA
4331
4332
4333 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QObject * o)4334 QDebug operator<<(QDebug dbg, const QObject *o)
4335 {
4336 QDebugStateSaver saver(dbg);
4337 if (!o)
4338 return dbg << "QObject(0x0)";
4339 dbg.nospace() << o->metaObject()->className() << '(' << (const void *)o;
4340 if (!o->objectName().isEmpty())
4341 dbg << ", name = " << o->objectName();
4342 dbg << ')';
4343 return dbg;
4344 }
4345 #endif
4346
4347 /*!
4348 \macro Q_CLASSINFO(Name, Value)
4349 \relates QObject
4350
4351 This macro associates extra information to the class, which is available
4352 using QObject::metaObject(). Qt makes only limited use of this feature, in
4353 the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML module}{Qt QML}.
4354
4355 The extra information takes the form of a \a Name string and a \a Value
4356 literal string.
4357
4358 Example:
4359
4360 \snippet code/src_corelib_kernel_qobject.cpp 35
4361
4362 \sa QMetaObject::classInfo()
4363 \sa QAxFactory
4364 \sa {Using Qt D-Bus Adaptors}
4365 \sa {Extending QML}
4366 */
4367
4368 /*!
4369 \macro Q_INTERFACES(...)
4370 \relates QObject
4371
4372 This macro tells Qt which interfaces the class implements. This
4373 is used when implementing plugins.
4374
4375 Example:
4376
4377 \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 1
4378 \dots
4379 \snippet ../widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.h 3
4380
4381 See the \l{tools/plugandpaint/plugins/basictools}{Plug & Paint
4382 Basic Tools} example for details.
4383
4384 \sa Q_DECLARE_INTERFACE(), Q_PLUGIN_METADATA(), {How to Create Qt Plugins}
4385 */
4386
4387 /*!
4388 \macro Q_PROPERTY(...)
4389 \relates QObject
4390
4391 This macro is used for declaring properties in classes that
4392 inherit QObject. Properties behave like class data members, but
4393 they have additional features accessible through the \l
4394 {Meta-Object System}.
4395
4396 \snippet code/doc_src_properties.cpp 0
4397
4398 The property name and type and the \c READ function are required.
4399 The type can be any type supported by QVariant, or it can be a
4400 user-defined type. The other items are optional, but a \c WRITE
4401 function is common. The attributes default to true except \c USER,
4402 which defaults to false.
4403
4404 For example:
4405
4406 \snippet code/src_corelib_kernel_qobject.cpp 37
4407
4408 For more details about how to use this macro, and a more detailed
4409 example of its use, see the discussion on \l {Qt's Property System}.
4410
4411 \sa {Qt's Property System}
4412 */
4413
4414 /*!
4415 \macro Q_ENUMS(...)
4416 \relates QObject
4417 \obsolete
4418
4419 In new code, you should prefer the use of the Q_ENUM() macro, which makes the
4420 type available also to the meta type system.
4421 For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS().
4422
4423 This macro registers one or several enum types to the meta-object
4424 system.
4425
4426 If you want to register an enum that is declared in another class,
4427 the enum must be fully qualified with the name of the class
4428 defining it. In addition, the class \e defining the enum has to
4429 inherit QObject as well as declare the enum using Q_ENUMS().
4430
4431 \sa {Qt's Property System}
4432 */
4433
4434 /*!
4435 \macro Q_FLAGS(...)
4436 \relates QObject
4437 \obsolete
4438
4439 This macro registers one or several \l{QFlags}{flags types} with the
4440 meta-object system. It is typically used in a class definition to declare
4441 that values of a given enum can be used as flags and combined using the
4442 bitwise OR operator.
4443
4444 \note This macro takes care of registering individual flag values
4445 with the meta-object system, so it is unnecessary to use Q_ENUMS()
4446 in addition to this macro.
4447
4448 In new code, you should prefer the use of the Q_FLAG() macro, which makes the
4449 type available also to the meta type system.
4450
4451 \sa {Qt's Property System}
4452 */
4453
4454 /*!
4455 \macro Q_ENUM(...)
4456 \relates QObject
4457 \since 5.5
4458
4459 This macro registers an enum type with the meta-object system.
4460 It must be placed after the enum declaration in a class that has the Q_OBJECT or the
4461 Q_GADGET macro. For namespaces use \l Q_ENUM_NS() instead.
4462
4463 For example:
4464
4465 \snippet code/src_corelib_kernel_qobject.cpp 38
4466
4467 Enumerations that are declared with Q_ENUM have their QMetaEnum registered in the
4468 enclosing QMetaObject. You can also use QMetaEnum::fromType() to get the QMetaEnum.
4469
4470 Registered enumerations are automatically registered also to the Qt meta
4471 type system, making them known to QMetaType without the need to use
4472 Q_DECLARE_METATYPE(). This will enable useful features; for example, if used
4473 in a QVariant, you can convert them to strings. Likewise, passing them to
4474 QDebug will print out their names.
4475
4476 Mind that the enum values are stored as signed \c int in the meta object system.
4477 Registering enumerations with values outside the range of values valid for \c int
4478 will lead to overflows and potentially undefined behavior when accessing them through
4479 the meta object system. QML, for example, does access registered enumerations through
4480 the meta object system.
4481
4482 \sa {Qt's Property System}
4483 */
4484
4485
4486 /*!
4487 \macro Q_FLAG(...)
4488 \relates QObject
4489 \since 5.5
4490
4491 This macro registers a single \l{QFlags}{flags type} with the
4492 meta-object system. It is typically used in a class definition to declare
4493 that values of a given enum can be used as flags and combined using the
4494 bitwise OR operator. For namespaces use \l Q_FLAG_NS() instead.
4495
4496 The macro must be placed after the enum declaration. The declaration of
4497 the flags type is done using the \l Q_DECLARE_FLAGS() macro.
4498
4499 For example, in QItemSelectionModel, the
4500 \l{QItemSelectionModel::SelectionFlags}{SelectionFlags} flag is
4501 declared in the following way:
4502
4503 \snippet code/src_corelib_kernel_qobject.cpp 39
4504
4505 \note The Q_FLAG macro takes care of registering individual flag values
4506 with the meta-object system, so it is unnecessary to use Q_ENUM()
4507 in addition to this macro.
4508
4509 \sa {Qt's Property System}
4510 */
4511
4512 /*!
4513 \macro Q_ENUM_NS(...)
4514 \relates QObject
4515 \since 5.8
4516
4517 This macro registers an enum type with the meta-object system.
4518 It must be placed after the enum declaration in a namespace that
4519 has the Q_NAMESPACE macro. It is the same as \l Q_ENUM but in a
4520 namespace.
4521
4522 Enumerations that are declared with Q_ENUM_NS have their QMetaEnum
4523 registered in the enclosing QMetaObject. You can also use
4524 QMetaEnum::fromType() to get the QMetaEnum.
4525
4526 Registered enumerations are automatically registered also to the Qt meta
4527 type system, making them known to QMetaType without the need to use
4528 Q_DECLARE_METATYPE(). This will enable useful features; for example, if
4529 used in a QVariant, you can convert them to strings. Likewise, passing them
4530 to QDebug will print out their names.
4531
4532 Mind that the enum values are stored as signed \c int in the meta object system.
4533 Registering enumerations with values outside the range of values valid for \c int
4534 will lead to overflows and potentially undefined behavior when accessing them through
4535 the meta object system. QML, for example, does access registered enumerations through
4536 the meta object system.
4537
4538 \sa {Qt's Property System}
4539 */
4540
4541
4542 /*!
4543 \macro Q_FLAG_NS(...)
4544 \relates QObject
4545 \since 5.8
4546
4547 This macro registers a single \l{QFlags}{flags type} with the
4548 meta-object system. It is used in a namespace that has the
4549 Q_NAMESPACE macro, to declare that values of a given enum can be
4550 used as flags and combined using the bitwise OR operator.
4551 It is the same as \l Q_FLAG but in a namespace.
4552
4553 The macro must be placed after the enum declaration.
4554
4555 \note The Q_FLAG_NS macro takes care of registering individual flag
4556 values with the meta-object system, so it is unnecessary to use
4557 Q_ENUM_NS() in addition to this macro.
4558
4559 \sa {Qt's Property System}
4560 */
4561
4562
4563 /*!
4564 \macro Q_OBJECT
4565 \relates QObject
4566
4567 The Q_OBJECT macro must appear in the private section of a class
4568 definition that declares its own signals and slots or that uses
4569 other services provided by Qt's meta-object system.
4570
4571 For example:
4572
4573 \snippet signalsandslots/signalsandslots.h 1
4574 \codeline
4575 \snippet signalsandslots/signalsandslots.h 2
4576 \snippet signalsandslots/signalsandslots.h 3
4577
4578 \note This macro requires the class to be a subclass of QObject. Use
4579 Q_GADGET instead of Q_OBJECT to enable the meta object system's support
4580 for enums in a class that is not a QObject subclass.
4581
4582 \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
4583 */
4584
4585 /*!
4586 \macro Q_GADGET
4587 \relates QObject
4588
4589 The Q_GADGET macro is a lighter version of the Q_OBJECT macro for classes
4590 that do not inherit from QObject but still want to use some of the
4591 reflection capabilities offered by QMetaObject. Just like the Q_OBJECT
4592 macro, it must appear in the private section of a class definition.
4593
4594 Q_GADGETs can have Q_ENUM, Q_PROPERTY and Q_INVOKABLE, but they cannot have
4595 signals or slots.
4596
4597 Q_GADGET makes a class member, \c{staticMetaObject}, available.
4598 \c{staticMetaObject} is of type QMetaObject and provides access to the
4599 enums declared with Q_ENUMS.
4600 */
4601
4602 /*!
4603 \macro Q_NAMESPACE
4604 \relates QObject
4605 \since 5.8
4606
4607 The Q_NAMESPACE macro can be used to add QMetaObject capabilities
4608 to a namespace.
4609
4610 Q_NAMESPACEs can have Q_CLASSINFO, Q_ENUM_NS, Q_FLAG_NS, but they
4611 cannot have Q_ENUM, Q_FLAG, Q_PROPERTY, Q_INVOKABLE, signals nor slots.
4612
4613 Q_NAMESPACE makes an external variable, \c{staticMetaObject}, available.
4614 \c{staticMetaObject} is of type QMetaObject and provides access to the
4615 enums declared with Q_ENUM_NS/Q_FLAG_NS.
4616
4617 For example:
4618
4619 \code
4620 namespace test {
4621 Q_NAMESPACE
4622 ...
4623 \endcode
4624
4625 \sa Q_NAMESPACE_EXPORT
4626 */
4627
4628 /*!
4629 \macro Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4630 \relates QObject
4631 \since 5.14
4632
4633 The Q_NAMESPACE_EXPORT macro can be used to add QMetaObject capabilities
4634 to a namespace.
4635
4636 It works exactly like the Q_NAMESPACE macro. However, the external
4637 \c{staticMetaObject} variable that gets defined in the namespace
4638 is declared with the supplied \a EXPORT_MACRO qualifier. This is
4639 useful if the object needs to be exported from a dynamic library.
4640
4641 For example:
4642
4643 \code
4644 namespace test {
4645 Q_NAMESPACE_EXPORT(EXPORT_MACRO)
4646 ...
4647 \endcode
4648
4649 \sa Q_NAMESPACE, {Creating Shared Libraries}
4650 */
4651
4652 /*!
4653 \macro Q_SIGNALS
4654 \relates QObject
4655
4656 Use this macro to replace the \c signals keyword in class
4657 declarations, when you want to use Qt Signals and Slots with a
4658 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4659
4660 The macro is normally used when \c no_keywords is specified with
4661 the \c CONFIG variable in the \c .pro file, but it can be used
4662 even when \c no_keywords is \e not specified.
4663 */
4664
4665 /*!
4666 \macro Q_SIGNAL
4667 \relates QObject
4668
4669 This is an additional macro that allows you to mark a single
4670 function as a signal. It can be quite useful, especially when you
4671 use a 3rd-party source code parser which doesn't understand a \c
4672 signals or \c Q_SIGNALS groups.
4673
4674 Use this macro to replace the \c signals keyword in class
4675 declarations, when you want to use Qt Signals and Slots with a
4676 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4677
4678 The macro is normally used when \c no_keywords is specified with
4679 the \c CONFIG variable in the \c .pro file, but it can be used
4680 even when \c no_keywords is \e not specified.
4681 */
4682
4683 /*!
4684 \macro Q_SLOTS
4685 \relates QObject
4686
4687 Use this macro to replace the \c slots keyword in class
4688 declarations, when you want to use Qt Signals and Slots with a
4689 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4690
4691 The macro is normally used when \c no_keywords is specified with
4692 the \c CONFIG variable in the \c .pro file, but it can be used
4693 even when \c no_keywords is \e not specified.
4694 */
4695
4696 /*!
4697 \macro Q_SLOT
4698 \relates QObject
4699
4700 This is an additional macro that allows you to mark a single
4701 function as a slot. It can be quite useful, especially when you
4702 use a 3rd-party source code parser which doesn't understand a \c
4703 slots or \c Q_SLOTS groups.
4704
4705 Use this macro to replace the \c slots keyword in class
4706 declarations, when you want to use Qt Signals and Slots with a
4707 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4708
4709 The macro is normally used when \c no_keywords is specified with
4710 the \c CONFIG variable in the \c .pro file, but it can be used
4711 even when \c no_keywords is \e not specified.
4712 */
4713
4714 /*!
4715 \macro Q_EMIT
4716 \relates QObject
4717
4718 Use this macro to replace the \c emit keyword for emitting
4719 signals, when you want to use Qt Signals and Slots with a
4720 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4721
4722 The macro is normally used when \c no_keywords is specified with
4723 the \c CONFIG variable in the \c .pro file, but it can be used
4724 even when \c no_keywords is \e not specified.
4725 */
4726
4727 /*!
4728 \macro Q_INVOKABLE
4729 \relates QObject
4730
4731 Apply this macro to declarations of member functions to allow them to
4732 be invoked via the meta-object system. The macro is written before
4733 the return type, as shown in the following example:
4734
4735 \snippet qmetaobject-invokable/window.h Window class with invokable method
4736
4737 The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
4738 it to be registered with the meta-object system and enabling it to be
4739 invoked using QMetaObject::invokeMethod().
4740 Since \c normalMethod() function is not registered in this way, it cannot
4741 be invoked using QMetaObject::invokeMethod().
4742
4743 If an invokable member function returns a pointer to a QObject or a
4744 subclass of QObject and it is invoked from QML, special ownership rules
4745 apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++}
4746 for more information.
4747 */
4748
4749 /*!
4750 \macro Q_REVISION
4751 \relates QObject
4752
4753 Apply this macro to declarations of member functions to tag them with a
4754 revision number in the meta-object system. The macro is written before
4755 the return type, as shown in the following example:
4756
4757 \snippet qmetaobject-revision/window.h Window class with revision
4758
4759 This is useful when using the meta-object system to dynamically expose
4760 objects to another API, as you can match the version expected by multiple
4761 versions of the other API. Consider the following simplified example:
4762
4763 \snippet qmetaobject-revision/main.cpp Window class using revision
4764
4765 Using the same Window class as the previous example, the newProperty and
4766 newMethod would only be exposed in this code when the expected version is
4767 1 or greater.
4768
4769 Since all methods are considered to be in revision 0 if untagged, a tag
4770 of Q_REVISION(0) is invalid and ignored.
4771
4772 This tag is not used by the meta-object system itself. Currently this is only
4773 used by the QtQml module.
4774
4775 For a more generic string tag, see \l QMetaMethod::tag()
4776
4777 \sa QMetaMethod::revision()
4778 */
4779
4780 /*!
4781 \macro Q_SET_OBJECT_NAME(Object)
4782 \relates QObject
4783 \since 5.0
4784
4785 This macro assigns \a Object the objectName "Object".
4786
4787 It doesn't matter whether \a Object is a pointer or not, the
4788 macro figures that out by itself.
4789
4790 \sa QObject::objectName()
4791 */
4792
4793 /*!
4794 \macro QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
4795 \relates QObject
4796 \since 5.8
4797
4798 Defining this macro will disable narrowing and floating-point-to-integral
4799 conversions between the arguments carried by a signal and the arguments
4800 accepted by a slot, when the signal and the slot are connected using the
4801 PMF-based syntax.
4802
4803 \sa QObject::connect
4804 */
4805
4806 /*!
4807 \typedef QObjectList
4808 \relates QObject
4809
4810 Synonym for QList<QObject *>.
4811 */
4812
qDeleteInEventHandler(QObject * o)4813 void qDeleteInEventHandler(QObject *o)
4814 {
4815 delete o;
4816 }
4817
4818 /*!
4819 \fn template<typename PointerToMemberFunction> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type)
4820 \overload connect()
4821 \threadsafe
4822
4823 Creates a connection of the given \a type from the \a signal in
4824 the \a sender object to the \a method in the \a receiver object.
4825 Returns a handle to the connection that can be used to disconnect
4826 it later.
4827
4828 The signal must be a function declared as a signal in the header.
4829 The slot function can be any member function that can be connected
4830 to the signal.
4831 A slot can be connected to a given signal if the signal has at
4832 least as many arguments as the slot, and there is an implicit
4833 conversion between the types of the corresponding arguments in the
4834 signal and the slot.
4835
4836 Example:
4837
4838 \snippet code/src_corelib_kernel_qobject.cpp 44
4839
4840 This example ensures that the label always displays the current
4841 line edit text.
4842
4843 A signal can be connected to many slots and signals. Many signals
4844 can be connected to one slot.
4845
4846 If a signal is connected to several slots, the slots are activated
4847 in the same order as the order the connection was made, when the
4848 signal is emitted
4849
4850 The function returns an handle to a connection if it successfully
4851 connects the signal to the slot. The Connection handle will be invalid
4852 if it cannot create the connection, for example, if QObject is unable
4853 to verify the existence of \a signal (if it was not declared as a signal)
4854 You can check if the QMetaObject::Connection is valid by casting it to a bool.
4855
4856 By default, a signal is emitted for every connection you make;
4857 two signals are emitted for duplicate connections. You can break
4858 all of these connections with a single disconnect() call.
4859 If you pass the Qt::UniqueConnection \a type, the connection will only
4860 be made if it is not a duplicate. If there is already a duplicate
4861 (exact same signal to the exact same slot on the same objects),
4862 the connection will fail and connect will return an invalid QMetaObject::Connection.
4863
4864 The optional \a type parameter describes the type of connection
4865 to establish. In particular, it determines whether a particular
4866 signal is delivered to a slot immediately or queued for delivery
4867 at a later time. If the signal is queued, the parameters must be
4868 of types that are known to Qt's meta-object system, because Qt
4869 needs to copy the arguments to store them in an event behind the
4870 scenes. If you try to use a queued connection and get the error
4871 message
4872
4873 \snippet code/src_corelib_kernel_qobject.cpp 25
4874
4875 make sure to declare the argument type with Q_DECLARE_METATYPE
4876
4877 Overloaded functions can be resolved with help of \l qOverload.
4878
4879 \sa {Differences between String-Based and Functor-Based Connections}
4880 */
4881
4882 /*!
4883 \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
4884
4885 \threadsafe
4886 \overload connect()
4887
4888 Creates a connection from \a signal in
4889 \a sender object to \a functor, and returns a handle to the connection
4890
4891 The signal must be a function declared as a signal in the header.
4892 The slot function can be any function or functor that can be connected
4893 to the signal.
4894 A function can be connected to a given signal if the signal has at
4895 least as many argument as the slot. A functor can be connected to a signal
4896 if they have exactly the same number of arguments. There must exist implicit
4897 conversion between the types of the corresponding arguments in the
4898 signal and the slot.
4899
4900 Example:
4901
4902 \snippet code/src_corelib_kernel_qobject.cpp 45
4903
4904 Lambda expressions can also be used:
4905
4906 \snippet code/src_corelib_kernel_qobject.cpp 46
4907
4908 The connection will automatically disconnect if the sender is destroyed.
4909 However, you should take care that any objects used within the functor
4910 are still alive when the signal is emitted.
4911
4912 Overloaded functions can be resolved with help of \l qOverload.
4913
4914 */
4915
4916 /*!
4917 \fn template<typename PointerToMemberFunction, typename Functor> QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
4918
4919 \threadsafe
4920 \overload connect()
4921
4922 \since 5.2
4923
4924 Creates a connection of a given \a type from \a signal in
4925 \a sender object to \a functor to be placed in a specific event
4926 loop of \a context, and returns a handle to the connection.
4927
4928 \note Qt::UniqueConnections do not work for lambdas, non-member functions
4929 and functors; they only apply to connecting to member functions.
4930
4931 The signal must be a function declared as a signal in the header.
4932 The slot function can be any function or functor that can be connected
4933 to the signal.
4934 A function can be connected to a given signal if the signal has at
4935 least as many argument as the slot. A functor can be connected to a signal
4936 if they have exactly the same number of arguments. There must exist implicit
4937 conversion between the types of the corresponding arguments in the
4938 signal and the slot.
4939
4940 Example:
4941
4942 \snippet code/src_corelib_kernel_qobject.cpp 50
4943
4944 Lambda expressions can also be used:
4945
4946 \snippet code/src_corelib_kernel_qobject.cpp 51
4947
4948 The connection will automatically disconnect if the sender or the context
4949 is destroyed.
4950 However, you should take care that any objects used within the functor
4951 are still alive when the signal is emitted.
4952
4953 Overloaded functions can be resolved with help of \l qOverload.
4954 */
4955
4956 /*!
4957 \internal
4958
4959 Implementation of the template version of connect
4960
4961 \a sender is the sender object
4962 \a signal is a pointer to a pointer to a member signal of the sender
4963 \a receiver is the receiver object, may not be \nullptr, will be equal to sender when
4964 connecting to a static function or a functor
4965 \a slot a pointer only used when using Qt::UniqueConnection
4966 \a type the Qt::ConnectionType passed as argument to connect
4967 \a types an array of integer with the metatype id of the parameter of the signal
4968 to be used with queued connection
4969 must stay valid at least for the whole time of the connection, this function
4970 do not take ownership. typically static data.
4971 If \nullptr, then the types will be computed when the signal is emit in a queued
4972 connection from the types from the signature.
4973 \a senderMetaObject is the metaobject used to lookup the signal, the signal must be in
4974 this metaobject
4975 */
connectImpl(const QObject * sender,void ** signal,const QObject * receiver,void ** slot,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type,const int * types,const QMetaObject * senderMetaObject)4976 QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal,
4977 const QObject *receiver, void **slot,
4978 QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
4979 const int *types, const QMetaObject *senderMetaObject)
4980 {
4981 if (!signal) {
4982 qWarning("QObject::connect: invalid nullptr parameter");
4983 if (slotObj)
4984 slotObj->destroyIfLastRef();
4985 return QMetaObject::Connection();
4986 }
4987
4988 int signal_index = -1;
4989 void *args[] = { &signal_index, signal };
4990 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
4991 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
4992 if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
4993 break;
4994 }
4995 if (!senderMetaObject) {
4996 qWarning("QObject::connect: signal not found in %s", sender->metaObject()->className());
4997 slotObj->destroyIfLastRef();
4998 return QMetaObject::Connection(nullptr);
4999 }
5000 signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
5001 return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
5002 }
5003
5004 /*!
5005 \internal
5006
5007 Internal version of connect used by the template version of QObject::connect (called via connectImpl) and
5008 also used by the QObjectPrivate::connect version used by QML. The signal_index is expected to be relative
5009 to the number of signals.
5010 */
connectImpl(const QObject * sender,int signal_index,const QObject * receiver,void ** slot,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type,const int * types,const QMetaObject * senderMetaObject)5011 QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int signal_index,
5012 const QObject *receiver, void **slot,
5013 QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
5014 const int *types, const QMetaObject *senderMetaObject)
5015 {
5016 if (!sender || !receiver || !slotObj || !senderMetaObject) {
5017 const char *senderString = sender ? sender->metaObject()->className()
5018 : senderMetaObject ? senderMetaObject->className()
5019 : "Unknown";
5020 const char *receiverString = receiver ? receiver->metaObject()->className()
5021 : "Unknown";
5022 qWarning("QObject::connect(%s, %s): invalid nullptr parameter", senderString, receiverString);
5023 if (slotObj)
5024 slotObj->destroyIfLastRef();
5025 return QMetaObject::Connection();
5026 }
5027
5028 QObject *s = const_cast<QObject *>(sender);
5029 QObject *r = const_cast<QObject *>(receiver);
5030
5031 QOrderedMutexLocker locker(signalSlotLock(sender),
5032 signalSlotLock(receiver));
5033
5034 if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) {
5035 QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
5036 if (connections->signalVectorCount() > signal_index) {
5037 const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();
5038
5039 while (c2) {
5040 if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
5041 slotObj->destroyIfLastRef();
5042 return QMetaObject::Connection();
5043 }
5044 c2 = c2->nextConnectionList.loadRelaxed();
5045 }
5046 }
5047 type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
5048 }
5049
5050 std::unique_ptr<QObjectPrivate::Connection> c{new QObjectPrivate::Connection};
5051 c->sender = s;
5052 c->signal_index = signal_index;
5053 QThreadData *td = r->d_func()->threadData;
5054 td->ref();
5055 c->receiverThreadData.storeRelaxed(td);
5056 c->receiver.storeRelaxed(r);
5057 c->slotObj = slotObj;
5058 c->connectionType = type;
5059 c->isSlotObject = true;
5060 if (types) {
5061 c->argumentTypes.storeRelaxed(types);
5062 c->ownArgumentTypes = false;
5063 }
5064
5065 QObjectPrivate::get(s)->addConnection(signal_index, c.get());
5066 QMetaObject::Connection ret(c.release());
5067 locker.unlock();
5068
5069 QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index);
5070 Q_ASSERT(method.isValid());
5071 s->connectNotify(method);
5072
5073 return ret;
5074 }
5075
5076 /*!
5077 Disconnect a connection.
5078
5079 If the \a connection is invalid or has already been disconnected, do nothing
5080 and return false.
5081
5082 \sa connect()
5083 */
disconnect(const QMetaObject::Connection & connection)5084 bool QObject::disconnect(const QMetaObject::Connection &connection)
5085 {
5086 QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
5087
5088 if (!c)
5089 return false;
5090 QObject *receiver = c->receiver.loadRelaxed();
5091 if (!receiver)
5092 return false;
5093
5094 QBasicMutex *senderMutex = signalSlotLock(c->sender);
5095 QBasicMutex *receiverMutex = signalSlotLock(receiver);
5096
5097 QObjectPrivate::ConnectionData *connections;
5098 {
5099 QOrderedMutexLocker locker(senderMutex, receiverMutex);
5100
5101 // load receiver once again and recheck to ensure nobody else has removed the connection in the meantime
5102 receiver = c->receiver.loadRelaxed();
5103 if (!receiver)
5104 return false;
5105
5106 connections = QObjectPrivate::get(c->sender)->connections.loadRelaxed();
5107 Q_ASSERT(connections);
5108 connections->removeConnection(c);
5109 }
5110
5111 connections->cleanOrphanedConnections(c->sender);
5112
5113 c->sender->disconnectNotify(QMetaObjectPrivate::signal(c->sender->metaObject(),
5114 c->signal_index));
5115
5116 const_cast<QMetaObject::Connection &>(connection).d_ptr = nullptr;
5117 c->deref(); // has been removed from the QMetaObject::Connection object
5118
5119 return true;
5120 }
5121
5122 /*! \fn template<typename PointerToMemberFunction> bool QObject::disconnect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method)
5123 \overload disconnect()
5124 \threadsafe
5125
5126 Disconnects \a signal in object \a sender from \a method in object
5127 \a receiver. Returns \c true if the connection is successfully broken;
5128 otherwise returns \c false.
5129
5130 A signal-slot connection is removed when either of the objects
5131 involved are destroyed.
5132
5133 disconnect() is typically used in three ways, as the following
5134 examples demonstrate.
5135 \list 1
5136 \li Disconnect everything connected to an object's signals:
5137
5138 \snippet code/src_corelib_kernel_qobject.cpp 26
5139
5140 \li Disconnect everything connected to a specific signal:
5141
5142 \snippet code/src_corelib_kernel_qobject.cpp 47
5143
5144 \li Disconnect a specific receiver:
5145
5146 \snippet code/src_corelib_kernel_qobject.cpp 30
5147
5148 \li Disconnect a connection from one specific signal to a specific slot:
5149
5150 \snippet code/src_corelib_kernel_qobject.cpp 48
5151
5152
5153 \endlist
5154
5155 \nullptr may be used as a wildcard, meaning "any signal", "any receiving
5156 object", or "any slot in the receiving object", respectively.
5157
5158 The \a sender may never be \nullptr. (You cannot disconnect signals
5159 from more than one object in a single call.)
5160
5161 If \a signal is \nullptr, it disconnects \a receiver and \a method from
5162 any signal. If not, only the specified signal is disconnected.
5163
5164 If \a receiver is \nullptr, it disconnects anything connected to \a
5165 signal. If not, slots in objects other than \a receiver are not
5166 disconnected.
5167
5168 If \a method is \nullptr, it disconnects anything that is connected to \a
5169 receiver. If not, only slots named \a method will be disconnected,
5170 and all other slots are left alone. The \a method must be \nullptr
5171 if \a receiver is left out, so you cannot disconnect a
5172 specifically-named slot on all objects.
5173
5174 \note It is not possible to use this overload to disconnect signals
5175 connected to functors or lambda expressions. That is because it is not
5176 possible to compare them. Instead, use the overload that takes a
5177 QMetaObject::Connection
5178
5179 \sa connect()
5180 */
5181
disconnectImpl(const QObject * sender,void ** signal,const QObject * receiver,void ** slot,const QMetaObject * senderMetaObject)5182 bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject *receiver, void **slot, const QMetaObject *senderMetaObject)
5183 {
5184 if (sender == nullptr || (receiver == nullptr && slot != nullptr)) {
5185 qWarning("QObject::disconnect: Unexpected nullptr parameter");
5186 return false;
5187 }
5188
5189 int signal_index = -1;
5190 if (signal) {
5191 void *args[] = { &signal_index, signal };
5192 for (; senderMetaObject && signal_index < 0; senderMetaObject = senderMetaObject->superClass()) {
5193 senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
5194 if (signal_index >= 0 && signal_index < QMetaObjectPrivate::get(senderMetaObject)->signalCount)
5195 break;
5196 }
5197 if (!senderMetaObject) {
5198 qWarning("QObject::disconnect: signal not found in %s", sender->metaObject()->className());
5199 return false;
5200 }
5201 signal_index += QMetaObjectPrivate::signalOffset(senderMetaObject);
5202 }
5203
5204 return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1, slot);
5205 }
5206
5207 /*!
5208 \internal
5209 Used by QML to connect a signal by index to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass).
5210
5211 The signal_index is an index relative to the number of methods.
5212 */
connect(const QObject * sender,int signal_index,QtPrivate::QSlotObjectBase * slotObj,Qt::ConnectionType type)5213 QMetaObject::Connection QObjectPrivate::connect(const QObject *sender, int signal_index, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type)
5214 {
5215 if (!sender) {
5216 qWarning("QObject::connect: invalid nullptr parameter");
5217 if (slotObj)
5218 slotObj->destroyIfLastRef();
5219 return QMetaObject::Connection();
5220 }
5221 const QMetaObject *senderMetaObject = sender->metaObject();
5222 signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5223
5224 return QObjectPrivate::connectImpl(sender, signal_index, sender, /*slot*/nullptr, slotObj, type, /*types*/nullptr, senderMetaObject);
5225 }
5226
5227 /*!
5228 \internal
5229 Used by QML to disconnect a signal by index that's connected to a slot implemented in JavaScript (wrapped in a custom QSlotObjectBase subclass)
5230 In the QML case the slot is not a pointer to a pointer to the function to disconnect, but instead it is a pointer to an array of internal values
5231 required for the disconnect.
5232 */
disconnect(const QObject * sender,int signal_index,void ** slot)5233 bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void **slot)
5234 {
5235 const QMetaObject *senderMetaObject = sender->metaObject();
5236 signal_index = methodIndexToSignalIndex(&senderMetaObject, signal_index);
5237
5238 return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, sender, -1, slot);
5239 }
5240
5241 /*! \class QMetaObject::Connection
5242 \inmodule QtCore
5243 Represents a handle to a signal-slot (or signal-functor) connection.
5244
5245 It can be used to check if the connection is valid and to disconnect it using
5246 QObject::disconnect(). For a signal-functor connection without a context object,
5247 it is the only way to selectively disconnect that connection.
5248
5249 As Connection is just a handle, the underlying signal-slot connection is unaffected
5250 when Connection is destroyed or reassigned.
5251 */
5252
5253 /*!
5254 Create a copy of the handle to the \a other connection
5255 */
Connection(const QMetaObject::Connection & other)5256 QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_ptr(other.d_ptr)
5257 {
5258 if (d_ptr)
5259 static_cast<QObjectPrivate::Connection *>(d_ptr)->ref();
5260 }
5261
5262 /*!
5263 Assigns \a other to this connection and returns a reference to this connection.
5264 */
operator =(const QMetaObject::Connection & other)5265 QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
5266 {
5267 if (other.d_ptr != d_ptr) {
5268 if (d_ptr)
5269 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5270 d_ptr = other.d_ptr;
5271 if (other.d_ptr)
5272 static_cast<QObjectPrivate::Connection *>(other.d_ptr)->ref();
5273 }
5274 return *this;
5275 }
5276
5277 /*!
5278 Creates a Connection instance.
5279 */
5280
Connection()5281 QMetaObject::Connection::Connection() : d_ptr(nullptr) {}
5282
5283 /*!
5284 Destructor for QMetaObject::Connection.
5285 */
~Connection()5286 QMetaObject::Connection::~Connection()
5287 {
5288 if (d_ptr)
5289 static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
5290 }
5291
5292 /*! \internal Returns true if the object is still connected */
isConnected_helper() const5293 bool QMetaObject::Connection::isConnected_helper() const
5294 {
5295 Q_ASSERT(d_ptr); // we're only called from operator RestrictedBool() const
5296 QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(d_ptr);
5297
5298 return c->receiver.loadRelaxed();
5299 }
5300
5301
5302 /*!
5303 \fn QMetaObject::Connection::operator bool() const
5304
5305 Returns \c true if the connection is valid.
5306
5307 The connection is valid if the call to QObject::connect succeeded.
5308 The connection is invalid if QObject::connect was not able to find
5309 the signal or the slot, or if the arguments do not match.
5310 */
5311
5312 QT_END_NAMESPACE
5313
5314 #include "moc_qnamespace.cpp"
5315 #include "moc_qobject.cpp"
5316