home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / include / scribus-ng / observable.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-02-08  |  7.1 KB  |  298 lines

  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>
  72. struct Private_Memento : public UpdateMemento
  73. {
  74.     Private_Memento(OBSERVED data) : m_data(data) {};
  75.     
  76.     OBSERVED m_data;
  77. };
  78.  
  79.  
  80.  
  81. /**
  82.   Implement this interface if you want to observe an observable but dont want to derive from QObject 
  83.  */
  84. template<class OBSERVED>
  85. class SCRIBUS_API Observer {
  86. public:
  87.     virtual void changed(OBSERVED) = 0;
  88.     virtual ~Observer() {}
  89. };
  90.  
  91.  
  92.  
  93.  
  94. /**
  95.  An MassObservable is basically just the source of a changed() signal.
  96.  Observers can register via the Qt signal/slot mechanism or via the above interface.
  97.  
  98.  The difference to Observable (below) is that a MassObservable doesnt report changes to
  99.  itself but to a bunch of SingleObservables.
  100.  When you call update() on the SingleObservable, it will tell the associated
  101.  MassObservable to notify all observers with the "changed" signal,
  102.  providing a pointer to the single Observable. 
  103.  
  104.  The class parameter OBSERVED is usually a pointer to a subclass of SingleObservable. 
  105.  
  106.  MassObservable does not inherit QObject since that makes it difficult to use it as a mixin class.
  107.  */
  108. template<class OBSERVED>
  109. class MassObservable : public UpdateManaged 
  110. {    
  111.     friend class UpdateManager;
  112.     
  113. public:
  114.     MassObservable(UpdateManager* um = NULL);
  115.     virtual ~MassObservable();
  116.     /**
  117.         Used if the UpdateManager is not available when the constructor is called
  118.     */
  119.     void setUpdateManager(UpdateManager* um);
  120.     
  121.     /**
  122.         This method will be called by the SingleObservable.
  123.         If updates are enabled, it calls updateNow() directly, otherwise the undomanager
  124.         will take care of that.
  125.      */
  126.     virtual void update(OBSERVED what);
  127.     
  128.     void connectObserver(Observer<OBSERVED>* o);
  129.     void disconnectObserver(Observer<OBSERVED>* o);
  130.     
  131.     bool connectObserver(QObject* o, const char* slot);
  132.     bool disconnectObserver(QObject* o, const char* slot = 0);
  133.     
  134. protected:
  135.     /**
  136.         This method will be called by the updatemanager or by update()
  137.      */
  138.     virtual void updateNow(UpdateMemento* what);
  139.  
  140.     QSet<Observer<OBSERVED>*> m_observers;
  141.     Private_Signal* changedSignal;
  142.     UpdateManager* m_um;
  143. };
  144.  
  145.  
  146.  
  147.  
  148. /**
  149.   This mixin class just provides the update() method.
  150.  */
  151. template<class OBSERVED>
  152. class SCRIBUS_API SingleObservable
  153. {
  154. public:
  155.     /**
  156.       Connects this SingleObservale to the MassObservable
  157.      */
  158.     SingleObservable(MassObservable<OBSERVED*> * massObservable) : m_massObservable(massObservable) 
  159.     {};
  160.     
  161.     virtual ~SingleObservable() 
  162.     {};
  163.     
  164.     void setMassObservable(MassObservable<OBSERVED*> * massObservable) 
  165.     {
  166.         m_massObservable = massObservable;
  167.     }
  168.     
  169.     virtual void update() 
  170.     { 
  171.         m_massObservable->update(dynamic_cast<OBSERVED*>(this)); 
  172.     }
  173.     
  174. private:
  175.     MassObservable<OBSERVED*>* m_massObservable;
  176. };
  177.  
  178.  
  179.  
  180.  
  181.  
  182. /**
  183.   An Observable is basically just the source of a changed() signal.
  184.   Observers can register via the Qt signal/slot mechanism or via the above interface.
  185.  
  186.   When you call update(), all observers will receive the "changed" signal with a pointer
  187.   to the Observable (this).
  188.  
  189.   Observable is implemented as a MassObservable which.
  190.  
  191.   The class parameter OBSERVED should be the implementing class.
  192.  */
  193. template<class OBSERVED>
  194. class SCRIBUS_API Observable : public MassObservable<OBSERVED*> 
  195. {    
  196. public:
  197.     Observable(UpdateManager* um = NULL) : MassObservable<OBSERVED*>(um) 
  198.     {};
  199.     
  200.     virtual void update() 
  201.     { 
  202.         MassObservable<OBSERVED*>::update(dynamic_cast<OBSERVED*>(this)); 
  203.     }
  204. };
  205.  
  206.  
  207.  
  208. // IMPLEMENTATION
  209.  
  210.  
  211.  
  212. template<class OBSERVED>
  213. inline MassObservable<OBSERVED>::MassObservable(UpdateManager* um) : m_observers(), changedSignal(new Private_Signal()), m_um(um)
  214. {
  215. }
  216.  
  217. template<class OBSERVED>
  218. inline MassObservable<OBSERVED>::~MassObservable()
  219. {
  220.     m_observers.clear();
  221.     delete changedSignal;
  222. }
  223.  
  224.  
  225. template<class OBSERVED>
  226. inline void MassObservable<OBSERVED>::setUpdateManager(UpdateManager* um)
  227. {
  228.     m_um = um;
  229. }
  230.  
  231.  
  232. template<class OBSERVED>
  233. inline void MassObservable<OBSERVED>::update(OBSERVED what)
  234. {
  235.     Private_Memento<OBSERVED>* memento = new Private_Memento<OBSERVED>(what);
  236.     if (m_um == NULL || m_um->requestUpdate(this, memento))
  237.     {
  238.         updateNow(memento);
  239.     }
  240. }
  241.  
  242.  
  243. template<class OBSERVED>
  244. inline void MassObservable<OBSERVED>::updateNow(UpdateMemento* what)
  245. {
  246.     Private_Memento<OBSERVED>* memento = dynamic_cast<Private_Memento<OBSERVED>*>(what);
  247.     foreach (Observer<OBSERVED>* obs, m_observers)
  248.     {
  249.         obs->changed(memento->m_data);
  250.     }
  251.     changedSignal->emitSignal(QVariant::fromValue(memento->m_data));
  252.     delete memento;
  253. }
  254.  
  255.  
  256. template<class OBSERVED>
  257. inline void MassObservable<OBSERVED>::connectObserver(Observer<OBSERVED>* o)
  258. {
  259.     m_observers.insert(o);
  260. }
  261.  
  262. template<class OBSERVED>
  263. inline void MassObservable<OBSERVED>::disconnectObserver(Observer<OBSERVED>* o)
  264. {
  265.     m_observers.remove(o);
  266. }
  267.  
  268.  
  269. template <typename T>
  270. inline void Private_Init(T& dummy) {}
  271.  
  272. template <>
  273. inline void Private_Init(QObject*& dummy) 
  274. //    dummy->die_compiler_die(); 
  275.     dummy = 0;
  276. }
  277.  
  278.  
  279. template<class OBSERVED>
  280. inline bool MassObservable<OBSERVED>::connectObserver(QObject* o, const char* slot)
  281. {
  282.     OBSERVED dummy;
  283.     Private_Init(dummy);
  284.     return changedSignal->connectSignal(QVariant::fromValue(dummy), o, slot);
  285. }
  286.  
  287. template<class OBSERVED>
  288. inline bool MassObservable<OBSERVED>::disconnectObserver(QObject* o, const char* slot)
  289. {
  290.     OBSERVED dummy;
  291.     Private_Init(dummy);
  292.     return changedSignal->disconnectSignal(QVariant::fromValue(dummy), o, slot);
  293. }
  294.  
  295.  
  296. #endif
  297.