Scribus
Open source desktop publishing at your fingertips
observable.h
1 /*
2  For general Scribus (>=1.3.2) copyright and licensing information please refer
3  to the COPYING file provided with the program. Following this notice may exist
4  a copyright and/or license notice that predates the release of Scribus 1.3.2
5  for which a new license (GPL+exception) is in place.
6  */
7 /***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15 
16 #ifndef OBSERVABLE_H
17 #define OBSERVABLE_H
18 
19 #include "scribusapi.h"
20 
21 #include <QObject>
22 #include <QSet>
23 #include <QVariant>
24 
25 #include "updatemanager.h"
26 
27 
28 //#include "observable_private.h"
29 struct SCRIBUS_API Private_Signal : public QObject
30 {
31  Q_OBJECT;
32 
33 public:
34  void emitSignal(QObject* what)
35 {
36  emit changedObject(what);
37 }
38 
39 void emitSignal(QVariant what)
40 {
41  emit changedData(what);
42 }
43 
44 bool connectSignal(QObject*, QObject* o, const char* slot)
45 {
46  return QObject::connect(this, SIGNAL(changedObject(QObject*)), o, slot);
47 }
48 
49 bool disconnectSignal(QObject*, QObject* o, const char* slot)
50 {
51  return QObject::disconnect(this, SIGNAL(changedObject(QObject*)), o, slot);
52 }
53 
54 bool connectSignal(QVariant, QObject* o, const char* slot)
55 {
56  return QObject::connect(this, SIGNAL(changedData(QVariant)), o, slot);
57 }
58 
59 bool disconnectSignal(QVariant, QObject* o, const char* slot)
60 {
61  return QObject::disconnect(this, SIGNAL(changedData(QVariant)), o, slot);
62 }
63 
64 signals:
65 void changedObject(QObject* what);
66 void changedData(QVariant what);
67 };
68 
69 
70 
71 template<class OBSERVED>
73 {
74  Private_Memento(OBSERVED data) : m_data(data), m_layout(false) {};
75  Private_Memento(OBSERVED data, bool layout) : m_data(data), m_layout(layout) {};
76 
77  OBSERVED m_data;
78  bool m_layout;
79 };
80 
81 
82 
86 template<class OBSERVED>
87 class SCRIBUS_API Observer {
88 public:
89  virtual void changed(OBSERVED, bool doLayout) = 0;
90  virtual ~Observer() {}
91 };
92 
93 
94 
95 
110 template<class OBSERVED>
112 {
113  friend class UpdateManager;
114 
115 public:
116  MassObservable(UpdateManager* um = NULL);
117  virtual ~MassObservable();
122 
128  virtual void update(OBSERVED what);
129 
133  virtual void updateLayout(OBSERVED what);
134 
135  void connectObserver(Observer<OBSERVED>* o);
136  void disconnectObserver(Observer<OBSERVED>* o);
137 
138  bool connectObserver(QObject* o, const char* slot);
139  bool disconnectObserver(QObject* o, const char* slot = 0);
140 
141 protected:
145  virtual void updateNow(UpdateMemento* what);
146 
147  QSet<Observer<OBSERVED>*> m_observers;
148  Private_Signal* changedSignal;
149  UpdateManager* m_um;
150 };
151 
152 
153 
154 
158 template<class OBSERVED>
159 class SCRIBUS_API SingleObservable
160 {
161 public:
165  SingleObservable(MassObservable<OBSERVED*> * massObservable) : m_massObservable(massObservable)
166  {};
167 
168  virtual ~SingleObservable()
169  {};
170 
171  void setMassObservable(MassObservable<OBSERVED*> * massObservable)
172  {
173  m_massObservable = massObservable;
174  }
175 
176  virtual void update()
177  {
178  m_massObservable->update(dynamic_cast<OBSERVED*>(this));
179  }
180 
181  virtual void updateLayout()
182  {
183  m_massObservable->updateLayout(dynamic_cast<OBSERVED*>(this));
184  }
185 
186 private:
187  MassObservable<OBSERVED*>* m_massObservable;
188 };
189 
190 
191 
192 
193 
205 template<class OBSERVED>
206 class SCRIBUS_API Observable : public MassObservable<OBSERVED*>
207 {
208 public:
210  {};
211 
212  virtual void update()
213  {
214  MassObservable<OBSERVED*>::update(dynamic_cast<OBSERVED*>(this));
215  }
216 private:
218 };
219 
220 
221 
222 // IMPLEMENTATION
223 
224 
225 
226 template<class OBSERVED>
227 inline MassObservable<OBSERVED>::MassObservable(UpdateManager* um) : m_observers(), changedSignal(new Private_Signal()), m_um(um)
228 {
229 }
230 
231 template<class OBSERVED>
233 {
234  m_observers.clear();
235  delete changedSignal;
236 }
237 
238 
239 template<class OBSERVED>
241 {
242  m_um = um;
243 }
244 
245 
246 template<class OBSERVED>
247 inline void MassObservable<OBSERVED>::update(OBSERVED what)
248 {
250  if (m_um == NULL || m_um->requestUpdate(this, memento))
251  {
252  updateNow(memento);
253  }
254 }
255 
256 template<class OBSERVED>
257 inline void MassObservable<OBSERVED>::updateLayout(OBSERVED what)
258 {
259  Private_Memento<OBSERVED>* memento = new Private_Memento<OBSERVED>(what, true);
260  if (m_um == NULL || m_um->requestUpdate(this, memento))
261  {
262  updateNow(memento);
263  }
264 }
265 
266 template<class OBSERVED>
268 {
269  Private_Memento<OBSERVED>* memento = dynamic_cast<Private_Memento<OBSERVED>*>(what);
270  foreach (Observer<OBSERVED>* obs, m_observers)
271  {
272  obs->changed(memento->m_data, memento->m_layout);
273  }
274  changedSignal->emitSignal(QVariant::fromValue(memento->m_data));
275  delete memento;
276 }
277 
278 
279 template<class OBSERVED>
281 {
282  m_observers.insert(o);
283 }
284 
285 template<class OBSERVED>
287 {
288  m_observers.remove(o);
289 }
290 
291 
292 template <typename T>
293 inline void Private_Init(T& dummy) {}
294 
295 template <>
296 inline void Private_Init(QObject*& dummy)
297 {
298 // dummy->die_compiler_die();
299  dummy = 0;
300 }
301 
302 
303 template<class OBSERVED>
304 inline bool MassObservable<OBSERVED>::connectObserver(QObject* o, const char* slot)
305 {
306  OBSERVED dummy;
307  Private_Init(dummy);
308  return changedSignal->connectSignal(QVariant::fromValue(dummy), o, slot);
309 }
310 
311 template<class OBSERVED>
312 inline bool MassObservable<OBSERVED>::disconnectObserver(QObject* o, const char* slot)
313 {
314  OBSERVED dummy;
315  Private_Init(dummy);
316  return changedSignal->disconnectSignal(QVariant::fromValue(dummy), o, slot);
317 }
318 
319 
320 #endif
Definition: observable.h:87
Definition: updatemanager.h:29
Definition: observable.h:159
virtual void updateNow(UpdateMemento *what)
Definition: observable.h:267
Definition: observable.h:29
Definition: observable.h:206
virtual void update(OBSERVED what)
Definition: observable.h:247
Definition: updatemanager.h:41
SingleObservable(MassObservable< OBSERVED * > *massObservable)
Definition: observable.h:165
void setUpdateManager(UpdateManager *um)
Definition: observable.h:240
Definition: observable.h:111
Definition: updatemanager.h:66
Definition: observable.h:72
virtual void updateLayout(OBSERVED what)
Definition: observable.h:257