1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #ifndef QQMLNOTIFIER_P_H
43 #define QQMLNOTIFIER_P_H
45 #include "qqmldata_p.h"
46 #include "qqmlguard_p.h"
47 #include <QtCore/qmetaobject.h>
48 #include <private/qmetaobject_p.h>
52 class QQmlNotifierEndpoint;
53 class Q_QML_PRIVATE_EXPORT QQmlNotifier
56 inline QQmlNotifier();
57 inline ~QQmlNotifier();
61 friend class QQmlData;
62 friend class QQmlNotifierEndpoint;
63 friend class QQmlThreadNotifierProxyObject;
65 static void emitNotify(QQmlNotifierEndpoint *, void **a);
66 QQmlNotifierEndpoint *endpoints;
70 class QQmlNotifierEndpoint
73 inline QQmlNotifierEndpoint();
74 inline ~QQmlNotifierEndpoint();
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).
83 QQmlJavaScriptExpressionGuard = 2,
84 QQmlVMEMetaObjectEndpoint = 3,
85 QV4BindingsSubscription = 4
88 inline void setCallback(Callback c) { callback = c; }
90 inline bool isConnected();
91 inline bool isConnected(QObject *source, int sourceSignal);
92 inline bool isConnected(QQmlNotifier *);
94 void connect(QObject *source, int sourceSignal, QQmlEngine *engine);
95 inline void connect(QQmlNotifier *);
96 inline void disconnect();
98 inline bool isNotifying() const;
99 inline void cancelNotify();
102 friend class QQmlData;
103 friend class QQmlNotifier;
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.
109 inline QObject *senderAsObject() const;
110 inline QQmlNotifier *senderAsNotifier() const;
113 // The index is in the range returned by QObjectPrivate::signalIndex().
114 // This is different from QMetaMethod::methodIndex().
115 signed int sourceSignal:28;
117 QQmlNotifierEndpoint *next;
118 QQmlNotifierEndpoint **prev;
121 QQmlNotifier::QQmlNotifier()
126 QQmlNotifier::~QQmlNotifier()
128 QQmlNotifierEndpoint *endpoint = endpoints;
130 QQmlNotifierEndpoint *n = endpoint;
133 if (n->isNotifying()) *((intptr_t *)(n->senderPtr & ~0x1)) = 0;
138 n->sourceSignal = -1;
143 void QQmlNotifier::notify()
145 void *args[] = { 0 };
146 if (endpoints) emitNotify(endpoints, args);
149 QQmlNotifierEndpoint::QQmlNotifierEndpoint()
150 : senderPtr(0), callback(None), sourceSignal(-1), next(0), prev(0)
154 QQmlNotifierEndpoint::~QQmlNotifierEndpoint()
159 bool QQmlNotifierEndpoint::isConnected()
165 \a sourceSignal MUST be in the signal index range (see QObjectPrivate::signalIndex()).
166 This is different from QMetaMethod::methodIndex().
168 bool QQmlNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
170 return this->sourceSignal != -1 && senderAsObject() == source &&
171 this->sourceSignal == sourceSignal;
174 bool QQmlNotifierEndpoint::isConnected(QQmlNotifier *notifier)
176 return sourceSignal == -1 && senderAsNotifier() == notifier;
179 void QQmlNotifierEndpoint::connect(QQmlNotifier *notifier)
183 next = notifier->endpoints;
184 if (next) { next->prev = &next; }
185 notifier->endpoints = this;
186 prev = ¬ifier->endpoints;
187 senderPtr = intptr_t(notifier);
190 void QQmlNotifierEndpoint::disconnect()
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;
197 if (sourceSignal != -1) {
198 QObject * const obj = senderAsObject();
199 QObjectPrivate * const priv = QObjectPrivate::get(obj);
200 priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal));
203 if (isNotifying()) *((intptr_t *)(senderPtr & ~0x1)) = 0;
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
215 An in progress notify can be cancelled by calling cancelNotify.
217 bool QQmlNotifierEndpoint::isNotifying() const
219 return senderPtr & 0x1;
223 Cancel any notifies that are in progress.
225 void QQmlNotifierEndpoint::cancelNotify()
228 intptr_t sp = *((intptr_t *)(senderPtr & ~0x1));
229 *((intptr_t *)(senderPtr & ~0x1)) = 0;
234 QObject *QQmlNotifierEndpoint::senderAsObject() const
236 return isNotifying()?((QObject *)(*((intptr_t *)(senderPtr & ~0x1)))):((QObject *)senderPtr);
239 QQmlNotifier *QQmlNotifierEndpoint::senderAsNotifier() const
241 return isNotifying()?((QQmlNotifier *)(*((intptr_t *)(senderPtr & ~0x1)))):((QQmlNotifier *)senderPtr);
246 #endif // QQMLNOTIFIER_P_H