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