Fix aliasing bug when compiled with gcc 4.6
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativenotifier_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QDECLARATIVENOTIFIER_P_H
43 #define QDECLARATIVENOTIFIER_P_H
44
45 #include "private/qdeclarativeguard_p.h"
46
47 QT_BEGIN_NAMESPACE
48
49 class QDeclarativeNotifierEndpoint;
50 class Q_DECLARATIVE_EXPORT QDeclarativeNotifier
51 {
52 public:
53     inline QDeclarativeNotifier();
54     inline ~QDeclarativeNotifier();
55     inline void notify();
56
57 private:
58     friend class QDeclarativeNotifierEndpoint;
59
60     static void emitNotify(QDeclarativeNotifierEndpoint *);
61     QDeclarativeNotifierEndpoint *endpoints;
62 };
63
64 class QDeclarativeNotifierEndpoint
65 {
66 public:
67     inline QDeclarativeNotifierEndpoint();
68     inline QDeclarativeNotifierEndpoint(QObject *t, int m);
69     inline ~QDeclarativeNotifierEndpoint();
70
71     QObject *target;
72     int targetMethod;
73
74     inline bool isConnected();
75     inline bool isConnected(QObject *source, int sourceSignal);
76     inline bool isConnected(QDeclarativeNotifier *);
77
78     void connect(QObject *source, int sourceSignal);
79     inline void connect(QDeclarativeNotifier *);
80     inline void disconnect();
81
82     void copyAndClear(QDeclarativeNotifierEndpoint &other);
83
84 private:
85     friend class QDeclarativeNotifier;
86
87     struct Signal {
88         QDeclarativeGuard<QObject> source;
89         int sourceSignal;
90     };
91
92     struct Notifier {
93         QDeclarativeNotifier *notifier;
94         QDeclarativeNotifierEndpoint **disconnected;
95
96         QDeclarativeNotifierEndpoint  *next;
97         QDeclarativeNotifierEndpoint **prev;
98     };
99
100     enum { InvalidType, SignalType, NotifierType } type;
101     union {
102         struct {
103             Signal *signal;
104             union {
105                 char signalData[sizeof(Signal)];
106                 qint64 q_for_alignment_1;
107                 double q_for_alignment_2;
108             };
109         };
110         Notifier notifier;
111     };
112
113     inline Notifier *toNotifier();
114     inline Notifier *asNotifier();
115     inline Signal *toSignal();
116     inline Signal *asSignal();
117 };
118
119 QDeclarativeNotifier::QDeclarativeNotifier()
120 : endpoints(0)
121 {
122 }
123
124 QDeclarativeNotifier::~QDeclarativeNotifier()
125 {    
126     QDeclarativeNotifierEndpoint *endpoint = endpoints;
127     while (endpoint) {
128         QDeclarativeNotifierEndpoint::Notifier *n = endpoint->asNotifier();
129         endpoint = n->next;
130
131         n->next = 0;
132         n->prev = 0;
133         n->notifier = 0;
134         if (n->disconnected) *n->disconnected = 0;
135         n->disconnected = 0;
136     }
137     endpoints = 0;
138 }
139
140 void QDeclarativeNotifier::notify()
141 {
142     if (endpoints) emitNotify(endpoints);
143 }
144
145 QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint()
146 : target(0), targetMethod(0), type(InvalidType) 
147 {
148 }
149
150 QDeclarativeNotifierEndpoint::QDeclarativeNotifierEndpoint(QObject *t, int m)
151 : target(t), targetMethod(m), type(InvalidType) 
152 {
153 }
154
155 QDeclarativeNotifierEndpoint::~QDeclarativeNotifierEndpoint()
156 {
157     disconnect();
158     if (SignalType == type) {
159         Signal *s = asSignal();
160         s->~Signal();
161     }
162 }
163
164 bool QDeclarativeNotifierEndpoint::isConnected()
165 {
166     if (SignalType == type) {
167         return asSignal()->source;
168     } else if (NotifierType == type) {
169         return asNotifier()->notifier;
170     } else {
171         return false;
172     }
173 }
174
175 bool QDeclarativeNotifierEndpoint::isConnected(QObject *source, int sourceSignal)
176 {
177     return SignalType == type && asSignal()->source == source && asSignal()->sourceSignal == sourceSignal;
178 }
179
180 bool QDeclarativeNotifierEndpoint::isConnected(QDeclarativeNotifier *notifier)
181 {
182     return NotifierType == type && asNotifier()->notifier == notifier;
183 }
184
185 void QDeclarativeNotifierEndpoint::connect(QDeclarativeNotifier *notifier)
186 {
187     Notifier *n = toNotifier();
188     
189     if (n->notifier == notifier)
190         return;
191
192     disconnect();
193
194     n->next = notifier->endpoints;
195     if (n->next) { n->next->asNotifier()->prev = &n->next; }
196     notifier->endpoints = this;
197     n->prev = &notifier->endpoints;
198     n->notifier = notifier;
199 }
200
201 void QDeclarativeNotifierEndpoint::disconnect()
202 {
203     if (type == SignalType) {
204         Signal *s = asSignal();
205         if (s->source) {
206             QMetaObject::disconnectOne(s->source, s->sourceSignal, target, targetMethod);
207             s->source = 0;
208         }
209     } else if (type == NotifierType) {
210         Notifier *n = asNotifier();
211
212         if (n->next) n->next->asNotifier()->prev = n->prev;
213         if (n->prev) *n->prev = n->next;
214         if (n->disconnected) *n->disconnected = 0;
215         n->next = 0;
216         n->prev = 0;
217         n->disconnected = 0;
218         n->notifier = 0;
219     }
220 }
221
222 QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::toNotifier()
223 {
224     if (NotifierType == type) 
225         return asNotifier();
226
227     if (SignalType == type) {
228         disconnect();
229         Signal *s = asSignal();
230         s->~Signal();
231     }
232
233     Notifier *n = asNotifier();
234     n->next = 0;
235     n->prev = 0;
236     n->disconnected = 0;
237     n->notifier = 0;
238     type = NotifierType;
239     return n;
240 }
241
242 QDeclarativeNotifierEndpoint::Notifier *QDeclarativeNotifierEndpoint::asNotifier() 
243
244     Q_ASSERT(type == NotifierType);
245     return &notifier;
246 }
247
248 QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::toSignal()
249 {
250     if (SignalType == type) 
251         return asSignal();
252
253     disconnect();
254     signal = new (&signalData) Signal;
255     type = SignalType;
256     return signal;
257 }
258
259 QDeclarativeNotifierEndpoint::Signal *QDeclarativeNotifierEndpoint::asSignal() 
260
261     Q_ASSERT(type == SignalType);
262     return signal;
263 }
264
265 QT_END_NAMESPACE
266
267 #endif // QDECLARATIVENOTIFIER_P_H
268