Improve documentation.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlnotifier_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml 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 QQMLNOTIFIER_P_H
43 #define QQMLNOTIFIER_P_H
44
45 #include "qqmldata_p.h"
46 #include "qqmlguard_p.h"
47 #include <QtCore/qmetaobject.h>
48 #include <private/qmetaobject_p.h>
49
50 QT_BEGIN_NAMESPACE
51
52 class QQmlNotifierEndpoint;
53 class Q_QML_PRIVATE_EXPORT QQmlNotifier
54 {
55 public:
56     inline QQmlNotifier();
57     inline ~QQmlNotifier();
58     inline void notify();
59
60 private:
61     friend class QQmlData;
62     friend class QQmlNotifierEndpoint;
63     friend class QQmlThreadNotifierProxyObject;
64
65     static void emitNotify(QQmlNotifierEndpoint *, void **a);
66     QQmlNotifierEndpoint *endpoints;
67 };
68
69 class QQmlEngine;
70 class QQmlNotifierEndpoint
71 {
72 public:
73     inline QQmlNotifierEndpoint();
74     inline ~QQmlNotifierEndpoint();
75
76     // QQmlNotifierEndpoint can only invoke one of a set of pre-defined callbacks.
77     // To add another callback, extend this enum and add the callback to the top
78     // of qqmlnotifier.cpp.  Four bits are reserved for the callback, so there can
79     // be up to 15 of them (0 is reserved).
80     enum Callback {
81         None = 0,
82         QQmlBoundSignal = 1,
83         QQmlJavaScriptExpressionGuard = 2,
84         QQmlVMEMetaObjectEndpoint = 3,
85         QV4BindingsSubscription = 4
86     };
87
88     inline void setCallback(Callback c) { callback = c; }
89
90     inline bool isConnected();
91     inline bool isConnected(QObject *source, int sourceSignal);
92     inline bool isConnected(QQmlNotifier *);
93
94     void connect(QObject *source, int sourceSignal, QQmlEngine *engine);
95     inline void connect(QQmlNotifier *);
96     inline void disconnect();
97
98     inline bool isNotifying() const;
99     inline void cancelNotify();
100
101 private:
102     friend class QQmlData;
103     friend class QQmlNotifier;
104
105     // Contains either the QObject*, or the QQmlNotifier* that this
106     // endpoint is connected to.  While the endpoint is notifying, the
107     // senderPtr points to another intptr_t that contains this value.
108     intptr_t senderPtr;
109     inline QObject *senderAsObject() const;
110     inline QQmlNotifier *senderAsNotifier() const;
111
112     Callback callback:4;
113     // The index is in the range returned by QObjectPrivate::signalIndex().
114     // This is different from QMetaMethod::methodIndex().
115     signed int sourceSignal:28;
116
117     QQmlNotifierEndpoint  *next;
118     QQmlNotifierEndpoint **prev;
119 };
120
121 QQmlNotifier::QQmlNotifier()
122 : endpoints(0)
123 {
124 }
125
126 QQmlNotifier::~QQmlNotifier()
127 {    
128     QQmlNotifierEndpoint *endpoint = endpoints;
129     while (endpoint) {
130         QQmlNotifierEndpoint *n = endpoint;
131         endpoint = n->next;
132
133         if (n->isNotifying()) *((intptr_t *)(n->senderPtr & ~0x1)) = 0;
134
135         n->next = 0;
136         n->prev = 0;
137         n->senderPtr = 0;
138         n->sourceSignal = -1;
139     }
140     endpoints = 0;
141 }
142
143 void QQmlNotifier::notify()
144 {
145     void *args[] = { 0 };
146     if (endpoints) emitNotify(endpoints, args);
147 }
148
149 QQmlNotifierEndpoint::QQmlNotifierEndpoint()
150 : senderPtr(0), callback(None), sourceSignal(-1), next(0), prev(0)
151 {
152 }
153
154 QQmlNotifierEndpoint::~QQmlNotifierEndpoint()
155 {
156     disconnect();
157 }
158
159 bool QQmlNotifierEndpoint::isConnected()
160 {
161     return prev != 0;
162 }
163
164 /*! \internal
165     \a sourceSignal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
166     This is different from QMetaMethod::methodIndex().
167 */
168 bool QQmlNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
169 {
170     return this->sourceSignal != -1 && senderAsObject() == source &&
171            this->sourceSignal == sourceSignal;
172 }
173
174 bool QQmlNotifierEndpoint::isConnected(QQmlNotifier *notifier)
175 {
176     return sourceSignal == -1 && senderAsNotifier() == notifier;
177 }
178
179 void QQmlNotifierEndpoint::connect(QQmlNotifier *notifier)
180 {
181     disconnect();
182
183     next = notifier->endpoints;
184     if (next) { next->prev = &next; }
185     notifier->endpoints = this;
186     prev = &notifier->endpoints;
187     senderPtr = intptr_t(notifier);
188 }
189
190 void QQmlNotifierEndpoint::disconnect()
191 {
192     // Remove from notifier chain before calling disconnectNotify(), so that that
193     // QObject::receivers() returns the correct value in there
194     if (next) next->prev = prev;
195     if (prev) *prev = next;
196
197     if (sourceSignal != -1) {
198         QObject * const obj = senderAsObject();
199         QObjectPrivate * const priv = QObjectPrivate::get(obj);
200         priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal));
201     }
202
203     if (isNotifying()) *((intptr_t *)(senderPtr & ~0x1)) = 0;
204     next = 0;
205     prev = 0;
206     senderPtr = 0;
207     sourceSignal = -1;
208 }
209
210 /*!
211 Returns true if a notify is in progress.  This means that the signal or QQmlNotifier
212 that this endpoing is connected to has been triggered, but this endpoint's callback has not
213 yet been called.
214
215 An in progress notify can be cancelled by calling cancelNotify.
216 */
217 bool QQmlNotifierEndpoint::isNotifying() const
218 {
219     return senderPtr & 0x1;
220 }
221
222 /*!
223 Cancel any notifies that are in progress.
224 */
225 void QQmlNotifierEndpoint::cancelNotify() 
226 {
227     if (isNotifying()) {
228         intptr_t sp = *((intptr_t *)(senderPtr & ~0x1));
229         *((intptr_t *)(senderPtr & ~0x1)) = 0;
230         senderPtr = sp;
231     }
232 }
233
234 QObject *QQmlNotifierEndpoint::senderAsObject() const
235 {
236     return isNotifying()?((QObject *)(*((intptr_t *)(senderPtr & ~0x1)))):((QObject *)senderPtr);
237 }
238
239 QQmlNotifier *QQmlNotifierEndpoint::senderAsNotifier() const
240 {
241     return isNotifying()?((QQmlNotifier *)(*((intptr_t *)(senderPtr & ~0x1)))):((QQmlNotifier *)senderPtr);
242 }
243
244 QT_END_NAMESPACE
245
246 #endif // QQMLNOTIFIER_P_H
247