1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
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 "qcoreapplication.h"
48#include "qcoreapplication_p.h"
49#include "qvariant.h"
50#include "qmetaobject.h"
51#include <qregexp.h>
52#include <qthread.h>
53#include <private/qthread_p.h>
54#include <qdebug.h>
55#include <qhash.h>
56#include <qpair.h>
57#include <qset.h>
58#include <qsemaphore.h>
59#include <qsharedpointer.h>
60
61#include <private/qorderedmutexlocker_p.h>
62#include <private/qmutexpool_p.h>
63
64#include <new>
65
66#include <ctype.h>
67#include <limits.h>
68
69QT_BEGIN_NAMESPACE
70
71static int DIRECT_CONNECTION_ONLY = 0;
72
73static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
74{
75 int *types = new int [typeNames.count() + 1];
76 Q_CHECK_PTR(types);
77 for (int i = 0; i < typeNames.count(); ++i) {
78 const QByteArray typeName = typeNames.at(i);
79 if (typeName.endsWith('*'))
80 types[i] = QMetaType::VoidStar;
81 else
82 types[i] = QMetaType::type(typeName);
83
84 if (!types[i]) {
85 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
86 "(Make sure '%s' is registered using qRegisterMetaType().)",
87 typeName.constData(), typeName.constData());
88 delete [] types;
89 return 0;
90 }
91 }
92 types[typeNames.count()] = 0;
93
94 return types;
95}
96
97static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
98static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
99
100/** \internal
101 * mutex to be locked when accessing the connectionlists or the senders list
102 */
103static inline QMutex *signalSlotLock(const QObject *o)
104{
105 if (!signalSlotMutexes) {
106 QMutexPool *mp = new QMutexPool;
107 if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
108 delete mp;
109 }
110 }
111 return signalSlotMutexes->get(o);
112}
113
114extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
115{
116 objectCount.ref();
117}
118
119extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
120{
121 if(!objectCount.deref()) {
122 QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
123 delete old;
124 }
125}
126
127void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
128void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
129void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
130
131QObjectData::~QObjectData() {}
132
133QObjectPrivate::QObjectPrivate(int version)
134 : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
135{
136 if (version != QObjectPrivateVersion)
137 qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
138 version, QObjectPrivateVersion);
139
140 // QObjectData initialization
141 q_ptr = 0;
142 parent = 0; // no parent yet. It is set by setParent()
143 isWidget = false; // assume not a widget object
144 pendTimer = false; // no timers yet
145 blockSig = false; // not blocking signals
146 wasDeleted = false; // double-delete catcher
147 sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
148 receiveChildEvents = true;
149 postedEvents = 0;
150 extraData = 0;
151 connectedSignals[0] = connectedSignals[1] = 0;
152 inThreadChangeEvent = false;
153#ifdef QT_JAMBI_BUILD
154 inEventHandler = false;
155 deleteWatch = 0;
156#endif
157 metaObject = 0;
158 hasGuards = false;
159}
160
161QObjectPrivate::~QObjectPrivate()
162{
163 if (pendTimer) {
164 // unregister pending timers
165 if (threadData && threadData->eventDispatcher)
166 threadData->eventDispatcher->unregisterTimers(q_ptr);
167 }
168
169 if (postedEvents)
170 QCoreApplication::removePostedEvents(q_ptr, 0);
171
172 if (threadData)
173 threadData->deref();
174
175 delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
176#ifdef QT_JAMBI_BUILD
177 if (deleteWatch)
178 *deleteWatch = 1;
179#endif
180#ifndef QT_NO_USERDATA
181 if (extraData)
182 qDeleteAll(extraData->userData);
183 delete extraData;
184#endif
185}
186
187
188#ifdef QT_JAMBI_BUILD
189int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) {
190 int *old = d->deleteWatch;
191 d->deleteWatch = w;
192 return old;
193}
194
195
196void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch) {
197 if (!deleteWatch)
198 d->deleteWatch = oldWatch;
199
200 if (oldWatch)
201 *oldWatch = deleteWatch;
202}
203#endif
204
205#ifdef QT3_SUPPORT
206void QObjectPrivate::sendPendingChildInsertedEvents()
207{
208 Q_Q(QObject);
209 for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
210 QObject *c = pendingChildInsertedEvents.at(i).data();
211 if (!c || c->parent() != q)
212 continue;
213 QChildEvent childEvent(QEvent::ChildInserted, c);
214 QCoreApplication::sendEvent(q, &childEvent);
215 }
216 pendingChildInsertedEvents.clear();
217}
218
219#endif
220
221
222/*!\internal
223 For a given metaobject, compute the signal offset, and the method offset (including signals)
224*/
225static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
226{
227 *signalOffset = *methodOffset = 0;
228 const QMetaObject *m = metaobject->d.superdata;
229 while (m) {
230 const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
231 *methodOffset += d->methodCount;
232 *signalOffset += (d->revision >= 4) ? d->signalCount : d->methodCount;
233 /*Before Qt 4.6 (revision 4), the signalCount information was not generated by moc.
234 so for compatibility we consider all the method as slot for old moc output*/
235 m = m->d.superdata;
236 }
237}
238
239/*
240 This vector contains the all connections from an object.
241
242 Each object may have one vector containing the lists of
243 connections for a given signal. The index in the vector correspond
244 to the signal index. The signal index is the one returned by
245 QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
246 Negative index means connections to all signals.
247
248 This vector is protected by the object mutex (signalSlotMutexes())
249
250 Each Connection is also part of a 'senders' linked list. The mutex
251 of the receiver must be locked when touching the pointers of this
252 linked list.
253*/
254class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
255{
256public:
257 bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
258 bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
259 int inUse; //number of functions that are currently accessing this object or its connections
260 QObjectPrivate::ConnectionList allsignals;
261
262 QObjectConnectionListVector()
263 : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
264 { }
265
266 QObjectPrivate::ConnectionList &operator[](int at)
267 {
268 if (at < 0)
269 return allsignals;
270 return QVector<QObjectPrivate::ConnectionList>::operator[](at);
271 }
272};
273
274// Used by QAccessibleWidget
275bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
276{
277 Q_Q(const QObject);
278 int signal_index = signalIndex(signal);
279 if (signal_index < 0)
280 return false;
281 QMutexLocker locker(signalSlotLock(q));
282 if (connectionLists) {
283 if (signal_index < connectionLists->count()) {
284 const QObjectPrivate::Connection *c =
285 connectionLists->at(signal_index).first;
286
287 while (c) {
288 if (c->receiver == receiver)
289 return true;
290 c = c->nextConnectionList;
291 }
292 }
293 }
294 return false;
295}
296
297// Used by QAccessibleWidget
298QObjectList QObjectPrivate::receiverList(const char *signal) const
299{
300 Q_Q(const QObject);
301 QObjectList returnValue;
302 int signal_index = signalIndex(signal);
303 if (signal_index < 0)
304 return returnValue;
305 QMutexLocker locker(signalSlotLock(q));
306 if (connectionLists) {
307 if (signal_index < connectionLists->count()) {
308 const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
309
310 while (c) {
311 if (c->receiver)
312 returnValue << c->receiver;
313 c = c->nextConnectionList;
314 }
315 }
316 }
317 return returnValue;
318}
319
320// Used by QAccessibleWidget
321QObjectList QObjectPrivate::senderList() const
322{
323 QObjectList returnValue;
324 QMutexLocker locker(signalSlotLock(q_func()));
325 for (Connection *c = senders; c; c = c->next)
326 returnValue << c->sender;
327 return returnValue;
328}
329
330void QObjectPrivate::addConnection(int signal, Connection *c)
331{
332 if (!connectionLists)
333 connectionLists = new QObjectConnectionListVector();
334 if (signal >= connectionLists->count())
335 connectionLists->resize(signal + 1);
336
337 ConnectionList &connectionList = (*connectionLists)[signal];
338 if (connectionList.last) {
339 connectionList.last->nextConnectionList = c;
340 } else {
341 connectionList.first = c;
342 }
343 connectionList.last = c;
344
345 cleanConnectionLists();
346}
347
348void QObjectPrivate::cleanConnectionLists()
349{
350 if (connectionLists->dirty && !connectionLists->inUse) {
351 // remove broken connections
352 for (int signal = -1; signal < connectionLists->count(); ++signal) {
353 QObjectPrivate::ConnectionList &connectionList =
354 (*connectionLists)[signal];
355
356 // Set to the last entry in the connection list that was *not*
357 // deleted. This is needed to update the list's last pointer
358 // at the end of the cleanup.
359 QObjectPrivate::Connection *last = 0;
360
361 QObjectPrivate::Connection **prev = &connectionList.first;
362 QObjectPrivate::Connection *c = *prev;
363 while (c) {
364 if (c->receiver) {
365 last = c;
366 prev = &c->nextConnectionList;
367 c = *prev;
368 } else {
369 QObjectPrivate::Connection *next = c->nextConnectionList;
370 *prev = next;
371 delete c;
372 c = next;
373 }
374 }
375
376 // Correct the connection list's last pointer.
377 // As conectionList.last could equal last, this could be a noop
378 connectionList.last = last;
379 }
380 connectionLists->dirty = false;
381 }
382}
383
384typedef QMultiHash<QObject *, QObject **> GuardHash;
385Q_GLOBAL_STATIC(GuardHash, guardHash)
386Q_GLOBAL_STATIC(QMutex, guardHashLock)
387
388/*!\internal
389 */
390void QMetaObject::addGuard(QObject **ptr)
391{
392 if (!*ptr)
393 return;
394 GuardHash *hash = guardHash();
395 if (!hash) {
396 *ptr = 0;
397 return;
398 }
399 QMutexLocker locker(guardHashLock());
400 QObjectPrivate::get(*ptr)->hasGuards = true;
401 hash->insert(*ptr, ptr);
402}
403
404/*!\internal
405 */
406void QMetaObject::removeGuard(QObject **ptr)
407{
408 if (!*ptr)
409 return;
410 GuardHash *hash = guardHash();
411 /* check that the hash is empty - otherwise we might detach
412 the shared_null hash, which will alloc, which is not nice */
413 if (!hash || hash->isEmpty())
414 return;
415 QMutexLocker locker(guardHashLock());
416 if (!*ptr) //check again, under the lock
417 return;
418 GuardHash::iterator it = hash->find(*ptr);
419 const GuardHash::iterator end = hash->end();
420 bool more = false; //if the QObject has more pointer attached to it.
421 for (; it.key() == *ptr && it != end; ++it) {
422 if (it.value() == ptr) {
423 it = hash->erase(it);
424 if (!more) more = (it != end && it.key() == *ptr);
425 break;
426 }
427 more = true;
428 }
429 if (!more)
430 QObjectPrivate::get(*ptr)->hasGuards = false;
431}
432
433/*!\internal
434 */
435void QMetaObject::changeGuard(QObject **ptr, QObject *o)
436{
437 GuardHash *hash = guardHash();
438 if (!hash) {
439 *ptr = 0;
440 return;
441 }
442 QMutexLocker locker(guardHashLock());
443 if (o) {
444 hash->insert(o, ptr);
445 QObjectPrivate::get(o)->hasGuards = true;
446 }
447 if (*ptr) {
448 bool more = false; //if the QObject has more pointer attached to it.
449 GuardHash::iterator it = hash->find(*ptr);
450 const GuardHash::iterator end = hash->end();
451 for (; it.key() == *ptr && it != end; ++it) {
452 if (it.value() == ptr) {
453 it = hash->erase(it);
454 if (!more) more = (it != end && it.key() == *ptr);
455 break;
456 }
457 more = true;
458 }
459 if (!more)
460 QObjectPrivate::get(*ptr)->hasGuards = false;
461 }
462 *ptr = o;
463}
464
465/*! \internal
466 */
467void QObjectPrivate::clearGuards(QObject *object)
468{
469 GuardHash *hash = 0;
470 QMutex *mutex = 0;
471 QT_TRY {
472 hash = guardHash();
473 mutex = guardHashLock();
474 } QT_CATCH(const std::bad_alloc &) {
475 // do nothing in case of OOM - code below is safe
476 }
477
478 /* check that the hash is empty - otherwise we might detach
479 the shared_null hash, which will alloc, which is not nice */
480 if (hash && !hash->isEmpty()) {
481 QMutexLocker locker(mutex);
482 GuardHash::iterator it = hash->find(object);
483 const GuardHash::iterator end = hash->end();
484 while (it.key() == object && it != end) {
485 *it.value() = 0;
486 it = hash->erase(it);
487 }
488 }
489}
490
491/*! \internal
492 */
493QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
494 const QObject *sender, int signalId,
495 int nargs, int *types, void **args, QSemaphore *semaphore)
496 : QEvent(MetaCall), sender_(sender), signalId_(signalId),
497 nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
498 callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
499{ }
500
501/*! \internal
502 */
503QMetaCallEvent::~QMetaCallEvent()
504{
505 if (types_) {
506 for (int i = 0; i < nargs_; ++i) {
507 if (types_[i] && args_[i])
508 QMetaType::destroy(types_[i], args_[i]);
509 }
510 qFree(types_);
511 qFree(args_);
512 }
513#ifndef QT_NO_THREAD
514 if (semaphore_)
515 semaphore_->release();
516#endif
517}
518
519/*! \internal
520 */
521void QMetaCallEvent::placeMetaCall(QObject *object)
522{
523 if (callFunction_) {
524 callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
525 } else {
526 QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
527 }
528}
529
530/*!
531 \class QObject
532 \brief The QObject class is the base class of all Qt objects.
533
534 \ingroup objectmodel
535
536 \reentrant
537
538 QObject is the heart of the Qt \l{Object Model}. The central
539 feature in this model is a very powerful mechanism for seamless
540 object communication called \l{signals and slots}. You can
541 connect a signal to a slot with connect() and destroy the
542 connection with disconnect(). To avoid never ending notification
543 loops you can temporarily block signals with blockSignals(). The
544 protected functions connectNotify() and disconnectNotify() make
545 it possible to track connections.
546
547 QObjects organize themselves in \l {Object Trees & Ownership}
548 {object trees}. When you create a QObject with another object as
549 parent, the object will automatically add itself to the parent's
550 children() list. The parent takes ownership of the object; i.e.,
551 it will automatically delete its children in its destructor. You
552 can look for an object by name and optionally type using
553 findChild() or findChildren().
554
555 Every object has an objectName() and its class name can be found
556 via the corresponding metaObject() (see QMetaObject::className()).
557 You can determine whether the object's class inherits another
558 class in the QObject inheritance hierarchy by using the
559 inherits() function.
560
561 When an object is deleted, it emits a destroyed() signal. You can
562 catch this signal to avoid dangling references to QObjects.
563
564 QObjects can receive events through event() and filter the events
565 of other objects. See installEventFilter() and eventFilter() for
566 details. A convenience handler, childEvent(), can be reimplemented
567 to catch child events.
568
569 Last but not least, QObject provides the basic timer support in
570 Qt; see QTimer for high-level support for timers.
571
572 Notice that the Q_OBJECT macro is mandatory for any object that
573 implements signals, slots or properties. You also need to run the
574 \l{moc}{Meta Object Compiler} on the source file. We strongly
575 recommend the use of this macro in all subclasses of QObject
576 regardless of whether or not they actually use signals, slots and
577 properties, since failure to do so may lead certain functions to
578 exhibit strange behavior.
579
580 All Qt widgets inherit QObject. The convenience function
581 isWidgetType() returns whether an object is actually a widget. It
582 is much faster than
583 \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
584 \e{obj}->\l{inherits()}{inherits}("QWidget").
585
586 Some QObject functions, e.g. children(), return a QObjectList.
587 QObjectList is a typedef for QList<QObject *>.
588
589 \section1 Thread Affinity
590
591 A QObject instance is said to have a \e{thread affinity}, or that
592 it \e{lives} in a certain thread. When a QObject receives a
593 \l{Qt::QueuedConnection}{queued signal} or a \l{The Event
594 System#Sending Events}{posted event}, the slot or event handler
595 will run in the thread that the object lives in.
596
597 \note If a QObject has no thread affinity (that is, if thread()
598 returns zero), or if it lives in a thread that has no running event
599 loop, then it cannot receive queued signals or posted events.
600
601 By default, a QObject lives in the thread in which it is created.
602 An object's thread affinity can be queried using thread() and
603 changed using moveToThread().
604
605 All QObjects must live in the same thread as their parent. Consequently:
606
607 \list
608 \li setParent() will fail if the two QObjects involved live in
609 different threads.
610 \li When a QObject is moved to another thread, all its children
611 will be automatically moved too.
612 \li moveToThread() will fail if the QObject has a parent.
613 \li If \l{QObject}s are created within QThread::run(), they cannot
614 become children of the QThread object because the QThread does
615 not live in the thread that calls QThread::run().
616 \endlist
617
618 \note A QObject's member variables \e{do not} automatically become
619 its children. The parent-child relationship must be set by either
620 passing a pointer to the child's \l{QObject()}{constructor}, or by
621 calling setParent(). Without this step, the object's member variables
622 will remain in the old thread when moveToThread() is called.
623
624 \target No copy constructor
625 \section1 No copy constructor or assignment operator
626
627 QObject has neither a copy constructor nor an assignment operator.
628 This is by design. Actually, they are declared, but in a
629 \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
630 Qt classes derived from QObject (direct or indirect) use this
631 macro to declare their copy constructor and assignment operator to
632 be private. The reasoning is found in the discussion on
633 \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
634 Model} page.
635
636 The main consequence is that you should use pointers to QObject
637 (or to your QObject subclass) where you might otherwise be tempted
638 to use your QObject subclass as a value. For example, without a
639 copy constructor, you can't use a subclass of QObject as the value
640 to be stored in one of the container classes. You must store
641 pointers.
642
643 \section1 Auto-Connection
644
645 Qt's meta-object system provides a mechanism to automatically connect
646 signals and slots between QObject subclasses and their children. As long
647 as objects are defined with suitable object names, and slots follow a
648 simple naming convention, this connection can be performed at run-time
649 by the QMetaObject::connectSlotsByName() function.
650
651 \l uic generates code that invokes this function to enable
652 auto-connection to be performed between widgets on forms created
653 with \QD. More information about using auto-connection with \QD is
654 given in the \l{Using a Designer UI File in Your Application} section of
655 the \QD manual.
656
657 \section1 Dynamic Properties
658
659 From Qt 4.2, dynamic properties can be added to and removed from QObject
660 instances at run-time. Dynamic properties do not need to be declared at
661 compile-time, yet they provide the same advantages as static properties
662 and are manipulated using the same API - using property() to read them
663 and setProperty() to write them.
664
665 From Qt 4.3, dynamic properties are supported by
666 \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
667 and both standard Qt widgets and user-created forms can be given dynamic
668 properties.
669
670 \section1 Internationalization (i18n)
671
672 All QObject subclasses support Qt's translation features, making it possible
673 to translate an application's user interface into different languages.
674
675 To make user-visible text translatable, it must be wrapped in calls to
676 the tr() function. This is explained in detail in the
677 \l{Writing Source Code for Translation} document.
678
679 \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
680 \sa {Object Trees & Ownership}
681*/
682
683/*!
684 \relates QObject
685
686 Returns a pointer to the object named \a name that inherits \a
687 type and with a given \a parent.
688
689 Returns 0 if there is no such child.
690
691 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 0
692*/
693
694void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
695{
696 QObjectList list = parent->children();
697 if (list.size() == 0) return 0;
698 for (int i = 0; i < list.size(); ++i) {
699 QObject *obj = list.at(i);
700 if (name == obj->objectName() && obj->inherits(type))
701 return obj;
702 }
703 return 0;
704}
705
706
707/*****************************************************************************
708 QObject member functions
709 *****************************************************************************/
710
711// check the constructor's parent thread argument
712static bool check_parent_thread(QObject *parent,
713 QThreadData *parentThreadData,
714 QThreadData *currentThreadData)
715{
716 if (parent && parentThreadData != currentThreadData) {
717 QThread *parentThread = parentThreadData->thread;
718 QThread *currentThread = currentThreadData->thread;
719 qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
720 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
721 parent->metaObject()->className(),
722 parent,
723 parentThread ? parentThread->metaObject()->className() : "QThread",
724 parentThread,
725 currentThread ? currentThread->metaObject()->className() : "QThread",
726 currentThread);
727 return false;
728 }
729 return true;
730}
731
732/*!
733 Constructs an object with parent object \a parent.
734
735 The parent of an object may be viewed as the object's owner. For
736 instance, a \l{QDialog}{dialog box} is the parent of the \gui OK
737 and \gui Cancel buttons it contains.
738
739 The destructor of a parent object destroys all child objects.
740
741 Setting \a parent to 0 constructs an object with no parent. If the
742 object is a widget, it will become a top-level window.
743
744 \sa parent(), findChild(), findChildren()
745*/
746
747QObject::QObject(QObject *parent)
748 : d_ptr(new QObjectPrivate)
749{
750 Q_D(QObject);
751 d_ptr->q_ptr = this;
752 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
753 d->threadData->ref();
754 if (parent) {
755 QT_TRY {
756 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
757 parent = 0;
758 setParent(parent);
759 } QT_CATCH(...) {
760 d->threadData->deref();
761 QT_RETHROW;
762 }
763 }
764 qt_addObject(this);
765}
766
767#ifdef QT3_SUPPORT
768/*!
769 \overload QObject()
770 \obsolete
771
772 Creates a new QObject with the given \a parent and object \a name.
773 */
774QObject::QObject(QObject *parent, const char *name)
775 : d_ptr(new QObjectPrivate)
776{
777 Q_D(QObject);
778 qt_addObject(d_ptr->q_ptr = this);
779 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
780 d->threadData->ref();
781 if (parent) {
782 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
783 parent = 0;
784 setParent(parent);
785 }
786 setObjectName(QString::fromAscii(name));
787}
788#endif
789
790/*! \internal
791 */
792QObject::QObject(QObjectPrivate &dd, QObject *parent)
793 : d_ptr(&dd)
794{
795 Q_D(QObject);
796 d_ptr->q_ptr = this;
797 d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
798 d->threadData->ref();
799 if (parent) {
800 QT_TRY {
801 if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
802 parent = 0;
803 if (d->isWidget) {
804 if (parent) {
805 d->parent = parent;
806 d->parent->d_func()->children.append(this);
807 }
808 // no events sent here, this is done at the end of the QWidget constructor
809 } else {
810 setParent(parent);
811 }
812 } QT_CATCH(...) {
813 d->threadData->deref();
814 QT_RETHROW;
815 }
816 }
817 qt_addObject(this);
818}
819
820/*!
821 Destroys the object, deleting all its child objects.
822
823 All signals to and from the object are automatically disconnected, and
824 any pending posted events for the object are removed from the event
825 queue. However, it is often safer to use deleteLater() rather than
826 deleting a QObject subclass directly.
827
828 \warning All child objects are deleted. If any of these objects
829 are on the stack or global, sooner or later your program will
830 crash. We do not recommend holding pointers to child objects from
831 outside the parent. If you still do, the destroyed() signal gives
832 you an opportunity to detect when an object is destroyed.
833
834 \warning Deleting a QObject while pending events are waiting to
835 be delivered can cause a crash. You must not delete the QObject
836 directly if it exists in a different thread than the one currently
837 executing. Use deleteLater() instead, which will cause the event
838 loop to delete the object after all pending events have been
839 delivered to it.
840
841 \sa deleteLater()
842*/
843
844QObject::~QObject()
845{
846 Q_D(QObject);
847 d->wasDeleted = true;
848 d->blockSig = 0; // unblock signals so we always emit destroyed()
849
850 if (d->hasGuards && !d->isWidget) {
851 // set all QPointers for this object to zero - note that
852 // ~QWidget() does this for us, so we don't have to do it twice
853 QObjectPrivate::clearGuards(this);
854 }
855
856 if (d->sharedRefcount) {
857 if (d->sharedRefcount->strongref > 0) {
858 qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
859 // but continue deleting, it's too late to stop anyway
860 }
861
862 // indicate to all QWeakPointers that this QObject has now been deleted
863 d->sharedRefcount->strongref = 0;
864 if (!d->sharedRefcount->weakref.deref())
865 delete d->sharedRefcount;
866 }
867
868
869 if (d->isSignalConnected(0)) {
870 QT_TRY {
871 emit destroyed(this);
872 } QT_CATCH(...) {
873 // all the signal/slots connections are still in place - if we don't
874 // quit now, we will crash pretty soon.
875 qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
876 QT_RETHROW;
877 }
878 }
879
880 if (d->declarativeData)
881 QAbstractDeclarativeData::destroyed(d->declarativeData, this);
882
883 // set ref to zero to indicate that this object has been deleted
884 if (d->currentSender != 0)
885 d->currentSender->ref = 0;
886 d->currentSender = 0;
887
888 if (d->connectionLists || d->senders) {
889 QMutex *signalSlotMutex = signalSlotLock(this);
890 QMutexLocker locker(signalSlotMutex);
891
892 // disconnect all receivers
893 if (d->connectionLists) {
894 ++d->connectionLists->inUse;
895 int connectionListsCount = d->connectionLists->count();
896 for (int signal = -1; signal < connectionListsCount; ++signal) {
897 QObjectPrivate::ConnectionList &connectionList =
898 (*d->connectionLists)[signal];
899
900 while (QObjectPrivate::Connection *c = connectionList.first) {
901 if (!c->receiver) {
902 connectionList.first = c->nextConnectionList;
903 delete c;
904 continue;
905 }
906
907 QMutex *m = signalSlotLock(c->receiver);
908 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
909
910 if (c->receiver) {
911 *c->prev = c->next;
912 if (c->next) c->next->prev = c->prev;
913 }
914 if (needToUnlock)
915 m->unlockInline();
916
917 connectionList.first = c->nextConnectionList;
918 delete c;
919 }
920 }
921
922 if (!--d->connectionLists->inUse) {
923 delete d->connectionLists;
924 } else {
925 d->connectionLists->orphaned = true;
926 }
927 d->connectionLists = 0;
928 }
929
930 // disconnect all senders
931 QObjectPrivate::Connection *node = d->senders;
932 while (node) {
933 QObject *sender = node->sender;
934 QMutex *m = signalSlotLock(sender);
935 node->prev = &node;
936 bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
937 //the node has maybe been removed while the mutex was unlocked in relock?
938 if (!node || node->sender != sender) {
939 m->unlockInline();
940 continue;
941 }
942 node->receiver = 0;
943 QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
944 if (senderLists)
945 senderLists->dirty = true;
946
947 node = node->next;
948 if (needToUnlock)
949 m->unlockInline();
950 }
951 }
952
953 if (!d->children.isEmpty())
954 d->deleteChildren();
955
956 qt_removeObject(this);
957
958 if (d->parent) // remove it from parent object
959 d->setParent_helper(0);
960
961#ifdef QT_JAMBI_BUILD
962 if (d->inEventHandler) {
963 qWarning("QObject: Do not delete object, '%s', during its event handler!",
964 objectName().isNull() ? "unnamed" : qPrintable(objectName()));
965 }
966#endif
967}
968
969QObjectPrivate::Connection::~Connection()
970{
971 if (argumentTypes != &DIRECT_CONNECTION_ONLY)
972 delete [] static_cast<int *>(argumentTypes);
973}
974
975
976/*!
977 \fn QMetaObject *QObject::metaObject() const
978
979 Returns a pointer to the meta-object of this object.
980
981 A meta-object contains information about a class that inherits
982 QObject, e.g. class name, superclass name, properties, signals and
983 slots. Every QObject subclass that contains the Q_OBJECT macro will have a
984 meta-object.
985
986 The meta-object information is required by the signal/slot
987 connection mechanism and the property system. The inherits()
988 function also makes use of the meta-object.
989
990 If you have no pointer to an actual object instance but still
991 want to access the meta-object of a class, you can use \l
992 staticMetaObject.
993
994 Example:
995
996 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 1
997
998 \sa staticMetaObject
999*/
1000
1001/*!
1002 \variable QObject::staticMetaObject
1003
1004 This variable stores the meta-object for the class.
1005
1006 A meta-object contains information about a class that inherits
1007 QObject, e.g. class name, superclass name, properties, signals and
1008 slots. Every class that contains the Q_OBJECT macro will also have
1009 a meta-object.
1010
1011 The meta-object information is required by the signal/slot
1012 connection mechanism and the property system. The inherits()
1013 function also makes use of the meta-object.
1014
1015 If you have a pointer to an object, you can use metaObject() to
1016 retrieve the meta-object associated with that object.
1017
1018 Example:
1019
1020 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 2
1021
1022 \sa metaObject()
1023*/
1024
1025/*! \fn T *qobject_cast<T *>(QObject *object)
1026 \relates QObject
1027
1028 Returns the given \a object cast to type T if the object is of type
1029 T (or of a subclass); otherwise returns 0. If \a object is 0 then
1030 it will also return 0.
1031
1032 The class T must inherit (directly or indirectly) QObject and be
1033 declared with the \l Q_OBJECT macro.
1034
1035 A class is considered to inherit itself.
1036
1037 Example:
1038
1039 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 3
1040
1041 The qobject_cast() function behaves similarly to the standard C++
1042 \c dynamic_cast(), with the advantages that it doesn't require
1043 RTTI support and it works across dynamic library boundaries.
1044
1045 qobject_cast() can also be used in conjunction with interfaces;
1046 see the \l{tools/plugandpaint}{Plug & Paint} example for details.
1047
1048 \warning If T isn't declared with the Q_OBJECT macro, this
1049 function's return value is undefined.
1050
1051 \sa QObject::inherits()
1052*/
1053
1054/*!
1055 \fn bool QObject::inherits(const char *className) const
1056
1057 Returns true if this object is an instance of a class that
1058 inherits \a className or a QObject subclass that inherits \a
1059 className; otherwise returns false.
1060
1061 A class is considered to inherit itself.
1062
1063 Example:
1064
1065 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4
1066
1067 If you need to determine whether an object is an instance of a particular
1068 class for the purpose of casting it, consider using qobject_cast<Type *>(object)
1069 instead.
1070
1071 \sa metaObject(), qobject_cast()
1072*/
1073
1074/*!
1075 \property QObject::objectName
1076
1077 \brief the name of this object
1078
1079 You can find an object by name (and type) using findChild(). You can
1080 find a set of objects with findChildren().
1081
1082 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 5
1083
1084 By default, this property contains an empty string.
1085
1086 \sa metaObject(), QMetaObject::className()
1087*/
1088
1089QString QObject::objectName() const
1090{
1091 Q_D(const QObject);
1092 return d->objectName;
1093}
1094
1095/*
1096 Sets the object's name to \a name.
1097*/
1098void QObject::setObjectName(const QString &name)
1099{
1100 Q_D(QObject);
1101 bool objectNameChanged = d->declarativeData && d->objectName != name;
1102
1103 d->objectName = name;
1104
1105 if (objectNameChanged)
1106 d->declarativeData->objectNameChanged(d->declarativeData, this);
1107}
1108
1109
1110#ifdef QT3_SUPPORT
1111/*! \internal
1112 QObject::child is compat but needs to call itself recursively,
1113 that's why we need this helper.
1114*/
1115static QObject *qChildHelper(const char *objName, const char *inheritsClass,
1116 bool recursiveSearch, const QObjectList &children)
1117{
1118 if (children.isEmpty())
1119 return 0;
1120
1121 bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
1122 const QLatin1String oName(objName);
1123 for (int i = 0; i < children.size(); ++i) {
1124 QObject *obj = children.at(i);
1125 if (onlyWidgets) {
1126 if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
1127 return obj;
1128 } else if ((!inheritsClass || obj->inherits(inheritsClass))
1129 && (!objName || obj->objectName() == oName))
1130 return obj;
1131 if (recursiveSearch && (obj = qChildHelper(objName, inheritsClass,
1132 recursiveSearch, obj->children())))
1133 return obj;
1134 }
1135 return 0;
1136}
1137
1138
1139/*!
1140 Searches the children and optionally grandchildren of this object,
1141 and returns a child that is called \a objName that inherits \a
1142 inheritsClass. If \a inheritsClass is 0 (the default), any class
1143 matches.
1144
1145 If \a recursiveSearch is true (the default), child() performs a
1146 depth-first search of the object's children.
1147
1148 If there is no such object, this function returns 0. If there are
1149 more than one, the first one found is returned.
1150*/
1151QObject* QObject::child(const char *objName, const char *inheritsClass,
1152 bool recursiveSearch) const
1153{
1154 Q_D(const QObject);
1155 return qChildHelper(objName, inheritsClass, recursiveSearch, d->children);
1156}
1157#endif
1158
1159/*!
1160 \fn bool QObject::isWidgetType() const
1161
1162 Returns true if the object is a widget; otherwise returns false.
1163
1164 Calling this function is equivalent to calling
1165 inherits("QWidget"), except that it is much faster.
1166*/
1167
1168
1169/*!
1170 This virtual function receives events to an object and should
1171 return true if the event \a e was recognized and processed.
1172
1173 The event() function can be reimplemented to customize the
1174 behavior of an object.
1175
1176 \sa installEventFilter(), timerEvent(), QApplication::sendEvent(),
1177 QApplication::postEvent(), QWidget::event()
1178*/
1179
1180bool QObject::event(QEvent *e)
1181{
1182 switch (e->type()) {
1183 case QEvent::Timer:
1184 timerEvent((QTimerEvent*)e);
1185 break;
1186
1187#ifdef QT3_SUPPORT
1188 case QEvent::ChildInsertedRequest:
1189 d_func()->sendPendingChildInsertedEvents();
1190 break;
1191#endif
1192
1193 case QEvent::ChildAdded:
1194 case QEvent::ChildPolished:
1195#ifdef QT3_SUPPORT
1196 case QEvent::ChildInserted:
1197#endif
1198 case QEvent::ChildRemoved:
1199 childEvent((QChildEvent*)e);
1200 break;
1201
1202 case QEvent::DeferredDelete:
1203 qDeleteInEventHandler(this);
1204 break;
1205
1206 case QEvent::MetaCall:
1207 {
1208#ifdef QT_JAMBI_BUILD
1209 d_func()->inEventHandler = false;
1210#endif
1211 QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
1212 QObjectPrivate::Sender currentSender;
1213 currentSender.sender = const_cast<QObject*>(mce->sender());
1214 currentSender.signal = mce->signalId();
1215 currentSender.ref = 1;
1216 QObjectPrivate::Sender * const previousSender =
1217 QObjectPrivate::setCurrentSender(this, &currentSender);
1218#if defined(QT_NO_EXCEPTIONS)
1219 mce->placeMetaCall(this);
1220#else
1221 QT_TRY {
1222 mce->placeMetaCall(this);
1223 } QT_CATCH(...) {
1224 QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
1225 QT_RETHROW;
1226 }
1227#endif
1228 QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
1229 break;
1230 }
1231
1232 case QEvent::ThreadChange: {
1233 Q_D(QObject);
1234 QThreadData *threadData = d->threadData;
1235 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1236 if (eventDispatcher) {
1237 QList<QPair<int, int> > timers = eventDispatcher->registeredTimers(this);
1238 if (!timers.isEmpty()) {
1239 // set inThreadChangeEvent to true to tell the dispatcher not to release out timer ids
1240 // back to the pool (since the timer ids are moving to a new thread).
1241 d->inThreadChangeEvent = true;
1242 eventDispatcher->unregisterTimers(this);
1243 d->inThreadChangeEvent = false;
1244 QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
1245 Q_ARG(void*, (new QList<QPair<int, int> >(timers))));
1246 }
1247 }
1248 break;
1249 }
1250
1251 default:
1252 if (e->type() >= QEvent::User) {
1253 customEvent(e);
1254 break;
1255 }
1256 return false;
1257 }
1258 return true;
1259}
1260
1261/*!
1262 \fn void QObject::timerEvent(QTimerEvent *event)
1263
1264 This event handler can be reimplemented in a subclass to receive
1265 timer events for the object.
1266
1267 QTimer provides a higher-level interface to the timer
1268 functionality, and also more general information about timers. The
1269 timer event is passed in the \a event parameter.
1270
1271 \sa startTimer(), killTimer(), event()
1272*/
1273
1274void QObject::timerEvent(QTimerEvent *)
1275{
1276}
1277
1278
1279/*!
1280 This event handler can be reimplemented in a subclass to receive
1281 child events. The event is passed in the \a event parameter.
1282
1283 QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
1284 objects when children are added or removed. In both cases you can
1285 only rely on the child being a QObject, or if isWidgetType()
1286 returns true, a QWidget. (This is because, in the
1287 \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
1288 fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
1289 case it might have been destructed already).
1290
1291 QEvent::ChildPolished events are sent to widgets when children
1292 are polished, or when polished children are added. If you receive
1293 a child polished event, the child's construction is usually
1294 completed. However, this is not guaranteed, and multiple polish
1295 events may be delivered during the execution of a widget's
1296 constructor.
1297
1298 For every child widget, you receive one
1299 \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
1300 \l{QEvent::ChildPolished}{ChildPolished} events, and one
1301 \l{QEvent::ChildRemoved}{ChildRemoved} event.
1302
1303 The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
1304 a child is removed immediately after it is added. If a child is
1305 polished several times during construction and destruction, you
1306 may receive several child polished events for the same child,
1307 each time with a different virtual table.
1308
1309 \sa event()
1310*/
1311
1312void QObject::childEvent(QChildEvent * /* event */)
1313{
1314}
1315
1316
1317/*!
1318 This event handler can be reimplemented in a subclass to receive
1319 custom events. Custom events are user-defined events with a type
1320 value at least as large as the QEvent::User item of the
1321 QEvent::Type enum, and is typically a QEvent subclass. The event
1322 is passed in the \a event parameter.
1323
1324 \sa event(), QEvent
1325*/
1326void QObject::customEvent(QEvent * /* event */)
1327{
1328}
1329
1330
1331
1332/*!
1333 Filters events if this object has been installed as an event
1334 filter for the \a watched object.
1335
1336 In your reimplementation of this function, if you want to filter
1337 the \a event out, i.e. stop it being handled further, return
1338 true; otherwise return false.
1339
1340 Example:
1341 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 6
1342
1343 Notice in the example above that unhandled events are passed to
1344 the base class's eventFilter() function, since the base class
1345 might have reimplemented eventFilter() for its own internal
1346 purposes.
1347
1348 \warning If you delete the receiver object in this function, be
1349 sure to return true. Otherwise, Qt will forward the event to the
1350 deleted object and the program might crash.
1351
1352 \sa installEventFilter()
1353*/
1354
1355bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
1356{
1357 return false;
1358}
1359
1360/*!
1361 \fn bool QObject::signalsBlocked() const
1362
1363 Returns true if signals are blocked; otherwise returns false.
1364
1365 Signals are not blocked by default.
1366
1367 \sa blockSignals()
1368*/
1369
1370/*!
1371 If \a block is true, signals emitted by this object are blocked
1372 (i.e., emitting a signal will not invoke anything connected to it).
1373 If \a block is false, no such blocking will occur.
1374
1375 The return value is the previous value of signalsBlocked().
1376
1377 Note that the destroyed() signal will be emitted even if the signals
1378 for this object have been blocked.
1379
1380 \sa signalsBlocked()
1381*/
1382
1383bool QObject::blockSignals(bool block)
1384{
1385 Q_D(QObject);
1386 bool previous = d->blockSig;
1387 d->blockSig = block;
1388 return previous;
1389}
1390
1391/*!
1392 Returns the thread in which the object lives.
1393
1394 \sa moveToThread()
1395*/
1396QThread *QObject::thread() const
1397{
1398 return d_func()->threadData->thread;
1399}
1400
1401/*!
1402 Changes the thread affinity for this object and its children. The
1403 object cannot be moved if it has a parent. Event processing will
1404 continue in the \a targetThread.
1405
1406 To move an object to the main thread, use QApplication::instance()
1407 to retrieve a pointer to the current application, and then use
1408 QApplication::thread() to retrieve the thread in which the
1409 application lives. For example:
1410
1411 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 7
1412
1413 If \a targetThread is zero, all event processing for this object
1414 and its children stops.
1415
1416 Note that all active timers for the object will be reset. The
1417 timers are first stopped in the current thread and restarted (with
1418 the same interval) in the \a targetThread. As a result, constantly
1419 moving an object between threads can postpone timer events
1420 indefinitely.
1421
1422 A QEvent::ThreadChange event is sent to this object just before
1423 the thread affinity is changed. You can handle this event to
1424 perform any special processing. Note that any new events that are
1425 posted to this object will be handled in the \a targetThread.
1426
1427 \warning This function is \e not thread-safe; the current thread
1428 must be same as the current thread affinity. In other words, this
1429 function can only "push" an object from the current thread to
1430 another thread, it cannot "pull" an object from any arbitrary
1431 thread to the current thread.
1432
1433 \sa thread()
1434 */
1435void QObject::moveToThread(QThread *targetThread)
1436{
1437 Q_D(QObject);
1438
1439 if (d->threadData->thread == targetThread) {
1440 // object is already in this thread
1441 return;
1442 }
1443
1444 if (d->parent != 0) {
1445 qWarning("QObject::moveToThread: Cannot move objects with a parent");
1446 return;
1447 }
1448 if (d->isWidget) {
1449 qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
1450 return;
1451 }
1452
1453 QThreadData *currentData = QThreadData::current();
1454 QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);
1455 if (d->threadData->thread == 0 && currentData == targetData) {
1456 // one exception to the rule: we allow moving objects with no thread affinity to the current thread
1457 currentData = d->threadData;
1458 } else if (d->threadData != currentData) {
1459 qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
1460 "Cannot move to target thread (%p)\n",
1461 currentData->thread, d->threadData->thread, targetData->thread);
1462
1463#ifdef Q_WS_MAC
1464 qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
1465 "Check that all plugins are compiled against the right Qt binaries. Export "
1466 "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
1467#endif
1468
1469 return;
1470 }
1471
1472 // prepare to move
1473 d->moveToThread_helper();
1474
1475 QOrderedMutexLocker locker(&currentData->postEventList.mutex,
1476 &targetData->postEventList.mutex);
1477
1478 // keep currentData alive (since we've got it locked)
1479 currentData->ref();
1480
1481 // move the object
1482 d_func()->setThreadData_helper(currentData, targetData);
1483
1484 locker.unlock();
1485
1486 // now currentData can commit suicide if it wants to
1487 currentData->deref();
1488}
1489
1490void QObjectPrivate::moveToThread_helper()
1491{
1492 Q_Q(QObject);
1493 QEvent e(QEvent::ThreadChange);
1494 QCoreApplication::sendEvent(q, &e);
1495 for (int i = 0; i < children.size(); ++i) {
1496 QObject *child = children.at(i);
1497 child->d_func()->moveToThread_helper();
1498 }
1499}
1500
1501void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
1502{
1503 Q_Q(QObject);
1504
1505 // move posted events
1506 int eventsMoved = 0;
1507 for (int i = 0; i < currentData->postEventList.size(); ++i) {
1508 const QPostEvent &pe = currentData->postEventList.at(i);
1509 if (!pe.event)
1510 continue;
1511 if (pe.receiver == q) {
1512 // move this post event to the targetList
1513 targetData->postEventList.addEvent(pe);
1514 const_cast<QPostEvent &>(pe).event = 0;
1515 ++eventsMoved;
1516 }
1517 }
1518 if (eventsMoved > 0 && targetData->eventDispatcher) {
1519 targetData->canWait = false;
1520 targetData->eventDispatcher->wakeUp();
1521 }
1522
1523 // the current emitting thread shouldn't restore currentSender after calling moveToThread()
1524 if (currentSender)
1525 currentSender->ref = 0;
1526 currentSender = 0;
1527
1528#ifdef QT_JAMBI_BUILD
1529 // the current event thread also shouldn't restore the delete watch
1530 inEventHandler = false;
1531
1532 if (deleteWatch)
1533 *deleteWatch = 1;
1534 deleteWatch = 0;
1535#endif
1536
1537 // set new thread data
1538 targetData->ref();
1539 threadData->deref();
1540 threadData = targetData;
1541
1542 for (int i = 0; i < children.size(); ++i) {
1543 QObject *child = children.at(i);
1544 child->d_func()->setThreadData_helper(currentData, targetData);
1545 }
1546}
1547
1548void QObjectPrivate::_q_reregisterTimers(void *pointer)
1549{
1550 Q_Q(QObject);
1551 QList<QPair<int, int> > *timerList = reinterpret_cast<QList<QPair<int, int> > *>(pointer);
1552 QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
1553 for (int i = 0; i < timerList->size(); ++i) {
1554 const QPair<int, int> &pair = timerList->at(i);
1555 eventDispatcher->registerTimer(pair.first, pair.second, q);
1556 }
1557 delete timerList;
1558}
1559
1560
1561//
1562// The timer flag hasTimer is set when startTimer is called.
1563// It is not reset when killing the timer because more than
1564// one timer might be active.
1565//
1566
1567/*!
1568 Starts a timer and returns a timer identifier, or returns zero if
1569 it could not start a timer.
1570
1571 A timer event will occur every \a interval milliseconds until
1572 killTimer() is called. If \a interval is 0, then the timer event
1573 occurs once every time there are no more window system events to
1574 process.
1575
1576 The virtual timerEvent() function is called with the QTimerEvent
1577 event parameter class when a timer event occurs. Reimplement this
1578 function to get timer events.
1579
1580 If multiple timers are running, the QTimerEvent::timerId() can be
1581 used to find out which timer was activated.
1582
1583 Example:
1584
1585 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 8
1586
1587 Note that QTimer's accuracy depends on the underlying operating
1588 system and hardware. Most platforms support an accuracy of 20
1589 milliseconds; some provide more. If Qt is unable to deliver the
1590 requested number of timer events, it will silently discard some.
1591
1592 The QTimer class provides a high-level programming interface with
1593 single-shot timers and timer signals instead of events. There is
1594 also a QBasicTimer class that is more lightweight than QTimer and
1595 less clumsy than using timer IDs directly.
1596
1597 \sa timerEvent(), killTimer(), QTimer::singleShot()
1598*/
1599
1600int QObject::startTimer(int interval)
1601{
1602 Q_D(QObject);
1603
1604 if (interval < 0) {
1605 qWarning("QObject::startTimer: QTimer cannot have a negative interval");
1606 return 0;
1607 }
1608
1609 d->pendTimer = true; // set timer flag
1610
1611 if (!d->threadData->eventDispatcher) {
1612 qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
1613 return 0;
1614 }
1615 return d->threadData->eventDispatcher->registerTimer(interval, this);
1616}
1617
1618/*!
1619 Kills the timer with timer identifier, \a id.
1620
1621 The timer identifier is returned by startTimer() when a timer
1622 event is started.
1623
1624 \sa timerEvent(), startTimer()
1625*/
1626
1627void QObject::killTimer(int id)
1628{
1629 Q_D(QObject);
1630 if (d->threadData->eventDispatcher)
1631 d->threadData->eventDispatcher->unregisterTimer(id);
1632}
1633
1634
1635/*!
1636 \fn QObject *QObject::parent() const
1637
1638 Returns a pointer to the parent object.
1639
1640 \sa children()
1641*/
1642
1643/*!
1644 \fn const QObjectList &QObject::children() const
1645
1646 Returns a list of child objects.
1647 The QObjectList class is defined in the \c{<QObject>} header
1648 file as the following:
1649
1650 \quotefromfile src/corelib/kernel/qobject.h
1651 \skipto /typedef .*QObjectList/
1652 \printuntil QObjectList
1653
1654 The first child added is the \l{QList::first()}{first} object in
1655 the list and the last child added is the \l{QList::last()}{last}
1656 object in the list, i.e. new children are appended at the end.
1657
1658 Note that the list order changes when QWidget children are
1659 \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
1660 widget that is raised becomes the last object in the list, and a
1661 widget that is lowered becomes the first object in the list.
1662
1663 \sa findChild(), findChildren(), parent(), setParent()
1664*/
1665
1666#ifdef QT3_SUPPORT
1667static void objSearch(QObjectList &result,
1668 const QObjectList &list,
1669 const char *inheritsClass,
1670 bool onlyWidgets,
1671 const char *objName,
1672 QRegExp *rx,
1673 bool recurse)
1674{
1675 for (int i = 0; i < list.size(); ++i) {
1676 QObject *obj = list.at(i);
1677 if (!obj)
1678 continue;
1679 bool ok = true;
1680 if (onlyWidgets)
1681 ok = obj->isWidgetType();
1682 else if (inheritsClass && !obj->inherits(inheritsClass))
1683 ok = false;
1684 if (ok) {
1685 if (objName)
1686 ok = (obj->objectName() == QLatin1String(objName));
1687#ifndef QT_NO_REGEXP
1688 else if (rx)
1689 ok = (rx->indexIn(obj->objectName()) != -1);
1690#endif
1691 }
1692 if (ok) // match!
1693 result.append(obj);
1694 if (recurse) {
1695 QObjectList clist = obj->children();
1696 if (!clist.isEmpty())
1697 objSearch(result, clist, inheritsClass,
1698 onlyWidgets, objName, rx, recurse);
1699 }
1700 }
1701}
1702
1703/*!
1704 \internal
1705
1706 Searches the children and optionally grandchildren of this object,
1707 and returns a list of those objects that are named or that match
1708 \a objName and inherit \a inheritsClass. If \a inheritsClass is 0
1709 (the default), all classes match. If \a objName is 0 (the
1710 default), all object names match.
1711
1712 If \a regexpMatch is true (the default), \a objName is a regular
1713 expression that the objects's names must match. The syntax is that
1714 of a QRegExp. If \a regexpMatch is false, \a objName is a string
1715 and object names must match it exactly.
1716
1717 Note that \a inheritsClass uses single inheritance from QObject,
1718 the way inherits() does. According to inherits(), QWidget
1719 inherits QObject but not QPaintDevice. This does not quite match
1720 reality, but is the best that can be done on the wide variety of
1721 compilers Qt supports.
1722
1723 Finally, if \a recursiveSearch is true (the default), queryList()
1724 searches \e{n}th-generation as well as first-generation children.
1725
1726 If all this seems a bit complex for your needs, the simpler
1727 child() function may be what you want.
1728
1729 This somewhat contrived example disables all the buttons in this
1730 window:
1731
1732 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 9
1733
1734 \warning Delete the list as soon you have finished using it. The
1735 list contains pointers that may become invalid at almost any time
1736 without notice (as soon as the user closes a window you may have
1737 dangling pointers, for example).
1738
1739 \sa child() children(), parent(), inherits(), objectName(), QRegExp
1740*/
1741
1742QObjectList QObject::queryList(const char *inheritsClass,
1743 const char *objName,
1744 bool regexpMatch,
1745 bool recursiveSearch) const
1746{
1747 Q_D(const QObject);
1748 QObjectList list;
1749 bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
1750#ifndef QT_NO_REGEXP
1751 if (regexpMatch && objName) { // regexp matching
1752 QRegExp rx(QString::fromLatin1(objName));
1753 objSearch(list, d->children, inheritsClass, onlyWidgets, 0, &rx, recursiveSearch);
1754 } else
1755#endif
1756 {
1757 objSearch(list, d->children, inheritsClass, onlyWidgets, objName, 0, recursiveSearch);
1758 }
1759 return list;
1760}
1761#endif
1762
1763/*!
1764 \fn T *QObject::findChild(const QString &name) const
1765
1766 Returns the child of this object that can be cast into type T and
1767 that is called \a name, or 0 if there is no such object.
1768 Omitting the \a name argument causes all object names to be matched.
1769 The search is performed recursively.
1770
1771 If there is more than one child matching the search, the most
1772 direct ancestor is returned. If there are several direct
1773 ancestors, it is undefined which one will be returned. In that
1774 case, findChildren() should be used.
1775
1776 This example returns a child \l{QPushButton} of \c{parentWidget}
1777 named \c{"button1"}:
1778
1779 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 10
1780
1781 This example returns a \l{QListWidget} child of \c{parentWidget}:
1782
1783 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11
1784
1785 \sa findChildren()
1786*/
1787
1788/*!
1789 \fn QList<T> QObject::findChildren(const QString &name) const
1790
1791 Returns all children of this object with the given \a name that can be
1792 cast to type T, or an empty list if there are no such objects.
1793 Omitting the \a name argument causes all object names to be matched.
1794 The search is performed recursively.
1795
1796 The following example shows how to find a list of child \l{QWidget}s of
1797 the specified \c{parentWidget} named \c{widgetname}:
1798
1799 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 12
1800
1801 This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
1802
1803 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13
1804
1805 \sa findChild()
1806*/
1807
1808/*!
1809 \fn QList<T> QObject::findChildren(const QRegExp &regExp) const
1810 \overload findChildren()
1811
1812 Returns the children of this object that can be cast to type T
1813 and that have names matching the regular expression \a regExp,
1814 or an empty list if there are no such objects.
1815 The search is performed recursively.
1816*/
1817
1818/*!
1819 \fn T qFindChild(const QObject *obj, const QString &name)
1820 \relates QObject
1821 \overload qFindChildren()
1822 \obsolete
1823
1824 This function is equivalent to
1825 \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
1826
1827 \note This function was provided as a workaround for MSVC 6
1828 which did not support member template functions. It is advised
1829 to use the other form in new code.
1830
1831 \sa QObject::findChild()
1832*/
1833
1834/*!
1835 \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
1836 \relates QObject
1837 \overload qFindChildren()
1838 \obsolete
1839
1840 This function is equivalent to
1841 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
1842
1843 \note This function was provided as a workaround for MSVC 6
1844 which did not support member template functions. It is advised
1845 to use the other form in new code.
1846
1847 \sa QObject::findChildren()
1848*/
1849
1850/*!
1851 \fn QList<T> qFindChildren(const QObject *obj, const QRegExp &regExp)
1852 \relates QObject
1853 \overload qFindChildren()
1854
1855 This function is equivalent to
1856 \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
1857
1858 \note This function was provided as a workaround for MSVC 6
1859 which did not support member template functions. It is advised
1860 to use the other form in new code.
1861
1862 \sa QObject::findChildren()
1863*/
1864
1865/*!
1866 \internal
1867*/
1868void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
1869 const QMetaObject &mo, QList<void*> *list)
1870{
1871 if (!parent || !list)
1872 return;
1873 const QObjectList &children = parent->children();
1874 QObject *obj;
1875 for (int i = 0; i < children.size(); ++i) {
1876 obj = children.at(i);
1877 if (mo.cast(obj)) {
1878 if (re) {
1879 if (re->indexIn(obj->objectName()) != -1)
1880 list->append(obj);
1881 } else {
1882 if (name.isNull() || obj->objectName() == name)
1883 list->append(obj);
1884 }
1885 }
1886 qt_qFindChildren_helper(obj, name, re, mo, list);
1887 }
1888}
1889
1890/*! \internal
1891 */
1892QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo)
1893{
1894 if (!parent)
1895 return 0;
1896 const QObjectList &children = parent->children();
1897 QObject *obj;
1898 int i;
1899 for (i = 0; i < children.size(); ++i) {
1900 obj = children.at(i);
1901 if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
1902 return obj;
1903 }
1904 for (i = 0; i < children.size(); ++i) {
1905 obj = qt_qFindChild_helper(children.at(i), name, mo);
1906 if (obj)
1907 return obj;
1908 }
1909 return 0;
1910}
1911
1912/*!
1913 Makes the object a child of \a parent.
1914
1915 \sa QWidget::setParent()
1916*/
1917
1918void QObject::setParent(QObject *parent)
1919{
1920 Q_D(QObject);
1921 Q_ASSERT(!d->isWidget);
1922 d->setParent_helper(parent);
1923}
1924
1925void QObjectPrivate::deleteChildren()
1926{
1927 const bool reallyWasDeleted = wasDeleted;
1928 wasDeleted = true;
1929 // delete children objects
1930 // don't use qDeleteAll as the destructor of the child might
1931 // delete siblings
1932 for (int i = 0; i < children.count(); ++i) {
1933 currentChildBeingDeleted = children.at(i);
1934 children[i] = 0;
1935 delete currentChildBeingDeleted;
1936 }
1937 children.clear();
1938 currentChildBeingDeleted = 0;
1939 wasDeleted = reallyWasDeleted;
1940}
1941
1942void QObjectPrivate::setParent_helper(QObject *o)
1943{
1944 Q_Q(QObject);
1945 if (o == parent)
1946 return;
1947 if (parent) {
1948 QObjectPrivate *parentD = parent->d_func();
1949 if (parentD->wasDeleted && wasDeleted
1950 && parentD->currentChildBeingDeleted == q) {
1951 // don't do anything since QObjectPrivate::deleteChildren() already
1952 // cleared our entry in parentD->children.
1953 } else {
1954 const int index = parentD->children.indexOf(q);
1955 if (parentD->wasDeleted) {
1956 parentD->children[index] = 0;
1957 } else {
1958 parentD->children.removeAt(index);
1959 if (sendChildEvents && parentD->receiveChildEvents) {
1960 QChildEvent e(QEvent::ChildRemoved, q);
1961 QCoreApplication::sendEvent(parent, &e);
1962 }
1963 }
1964 }
1965 }
1966 parent = o;
1967 if (parent) {
1968 // object hierarchies are constrained to a single thread
1969 if (threadData != parent->d_func()->threadData) {
1970 qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
1971 parent = 0;
1972 return;
1973 }
1974 parent->d_func()->children.append(q);
1975 if(sendChildEvents && parent->d_func()->receiveChildEvents) {
1976 if (!isWidget) {
1977 QChildEvent e(QEvent::ChildAdded, q);
1978 QCoreApplication::sendEvent(parent, &e);
1979#ifdef QT3_SUPPORT
1980 if (QCoreApplicationPrivate::useQt3Support) {
1981 if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
1982 QCoreApplication::postEvent(parent,
1983 new QEvent(QEvent::ChildInsertedRequest),
1984 Qt::HighEventPriority);
1985 }
1986 parent->d_func()->pendingChildInsertedEvents.append(q);
1987 }
1988#endif
1989 }
1990 }
1991 }
1992 if (!wasDeleted && declarativeData)
1993 QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
1994}
1995
1996/*!
1997 \fn void QObject::installEventFilter(QObject *filterObj)
1998
1999 Installs an event filter \a filterObj on this object. For example:
2000 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 14
2001
2002 An event filter is an object that receives all events that are
2003 sent to this object. The filter can either stop the event or
2004 forward it to this object. The event filter \a filterObj receives
2005 events via its eventFilter() function. The eventFilter() function
2006 must return true if the event should be filtered, (i.e. stopped);
2007 otherwise it must return false.
2008
2009 If multiple event filters are installed on a single object, the
2010 filter that was installed last is activated first.
2011
2012 Here's a \c KeyPressEater class that eats the key presses of its
2013 monitored objects:
2014
2015 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 15
2016
2017 And here's how to install it on two widgets:
2018
2019 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 16
2020
2021 The QShortcut class, for example, uses this technique to intercept
2022 shortcut key presses.
2023
2024 \warning If you delete the receiver object in your eventFilter()
2025 function, be sure to return true. If you return false, Qt sends
2026 the event to the deleted object and the program will crash.
2027
2028 Note that the filtering object must be in the same thread as this
2029 object. If \a filterObj is in a different thread, this function does
2030 nothing. If either \a filterObj or this object are moved to a different
2031 thread after calling this function, the event filter will not be
2032 called until both objects have the same thread affinity again (it
2033 is \e not removed).
2034
2035 \sa removeEventFilter(), eventFilter(), event()
2036*/
2037
2038void QObject::installEventFilter(QObject *obj)
2039{
2040 Q_D(QObject);
2041 if (!obj)
2042 return;
2043 if (d->threadData != obj->d_func()->threadData) {
2044 qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2045 return;
2046 }
2047
2048 // clean up unused items in the list
2049 d->eventFilters.removeAll((QObject*)0);
2050 d->eventFilters.removeAll(obj);
2051 d->eventFilters.prepend(obj);
2052}
2053
2054/*!
2055 Removes an event filter object \a obj from this object. The
2056 request is ignored if such an event filter has not been installed.
2057
2058 All event filters for this object are automatically removed when
2059 this object is destroyed.
2060
2061 It is always safe to remove an event filter, even during event
2062 filter activation (i.e. from the eventFilter() function).
2063
2064 \sa installEventFilter(), eventFilter(), event()
2065*/
2066
2067void QObject::removeEventFilter(QObject *obj)
2068{
2069 Q_D(QObject);
2070 for (int i = 0; i < d->eventFilters.count(); ++i) {
2071 if (d->eventFilters.at(i) == obj)
2072 d->eventFilters[i] = 0;
2073 }
2074}
2075
2076
2077/*!
2078 \fn QObject::destroyed(QObject *obj)
2079
2080 This signal is emitted immediately before the object \a obj is
2081 destroyed, and can not be blocked.
2082
2083 All the objects's children are destroyed immediately after this
2084 signal is emitted.
2085
2086 \sa deleteLater(), QPointer
2087*/
2088
2089/*!
2090 Schedules this object for deletion.
2091
2092 The object will be deleted when control returns to the event
2093 loop. If the event loop is not running when this function is
2094 called (e.g. deleteLater() is called on an object before
2095 QCoreApplication::exec()), the object will be deleted once the
2096 event loop is started. If deleteLater() is called after the main event loop
2097 has stopped, the object will not be deleted.
2098 Since Qt 4.8, if deleteLater() is called on an object that lives in a
2099 thread with no running event loop, the object will be destroyed when the
2100 thread finishes.
2101
2102 Note that entering and leaving a new event loop (e.g., by opening a modal
2103 dialog) will \e not perform the deferred deletion; for the object to be
2104 deleted, the control must return to the event loop from which
2105 deleteLater() was called.
2106
2107 \bold{Note:} It is safe to call this function more than once; when the
2108 first deferred deletion event is delivered, any pending events for the
2109 object are removed from the event queue.
2110
2111 \sa destroyed(), QPointer
2112*/
2113void QObject::deleteLater()
2114{
2115 QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
2116}
2117
2118/*!
2119 \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
2120 \reentrant
2121
2122 Returns a translated version of \a sourceText, optionally based on a
2123 \a disambiguation string and value of \a n for strings containing plurals;
2124 otherwise returns \a sourceText itself if no appropriate translated string
2125 is available.
2126
2127 Example:
2128 \snippet mainwindows/sdi/mainwindow.cpp implicit tr context
2129 \dots
2130
2131 If the same \a sourceText is used in different roles within the
2132 same context, an additional identifying string may be passed in
2133 \a disambiguation (0 by default). In Qt 4.4 and earlier, this was
2134 the preferred way to pass comments to translators.
2135
2136 Example:
2137
2138 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17
2139 \dots
2140
2141 See \l{Writing Source Code for Translation} for a detailed description of
2142 Qt's translation mechanisms in general, and the
2143 \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
2144 section for information on disambiguation.
2145
2146 \warning This method is reentrant only if all translators are
2147 installed \e before calling this method. Installing or removing
2148 translators while performing translations is not supported. Doing
2149 so will probably result in crashes or other undesirable behavior.
2150
2151 \sa trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt}
2152*/
2153
2154/*!
2155 \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
2156 \reentrant
2157
2158 Returns a translated version of \a sourceText, or
2159 QString::fromUtf8(\a sourceText) if there is no appropriate
2160 version. It is otherwise identical to tr(\a sourceText, \a
2161 disambiguation, \a n).
2162
2163 Note that using the Utf8 variants of the translation functions
2164 is not required if \c CODECFORTR is already set to UTF-8 in the
2165 qmake project file and QTextCodec::setCodecForTr("UTF-8") is
2166 used.
2167
2168 \warning This method is reentrant only if all translators are
2169 installed \e before calling this method. Installing or removing
2170 translators while performing translations is not supported. Doing
2171 so will probably result in crashes or other undesirable behavior.
2172
2173 \warning For portability reasons, we recommend that you use
2174 escape sequences for specifying non-ASCII characters in string
2175 literals to trUtf8(). For example:
2176
2177 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 20
2178
2179 \sa tr(), QApplication::translate(), {Internationalization with Qt}
2180*/
2181
2182
2183
2184
2185/*****************************************************************************
2186 Signals and slots
2187 *****************************************************************************/
2188
2189
2190const char *qFlagLocation(const char *method)
2191{
2192 QThreadData::current()->flaggedSignatures.store(method);
2193 return method;
2194}
2195
2196static int extract_code(const char *member)
2197{
2198 // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
2199 return (((int)(*member) - '0') & 0x3);
2200}
2201
2202static const char * extract_location(const char *member)
2203{
2204 if (QThreadData::current()->flaggedSignatures.contains(member)) {
2205 // signature includes location information after the first null-terminator
2206 const char *location = member + qstrlen(member) + 1;
2207 if (*location != '\0')
2208 return location;
2209 }
2210 return 0;
2211}
2212
2213static bool check_signal_macro(const QObject *sender, const char *signal,
2214 const char *func, const char *op)
2215{
2216 int sigcode = extract_code(signal);
2217 if (sigcode != QSIGNAL_CODE) {
2218 if (sigcode == QSLOT_CODE)
2219 qWarning("Object::%s: Attempt to %s non-signal %s::%s",
2220 func, op, sender->metaObject()->className(), signal+1);
2221 else
2222 qWarning("Object::%s: Use the SIGNAL macro to %s %s::%s",
2223 func, op, sender->metaObject()->className(), signal);
2224 return false;
2225 }
2226 return true;
2227}
2228
2229static bool check_method_code(int code, const QObject *object,
2230 const char *method, const char *func)
2231{
2232 if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
2233 qWarning("Object::%s: Use the SLOT or SIGNAL macro to "
2234 "%s %s::%s", func, func, object->metaObject()->className(), method);
2235 return false;
2236 }
2237 return true;
2238}
2239
2240static void err_method_notfound(const QObject *object,
2241 const char *method, const char *func)
2242{
2243 const char *type = "method";
2244 switch (extract_code(method)) {
2245 case QSLOT_CODE: type = "slot"; break;
2246 case QSIGNAL_CODE: type = "signal"; break;
2247 }
2248 const char *loc = extract_location(method);
2249 if (strchr(method,')') == 0) // common typing mistake
2250 qWarning("Object::%s: Parentheses expected, %s %s::%s%s%s",
2251 func, type, object->metaObject()->className(), method+1,
2252 loc ? " in ": "", loc ? loc : "");
2253 else
2254 qWarning("Object::%s: No such %s %s::%s%s%s",
2255 func, type, object->metaObject()->className(), method+1,
2256 loc ? " in ": "", loc ? loc : "");
2257
2258}
2259
2260
2261static void err_info_about_objects(const char * func,
2262 const QObject * sender,
2263 const QObject * receiver)
2264{
2265 QString a = sender ? sender->objectName() : QString();
2266 QString b = receiver ? receiver->objectName() : QString();
2267 if (!a.isEmpty())
2268 qWarning("Object::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
2269 if (!b.isEmpty())
2270 qWarning("Object::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
2271}
2272
2273/*!
2274 Returns a pointer to the object that sent the signal, if called in
2275 a slot activated by a signal; otherwise it returns 0. The pointer
2276 is valid only during the execution of the slot that calls this
2277 function from this object's thread context.
2278
2279 The pointer returned by this function becomes invalid if the
2280 sender is destroyed, or if the slot is disconnected from the
2281 sender's signal.
2282
2283 \warning This function violates the object-oriented principle of
2284 modularity. However, getting access to the sender might be useful
2285 when many signals are connected to a single slot.
2286
2287 \warning As mentioned above, the return value of this function is
2288 not valid when the slot is called via a Qt::DirectConnection from
2289 a thread different from this object's thread. Do not use this
2290 function in this type of scenario.
2291
2292 \sa senderSignalIndex(), QSignalMapper
2293*/
2294
2295QObject *QObject::sender() const
2296{
2297 Q_D(const QObject);
2298
2299 QMutexLocker locker(signalSlotLock(this));
2300 if (!d->currentSender)
2301 return 0;
2302
2303 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2304 if (c->sender == d->currentSender->sender)
2305 return d->currentSender->sender;
2306 }
2307
2308 return 0;
2309}
2310
2311/*!
2312 \since 4.8
2313
2314 Returns the meta-method index of the signal that called the currently
2315 executing slot, which is a member of the class returned by sender().
2316 If called outside of a slot activated by a signal, -1 is returned.
2317
2318 For signals with default parameters, this function will always return
2319 the index with all parameters, regardless of which was used with
2320 connect(). For example, the signal \c {destroyed(QObject *obj = 0)}
2321 will have two different indexes (with and without the parameter), but
2322 this function will always return the index with a parameter. This does
2323 not apply when overloading signals with different parameters.
2324
2325 \warning This function violates the object-oriented principle of
2326 modularity. However, getting access to the signal index might be useful
2327 when many signals are connected to a single slot.
2328
2329 \warning The return value of this function is not valid when the slot
2330 is called via a Qt::DirectConnection from a thread different from this
2331 object's thread. Do not use this function in this type of scenario.
2332
2333 \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
2334*/
2335
2336int QObject::senderSignalIndex() const
2337{
2338 Q_D(const QObject);
2339
2340 QMutexLocker locker(signalSlotLock(this));
2341 if (!d->currentSender)
2342 return -1;
2343
2344 for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
2345 if (c->sender == d->currentSender->sender)
2346 return d->currentSender->signal;
2347 }
2348
2349 return -1;
2350}
2351
2352/*!
2353 Returns the number of receivers connected to the \a signal.
2354
2355 Since both slots and signals can be used as receivers for signals,
2356 and the same connections can be made many times, the number of
2357 receivers is the same as the number of connections made from this
2358 signal.
2359
2360 When calling this function, you can use the \c SIGNAL() macro to
2361 pass a specific signal:
2362
2363 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 21
2364
2365 As the code snippet above illustrates, you can use this function
2366 to avoid emitting a signal that nobody listens to.
2367
2368 \warning This function violates the object-oriented principle of
2369 modularity. However, it might be useful when you need to perform
2370 expensive initialization only if something is connected to a
2371 signal.
2372*/
2373
2374int QObject::receivers(const char *signal) const
2375{
2376 Q_D(const QObject);
2377 int receivers = 0;
2378 if (signal) {
2379 QByteArray signal_name = QMetaObject::normalizedSignature(signal);
2380 signal = signal_name;
2381#ifndef QT_NO_DEBUG
2382 if (!check_signal_macro(this, signal, "receivers", "bind"))
2383 return 0;
2384#endif
2385 signal++; // skip code
2386 int signal_index = d->signalIndex(signal);
2387 if (signal_index < 0) {
2388#ifndef QT_NO_DEBUG
2389 err_method_notfound(this, signal-1, "receivers");
2390#endif
2391 return false;
2392 }
2393
2394 Q_D(const QObject);
2395 QMutexLocker locker(signalSlotLock(this));
2396 if (d->connectionLists) {
2397 if (signal_index < d->connectionLists->count()) {
2398 const QObjectPrivate::Connection *c =
2399 d->connectionLists->at(signal_index).first;
2400 while (c) {
2401 receivers += c->receiver ? 1 : 0;
2402 c = c->nextConnectionList;
2403 }
2404 }
2405 }
2406 }
2407 return receivers;
2408}
2409
2410/*!
2411 \internal
2412
2413 This helper function calculates signal and method index for the given
2414 member in the specified class.
2415
2416 \list
2417 \o If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
2418
2419 \o If specified member is not a member of obj instance class (or one of
2420 its parent classes) then both signalIndex and methodIndex are set to -1.
2421 \endlist
2422
2423 This function is used by QObject::connect and QObject::disconnect which
2424 are working with QMetaMethod.
2425
2426 \a signalIndex is set to the signal index of member. If the member
2427 specified is not signal this variable is set to -1.
2428
2429 \a methodIndex is set to the method index of the member. If the
2430 member is not a method of the object specified by the \a obj argument this
2431 variable is set to -1.
2432*/
2433void QMetaObjectPrivate::memberIndexes(const QObject *obj,
2434 const QMetaMethod &member,
2435 int *signalIndex, int *methodIndex)
2436{
2437 *signalIndex = -1;
2438 *methodIndex = -1;
2439 if (!obj || !member.mobj)
2440 return;
2441 const QMetaObject *m = obj->metaObject();
2442 // Check that member is member of obj class
2443 while (m != 0 && m != member.mobj)
2444 m = m->d.superdata;
2445 if (!m)
2446 return;
2447 *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
2448
2449 int signalOffset;
2450 int methodOffset;
2451 computeOffsets(m, &signalOffset, &methodOffset);
2452
2453 *methodIndex += methodOffset;
2454 if (member.methodType() == QMetaMethod::Signal) {
2455 *signalIndex = originalClone(m, *signalIndex);
2456 *signalIndex += signalOffset;
2457 } else {
2458 *signalIndex = -1;
2459 }
2460}
2461
2462static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
2463 const QMetaObject *receiver, const QMetaMethod &method)
2464{
2465 if (signal.attributes() & QMetaMethod::Compatibility) {
2466 if (!(method.attributes() & QMetaMethod::Compatibility))
2467 qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
2468 sender->className(), signal.signature());
2469 } else if ((method.attributes() & QMetaMethod::Compatibility) &&
2470 method.methodType() == QMetaMethod::Signal) {
2471 qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
2472 sender->className(), signal.signature(),
2473 receiver->className(), method.signature());
2474 }
2475}
2476
2477/*!
2478 \threadsafe
2479
2480 Creates a connection of the given \a type from the \a signal in
2481 the \a sender object to the \a method in the \a receiver object.
2482 Returns true if the connection succeeds; otherwise returns false.
2483
2484 You must use the \c SIGNAL() and \c SLOT() macros when specifying
2485 the \a signal and the \a method, for example:
2486
2487 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
2488
2489 This example ensures that the label always displays the current
2490 scroll bar value. Note that the signal and slots parameters must not
2491 contain any variable names, only the type. E.g. the following would
2492 not work and return false:
2493
2494 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
2495
2496 A signal can also be connected to another signal:
2497
2498 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
2499
2500 In this example, the \c MyWidget constructor relays a signal from
2501 a private member variable, and makes it available under a name
2502 that relates to \c MyWidget.
2503
2504 A signal can be connected to many slots and signals. Many signals
2505 can be connected to one slot.
2506
2507 If a signal is connected to several slots, the slots are activated
2508 in the same order as the order the connection was made, when the
2509 signal is emitted.
2510
2511 The function returns true if it successfully connects the signal
2512 to the slot. It will return false if it cannot create the
2513 connection, for example, if QObject is unable to verify the
2514 existence of either \a signal or \a method, or if their signatures
2515 aren't compatible.
2516
2517 By default, a signal is emitted for every connection you make;
2518 two signals are emitted for duplicate connections. You can break
2519 all of these connections with a single disconnect() call.
2520 If you pass the Qt::UniqueConnection \a type, the connection will only
2521 be made if it is not a duplicate. If there is already a duplicate
2522 (exact same signal to the exact same slot on the same objects),
2523 the connection will fail and connect will return false.
2524
2525 The optional \a type parameter describes the type of connection
2526 to establish. In particular, it determines whether a particular
2527 signal is delivered to a slot immediately or queued for delivery
2528 at a later time. If the signal is queued, the parameters must be
2529 of types that are known to Qt's meta-object system, because Qt
2530 needs to copy the arguments to store them in an event behind the
2531 scenes. If you try to use a queued connection and get the error
2532 message
2533
2534 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
2535
2536 call qRegisterMetaType() to register the data type before you
2537 establish the connection.
2538
2539 \sa disconnect(), sender(), qRegisterMetaType(), Q_DECLARE_METATYPE()
2540*/
2541
2542bool QObject::connect(const QObject *sender, const char *signal,
2543 const QObject *receiver, const char *method,
2544 Qt::ConnectionType type)
2545{
2546 {
2547 const void *cbdata[] = { sender, signal, receiver, method, &type };
2548 if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
2549 return true;
2550 }
2551
2552#ifndef QT_NO_DEBUG
2553 bool warnCompat = true;
2554#endif
2555 if (type == Qt::AutoCompatConnection) {
2556 type = Qt::AutoConnection;
2557#ifndef QT_NO_DEBUG
2558 warnCompat = false;
2559#endif
2560 }
2561
2562 if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
2563 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2564 sender ? sender->metaObject()->className() : "(null)",
2565 (signal && *signal) ? signal+1 : "(null)",
2566 receiver ? receiver->metaObject()->className() : "(null)",
2567 (method && *method) ? method+1 : "(null)");
2568 return false;
2569 }
2570 QByteArray tmp_signal_name;
2571
2572 if (!check_signal_macro(sender, signal, "connect", "bind"))
2573 return false;
2574 const QMetaObject *smeta = sender->metaObject();
2575 const char *signal_arg = signal;
2576 ++signal; //skip code
2577 int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2578 if (signal_index < 0) {
2579 // check for normalized signatures
2580 tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
2581 signal = tmp_signal_name.constData() + 1;
2582
2583 smeta = sender->metaObject();
2584 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2585 }
2586 if (signal_index < 0) {
2587 // re-use tmp_signal_name and signal from above
2588
2589 smeta = sender->metaObject();
2590 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
2591 }
2592 if (signal_index < 0) {
2593 err_method_notfound(sender, signal_arg, "connect");
2594 err_info_about_objects("connect", sender, receiver);
2595 return false;
2596 }
2597 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2598 int signalOffset, methodOffset;
2599 computeOffsets(smeta, &signalOffset, &methodOffset);
2600 int signal_absolute_index = signal_index + methodOffset;
2601 signal_index += signalOffset;
2602
2603 QByteArray tmp_method_name;
2604 int membcode = extract_code(method);
2605
2606 if (!check_method_code(membcode, receiver, method, "connect"))
2607 return false;
2608 const char *method_arg = method;
2609 ++method; // skip code
2610
2611 const QMetaObject *rmeta = receiver->metaObject();
2612 int method_index_relative = -1;
2613 switch (membcode) {
2614 case QSLOT_CODE:
2615 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
2616 break;
2617 case QSIGNAL_CODE:
2618 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
2619 break;
2620 }
2621
2622 if (method_index_relative < 0) {
2623 // check for normalized methods
2624 tmp_method_name = QMetaObject::normalizedSignature(method);
2625 method = tmp_method_name.constData();
2626
2627 // rmeta may have been modified above
2628 rmeta = receiver->metaObject();
2629 switch (membcode) {
2630 case QSLOT_CODE:
2631 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
2632 if (method_index_relative < 0)
2633 method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
2634 break;
2635 case QSIGNAL_CODE:
2636 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
2637 if (method_index_relative < 0)
2638 method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
2639 break;
2640 }
2641 }
2642
2643 if (method_index_relative < 0) {
2644 err_method_notfound(receiver, method_arg, "connect");
2645 err_info_about_objects("connect", sender, receiver);
2646 return false;
2647 }
2648
2649 if (!QMetaObject::checkConnectArgs(signal, method)) {
2650 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2651 "\n %s::%s --> %s::%s",
2652 sender->metaObject()->className(), signal,
2653 receiver->metaObject()->className(), method);
2654 return false;
2655 }
2656
2657 int *types = 0;
2658 if ((type == Qt::QueuedConnection)
2659 && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
2660 return false;
2661
2662#ifndef QT_NO_DEBUG
2663 if (warnCompat) {
2664 QMetaMethod smethod = smeta->method(signal_absolute_index);
2665 QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
2666 check_and_warn_compat(smeta, smethod, rmeta, rmethod);
2667 }
2668#endif
2669 if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
2670 return false;
2671 const_cast<QObject*>(sender)->connectNotify(signal - 1);
2672 return true;
2673}
2674
2675/*!
2676 \since 4.8
2677
2678 Creates a connection of the given \a type from the \a signal in
2679 the \a sender object to the \a method in the \a receiver object.
2680 Returns true if the connection succeeds; otherwise returns false.
2681
2682 This function works in the same way as
2683 connect(const QObject *sender, const char *signal,
2684 const QObject *receiver, const char *method,
2685 Qt::ConnectionType type)
2686 but it uses QMetaMethod to specify signal and method.
2687
2688 \sa connect(const QObject *sender, const char *signal,
2689 const QObject *receiver, const char *method,
2690 Qt::ConnectionType type)
2691 */
2692bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
2693 const QObject *receiver, const QMetaMethod &method,
2694 Qt::ConnectionType type)
2695{
2696#ifndef QT_NO_DEBUG
2697 bool warnCompat = true;
2698#endif
2699 if (type == Qt::AutoCompatConnection) {
2700 type = Qt::AutoConnection;
2701#ifndef QT_NO_DEBUG
2702 warnCompat = false;
2703#endif
2704 }
2705
2706 if (sender == 0
2707 || receiver == 0
2708 || signal.methodType() != QMetaMethod::Signal
2709 || method.methodType() == QMetaMethod::Constructor) {
2710 qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
2711 sender ? sender->metaObject()->className() : "(null)",
2712 signal.signature(),
2713 receiver ? receiver->metaObject()->className() : "(null)",
2714 method.signature() );
2715 return false;
2716 }
2717
2718 QVarLengthArray<char> signalSignature;
2719 QObjectPrivate::signalSignature(signal, &signalSignature);
2720
2721 {
2722 QByteArray methodSignature;
2723 methodSignature.reserve(qstrlen(method.signature())+1);
2724 methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
2725 : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
2726 methodSignature.append(method.signature());
2727 const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type };
2728 if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
2729 return true;
2730 }
2731
2732
2733 int signal_index;
2734 int method_index;
2735 {
2736 int dummy;
2737 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
2738 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
2739 }
2740
2741 const QMetaObject *smeta = sender->metaObject();
2742 const QMetaObject *rmeta = receiver->metaObject();
2743 if (signal_index == -1) {
2744 qWarning("QObject::connect: Can't find signal %s on instance of class %s",
2745 signal.signature(), smeta->className());
2746 return false;
2747 }
2748 if (method_index == -1) {
2749 qWarning("QObject::connect: Can't find method %s on instance of class %s",
2750 method.signature(), rmeta->className());
2751 return false;
2752 }
2753
2754 if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
2755 qWarning("QObject::connect: Incompatible sender/receiver arguments"
2756 "\n %s::%s --> %s::%s",
2757 smeta->className(), signal.signature(),
2758 rmeta->className(), method.signature());
2759 return false;
2760 }
2761
2762 int *types = 0;
2763 if ((type == Qt::QueuedConnection)
2764 && !(types = queuedConnectionTypes(signal.parameterTypes())))
2765 return false;
2766
2767#ifndef QT_NO_DEBUG
2768 if (warnCompat)
2769 check_and_warn_compat(smeta, signal, rmeta, method);
2770#endif
2771 if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
2772 return false;
2773
2774 const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
2775 return true;
2776}
2777
2778/*!
2779 \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
2780 \overload connect()
2781 \threadsafe
2782
2783 Connects \a signal from the \a sender object to this object's \a
2784 method.
2785
2786 Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
2787
2788 Every connection you make emits a signal, so duplicate connections emit
2789 two signals. You can break a connection using disconnect().
2790
2791 \sa disconnect()
2792*/
2793
2794/*!
2795 \threadsafe
2796
2797 Disconnects \a signal in object \a sender from \a method in object
2798 \a receiver. Returns true if the connection is successfully broken;
2799 otherwise returns false.
2800
2801 A signal-slot connection is removed when either of the objects
2802 involved are destroyed.
2803
2804 disconnect() is typically used in three ways, as the following
2805 examples demonstrate.
2806 \list 1
2807 \i Disconnect everything connected to an object's signals:
2808
2809 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
2810
2811 equivalent to the non-static overloaded function
2812
2813 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27
2814
2815 \i Disconnect everything connected to a specific signal:
2816
2817 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28
2818
2819 equivalent to the non-static overloaded function
2820
2821 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29
2822
2823 \i Disconnect a specific receiver:
2824
2825 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
2826
2827 equivalent to the non-static overloaded function
2828
2829 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 31
2830
2831 \endlist
2832
2833 0 may be used as a wildcard, meaning "any signal", "any receiving
2834 object", or "any slot in the receiving object", respectively.
2835
2836 The \a sender may never be 0. (You cannot disconnect signals from
2837 more than one object in a single call.)
2838
2839 If \a signal is 0, it disconnects \a receiver and \a method from
2840 any signal. If not, only the specified signal is disconnected.
2841
2842 If \a receiver is 0, it disconnects anything connected to \a
2843 signal. If not, slots in objects other than \a receiver are not
2844 disconnected.
2845
2846 If \a method is 0, it disconnects anything that is connected to \a
2847 receiver. If not, only slots named \a method will be disconnected,
2848 and all other slots are left alone. The \a method must be 0 if \a
2849 receiver is left out, so you cannot disconnect a
2850 specifically-named slot on all objects.
2851
2852 \sa connect()
2853*/
2854bool QObject::disconnect(const QObject *sender, const char *signal,
2855 const QObject *receiver, const char *method)
2856{
2857 if (sender == 0 || (receiver == 0 && method != 0)) {
2858 qWarning("Object::disconnect: Unexpected null parameter");
2859 return false;
2860 }
2861
2862 {
2863 const void *cbdata[] = { sender, signal, receiver, method };
2864 if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
2865 return true;
2866 }
2867
2868 const char *signal_arg = signal;
2869 QByteArray signal_name;
2870 bool signal_found = false;
2871 if (signal) {
2872 QT_TRY {
2873 signal_name = QMetaObject::normalizedSignature(signal);
2874 signal = signal_name.constData();
2875 } QT_CATCH (const std::bad_alloc &) {
2876 // if the signal is already normalized, we can continue.
2877 if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
2878 QT_RETHROW;
2879 }
2880
2881 if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
2882 return false;
2883 signal++; // skip code
2884 }
2885
2886 QByteArray method_name;
2887 const char *method_arg = method;
2888 int membcode = -1;
2889 bool method_found = false;
2890 if (method) {
2891 QT_TRY {
2892 method_name = QMetaObject::normalizedSignature(method);
2893 method = method_name.constData();
2894 } QT_CATCH(const std::bad_alloc &) {
2895 // if the method is already normalized, we can continue.
2896 if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
2897 QT_RETHROW;
2898 }
2899
2900 membcode = extract_code(method);
2901 if (!check_method_code(membcode, receiver, method, "disconnect"))
2902 return false;
2903 method++; // skip code
2904 }
2905
2906 /* We now iterate through all the sender's and receiver's meta
2907 * objects in order to also disconnect possibly shadowed signals
2908 * and slots with the same signature.
2909 */
2910 bool res = false;
2911 const QMetaObject *smeta = sender->metaObject();
2912 do {
2913 int signal_index = -1;
2914 if (signal) {
2915 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
2916 if (signal_index < 0)
2917 signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
2918 if (signal_index < 0)
2919 break;
2920 signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
2921 int signalOffset, methodOffset;
2922 computeOffsets(smeta, &signalOffset, &methodOffset);
2923 signal_index += signalOffset;
2924 signal_found = true;
2925 }
2926
2927 if (!method) {
2928 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1);
2929 } else {
2930 const QMetaObject *rmeta = receiver->metaObject();
2931 do {
2932 int method_index = rmeta->indexOfMethod(method);
2933 if (method_index >= 0)
2934 while (method_index < rmeta->methodOffset())
2935 rmeta = rmeta->superClass();
2936 if (method_index < 0)
2937 break;
2938 res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index);
2939 method_found = true;
2940 } while ((rmeta = rmeta->superClass()));
2941 }
2942 } while (signal && (smeta = smeta->superClass()));
2943
2944 if (signal && !signal_found) {
2945 err_method_notfound(sender, signal_arg, "disconnect");
2946 err_info_about_objects("disconnect", sender, receiver);
2947 } else if (method && !method_found) {
2948 err_method_notfound(receiver, method_arg, "disconnect");
2949 err_info_about_objects("disconnect", sender, receiver);
2950 }
2951 if (res)
2952 const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
2953 return res;
2954}
2955
2956/*!
2957 \since 4.8
2958
2959 Disconnects \a signal in object \a sender from \a method in object
2960 \a receiver. Returns true if the connection is successfully broken;
2961 otherwise returns false.
2962
2963 This function provides the same possibilities like
2964 disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2965 but uses QMetaMethod to represent the signal and the method to be disconnected.
2966
2967 Additionally this function returnsfalse and no signals and slots disconnected
2968 if:
2969 \list 1
2970
2971 \i \a signal is not a member of sender class or one of its parent classes.
2972
2973 \i \a method is not a member of receiver class or one of its parent classes.
2974
2975 \i \a signal instance represents not a signal.
2976
2977 \endlist
2978
2979 QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
2980 In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
2981 method should also be QMetaMethod(). \a sender parameter should be never 0.
2982
2983 \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
2984 */
2985bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
2986 const QObject *receiver, const QMetaMethod &method)
2987{
2988 if (sender == 0 || (receiver == 0 && method.mobj != 0)) {
2989 qWarning("Object::disconnect: Unexpected null parameter");
2990 return false;
2991 }
2992 if (signal.mobj) {
2993 if(signal.methodType() != QMetaMethod::Signal) {
2994 qWarning("Object::%s: Attempt to %s non-signal %s::%s",
2995 "disconnect","unbind",
2996 sender->metaObject()->className(), signal.signature());
2997 return false;
2998 }
2999 }
3000 if (method.mobj) {
3001 if(method.methodType() == QMetaMethod::Constructor) {
3002 qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
3003 receiver->metaObject()->className(), method.signature());
3004 return false;
3005 }
3006 }
3007
3008 QVarLengthArray<char> signalSignature;
3009 if (signal.mobj)
3010 QObjectPrivate::signalSignature(signal, &signalSignature);
3011
3012 {
3013 QByteArray methodSignature;
3014 if (method.mobj) {
3015 methodSignature.reserve(qstrlen(method.signature())+1);
3016 methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
3017 : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
3018 methodSignature.append(method.signature());
3019 }
3020 const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0,
3021 receiver, method.mobj ? methodSignature.constData() : 0 };
3022 if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
3023 return true;
3024 }
3025
3026 int signal_index;
3027 int method_index;
3028 {
3029 int dummy;
3030 QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
3031 QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
3032 }
3033 // If we are here sender is not null. If signal is not null while signal_index
3034 // is -1 then this signal is not a member of sender.
3035 if (signal.mobj && signal_index == -1) {
3036 qWarning("QObject::disconect: signal %s not found on class %s",
3037 signal.signature(), sender->metaObject()->className());
3038 return false;
3039 }
3040 // If this condition is true then method is not a member of receeiver.
3041 if (receiver && method.mobj && method_index == -1) {
3042 qWarning("QObject::disconect: method %s not found on class %s",
3043 method.signature(), receiver->metaObject()->className());
3044 return false;
3045 }
3046
3047 if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index))
3048 return false;
3049
3050 const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
3051 return true;
3052}
3053
3054/*!
3055 \threadsafe
3056
3057 \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method)
3058 \overload disconnect()
3059
3060 Disconnects \a signal from \a method of \a receiver.
3061
3062 A signal-slot connection is removed when either of the objects
3063 involved are destroyed.
3064*/
3065
3066/*!
3067 \fn bool QObject::disconnect(const QObject *receiver, const char *method)
3068 \overload disconnect()
3069
3070 Disconnects all signals in this object from \a receiver's \a
3071 method.
3072
3073 A signal-slot connection is removed when either of the objects
3074 involved are destroyed.
3075*/
3076
3077
3078/*!
3079 \fn void QObject::connectNotify(const char *signal)
3080
3081 This virtual function is called when something has been connected
3082 to \a signal in this object.
3083
3084 If you want to compare \a signal with a specific signal, use
3085 QLatin1String and the \c SIGNAL() macro as follows:
3086
3087 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 32
3088
3089 If the signal contains multiple parameters or parameters that
3090 contain spaces, call QMetaObject::normalizedSignature() on
3091 the result of the \c SIGNAL() macro.
3092
3093 \warning This function violates the object-oriented principle of
3094 modularity. However, it might be useful when you need to perform
3095 expensive initialization only if something is connected to a
3096 signal.
3097
3098 \sa connect(), disconnectNotify()
3099*/
3100
3101void QObject::connectNotify(const char *)
3102{
3103}
3104
3105/*!
3106 \fn void QObject::disconnectNotify(const char *signal)
3107
3108 This virtual function is called when something has been
3109 disconnected from \a signal in this object.
3110
3111 See connectNotify() for an example of how to compare
3112 \a signal with a specific signal.
3113
3114 \warning This function violates the object-oriented principle of
3115 modularity. However, it might be useful for optimizing access to
3116 expensive resources.
3117
3118 \sa disconnect(), connectNotify()
3119*/
3120
3121void QObject::disconnectNotify(const char *)
3122{
3123}
3124
3125/* \internal
3126 convert a signal index from the method range to the signal range
3127 */
3128static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
3129{
3130 if (signal_index < 0)
3131 return signal_index;
3132 while (metaObject && metaObject->methodOffset() > signal_index)
3133 metaObject = metaObject->superClass();
3134
3135 if (metaObject) {
3136 int signalOffset, methodOffset;
3137 computeOffsets(metaObject, &signalOffset, &methodOffset);
3138 if (signal_index < metaObject->methodCount())
3139 signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
3140 else
3141 signal_index = signal_index - methodOffset + signalOffset;
3142 }
3143 return signal_index;
3144}
3145
3146/*!\internal
3147 \a types is a 0-terminated vector of meta types for queued
3148 connections.
3149
3150 if \a signal_index is -1, then we effectively connect *all* signals
3151 from the sender to the receiver's slot
3152 */
3153bool QMetaObject::connect(const QObject *sender, int signal_index,
3154 const QObject *receiver, int method_index, int type, int *types)
3155{
3156 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3157 return QMetaObjectPrivate::connect(sender, signal_index,
3158 receiver, method_index,
3159 0, //FIXME, we could speed this connection up by computing the relative index
3160 type, types);
3161}
3162
3163/*! \internal
3164 Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3165
3166 method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
3167 */
3168bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
3169 const QObject *receiver, int method_index,
3170 const QMetaObject *rmeta, int type, int *types)
3171{
3172 QObject *s = const_cast<QObject *>(sender);
3173 QObject *r = const_cast<QObject *>(receiver);
3174
3175 int method_offset = rmeta ? rmeta->methodOffset() : 0;
3176 QObjectPrivate::StaticMetaCallFunction callFunction =
3177 (rmeta && QMetaObjectPrivate::get(rmeta)->revision >= 6 && rmeta->d.extradata)
3178 ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
3179
3180 QOrderedMutexLocker locker(signalSlotLock(sender),
3181 signalSlotLock(receiver));
3182
3183 if (type & Qt::UniqueConnection) {
3184 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
3185 if (connectionLists && connectionLists->count() > signal_index) {
3186 const QObjectPrivate::Connection *c2 =
3187 (*connectionLists)[signal_index].first;
3188
3189 int method_index_absolute = method_index + method_offset;
3190
3191 while (c2) {
3192 if (c2->receiver == receiver && c2->method() == method_index_absolute)
3193 return false;
3194 c2 = c2->nextConnectionList;
3195 }
3196 }
3197 type &= Qt::UniqueConnection - 1;
3198 }
3199
3200 QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
3201 c->sender = s;
3202 c->receiver = r;
3203 c->method_relative = method_index;
3204 c->method_offset = method_offset;
3205 c->connectionType = type;
3206 c->argumentTypes = types;
3207 c->nextConnectionList = 0;
3208 c->callFunction = callFunction;
3209
3210 QT_TRY {
3211 QObjectPrivate::get(s)->addConnection(signal_index, c);
3212 } QT_CATCH(...) {
3213 delete c;
3214 QT_RETHROW;
3215 }
3216
3217 c->prev = &(QObjectPrivate::get(r)->senders);
3218 c->next = *c->prev;
3219 *c->prev = c;
3220 if (c->next)
3221 c->next->prev = &c->next;
3222
3223 QObjectPrivate *const sender_d = QObjectPrivate::get(s);
3224 if (signal_index < 0) {
3225 sender_d->connectedSignals[0] = sender_d->connectedSignals[1] = ~0;
3226 } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) {
3227 sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
3228 }
3229
3230 return true;
3231}
3232
3233/*!\internal
3234 */
3235bool QMetaObject::disconnect(const QObject *sender, int signal_index,
3236 const QObject *receiver, int method_index)
3237{
3238 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3239 return QMetaObjectPrivate::disconnect(sender, signal_index,
3240 receiver, method_index);
3241}
3242
3243/*!\internal
3244
3245Disconnect a single signal connection. If QMetaObject::connect() has been called
3246multiple times for the same sender, signal_index, receiver and method_index only
3247one of these connections will be removed.
3248 */
3249bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
3250 const QObject *receiver, int method_index)
3251{
3252 signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
3253 return QMetaObjectPrivate::disconnect(sender, signal_index,
3254 receiver, method_index,
3255 QMetaObjectPrivate::DisconnectOne);
3256}
3257
3258/*! \internal
3259 Helper function to remove the connection from the senders list and setting the receivers to 0
3260 */
3261bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
3262 const QObject *receiver, int method_index,
3263 QMutex *senderMutex, DisconnectType disconnectType)
3264{
3265 bool success = false;
3266 while (c) {
3267 if (c->receiver
3268 && (receiver == 0 || (c->receiver == receiver
3269 && (method_index < 0 || c->method() == method_index)))) {
3270 bool needToUnlock = false;
3271 QMutex *receiverMutex = 0;
3272 if (!receiver) {
3273 receiverMutex = signalSlotLock(c->receiver);
3274 // need to relock this receiver and sender in the correct order
3275 needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
3276 }
3277 if (c->receiver) {
3278 *c->prev = c->next;
3279 if (c->next)
3280 c->next->prev = c->prev;
3281 }
3282
3283 if (needToUnlock)
3284 receiverMutex->unlockInline();
3285
3286 c->receiver = 0;
3287
3288 success = true;
3289
3290 if (disconnectType == DisconnectOne)
3291 return success;
3292 }
3293 c = c->nextConnectionList;
3294 }
3295 return success;
3296}
3297
3298/*! \internal
3299 Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
3300 */
3301bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
3302 const QObject *receiver, int method_index,
3303 DisconnectType disconnectType)
3304{
3305 if (!sender)
3306 return false;
3307
3308 QObject *s = const_cast<QObject *>(sender);
3309
3310 QMutex *senderMutex = signalSlotLock(sender);
3311 QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
3312 QOrderedMutexLocker locker(senderMutex, receiverMutex);
3313
3314 QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
3315 if (!connectionLists)
3316 return false;
3317
3318 // prevent incoming connections changing the connectionLists while unlocked
3319 ++connectionLists->inUse;
3320
3321 bool success = false;
3322 if (signal_index < 0) {
3323 // remove from all connection lists
3324 for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
3325 QObjectPrivate::Connection *c =
3326 (*connectionLists)[signal_index].first;
3327 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
3328 success = true;
3329 connectionLists->dirty = true;
3330 }
3331 }
3332 } else if (signal_index < connectionLists->count()) {
3333 QObjectPrivate::Connection *c =
3334 (*connectionLists)[signal_index].first;
3335 if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
3336 success = true;
3337 connectionLists->dirty = true;
3338 }
3339 }
3340
3341 --connectionLists->inUse;
3342 Q_ASSERT(connectionLists->inUse >= 0);
3343 if (connectionLists->orphaned && !connectionLists->inUse)
3344 delete connectionLists;
3345
3346 return success;
3347}
3348
3349/*!
3350 \fn void QMetaObject::connectSlotsByName(QObject *object)
3351
3352 Searches recursively for all child objects of the given \a object, and connects
3353 matching signals from them to slots of \a object that follow the following form:
3354
3355 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 33
3356
3357 Let's assume our object has a child object of type QPushButton with
3358 the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
3359 button's \c{clicked()} signal would be:
3360
3361 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 34
3362
3363 \sa QObject::setObjectName()
3364 */
3365void QMetaObject::connectSlotsByName(QObject *o)
3366{
3367 if (!o)
3368 return;
3369 const QMetaObject *mo = o->metaObject();
3370 Q_ASSERT(mo);
3371 const QObjectList list = o->findChildren<QObject *>(QString());
3372 for (int i = 0; i < mo->methodCount(); ++i) {
3373 const char *slot = mo->method(i).signature();
3374 Q_ASSERT(slot);
3375 if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
3376 continue;
3377 bool foundIt = false;
3378 for(int j = 0; j < list.count(); ++j) {
3379 const QObject *co = list.at(j);
3380 QByteArray objName = co->objectName().toAscii();
3381 int len = objName.length();
3382 if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
3383 continue;
3384 int sigIndex = co->d_func()->signalIndex(slot + len + 4);
3385 if (sigIndex < 0) { // search for compatible signals
3386 const QMetaObject *smo = co->metaObject();
3387 int slotlen = qstrlen(slot + len + 4) - 1;
3388 for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
3389 QMetaMethod method = smo->method(k);
3390 if (method.methodType() != QMetaMethod::Signal)
3391 continue;
3392
3393 if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
3394 int signalOffset, methodOffset;
3395 computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
3396 sigIndex = k + - methodOffset + signalOffset;
3397 break;
3398 }
3399 }
3400 }
3401 if (sigIndex < 0)
3402 continue;
3403 if (QMetaObjectPrivate::connect(co, sigIndex, o, i)) {
3404 foundIt = true;
3405 break;
3406 }
3407 }
3408 if (foundIt) {
3409 // we found our slot, now skip all overloads
3410 while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
3411 ++i;
3412 } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
3413 qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
3414 }
3415 }
3416}
3417
3418static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
3419{
3420 if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
3421 QMetaMethod m = sender->metaObject()->method(signal);
3422 int *tmp = queuedConnectionTypes(m.parameterTypes());
3423 if (!tmp) // cannot queue arguments
3424 tmp = &DIRECT_CONNECTION_ONLY;
3425 if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
3426 if (tmp != &DIRECT_CONNECTION_ONLY)
3427 delete [] tmp;
3428 }
3429 }
3430 if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
3431 return;
3432 int nargs = 1; // include return type
3433 while (c->argumentTypes[nargs-1])
3434 ++nargs;
3435 int *types = (int *) qMalloc(nargs*sizeof(int));
3436 Q_CHECK_PTR(types);
3437 void **args = (void **) qMalloc(nargs*sizeof(void *));
3438 Q_CHECK_PTR(args);
3439 types[0] = 0; // return type
3440 args[0] = 0; // return value
3441 for (int n = 1; n < nargs; ++n)
3442 args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
3443 QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
3444 c->method_relative,
3445 c->callFunction,
3446 sender, signal, nargs,
3447 types, args));
3448}
3449
3450
3451/*!\internal
3452 \obsolete.
3453 Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) before Qt 4.6
3454 */
3455void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
3456{
3457 Q_UNUSED(to_signal_index);
3458 activate(sender, from_signal_index, argv);
3459}
3460
3461/*!\internal
3462 */
3463void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
3464 void **argv)
3465{
3466 int signalOffset;
3467 int methodOffset;
3468 computeOffsets(m, &signalOffset, &methodOffset);
3469
3470 int signal_index = signalOffset + local_signal_index;
3471
3472 if (!sender->d_func()->isSignalConnected(signal_index))
3473 return; // nothing connected to these signals, and no spy
3474
3475 if (sender->d_func()->blockSig)
3476 return;
3477
3478 int signal_absolute_index = methodOffset + local_signal_index;
3479
3480 void *empty_argv[] = { 0 };
3481 if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
3482 qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
3483 argv ? argv : empty_argv);
3484 }
3485
3486 Qt::HANDLE currentThreadId = QThread::currentThreadId();
3487
3488 QMutexLocker locker(signalSlotLock(sender));
3489 QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
3490 if (!connectionLists) {
3491 locker.unlock();
3492 if (qt_signal_spy_callback_set.signal_end_callback != 0)
3493 qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
3494 return;
3495 }
3496 ++connectionLists->inUse;
3497
3498
3499 const QObjectPrivate::ConnectionList *list;
3500 if (signal_index < connectionLists->count())
3501 list = &connectionLists->at(signal_index);
3502 else
3503 list = &connectionLists->allsignals;
3504
3505 do {
3506 QObjectPrivate::Connection *c = list->first;
3507 if (!c) continue;
3508 // We need to check against last here to ensure that signals added
3509 // during the signal emission are not emitted in this emission.
3510 QObjectPrivate::Connection *last = list->last;
3511
3512 do {
3513 if (!c->receiver)
3514 continue;
3515
3516 QObject * const receiver = c->receiver;
3517 const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
3518
3519 // determine if this connection should be sent immediately or
3520 // put into the event queue
3521 if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
3522 || (c->connectionType == Qt::QueuedConnection)) {
3523 queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
3524 continue;
3525#ifndef QT_NO_THREAD
3526 } else if (c->connectionType == Qt::BlockingQueuedConnection) {
3527 locker.unlock();
3528 if (receiverInSameThread) {
3529 qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
3530 "Sender is %s(%p), receiver is %s(%p)",
3531 sender->metaObject()->className(), sender,
3532 receiver->metaObject()->className(), receiver);
3533 }
3534 QSemaphore semaphore;
3535 QCoreApplication::postEvent(receiver, new QMetaCallEvent(c->method_offset, c->method_relative,
3536 c->callFunction,
3537 sender, signal_absolute_index,
3538 0, 0,
3539 argv ? argv : empty_argv,
3540 &semaphore));
3541 semaphore.acquire();
3542 locker.relock();
3543 continue;
3544#endif
3545 }
3546
3547 QObjectPrivate::Sender currentSender;
3548 QObjectPrivate::Sender *previousSender = 0;
3549 if (receiverInSameThread) {
3550 currentSender.sender = sender;
3551 currentSender.signal = signal_absolute_index;
3552 currentSender.ref = 1;
3553 previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
3554 }
3555 const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
3556 const int method_relative = c->method_relative;
3557 if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
3558 //we compare the vtable to make sure we are not in the destructor of the object.
3559 locker.unlock();
3560 if (qt_signal_spy_callback_set.slot_begin_callback != 0)
3561 qt_signal_spy_callback_set.slot_begin_callback(receiver, c->method(), argv ? argv : empty_argv);
3562
3563#if defined(QT_NO_EXCEPTIONS)
3564 callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
3565#else
3566 QT_TRY {
3567 callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
3568 } QT_CATCH(...) {
3569 locker.relock();
3570 if (receiverInSameThread)
3571 QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
3572
3573 --connectionLists->inUse;
3574 Q_ASSERT(connectionLists->inUse >= 0);
3575 if (connectionLists->orphaned && !connectionLists->inUse)
3576 delete connectionLists;
3577 QT_RETHROW;
3578 }
3579#endif
3580 if (qt_signal_spy_callback_set.slot_end_callback != 0)
3581 qt_signal_spy_callback_set.slot_end_callback(receiver, c->method());
3582 locker.relock();
3583 } else {
3584 const int method = method_relative + c->method_offset;
3585 locker.unlock();
3586
3587 if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
3588 qt_signal_spy_callback_set.slot_begin_callback(receiver,
3589 method,
3590 argv ? argv : empty_argv);
3591 }
3592
3593#if defined(QT_NO_EXCEPTIONS)
3594 metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
3595#else
3596 QT_TRY {
3597 metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
3598 } QT_CATCH(...) {
3599 locker.relock();
3600 if (receiverInSameThread)
3601 QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
3602
3603 --connectionLists->inUse;
3604 Q_ASSERT(connectionLists->inUse >= 0);
3605 if (connectionLists->orphaned && !connectionLists->inUse)
3606 delete connectionLists;
3607 QT_RETHROW;
3608 }
3609#endif
3610
3611 if (qt_signal_spy_callback_set.slot_end_callback != 0)
3612 qt_signal_spy_callback_set.slot_end_callback(receiver, method);
3613
3614 locker.relock();
3615 }
3616
3617 if (receiverInSameThread)
3618 QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
3619
3620 if (connectionLists->orphaned)
3621 break;
3622 } while (c != last && (c = c->nextConnectionList) != 0);
3623
3624 if (connectionLists->orphaned)
3625 break;
3626 } while (list != &connectionLists->allsignals &&
3627 //start over for all signals;
3628 ((list = &connectionLists->allsignals), true));
3629
3630 --connectionLists->inUse;
3631 Q_ASSERT(connectionLists->inUse >= 0);
3632 if (connectionLists->orphaned) {
3633 if (!connectionLists->inUse)
3634 delete connectionLists;
3635 } else if (connectionLists->dirty) {
3636 sender->d_func()->cleanConnectionLists();
3637 }
3638
3639 locker.unlock();
3640
3641 if (qt_signal_spy_callback_set.signal_end_callback != 0)
3642 qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
3643
3644}
3645
3646/*!\internal
3647 Obsolete. (signal_index comes from indexOfMethod())
3648*/
3649void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
3650{
3651 const QMetaObject *mo = sender->metaObject();
3652 while (mo->methodOffset() > signal_index)
3653 mo = mo->superClass();
3654 activate(sender, mo, signal_index - mo->methodOffset(), argv);
3655}
3656
3657/*!\internal
3658 Obsolete, called by moc generated code before Qt 4.6 for cloned signals
3659 But since Qt 4.6, all clones are connected to their original
3660 */
3661void QMetaObject::activate(QObject *sender, const QMetaObject *m,
3662 int from_local_signal_index, int to_local_signal_index, void **argv)
3663{
3664 Q_UNUSED(to_local_signal_index);
3665 Q_ASSERT(from_local_signal_index == QMetaObjectPrivate::originalClone(m, to_local_signal_index));
3666 activate(sender, m, from_local_signal_index, argv);
3667}
3668
3669/*! \internal
3670 Returns the signal index used in the internal connectionLists vector.
3671
3672 It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
3673 while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
3674*/
3675int QObjectPrivate::signalIndex(const char *signalName) const
3676{
3677 Q_Q(const QObject);
3678 const QMetaObject *base = q->metaObject();
3679 int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
3680 if (relative_index < 0)
3681 relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
3682 if (relative_index < 0)
3683 return relative_index;
3684 relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
3685 int signalOffset, methodOffset;
3686 computeOffsets(base, &signalOffset, &methodOffset);
3687 return relative_index + signalOffset;
3688}
3689
3690/*****************************************************************************
3691 Properties
3692 *****************************************************************************/
3693
3694#ifndef QT_NO_PROPERTIES
3695
3696/*!
3697 Sets the value of the object's \a name property to \a value.
3698
3699 If the property is defined in the class using Q_PROPERTY then
3700 true is returned on success and false otherwise. If the property
3701 is not defined using Q_PROPERTY, and therefore not listed in the
3702 meta-object, it is added as a dynamic property and false is returned.
3703
3704 Information about all available properties is provided through the
3705 metaObject() and dynamicPropertyNames().
3706
3707 Dynamic properties can be queried again using property() and can be
3708 removed by setting the property value to an invalid QVariant.
3709 Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
3710 to be sent to the object.
3711
3712 \bold{Note:} Dynamic properties starting with "_q_" are reserved for internal
3713 purposes.
3714
3715 \sa property(), metaObject(), dynamicPropertyNames()
3716*/
3717bool QObject::setProperty(const char *name, const QVariant &value)
3718{
3719 Q_D(QObject);
3720 const QMetaObject* meta = metaObject();
3721 if (!name || !meta)
3722 return false;
3723
3724 int id = meta->indexOfProperty(name);
3725 if (id < 0) {
3726 if (!d->extraData)
3727 d->extraData = new QObjectPrivate::ExtraData;
3728
3729 const int idx = d->extraData->propertyNames.indexOf(name);
3730
3731 if (!value.isValid()) {
3732 if (idx == -1)
3733 return false;
3734 d->extraData->propertyNames.removeAt(idx);
3735 d->extraData->propertyValues.removeAt(idx);
3736 } else {
3737 if (idx == -1) {
3738 d->extraData->propertyNames.append(name);
3739 d->extraData->propertyValues.append(value);
3740 } else {
3741 d->extraData->propertyValues[idx] = value;
3742 }
3743 }
3744
3745 QDynamicPropertyChangeEvent ev(name);
3746 QCoreApplication::sendEvent(this, &ev);
3747
3748 return false;
3749 }
3750 QMetaProperty p = meta->property(id);
3751#ifndef QT_NO_DEBUG
3752 if (!p.isWritable())
3753 qWarning("%s::setProperty: Property \"%s\" invalid,"
3754 " read-only or does not exist", metaObject()->className(), name);
3755#endif
3756 return p.write(this, value);
3757}
3758
3759/*!
3760 Returns the value of the object's \a name property.
3761
3762 If no such property exists, the returned variant is invalid.
3763
3764 Information about all available properties is provided through the
3765 metaObject() and dynamicPropertyNames().
3766
3767 \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
3768*/
3769QVariant QObject::property(const char *name) const
3770{
3771 Q_D(const QObject);
3772 const QMetaObject* meta = metaObject();
3773 if (!name || !meta)
3774 return QVariant();
3775
3776 int id = meta->indexOfProperty(name);
3777 if (id < 0) {
3778 if (!d->extraData)
3779 return QVariant();
3780 const int i = d->extraData->propertyNames.indexOf(name);
3781 return d->extraData->propertyValues.value(i);
3782 }
3783 QMetaProperty p = meta->property(id);
3784#ifndef QT_NO_DEBUG
3785 if (!p.isReadable())
3786 qWarning("%s::property: Property \"%s\" invalid or does not exist",
3787 metaObject()->className(), name);
3788#endif
3789 return p.read(this);
3790}
3791
3792/*!
3793 \since 4.2
3794
3795 Returns the names of all properties that were dynamically added to
3796 the object using setProperty().
3797*/
3798QList<QByteArray> QObject::dynamicPropertyNames() const
3799{
3800 Q_D(const QObject);
3801 if (d->extraData)
3802 return d->extraData->propertyNames;
3803 return QList<QByteArray>();
3804}
3805
3806#endif // QT_NO_PROPERTIES
3807
3808
3809/*****************************************************************************
3810 QObject debugging output routines.
3811 *****************************************************************************/
3812
3813static void dumpRecursive(int level, QObject *object)
3814{
3815#if defined(QT_DEBUG)
3816 if (object) {
3817 QByteArray buf;
3818 buf.fill(' ', level / 2 * 8);
3819 if (level % 2)
3820 buf += " ";
3821 QString name = object->objectName();
3822 QString flags = QLatin1String("");
3823#if 0
3824 if (qApp->focusWidget() == object)
3825 flags += 'F';
3826 if (object->isWidgetType()) {
3827 QWidget * w = (QWidget *)object;
3828 if (w->isVisible()) {
3829 QString t("<%1,%2,%3,%4>");
3830 flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
3831 } else {
3832 flags += 'I';
3833 }
3834 }
3835#endif
3836 qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
3837 flags.toLatin1().data());
3838 QObjectList children = object->children();
3839 if (!children.isEmpty()) {
3840 for (int i = 0; i < children.size(); ++i)
3841 dumpRecursive(level+1, children.at(i));
3842 }
3843 }
3844#else
3845 Q_UNUSED(level)
3846 Q_UNUSED(object)
3847#endif
3848}
3849
3850/*!
3851 Dumps a tree of children to the debug output.
3852
3853 This function is useful for debugging, but does nothing if the
3854 library has been compiled in release mode (i.e. without debugging
3855 information).
3856
3857 \sa dumpObjectInfo()
3858*/
3859
3860void QObject::dumpObjectTree()
3861{
3862 dumpRecursive(0, this);
3863}
3864
3865/*!
3866 Dumps information about signal connections, etc. for this object
3867 to the debug output.
3868
3869 This function is useful for debugging, but does nothing if the
3870 library has been compiled in release mode (i.e. without debugging
3871 information).
3872
3873 \sa dumpObjectTree()
3874*/
3875
3876void QObject::dumpObjectInfo()
3877{
3878#if defined(QT_DEBUG)
3879 qDebug("OBJECT %s::%s", metaObject()->className(),
3880 objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
3881
3882 Q_D(QObject);
3883 QMutexLocker locker(signalSlotLock(this));
3884
3885 // first, look for connections where this object is the sender
3886 qDebug(" SIGNALS OUT");
3887
3888 if (d->connectionLists) {
3889 int offset = 0;
3890 int offsetToNextMetaObject = 0;
3891 for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
3892 if (signal_index >= offsetToNextMetaObject) {
3893 const QMetaObject *mo = metaObject();
3894 int signalOffset, methodOffset;
3895 computeOffsets(mo, &signalOffset, &methodOffset);
3896 while (signalOffset > signal_index) {
3897 mo = mo->superClass();
3898 offsetToNextMetaObject = signalOffset;
3899 computeOffsets(mo, &signalOffset, &methodOffset);
3900 }
3901 offset = methodOffset - signalOffset;
3902 }
3903 const QMetaMethod signal = metaObject()->method(signal_index + offset);
3904 qDebug(" signal: %s", signal.signature());
3905
3906 // receivers
3907 const QObjectPrivate::Connection *c =
3908 d->connectionLists->at(signal_index).first;
3909 while (c) {
3910 if (!c->receiver) {
3911 qDebug(" <Disconnected receiver>");
3912 c = c->nextConnectionList;
3913 continue;
3914 }
3915 const QMetaObject *receiverMetaObject = c->receiver->metaObject();
3916 const QMetaMethod method = receiverMetaObject->method(c->method());
3917 qDebug(" --> %s::%s %s",
3918 receiverMetaObject->className(),
3919 c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
3920 method.signature());
3921 c = c->nextConnectionList;
3922 }
3923 }
3924 } else {
3925 qDebug( " <None>" );
3926 }
3927
3928 // now look for connections where this object is the receiver
3929 qDebug(" SIGNALS IN");
3930
3931 if (d->senders) {
3932 for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
3933 const QMetaMethod slot = metaObject()->method(s->method());
3934 qDebug(" <-- %s::%s %s",
3935 s->sender->metaObject()->className(),
3936 s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
3937 slot.signature());
3938 }
3939 } else {
3940 qDebug(" <None>");
3941 }
3942#endif
3943}
3944
3945#ifndef QT_NO_USERDATA
3946/*!\internal
3947 */
3948uint QObject::registerUserData()
3949{
3950 static int user_data_registration = 0;
3951 return user_data_registration++;
3952}
3953
3954/*!\internal
3955 */
3956QObjectUserData::~QObjectUserData()
3957{
3958}
3959
3960/*!\internal
3961 */
3962void QObject::setUserData(uint id, QObjectUserData* data)
3963{
3964 Q_D(QObject);
3965 if (!d->extraData)
3966 d->extraData = new QObjectPrivate::ExtraData;
3967
3968 if (d->extraData->userData.size() <= (int) id)
3969 d->extraData->userData.resize((int) id + 1);
3970 d->extraData->userData[id] = data;
3971}
3972
3973/*!\internal
3974 */
3975QObjectUserData* QObject::userData(uint id) const
3976{
3977 Q_D(const QObject);
3978 if (!d->extraData)
3979 return 0;
3980 if ((int)id < d->extraData->userData.size())
3981 return d->extraData->userData.at(id);
3982 return 0;
3983}
3984
3985#endif // QT_NO_USERDATA
3986
3987
3988#ifndef QT_NO_DEBUG_STREAM
3989QDebug operator<<(QDebug dbg, const QObject *o) {
3990#ifndef Q_BROKEN_DEBUG_STREAM
3991 if (!o)
3992 return dbg << "QObject(0x0) ";
3993 dbg.nospace() << o->metaObject()->className() << '(' << (void *)o;
3994 if (!o->objectName().isEmpty())
3995 dbg << ", name = " << o->objectName();
3996 dbg << ')';
3997 return dbg.space();
3998#else
3999 qWarning("This compiler doesn't support streaming QObject to QDebug");
4000 return dbg;
4001 Q_UNUSED(o);
4002#endif
4003}
4004#endif
4005
4006/*!
4007 \fn void QObject::insertChild(QObject *object)
4008
4009 Use setParent() instead, i.e., call object->setParent(this).
4010*/
4011
4012/*!
4013 \fn void QObject::removeChild(QObject *object)
4014
4015 Use setParent() instead, i.e., call object->setParent(0).
4016*/
4017
4018/*!
4019 \fn bool QObject::isA(const char *className) const
4020
4021 Compare \a className with the object's metaObject()->className() instead.
4022*/
4023
4024/*!
4025 \fn const char *QObject::className() const
4026
4027 Use metaObject()->className() instead.
4028*/
4029
4030/*!
4031 \fn const char *QObject::name() const
4032
4033 Use objectName() instead.
4034*/
4035
4036/*!
4037 \fn const char *QObject::name(const char *defaultName) const
4038
4039 Use objectName() instead.
4040*/
4041
4042/*!
4043 \fn void QObject::setName(const char *name)
4044
4045 Use setObjectName() instead.
4046*/
4047
4048/*!
4049 \fn bool QObject::checkConnectArgs(const char *signal, const
4050 QObject *object, const char *method)
4051
4052 Use QMetaObject::checkConnectArgs() instead.
4053*/
4054
4055/*!
4056 \fn QByteArray QObject::normalizeSignalSlot(const char *signalSlot)
4057
4058 Use QMetaObject::normalizedSignature() instead.
4059*/
4060
4061/*!
4062 \fn const char *QMetaObject::superClassName() const
4063
4064 \internal
4065*/
4066
4067/*!
4068 \macro Q_CLASSINFO(Name, Value)
4069 \relates QObject
4070
4071 This macro associates extra information to the class, which is
4072 available using QObject::metaObject(). Except for the ActiveQt
4073 extension, Qt doesn't use this information.
4074
4075 The extra information takes the form of a \a Name string and a \a
4076 Value literal string.
4077
4078 Example:
4079
4080 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 35
4081
4082 \sa QMetaObject::classInfo()
4083*/
4084
4085/*!
4086 \macro Q_INTERFACES(...)
4087 \relates QObject
4088
4089 This macro tells Qt which interfaces the class implements. This
4090 is used when implementing plugins.
4091
4092 Example:
4093
4094 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
4095 \dots
4096 \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
4097
4098 See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint
4099 Basic Tools} example for details.
4100
4101 \sa Q_DECLARE_INTERFACE(), Q_EXPORT_PLUGIN2(), {How to Create Qt Plugins}
4102*/
4103
4104/*!
4105 \macro Q_PROPERTY(...)
4106 \relates QObject
4107
4108 This macro is used for declaring properties in classes that
4109 inherit QObject. Properties behave like class data members, but
4110 they have additional features accessible through the \l
4111 {Meta-Object System}.
4112
4113 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 36
4114
4115 The property name and type and the \c READ function are required.
4116 The type can be any type supported by QVariant, or it can be a
4117 user-defined type. The other items are optional, but a \c WRITE
4118 function is common. The attributes default to true except \c USER,
4119 which defaults to false.
4120
4121 For example:
4122
4123 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 37
4124
4125 For more details about how to use this macro, and a more detailed
4126 example of its use, see the discussion on \l {Qt's Property System}.
4127
4128 \sa {Qt's Property System}
4129*/
4130
4131/*!
4132 \macro Q_ENUMS(...)
4133 \relates QObject
4134
4135 This macro registers one or several enum types to the meta-object
4136 system.
4137
4138 For example:
4139
4140 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 38
4141
4142 If you want to register an enum that is declared in another class,
4143 the enum must be fully qualified with the name of the class
4144 defining it. In addition, the class \e defining the enum has to
4145 inherit QObject as well as declare the enum using Q_ENUMS().
4146
4147 \sa {Qt's Property System}
4148*/
4149
4150/*!
4151 \macro Q_FLAGS(...)
4152 \relates QObject
4153
4154 This macro registers one or several \l{QFlags}{flags types} to the
4155 meta-object system. It is typically used in a class definition to declare
4156 that values of a given enum can be used as flags and combined using the
4157 bitwise OR operator.
4158
4159 For example, in QLibrary, the \l{QLibrary::LoadHints}{LoadHints} flag is
4160 declared in the following way:
4161
4162 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39a
4163
4164 The declaration of the flags themselves is performed in the public section
4165 of the QLibrary class itself, using the \l Q_DECLARE_FLAGS() macro:
4166
4167 \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39b
4168
4169 \note This macro takes care of registering individual flag values
4170 with the meta-object system, so it is unnecessary to use Q_ENUMS()
4171 in addition to this macro.
4172
4173 \sa {Qt's Property System}
4174*/
4175
4176/*!
4177 \macro Q_OBJECT
4178 \relates QObject
4179
4180 The Q_OBJECT macro must appear in the private section of a class
4181 definition that declares its own signals and slots or that uses
4182 other services provided by Qt's meta-object system.
4183
4184 For example:
4185
4186 \snippet doc/src/snippets/signalsandslots/signalsandslots.h 1
4187 \codeline
4188 \snippet doc/src/snippets/signalsandslots/signalsandslots.h 2
4189 \snippet doc/src/snippets/signalsandslots/signalsandslots.h 3
4190
4191 \note This macro requires the class to be a subclass of QObject. Use
4192 Q_GADGET instead of Q_OBJECT to enable the meta object system's support
4193 for enums in a class that is not a QObject subclass. Q_GADGET makes a
4194 class member, \c{staticMetaObject}, available.
4195 \c{staticMetaObject} is of type QMetaObject and provides access to the
4196 enums declared with Q_ENUMS.
4197 Q_GADGET is provided only for C++.
4198
4199 \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
4200*/
4201
4202/*!
4203 \macro Q_SIGNALS
4204 \relates QObject
4205
4206 Use this macro to replace the \c signals keyword in class
4207 declarations, when you want to use Qt Signals and Slots with a
4208 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4209
4210 The macro is normally used when \c no_keywords is specified with
4211 the \c CONFIG variable in the \c .pro file, but it can be used
4212 even when \c no_keywords is \e not specified.
4213*/
4214
4215/*!
4216 \macro Q_SIGNAL
4217 \relates QObject
4218
4219 This is an additional macro that allows you to mark a single
4220 function as a signal. It can be quite useful, especially when you
4221 use a 3rd-party source code parser which doesn't understand a \c
4222 signals or \c Q_SIGNALS groups.
4223
4224 Use this macro to replace the \c signals keyword in class
4225 declarations, when you want to use Qt Signals and Slots with a
4226 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4227
4228 The macro is normally used when \c no_keywords is specified with
4229 the \c CONFIG variable in the \c .pro file, but it can be used
4230 even when \c no_keywords is \e not specified.
4231*/
4232
4233/*!
4234 \macro Q_SLOTS
4235 \relates QObject
4236
4237 Use this macro to replace the \c slots keyword in class
4238 declarations, when you want to use Qt Signals and Slots with a
4239 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4240
4241 The macro is normally used when \c no_keywords is specified with
4242 the \c CONFIG variable in the \c .pro file, but it can be used
4243 even when \c no_keywords is \e not specified.
4244*/
4245
4246/*!
4247 \macro Q_SLOT
4248 \relates QObject
4249
4250 This is an additional macro that allows you to mark a single
4251 function as a slot. It can be quite useful, especially when you
4252 use a 3rd-party source code parser which doesn't understand a \c
4253 slots or \c Q_SLOTS groups.
4254
4255 Use this macro to replace the \c slots keyword in class
4256 declarations, when you want to use Qt Signals and Slots with a
4257 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4258
4259 The macro is normally used when \c no_keywords is specified with
4260 the \c CONFIG variable in the \c .pro file, but it can be used
4261 even when \c no_keywords is \e not specified.
4262*/
4263
4264/*!
4265 \macro Q_EMIT
4266 \relates QObject
4267
4268 Use this macro to replace the \c emit keyword for emitting
4269 signals, when you want to use Qt Signals and Slots with a
4270 \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
4271
4272 The macro is normally used when \c no_keywords is specified with
4273 the \c CONFIG variable in the \c .pro file, but it can be used
4274 even when \c no_keywords is \e not specified.
4275*/
4276
4277/*!
4278 \macro Q_INVOKABLE
4279 \relates QObject
4280
4281 Apply this macro to definitions of member functions to allow them to
4282 be invoked via the meta-object system. The macro is written before
4283 the return type, as shown in the following example:
4284
4285 \snippet snippets/qmetaobject-invokable/window.h Window class with invokable method
4286
4287 The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
4288 it to be registered with the meta-object system and enabling it to be
4289 invoked using QMetaObject::invokeMethod().
4290 Since \c normalMethod() function is not registered in this way, it cannot
4291 be invoked using QMetaObject::invokeMethod().
4292*/
4293
4294/*!
4295 \typedef QObjectList
4296 \relates QObject
4297
4298 Synonym for QList<QObject *>.
4299*/
4300
4301void qDeleteInEventHandler(QObject *o)
4302{
4303#ifdef QT_JAMBI_BUILD
4304 if (!o)
4305 return;
4306 QObjectPrivate::get(o)->inEventHandler = false;
4307#endif
4308 delete o;
4309}
4310
4311
4312QT_END_NAMESPACE
4313
4314#include "moc_qobject.cpp"
4315