1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #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 | #include "QtCore/qmetaobject.h" |
65 | #include "QtCore/qvarlengtharray.h" |
66 | |
67 | QT_BEGIN_NAMESPACE |
68 | |
69 | class QVariant; |
70 | class QThreadData; |
71 | class QObjectConnectionListVector; |
72 | namespace QtSharedPointer { struct ExternalRefCountData; } |
73 | |
74 | /* mirrored in QtTestLib, DON'T CHANGE without prior warning */ |
75 | struct QSignalSpyCallbackSet |
76 | { |
77 | typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv); |
78 | typedef void (*EndCallback)(QObject *caller, int method_index); |
79 | BeginCallback signal_begin_callback, |
80 | slot_begin_callback; |
81 | EndCallback signal_end_callback, |
82 | slot_end_callback; |
83 | }; |
84 | void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set); |
85 | |
86 | extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set; |
87 | |
88 | enum { QObjectPrivateVersion = QT_VERSION }; |
89 | |
90 | class Q_CORE_EXPORT QAbstractDeclarativeData |
91 | { |
92 | public: |
93 | static void (*destroyed)(QAbstractDeclarativeData *, QObject *); |
94 | static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); |
95 | static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *); |
96 | }; |
97 | |
98 | class Q_CORE_EXPORT QObjectPrivate : public QObjectData |
99 | { |
100 | Q_DECLARE_PUBLIC(QObject) |
101 | |
102 | public: |
103 | struct |
104 | { |
105 | () {} |
106 | #ifndef QT_NO_USERDATA |
107 | QVector<QObjectUserData *> ; |
108 | #endif |
109 | QList<QByteArray> ; |
110 | QList<QVariant> ; |
111 | }; |
112 | |
113 | typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); |
114 | struct Connection |
115 | { |
116 | QObject *sender; |
117 | QObject *receiver; |
118 | StaticMetaCallFunction callFunction; |
119 | // The next pointer for the singly-linked ConnectionList |
120 | Connection *nextConnectionList; |
121 | //senders linked list |
122 | Connection *next; |
123 | Connection **prev; |
124 | QBasicAtomicPointer<int> argumentTypes; |
125 | ushort method_offset; |
126 | ushort method_relative; |
127 | ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking |
128 | ~Connection(); |
129 | int method() const { return method_offset + method_relative; } |
130 | }; |
131 | // ConnectionList is a singly-linked list |
132 | struct ConnectionList { |
133 | ConnectionList() : first(0), last(0) {} |
134 | Connection *first; |
135 | Connection *last; |
136 | }; |
137 | |
138 | struct Sender |
139 | { |
140 | QObject *sender; |
141 | int signal; |
142 | int ref; |
143 | }; |
144 | |
145 | |
146 | QObjectPrivate(int version = QObjectPrivateVersion); |
147 | virtual ~QObjectPrivate(); |
148 | void deleteChildren(); |
149 | |
150 | void setParent_helper(QObject *); |
151 | void moveToThread_helper(); |
152 | void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); |
153 | void _q_reregisterTimers(void *pointer); |
154 | |
155 | bool isSender(const QObject *receiver, const char *signal) const; |
156 | QObjectList receiverList(const char *signal) const; |
157 | QObjectList senderList() const; |
158 | |
159 | void addConnection(int signal, Connection *c); |
160 | void cleanConnectionLists(); |
161 | |
162 | #ifdef QT3_SUPPORT |
163 | void sendPendingChildInsertedEvents(); |
164 | #endif |
165 | |
166 | static inline Sender *setCurrentSender(QObject *receiver, |
167 | Sender *sender); |
168 | static inline void resetCurrentSender(QObject *receiver, |
169 | Sender *currentSender, |
170 | Sender *previousSender); |
171 | #ifdef QT_JAMBI_BUILD |
172 | static int *setDeleteWatch(QObjectPrivate *d, int *newWatch); |
173 | static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); |
174 | #endif |
175 | static void clearGuards(QObject *); |
176 | |
177 | static QObjectPrivate *get(QObject *o) { |
178 | return o->d_func(); |
179 | } |
180 | |
181 | int signalIndex(const char *signalName) const; |
182 | inline bool isSignalConnected(uint signalIdx) const; |
183 | |
184 | // To allow arbitrary objects to call connectNotify()/disconnectNotify() without making |
185 | // the API public in QObject. This is used by QDeclarativeNotifierEndpoint. |
186 | inline void connectNotify(const char *signal); |
187 | inline void disconnectNotify(const char *signal); |
188 | |
189 | static inline void signalSignature(const QMetaMethod &signal, |
190 | QVarLengthArray<char> *result); |
191 | |
192 | public: |
193 | QString objectName; |
194 | ExtraData *; // extra data set by the user |
195 | QThreadData *threadData; // id of the thread that owns the object |
196 | |
197 | QObjectConnectionListVector *connectionLists; |
198 | |
199 | Connection *senders; // linked list of connections connected to this object |
200 | Sender *currentSender; // object currently activating the object |
201 | mutable quint32 connectedSignals[2]; |
202 | |
203 | #ifdef QT3_SUPPORT |
204 | QVector< QWeakPointer<QObject> > pendingChildInsertedEvents; |
205 | #else |
206 | // preserve binary compatibility with code compiled without Qt 3 support |
207 | // keeping the binary layout stable helps the Qt Creator debugger |
208 | void *unused; |
209 | #endif |
210 | |
211 | QList<QPointer<QObject> > eventFilters; |
212 | union { |
213 | QObject *currentChildBeingDeleted; |
214 | QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module |
215 | }; |
216 | |
217 | // these objects are all used to indicate that a QObject was deleted |
218 | // plus QPointer, which keeps a separate list |
219 | QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount; |
220 | #ifdef QT_JAMBI_BUILD |
221 | int *deleteWatch; |
222 | #endif |
223 | }; |
224 | |
225 | |
226 | /*! \internal |
227 | |
228 | Returns true if the signal with index \a signal_index from object \a sender is connected. |
229 | Signals with indices above a certain range are always considered connected (see connectedSignals |
230 | in QObjectPrivate). If a signal spy is installed, all signals are considered connected. |
231 | |
232 | \a signal_index must be the index returned by QObjectPrivate::signalIndex; |
233 | */ |
234 | inline bool QObjectPrivate::isSignalConnected(uint signal_index) const |
235 | { |
236 | return signal_index >= sizeof(connectedSignals) * 8 |
237 | || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f)) |
238 | || qt_signal_spy_callback_set.signal_begin_callback |
239 | || qt_signal_spy_callback_set.signal_end_callback); |
240 | } |
241 | |
242 | inline void QObjectPrivate::connectNotify(const char *signal) |
243 | { |
244 | q_ptr->connectNotify(signal); |
245 | } |
246 | |
247 | inline void QObjectPrivate::disconnectNotify(const char *signal) |
248 | { |
249 | q_ptr->disconnectNotify(signal); |
250 | } |
251 | |
252 | inline void QObjectPrivate::signalSignature(const QMetaMethod &signal, |
253 | QVarLengthArray<char> *result) |
254 | { |
255 | Q_ASSERT(result); |
256 | const int signatureLength = qstrlen(signal.signature()); |
257 | if (signatureLength == 0) { |
258 | result->append((char)0); |
259 | return; |
260 | } |
261 | result->reserve(signatureLength + 2); |
262 | result->append((char)(QSIGNAL_CODE + '0')); |
263 | result->append(signal.signature(), signatureLength + 1); |
264 | } |
265 | |
266 | inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver, |
267 | Sender *sender) |
268 | { |
269 | Sender *previousSender = receiver->d_func()->currentSender; |
270 | receiver->d_func()->currentSender = sender; |
271 | return previousSender; |
272 | } |
273 | |
274 | inline void QObjectPrivate::resetCurrentSender(QObject *receiver, |
275 | Sender *currentSender, |
276 | Sender *previousSender) |
277 | { |
278 | // ref is set to zero when this object is deleted during the metacall |
279 | if (currentSender->ref == 1) |
280 | receiver->d_func()->currentSender = previousSender; |
281 | // if we've recursed, we need to tell the caller about the objects deletion |
282 | if (previousSender) |
283 | previousSender->ref = currentSender->ref; |
284 | } |
285 | |
286 | |
287 | Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); |
288 | Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); |
289 | |
290 | class QSemaphore; |
291 | class Q_CORE_EXPORT QMetaCallEvent : public QEvent |
292 | { |
293 | public: |
294 | QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId, |
295 | int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0); |
296 | ~QMetaCallEvent(); |
297 | |
298 | inline int id() const { return method_offset_ + method_relative_; } |
299 | inline const QObject *sender() const { return sender_; } |
300 | inline int signalId() const { return signalId_; } |
301 | inline void **args() const { return args_; } |
302 | |
303 | virtual void placeMetaCall(QObject *object); |
304 | |
305 | private: |
306 | const QObject *sender_; |
307 | int signalId_; |
308 | int nargs_; |
309 | int *types_; |
310 | void **args_; |
311 | QSemaphore *semaphore_; |
312 | QObjectPrivate::StaticMetaCallFunction callFunction_; |
313 | ushort method_offset_; |
314 | ushort method_relative_; |
315 | }; |
316 | |
317 | class QBoolBlocker |
318 | { |
319 | public: |
320 | inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;} |
321 | inline ~QBoolBlocker(){block = reset; } |
322 | private: |
323 | bool █ |
324 | bool reset; |
325 | }; |
326 | |
327 | void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); |
328 | |
329 | |
330 | struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject |
331 | { |
332 | virtual ~QAbstractDynamicMetaObject() {} |
333 | virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } |
334 | virtual int createProperty(const char *, const char *) { return -1; } |
335 | }; |
336 | |
337 | QT_END_NAMESPACE |
338 | |
339 | #endif // QOBJECT_P_H |
340 | |