Docs - add missing images and code, clean up sections
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlnotifier_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
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     if (sourceSignal != -1) {
193         QObject * const obj = senderAsObject();
194         QObjectPrivate * const priv = QObjectPrivate::get(obj);
195         priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal));
196     }
197     if (next) next->prev = prev;
198     if (prev) *prev = next;
199     if (isNotifying()) *((intptr_t *)(senderPtr & ~0x1)) = 0;
200     next = 0;
201     prev = 0;
202     senderPtr = 0;
203     sourceSignal = -1;
204 }
205
206 /*!
207 Returns true if a notify is in progress.  This means that the signal or QQmlNotifier
208 that this endpoing is connected to has been triggered, but this endpoint's callback has not
209 yet been called.
210
211 An in progress notify can be cancelled by calling cancelNotify.
212 */
213 bool QQmlNotifierEndpoint::isNotifying() const
214 {
215     return senderPtr & 0x1;
216 }
217
218 /*!
219 Cancel any notifies that are in progress.
220 */
221 void QQmlNotifierEndpoint::cancelNotify() 
222 {
223     if (isNotifying()) {
224         intptr_t sp = *((intptr_t *)(senderPtr & ~0x1));
225         *((intptr_t *)(senderPtr & ~0x1)) = 0;
226         senderPtr = sp;
227     }
228 }
229
230 QObject *QQmlNotifierEndpoint::senderAsObject() const
231 {
232     return isNotifying()?((QObject *)(*((intptr_t *)(senderPtr & ~0x1)))):((QObject *)senderPtr);
233 }
234
235 QQmlNotifier *QQmlNotifierEndpoint::senderAsNotifier() const
236 {
237     return isNotifying()?((QQmlNotifier *)(*((intptr_t *)(senderPtr & ~0x1)))):((QQmlNotifier *)senderPtr);
238 }
239
240 QT_END_NAMESPACE
241
242 #endif // QQMLNOTIFIER_P_H
243