1
/****************************************************************************
2
**
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
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
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.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
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.
29
**
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.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
#ifndef QOBJECT_P_H
43
#define QOBJECT_P_H
44
45
//
46
//  W A R N I N G
47
//  -------------
48
//
49
// This file is not part of the Qt API.  It exists for the convenience
50
// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
51
// file may change from version to version without notice, or even be removed.
52
//
53
// We mean it.
54
//
55
56
#include "QtCore/qobject.h"
57
#include "QtCore/qpointer.h"
58
#include "QtCore/qsharedpointer.h"
59
#include "QtCore/qcoreevent.h"
60
#include "QtCore/qlist.h"
61
#include "QtCore/qvector.h"
62
#include "QtCore/qreadwritelock.h"
63
#include "QtCore/qvariant.h"
64
65
QT_BEGIN_NAMESPACE
66
67
class QVariant;
68
class QThreadData;
69
class QObjectConnectionListVector;
70
namespace QtSharedPointer { struct ExternalRefCountData; }
71
72
/* mirrored in QtTestLib, DON'T CHANGE without prior warning */
73
struct QSignalSpyCallbackSet
74
{
75
    typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv);
76
    typedef void (*EndCallback)(QObject *caller, int method_index);
77
    BeginCallback signal_begin_callback,
78
                    slot_begin_callback;
79
    EndCallback signal_end_callback,
80
                slot_end_callback;
81
};
82
void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
83
84
extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
85
86
enum { QObjectPrivateVersion = QT_VERSION };
87
88
class Q_CORE_EXPORT QAbstractDeclarativeData
89
{
90
public:
91
    static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
92
    static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
93
    static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *);
94
};
95
96
class Q_CORE_EXPORT QObjectPrivate : public QObjectData
97
{
98
    Q_DECLARE_PUBLIC(QObject)
99
100
public:
101
    struct ExtraData
102
    {
103
        ExtraData() {}
104
#ifndef QT_NO_USERDATA
105
        QVector<QObjectUserData *> userData;
106
#endif
107
        QList<QByteArray> propertyNames;
108
        QList<QVariant> propertyValues;
109
    };
110
111
    typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
112
    struct Connection
113
    {
114
        QObject *sender;
115
        QObject *receiver;
116
        StaticMetaCallFunction callFunction;
117
        // The next pointer for the singly-linked ConnectionList
118
        Connection *nextConnectionList;
119
        //senders linked list
120
        Connection *next;
121
        Connection **prev;
122
        QBasicAtomicPointer<int> argumentTypes;
123
        ushort method_offset;
124
        ushort method_relative;
125
        ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
126
        ~Connection();
127
        int method() const { return method_offset + method_relative; }
128
    };
129
    // ConnectionList is a singly-linked list
130
    struct ConnectionList {
131
        ConnectionList() : first(0), last(0) {}
132
        Connection *first;
133
        Connection *last;
134
    };
135
136
    struct Sender
137
    {
138
        QObject *sender;
139
        int signal;
140
        int ref;
141
    };
142
143
144
    QObjectPrivate(int version = QObjectPrivateVersion);
145
    virtual ~QObjectPrivate();
146
    void deleteChildren();
147
148
    void setParent_helper(QObject *);
149
    void moveToThread_helper();
150
    void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
151
    void _q_reregisterTimers(void *pointer);
152
153
    bool isSender(const QObject *receiver, const char *signal) const;
154
    QObjectList receiverList(const char *signal) const;
155
    QObjectList senderList() const;
156
157
    void addConnection(int signal, Connection *c);
158
    void cleanConnectionLists();
159
160
#ifdef QT3_SUPPORT
161
    void sendPendingChildInsertedEvents();
162
#endif
163
164
    static inline Sender *setCurrentSender(QObject *receiver,
165
                                    Sender *sender);
166
    static inline void resetCurrentSender(QObject *receiver,
167
                                   Sender *currentSender,
168
                                   Sender *previousSender);
169
#ifdef QT_JAMBI_BUILD
170
    static int *setDeleteWatch(QObjectPrivate *d, int *newWatch);
171
    static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch);
