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