From d69b8288ee0b6cc410b98f86601bedcc1c2b42fc Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Fri, 4 May 2012 16:04:19 +0100 Subject: [PATCH] Replace UpdateObserver with UpdateController class which uses signal/slot notifications using the sigslot library. --- CMakeLists.txt | 1 + external/sigslot/sigslot.h | 2507 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 2 + src/UpdateController.cpp | 6 + src/UpdateController.h | 23 + src/UpdateDialogCocoa.h | 15 +- src/UpdateDialogCocoa.mm | 7 +- src/UpdateDialogGtk.h | 9 +- src/UpdateDialogGtkWrapper.cpp | 6 +- src/UpdateDialogGtkWrapper.h | 11 +- src/UpdateDialogWin32.cpp | 7 +- src/UpdateDialogWin32.h | 15 +- src/UpdateInstaller.cpp | 26 +- src/UpdateInstaller.h | 6 +- src/main.cpp | 15 +- 15 files changed, 2608 insertions(+), 48 deletions(-) create mode 100644 external/sigslot/sigslot.h create mode 100644 src/UpdateController.cpp create mode 100644 src/UpdateController.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 23373a9..24cc66a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ option(SIGN_UPDATER OFF) include_directories(external) include_directories(external/TinyThread/source) +include_directories(external/sigslot/) if (WIN32) include_directories(external/zlib/) diff --git a/external/sigslot/sigslot.h b/external/sigslot/sigslot.h new file mode 100644 index 0000000..59a28bc --- /dev/null +++ b/external/sigslot/sigslot.h @@ -0,0 +1,2507 @@ +// sigslot.h: Signal/Slot classes +// +// Written by Sarah Thompson (sarah@telergy.com) 2002. +// +// License: Public domain. You are free to use this code however you like, with the proviso that +// the author takes on no responsibility or liability for any use. +// +// QUICK DOCUMENTATION +// +// (see also the full documentation at http://sigslot.sourceforge.net/) +// +// #define switches +// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables +// all of the thread safety support on platforms where it is +// available. +// +// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than +// gcc on a platform that supports Posix threads. (When using gcc, +// this is the default - use SIGSLOT_PURE_ISO to disable this if +// necessary) +// +// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global. +// Otherwise, the default is single_threaded. #define this yourself to +// override the default. In pure ISO mode, anything other than +// single_threaded will cause a compiler error. +// +// PLATFORM NOTES +// +// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream +// compilers do this by default, but you may need to define it +// yourself if your build environment is less standard. This causes +// the Win32 thread support to be compiled in and used automatically. +// +// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads +// available, so they are used automatically. You can override this +// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using +// something other than gcc but still want to use Posix threads, you +// need to #define SIGSLOT_USE_POSIX_THREADS. +// +// ISO C++ - If none of the supported platforms are detected, or if +// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off, +// along with any code that might cause a pure ISO C++ environment to +// complain. Before you ask, gcc -ansi -pedantic won't compile this +// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of +// errors that aren't really there. If you feel like investigating this, +// please contact the author. +// +// +// THREADING MODES +// +// single_threaded - Your program is assumed to be single threaded from the point of view +// of signal/slot usage (i.e. all objects using signals and slots are +// created and destroyed from a single thread). Behaviour if objects are +// destroyed concurrently is undefined (i.e. you'll get the occasional +// segmentation fault/memory exception). +// +// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and +// slots can be safely created and destroyed from any thread, even when +// connections exist. In multi_threaded_global mode, this is achieved by a +// single global mutex (actually a critical section on Windows because they +// are faster). This option uses less OS resources, but results in more +// opportunities for contention, possibly resulting in more context switches +// than are strictly necessary. +// +// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global, +// except that each signal, and each object that inherits has_slots, all +// have their own mutex/critical section. In practice, this means that +// mutex collisions (and hence context switches) only happen if they are +// absolutely essential. However, on some platforms, creating a lot of +// mutexes can slow down the whole OS, so use this option with care. +// +// USING THE LIBRARY +// +// See the full documentation at http://sigslot.sourceforge.net/ +// +// + +#ifndef SIGSLOT_H__ +#define SIGSLOT_H__ + +#include +#include + +#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS)) +# define _SIGSLOT_SINGLE_THREADED +#elif defined(WIN32) +# define _SIGSLOT_HAS_WIN32_THREADS +# include +#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS) +# define _SIGSLOT_HAS_POSIX_THREADS +# include +#else +# define _SIGSLOT_SINGLE_THREADED +#endif + +#ifndef SIGSLOT_DEFAULT_MT_POLICY +# ifdef _SIGSLOT_SINGLE_THREADED +# define SIGSLOT_DEFAULT_MT_POLICY single_threaded +# else +# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local +# endif +#endif + + +namespace sigslot { + + class single_threaded + { + public: + single_threaded() + { + ; + } + + virtual ~single_threaded() + { + ; + } + + virtual void lock() + { + ; + } + + virtual void unlock() + { + ; + } + }; + +#ifdef _SIGSLOT_HAS_WIN32_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + static bool isinitialised = false; + + if(!isinitialised) + { + InitializeCriticalSection(get_critsec()); + isinitialised = true; + } + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + virtual ~multi_threaded_global() + { + ; + } + + virtual void lock() + { + EnterCriticalSection(get_critsec()); + } + + virtual void unlock() + { + LeaveCriticalSection(get_critsec()); + } + + private: + CRITICAL_SECTION* get_critsec() + { + static CRITICAL_SECTION g_critsec; + return &g_critsec; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + InitializeCriticalSection(&m_critsec); + } + + multi_threaded_local(const multi_threaded_local&) + { + InitializeCriticalSection(&m_critsec); + } + + virtual ~multi_threaded_local() + { + DeleteCriticalSection(&m_critsec); + } + + virtual void lock() + { + EnterCriticalSection(&m_critsec); + } + + virtual void unlock() + { + LeaveCriticalSection(&m_critsec); + } + + private: + CRITICAL_SECTION m_critsec; + }; +#endif // _SIGSLOT_HAS_WIN32_THREADS + +#ifdef _SIGSLOT_HAS_POSIX_THREADS + // The multi threading policies only get compiled in if they are enabled. + class multi_threaded_global + { + public: + multi_threaded_global() + { + pthread_mutex_init(get_mutex(), 0); + } + + multi_threaded_global(const multi_threaded_global&) + { + ; + } + + virtual ~multi_threaded_global() + { + ; + } + + virtual void lock() + { + pthread_mutex_lock(get_mutex()); + } + + virtual void unlock() + { + pthread_mutex_unlock(get_mutex()); + } + + private: + pthread_mutex_t* get_mutex() + { + static pthread_mutex_t g_mutex; + return &g_mutex; + } + }; + + class multi_threaded_local + { + public: + multi_threaded_local() + { + pthread_mutex_init(&m_mutex, 0); + } + + multi_threaded_local(const multi_threaded_local&) + { + pthread_mutex_init(&m_mutex, 0); + } + + virtual ~multi_threaded_local() + { + pthread_mutex_destroy(&m_mutex); + } + + virtual void lock() + { + pthread_mutex_lock(&m_mutex); + } + + virtual void unlock() + { + pthread_mutex_unlock(&m_mutex); + } + + private: + pthread_mutex_t m_mutex; + }; +#endif // _SIGSLOT_HAS_POSIX_THREADS + + template + class lock_block + { + public: + mt_policy *m_mutex; + + lock_block(mt_policy *mtx) + : m_mutex(mtx) + { + m_mutex->lock(); + } + + ~lock_block() + { + m_mutex->unlock(); + } + }; + + template + class has_slots; + + template + class _connection_base0 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit() = 0; + virtual _connection_base0* clone() = 0; + virtual _connection_base0* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base1 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type) = 0; + virtual _connection_base1* clone() = 0; + virtual _connection_base1* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base2 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type) = 0; + virtual _connection_base2* clone() = 0; + virtual _connection_base2* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base3 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type) = 0; + virtual _connection_base3* clone() = 0; + virtual _connection_base3* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base4 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; + virtual _connection_base4* clone() = 0; + virtual _connection_base4* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base5 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type) = 0; + virtual _connection_base5* clone() = 0; + virtual _connection_base5* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base6 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type) = 0; + virtual _connection_base6* clone() = 0; + virtual _connection_base6* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base7 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type) = 0; + virtual _connection_base7* clone() = 0; + virtual _connection_base7* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _connection_base8 + { + public: + virtual has_slots* getdest() const = 0; + virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, + arg6_type, arg7_type, arg8_type) = 0; + virtual _connection_base8* clone() = 0; + virtual _connection_base8* duplicate(has_slots* pnewdest) = 0; + }; + + template + class _signal_base : public mt_policy + { + public: + virtual void slot_disconnect(has_slots* pslot) = 0; + virtual void slot_duplicate(const has_slots* poldslot, has_slots* pnewslot) = 0; + }; + + template + class has_slots : public mt_policy + { + private: + typedef std::set<_signal_base *> sender_set; + typedef typename sender_set::const_iterator const_iterator; + + public: + has_slots() + { + ; + } + + has_slots(const has_slots& hs) + : mt_policy(hs) + { + lock_block lock(this); + const_iterator it = hs.m_senders.begin(); + const_iterator itEnd = hs.m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_duplicate(&hs, this); + m_senders.insert(*it); + ++it; + } + } + + void signal_connect(_signal_base* sender) + { + lock_block lock(this); + m_senders.insert(sender); + } + + void signal_disconnect(_signal_base* sender) + { + lock_block lock(this); + m_senders.erase(sender); + } + + virtual ~has_slots() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + const_iterator it = m_senders.begin(); + const_iterator itEnd = m_senders.end(); + + while(it != itEnd) + { + (*it)->slot_disconnect(this); + ++it; + } + + m_senders.erase(m_senders.begin(), m_senders.end()); + } + + private: + sender_set m_senders; + }; + + template + class _signal_base0 : public _signal_base + { + public: + typedef typename std::list<_connection_base0 *> connections_list; + + _signal_base0() + { + ; + } + + _signal_base0(const _signal_base0& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + ~_signal_base0() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base1 : public _signal_base + { + public: + typedef std::list<_connection_base1 *> connections_list; + + _signal_base1() + { + ; + } + + _signal_base1(const _signal_base1& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base1() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base2 : public _signal_base + { + public: + typedef std::list<_connection_base2 *> + connections_list; + + _signal_base2() + { + ; + } + + _signal_base2(const _signal_base2& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base2() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base3 : public _signal_base + { + public: + typedef std::list<_connection_base3 *> + connections_list; + + _signal_base3() + { + ; + } + + _signal_base3(const _signal_base3& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base3() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base4 : public _signal_base + { + public: + typedef std::list<_connection_base4 *> connections_list; + + _signal_base4() + { + ; + } + + _signal_base4(const _signal_base4& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base4() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base5 : public _signal_base + { + public: + typedef std::list<_connection_base5 *> connections_list; + + _signal_base5() + { + ; + } + + _signal_base5(const _signal_base5& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base5() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base6 : public _signal_base + { + public: + typedef std::list<_connection_base6 *> connections_list; + + _signal_base6() + { + ; + } + + _signal_base6(const _signal_base6& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base6() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base7 : public _signal_base + { + public: + typedef std::list<_connection_base7 *> connections_list; + + _signal_base7() + { + ; + } + + _signal_base7(const _signal_base7& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base7() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + template + class _signal_base8 : public _signal_base + { + public: + typedef std::list<_connection_base8 *> + connections_list; + + _signal_base8() + { + ; + } + + _signal_base8(const _signal_base8& s) + : _signal_base(s) + { + lock_block lock(this); + typename connections_list::const_iterator it = s.m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_connect(this); + m_connected_slots.push_back((*it)->clone()); + + ++it; + } + } + + void slot_duplicate(const has_slots* oldtarget, has_slots* newtarget) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == oldtarget) + { + m_connected_slots.push_back((*it)->duplicate(newtarget)); + } + + ++it; + } + } + + ~_signal_base8() + { + disconnect_all(); + } + + void disconnect_all() + { + lock_block lock(this); + typename connections_list::const_iterator it = m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + (*it)->getdest()->signal_disconnect(this); + delete *it; + + ++it; + } + + m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + } + + void disconnect(has_slots* pclass) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + if((*it)->getdest() == pclass) + { + delete *it; + m_connected_slots.erase(it); + pclass->signal_disconnect(this); + return; + } + + ++it; + } + } + + void slot_disconnect(has_slots* pslot) + { + lock_block lock(this); + typename connections_list::iterator it = m_connected_slots.begin(); + typename connections_list::iterator itEnd = m_connected_slots.end(); + + while(it != itEnd) + { + typename connections_list::iterator itNext = it; + ++itNext; + + if((*it)->getdest() == pslot) + { + m_connected_slots.erase(it); + // delete *it; + } + + it = itNext; + } + } + + protected: + connections_list m_connected_slots; + }; + + + template + class _connection0 : public _connection_base0 + { + public: + _connection0() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base0* clone() + { + return new _connection0(*this); + } + + virtual _connection_base0* duplicate(has_slots* pnewdest) + { + return new _connection0((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit() + { + (m_pobject->*m_pmemfun)(); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(); + }; + + template + class _connection1 : public _connection_base1 + { + public: + _connection1() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base1* clone() + { + return new _connection1(*this); + } + + virtual _connection_base1* duplicate(has_slots* pnewdest) + { + return new _connection1((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1) + { + (m_pobject->*m_pmemfun)(a1); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type); + }; + + template + class _connection2 : public _connection_base2 + { + public: + _connection2() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base2* clone() + { + return new _connection2(*this); + } + + virtual _connection_base2* duplicate(has_slots* pnewdest) + { + return new _connection2((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2) + { + (m_pobject->*m_pmemfun)(a1, a2); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type); + }; + + template + class _connection3 : public _connection_base3 + { + public: + _connection3() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base3* clone() + { + return new _connection3(*this); + } + + virtual _connection_base3* duplicate(has_slots* pnewdest) + { + return new _connection3((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + (m_pobject->*m_pmemfun)(a1, a2, a3); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); + }; + + template + class _connection4 : public _connection_base4 + { + public: + _connection4() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base4* clone() + { + return new _connection4(*this); + } + + virtual _connection_base4* duplicate(has_slots* pnewdest) + { + return new _connection4((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, + arg4_type a4) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, + arg4_type); + }; + + template + class _connection5 : public _connection_base5 + { + public: + _connection5() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base5* clone() + { + return new _connection5(*this); + } + + virtual _connection_base5* duplicate(has_slots* pnewdest) + { + return new _connection5((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type); + }; + + template + class _connection6 : public _connection_base6 + { + public: + _connection6() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base6* clone() + { + return new _connection6(*this); + } + + virtual _connection_base6* duplicate(has_slots* pnewdest) + { + return new _connection6((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type); + }; + + template + class _connection7 : public _connection_base7 + { + public: + _connection7() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base7* clone() + { + return new _connection7(*this); + } + + virtual _connection_base7* duplicate(has_slots* pnewdest) + { + return new _connection7((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type); + }; + + template + class _connection8 : public _connection_base8 + { + public: + _connection8() + { + m_pobject = 0; + m_pmemfun = 0; + } + + _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + m_pobject = pobject; + m_pmemfun = pmemfun; + } + + virtual _connection_base8* clone() + { + return new _connection8(*this); + } + + virtual _connection_base8* duplicate(has_slots* pnewdest) + { + return new _connection8((dest_type *)pnewdest, m_pmemfun); + } + + virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + virtual has_slots* getdest() const + { + return m_pobject; + } + + private: + dest_type* m_pobject; + void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, + arg5_type, arg6_type, arg7_type, arg8_type); + }; + + template + class signal0 : public _signal_base0 + { + typedef _signal_base0 Base; + public: + signal0() + { + ; + } + + signal0(const signal0& s) + : _signal_base0(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)()) + { + lock_block lock(this); + _connection0* conn = + new _connection0(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit() + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + + void operator()() + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(); + + it = itNext; + } + } + }; + + template + class signal1 : public _signal_base1 + { + typedef _signal_base1 Base; + public: + signal1() + { + ; + } + + signal1(const signal1& s) + : _signal_base1(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) + { + lock_block lock(this); + _connection1* conn = + new _connection1(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + + void operator()(arg1_type a1) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1); + + it = itNext; + } + } + }; + + template + class signal2 : public _signal_base2 + { + typedef _signal_base2 Base; + public: + signal2() + { + ; + } + + signal2(const signal2& s) + : _signal_base2(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type)) + { + lock_block lock(this); + _connection2* conn = new + _connection2(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2); + + it = itNext; + } + } + }; + + template + class signal3 : public _signal_base3 + { + typedef _signal_base3 Base; + public: + signal3() + { + ; + } + + signal3(const signal3& s) + : _signal_base3(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type)) + { + lock_block lock(this); + _connection3* conn = + new _connection3(pclass, + pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3); + + it = itNext; + } + } + }; + + template + class signal4 : public _signal_base4 + { + typedef _signal_base4 Base; + public: + signal4() + { + ; + } + + signal4(const signal4& s) + : _signal_base4(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type)) + { + lock_block lock(this); + _connection4* + conn = new _connection4(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4); + + it = itNext; + } + } + }; + + template + class signal5 : public _signal_base5 + { + typedef _signal_base5 Base; + public: + signal5() + { + ; + } + + signal5(const signal5& s) + : _signal_base5(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type)) + { + lock_block lock(this); + _connection5* conn = new _connection5(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5); + + it = itNext; + } + } + }; + + + template + class signal6 : public _signal_base6 + { + typedef _signal_base6 Base; + + public: + signal6() + { + ; + } + + signal6(const signal6& s) + : _signal_base6(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) + { + lock_block lock(this); + _connection6* conn = + new _connection6(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6); + + it = itNext; + } + } + }; + + template + class signal7 : public _signal_base7 + { + typedef _signal_base7 Base; + public: + signal7() + { + ; + } + + signal7(const signal7& s) + : _signal_base7(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type)) + { + lock_block lock(this); + _connection7* conn = + new _connection7(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7); + + it = itNext; + } + } + }; + + template + class signal8 : public _signal_base8 + { + typedef _signal_base8 Base; + public: + signal8() + { + ; + } + + signal8(const signal8& s) + : _signal_base8(s) + { + ; + } + + template + void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, + arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, + arg7_type, arg8_type)) + { + lock_block lock(this); + _connection8* conn = + new _connection8(pclass, pmemfun); + Base::m_connected_slots.push_back(conn); + pclass->signal_connect(this); + } + + void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + + void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, + arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) + { + lock_block lock(this); + typename Base::connections_list::const_iterator itNext, it = Base::m_connected_slots.begin(); + typename Base::connections_list::const_iterator itEnd = Base::m_connected_slots.end(); + + while(it != itEnd) + { + itNext = it; + ++itNext; + + (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + + it = itNext; + } + } + }; + +} // namespace sigslot + +#endif // SIGSLOT_H__ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6eee376..6d05ee0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ set (SOURCES Log.cpp ProcessUtils.cpp StandardDirs.cpp + UpdateController.cpp UpdateInstaller.cpp UpdateScript.cpp UpdaterOptions.cpp @@ -65,6 +66,7 @@ set (HEADERS Log.h ProcessUtils.h StandardDirs.h + UpdateController.h UpdateInstaller.h UpdateScript.h UpdaterOptions.h diff --git a/src/UpdateController.cpp b/src/UpdateController.cpp new file mode 100644 index 0000000..9954a9d --- /dev/null +++ b/src/UpdateController.cpp @@ -0,0 +1,6 @@ +#include "UpdateController.h" + +UpdateController::UpdateController() +{ +} + diff --git a/src/UpdateController.h b/src/UpdateController.h new file mode 100644 index 0000000..04d6bca --- /dev/null +++ b/src/UpdateController.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +/** Controller used by the UI to drive the installation + * and monitor the status of the install. + */ +class UpdateController +{ + public: + UpdateController(); + + /** Emitted to indicate progress of update installation. */ + sigslot::signal1 installProgress; + + /** Emitted when installation fails for any reason. */ + sigslot::signal1 installError; + + /** Emitted when installation completes, whether successfully or + * following an unrecoverable error. + */ + sigslot::signal0<> finished; +}; diff --git a/src/UpdateDialogCocoa.h b/src/UpdateDialogCocoa.h index a1881d7..0c744ab 100644 --- a/src/UpdateDialogCocoa.h +++ b/src/UpdateDialogCocoa.h @@ -1,22 +1,23 @@ #pragma once -#include "UpdateObserver.h" +#include class UpdateDialogPrivate; +class UpdateController; -class UpdateDialogCocoa : public UpdateObserver +class UpdateDialogCocoa : public sigslot::has_slots<> { public: - UpdateDialogCocoa(); + UpdateDialogCocoa(UpdateController* controller); ~UpdateDialogCocoa(); void init(); void exec(); - // implements UpdateObserver - virtual void updateError(const std::string& errorMessage); - virtual void updateProgress(int percentage); - virtual void updateFinished(); + // slots for update notifications + void updateError(const std::string& errorMessage); + void updateProgress(int percentage); + void updateFinished(); static void* createAutoreleasePool(); static void releaseAutoreleasePool(void* data); diff --git a/src/UpdateDialogCocoa.mm b/src/UpdateDialogCocoa.mm index 16ae35d..6855fe3 100644 --- a/src/UpdateDialogCocoa.mm +++ b/src/UpdateDialogCocoa.mm @@ -6,6 +6,7 @@ #include "AppInfo.h" #include "Log.h" #include "StringUtils.h" +#include "UpdateController.h" @interface UpdateDialogDelegate : NSObject { @@ -78,9 +79,13 @@ class UpdateDialogPrivate } @end -UpdateDialogCocoa::UpdateDialogCocoa() +UpdateDialogCocoa::UpdateDialogCocoa(UpdateController* controller) : d(new UpdateDialogPrivate) { + controller->installProgress.connect(this, &UpdateDialogCocoa::updateProgress); + controller->installError.connect(this, &UpdateDialogCocoa::updateError); + controller->finished.connect(this, &UpdateDialogCocoa::updateFinished); + [NSApplication sharedApplication]; d->pool = [[NSAutoreleasePool alloc] init]; } diff --git a/src/UpdateDialogGtk.h b/src/UpdateDialogGtk.h index 05f8d43..a22105b 100644 --- a/src/UpdateDialogGtk.h +++ b/src/UpdateDialogGtk.h @@ -1,11 +1,10 @@ #pragma once #include "UpdateMessage.h" -#include "UpdateObserver.h" #include -class UpdateDialogGtk : public UpdateObserver +class UpdateDialogGtk { public: UpdateDialogGtk(); @@ -15,9 +14,9 @@ class UpdateDialogGtk : public UpdateObserver // observer callbacks - these may be called // from a background thread - virtual void updateError(const std::string& errorMessage); - virtual void updateProgress(int percentage); - virtual void updateFinished(); + void updateError(const std::string& errorMessage); + void updateProgress(int percentage); + void updateFinished(); private: static void finish(GtkWidget* widget, gpointer dialog); diff --git a/src/UpdateDialogGtkWrapper.cpp b/src/UpdateDialogGtkWrapper.cpp index e430d69..a41a9fe 100644 --- a/src/UpdateDialogGtkWrapper.cpp +++ b/src/UpdateDialogGtkWrapper.cpp @@ -2,6 +2,7 @@ #include "Log.h" #include "StringUtils.h" +#include "UpdateController.h" #include #include @@ -41,9 +42,12 @@ bool extractFileFromBinary(const char* path, const void* buffer, size_t length) return true; } -UpdateDialogGtkWrapper::UpdateDialogGtkWrapper() +UpdateDialogGtkWrapper::UpdateDialogGtkWrapper(UpdateController* controller) : m_dialog(0) { + controller->installProgress.connect(this, &UpdateDialogGtkWrapper::updateProgress); + controller->installError.connect(this, &UpdateDialogGtkWrapper::updateError); + controller->finished.connect(this, &UpdateDialogGtkWrapper::updateFinished); } bool UpdateDialogGtkWrapper::init(int argc, char** argv) diff --git a/src/UpdateDialogGtkWrapper.h b/src/UpdateDialogGtkWrapper.h index e103b46..a856d74 100644 --- a/src/UpdateDialogGtkWrapper.h +++ b/src/UpdateDialogGtkWrapper.h @@ -1,14 +1,15 @@ #pragma once -#include "UpdateObserver.h" +#include class UpdateDialogGtk; +class UpdateController; /** A wrapper around UpdateDialogGtk which allows the GTK UI to * be loaded dynamically at runtime if the GTK libraries are * available. */ -class UpdateDialogGtkWrapper : public UpdateObserver +class UpdateDialogGtkWrapper : public sigslot::has_slots<> { public: UpdateDialogGtkWrapper(); @@ -20,9 +21,9 @@ class UpdateDialogGtkWrapper : public UpdateObserver bool init(int argc, char** argv); void exec(); - virtual void updateError(const std::string& errorMessage); - virtual void updateProgress(int percentage); - virtual void updateFinished(); + void updateError(const std::string& errorMessage); + void updateProgress(int percentage); + void updateFinished(); private: UpdateDialogGtk* m_dialog; diff --git a/src/UpdateDialogWin32.cpp b/src/UpdateDialogWin32.cpp index 0b98240..de93202 100644 --- a/src/UpdateDialogWin32.cpp +++ b/src/UpdateDialogWin32.cpp @@ -1,5 +1,6 @@ #include "UpdateDialogWin32.h" +#include "UpdateController.h" #include "AppInfo.h" #include "Log.h" @@ -58,9 +59,13 @@ void registerWindowClass() RegisterClassEx(&wcex); } -UpdateDialogWin32::UpdateDialogWin32() +UpdateDialogWin32::UpdateDialogWin32(UpdateController* controller) : m_hadError(false) { + controller->installProgress.connect(this, &UpdateDialogWin32::updateProgress); + controller->installError.connect(this, &UpdateDialogWin32::updateError); + controller->finished.connect(this, &UpdateDialogWin32::updateFinished); + registerWindowClass(); } diff --git a/src/UpdateDialogWin32.h b/src/UpdateDialogWin32.h index 1070a1a..dca80e8 100644 --- a/src/UpdateDialogWin32.h +++ b/src/UpdateDialogWin32.h @@ -2,25 +2,28 @@ #include "Platform.h" #include "UpdateMessage.h" -#include "UpdateObserver.h" #include "wincore.h" #include "controls.h" #include "stdcontrols.h" -class UpdateDialogWin32 : public UpdateObserver +#include + +class UpdateController; + +class UpdateDialogWin32 : public has_slots<> { public: - UpdateDialogWin32(); + UpdateDialogWin32(UpdateController* controller); ~UpdateDialogWin32(); void init(); void exec(); // implements UpdateObserver - virtual void updateError(const std::string& errorMessage); - virtual void updateProgress(int percentage); - virtual void updateFinished(); + void updateError(const std::string& errorMessage); + void updateProgress(int percentage); + void updateFinished(); LRESULT WINAPI windowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam); diff --git a/src/UpdateInstaller.cpp b/src/UpdateInstaller.cpp index 11c8a9f..7aabf01 100644 --- a/src/UpdateInstaller.cpp +++ b/src/UpdateInstaller.cpp @@ -4,13 +4,13 @@ #include "FileUtils.h" #include "Log.h" #include "ProcessUtils.h" -#include "UpdateObserver.h" +#include "UpdateController.h" UpdateInstaller::UpdateInstaller() : m_mode(Setup) , m_waitPid(0) , m_script(0) -, m_observer(0) +, m_controller(0) , m_forceElevated(false) { } @@ -64,10 +64,10 @@ std::list UpdateInstaller::updaterArgs() const void UpdateInstaller::reportError(const std::string& error) { - if (m_observer) + if (m_controller) { - m_observer->updateError(error); - m_observer->updateFinished(); + m_controller->installError.emit(error); + m_controller->finished.emit(); } } @@ -213,19 +213,19 @@ void UpdateInstaller::run() throw () LOG(Error,"Error reverting partial update " + std::string(exception.what())); } - if (m_observer) + if (m_controller) { if (friendlyError.empty()) { friendlyError = error; } - m_observer->updateError(friendlyError); + m_controller->installError.emit(friendlyError); } } - if (m_observer) + if (m_controller) { - m_observer->updateFinished(); + m_controller->finished.emit(); } } } @@ -319,11 +319,11 @@ void UpdateInstaller::installFiles() { installFile(*iter); ++filesInstalled; - if (m_observer) + if (m_controller) { int toInstallCount = static_cast(m_script->filesToInstall().size()); double percentage = ((1.0 * filesInstalled) / toInstallCount) * 100.0; - m_observer->updateProgress(static_cast(percentage)); + m_controller->installProgress.emit(static_cast(percentage)); } } } @@ -395,9 +395,9 @@ bool UpdateInstaller::checkAccess() } } -void UpdateInstaller::setObserver(UpdateObserver* observer) +void UpdateInstaller::setController(UpdateController* controller) { - m_observer = observer; + m_controller = controller; } void UpdateInstaller::restartMainApp() diff --git a/src/UpdateInstaller.h b/src/UpdateInstaller.h index 971479f..0217633 100644 --- a/src/UpdateInstaller.h +++ b/src/UpdateInstaller.h @@ -8,7 +8,7 @@ #include #include -class UpdateObserver; +class UpdateController; /** Central class responsible for installing updates, * launching an elevated copy of the updater if required @@ -33,7 +33,7 @@ class UpdateInstaller void setWaitPid(PLATFORM_PID pid); void setForceElevated(bool elevated); - void setObserver(UpdateObserver* observer); + void setController(UpdateController* controller); void run() throw (); @@ -61,7 +61,7 @@ class UpdateInstaller std::string m_backupDir; PLATFORM_PID m_waitPid; UpdateScript* m_script; - UpdateObserver* m_observer; + UpdateController* m_controller; std::map m_backups; bool m_forceElevated; }; diff --git a/src/main.cpp b/src/main.cpp index af6265c..bdfe4d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "Platform.h" #include "ProcessUtils.h" #include "StringUtils.h" +#include "UpdateController.h" #include "UpdateScript.h" #include "UpdaterOptions.h" @@ -164,17 +165,18 @@ int main(int argc, char** argv) #ifdef PLATFORM_LINUX void runWithUi(int argc, char** argv, UpdateInstaller* installer) { - UpdateDialogAscii asciiDialog; - UpdateDialogGtkWrapper dialog; + UpdateController updateController; + UpdateDialogAscii asciiDialog(&updateController); + UpdateDialogGtkWrapper dialog(&updateController); bool useGtk = dialog.init(argc,argv); if (useGtk) { - installer->setObserver(&dialog); + installer->setController(&dialog); } else { asciiDialog.init(); - installer->setObserver(&asciiDialog); + installer->setController(&asciiDialog); } tthread::thread updaterThread(runUpdaterThread,installer); if (useGtk) @@ -188,8 +190,9 @@ void runWithUi(int argc, char** argv, UpdateInstaller* installer) #ifdef PLATFORM_MAC void runWithUi(int argc, char** argv, UpdateInstaller* installer) { - UpdateDialogCocoa dialog; - installer->setObserver(&dialog); + UpdateController updateController; + UpdateDialogCocoa dialog(&updateController); + installer->setController(&updateController); dialog.init(); tthread::thread updaterThread(runUpdaterThread,installer); dialog.exec();