172
#endif
173
    static void clearGuards(QObject *);
174
175
    static QObjectPrivate *get(QObject *o) {
176
        return o->d_func();
177
    }
178
179
    int signalIndex(const char *signalName) const;
180
    inline bool isSignalConnected(uint signalIdx) const;
181
182
public:
183
    QString objectName;
184
    ExtraData *extraData;    // extra data set by the user
185
    QThreadData *threadData; // id of the thread that owns the object
186
187
    QObjectConnectionListVector *connectionLists;
188
189
    Connection *senders;     // linked list of connections connected to this object
190
    Sender *currentSender;   // object currently activating the object
191
    mutable quint32 connectedSignals[2];
192
193
#ifdef QT3_SUPPORT
194
    QVector< QWeakPointer<QObject> > pendingChildInsertedEvents;
195
#else
196
    // preserve binary compatibility with code compiled without Qt 3 support
197
    // keeping the binary layout stable helps the Qt Creator debugger
198
    void *unused;
199
#endif
200
201
    QList<QPointer<QObject> > eventFilters;
202
    union {
203
        QObject *currentChildBeingDeleted;
204
        QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
205
    };
206
207
    // these objects are all used to indicate that a QObject was deleted
208
    // plus QPointer, which keeps a separate list
209
    QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
210
#ifdef QT_JAMBI_BUILD
211
    int *deleteWatch;
212
#endif
213
};
214
215
216
/*! \internal
217
218
  Returns true if the signal with index \a signal_index from object \a sender is connected.
219
  Signals with indices above a certain range are always considered connected (see connectedSignals
220
  in QObjectPrivate). If a signal spy is installed, all signals are considered connected.
221
222
  \a signal_index must be the index returned by QObjectPrivate::signalIndex;
223
*/
224
inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
225
{
226
    return signal_index >= sizeof(connectedSignals) * 8
227
        || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
228
        || qt_signal_spy_callback_set.signal_begin_callback
229
        || qt_signal_spy_callback_set.signal_end_callback);
230
}
231
232
inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
233
                                                         Sender *sender)
234
{
235
    Sender *previousSender = receiver->d_func()->currentSender;
236
    receiver->d_func()->currentSender = sender;
237
    return previousSender;
238
}
239
240
inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
241
                                        Sender *currentSender,
242
                                        Sender *previousSender)
243
{
244
    // ref is set to zero when this object is deleted during the metacall
245
    if (currentSender->ref == 1)
246
        receiver->d_func()->currentSender = previousSender;
247
    // if we've recursed, we need to tell the caller about the objects deletion
248
    if (previousSender)
249
        previousSender->ref = currentSender->ref;
250
}
251
252
253
Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
254
Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
255
256
class QSemaphore;
257
class Q_CORE_EXPORT QMetaCallEvent : public QEvent
258
{
259
public:
260
    QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
261
                   int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
262
    ~QMetaCallEvent();
263
264
    inline int id() const { return method_offset_ + method_relative_; }
265
    inline const QObject *sender() const { return sender_; }
266
    inline int signalId() const { return signalId_; }
267
    inline void **args() const { return args_; }
268
269
    virtual void placeMetaCall(QObject *object);
270
271
private:
272
    const QObject *sender_;
273
    int signalId_;
274
    int nargs_;
275
    int *types_;
276
    void **args_;
277
    QSemaphore *semaphore_;
278
    QObjectPrivate::StaticMetaCallFunction callFunction_;
279
    ushort method_offset_;
280
    ushort method_relative_;
281
};
282
283
class QBoolBlocker
284
{
285
public:
286
    inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
287
    inline ~QBoolBlocker(){block = reset; }
288
private:
289
    bool &block;
290
    bool reset;
291
};
292
293
void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
294
295
296
struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
297
{
298
    virtual ~QAbstractDynamicMetaObject() {}
299
    virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
300
    virtual int createProperty(const char *, const char *) { return -1; }
301
};
302
303
QT_END_NAMESPACE
304
305
#endif // QOBJECT_P_H