/* ircsignalhandler.h - Maps signals from the IRC engine to contacts Copyright (c) 2004 by Jason Keirstead Kopete (c) 2002-2003 by the Kopete developers ************************************************************************* * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ************************************************************************* */ #ifndef _IRC_SIGNAL_HANDLER_H #define _IRC_SIGNAL_HANDLER_H #include #include #include #include #include "ircaccount.h" #include "irccontactmanager.h" /*** * IRC Signal handler. Mapps a KIRC engine signal to the right contact. Avoids * Having a signal connected to 500+ slots where only one is valid, instead * uses the contact dictionary. * * Warning: This file has a lot of black magic in it. Avoid it if * you don't want your eyes to bleed. More below... * * Define some templated classes and methods to map a KIRC signal to the * right contact. Having these templates greatly cuts down *A LOT* on the amount of * code that would need to be in the signal mapper, at the expense of some readability. * * There are four IRCSignalMapping classes, one each for signals with 0, 1, 2, * and 3 arguments ( plus the contact ID ). The classes take the signal, look * up the contact it is for, and call the function passed into the class by the * mapping function. * * Since TQObjects cannot be inside templates, the QMember classes that connect * to the slots are seperate. */ /*** Pre-declare mapping types for the TQObjects **/ struct IRCSignalMappingBase{}; struct IRCSignalMappingT : IRCSignalMappingBase { virtual void exec( const TQString & ) = 0; virtual ~IRCSignalMappingT() {}; }; struct IRCSignalMappingSingleT : IRCSignalMappingBase { virtual void exec( const TQString &, const TQString & ) = 0; virtual ~IRCSignalMappingSingleT() {}; }; struct IRCSignalMappingDoubleT : IRCSignalMappingBase { virtual void exec( const TQString &, const TQString &, const TQString & ) = 0; virtual ~IRCSignalMappingDoubleT() {}; }; struct IRCSignalMappingTripleT : IRCSignalMappingBase { virtual void exec( const TQString &, const TQString &, const TQString &, const TQString & ) = 0; virtual ~IRCSignalMappingTripleT() {}; }; /*** TQObject members, these connect to the KIRC signals and call the Mapping functions when they emit. **/ class QMember : public TQObject { Q_OBJECT public: QMember( IRCSignalMappingT *m, TQObject *p ) : TQObject( p ), mapping( m ){}; public slots: void slotEmit( const TQString &id ) { //kdDebug(14120) << k_funcinfo << id << endl; mapping->exec(id); } private: IRCSignalMappingT *mapping; }; class QMemberSingle : public TQObject { Q_OBJECT public: QMemberSingle( IRCSignalMappingSingleT *m, TQObject *p ) : TQObject( p ), mapping( m ){} public slots: void slotEmit( const TQString &id, const TQString &arg ) { //kdDebug(14120) << k_funcinfo << id << " : " << arg << endl; mapping->exec(id,arg); } private: IRCSignalMappingSingleT *mapping; }; class QMemberDouble : public TQObject { Q_OBJECT public: QMemberDouble( IRCSignalMappingDoubleT *m, TQObject *p ) : TQObject( p ), mapping( m ){} public slots: void slotEmit( const TQString &id, const TQString &arg, const TQString &arg2 ) { //kdDebug(14120) << k_funcinfo << id << " : " << arg << " : " << arg2 << endl; mapping->exec(id,arg,arg2); } private: IRCSignalMappingDoubleT *mapping; }; class QMemberTriple : public TQObject { Q_OBJECT public: QMemberTriple( IRCSignalMappingTripleT *m, TQObject *p ) : TQObject( p ), mapping( m ){} public slots: void slotEmit( const TQString &id, const TQString &arg, const TQString &arg2, const TQString &arg3 ) { //kdDebug(14120) << k_funcinfo << id << " : " << arg << " : " << arg2 << " : " << arg3 << endl; mapping->exec(id,arg,arg2,arg3); } private: IRCSignalMappingTripleT *mapping; }; /*** Mapping classes. These contain pointers to the functions to call. We first look up the right contact in the contact manager's dictionary, and then call the method **/ template class IRCSignalMapping : public IRCSignalMappingT { public: IRCSignalMapping( IRCContactManager *mgr, const char * /*signal*/, void (TClass::*m)() ) : manager(mgr), method(m){} void exec( const TQString &id ) { TClass *c = (TClass*)manager->findContact( id ); if( c ) { void (TClass::*tmp)() = (void (TClass::*)())method; (*c.*tmp)(); } } private: IRCContactManager *manager; void (TClass::*method)(); }; template class IRCSignalMappingSingle : public IRCSignalMappingSingleT { public: IRCSignalMappingSingle( IRCContactManager *mgr, const char * /*signal*/, void (TClass::*m)(const TQString&) ) : manager(mgr), method(m){} void exec( const TQString &id, const TQString &arg ) { TClass *c = (TClass*)manager->findContact( id ); if( c ) { void (TClass::*tmp)(const TQString&) = (void (TClass::*)(const TQString&))method; (*c.*tmp)( arg ); } } private: IRCContactManager *manager; void (TClass::*method)(const TQString &); }; template class IRCSignalMappingDouble : public IRCSignalMappingDoubleT { public: IRCSignalMappingDouble( IRCContactManager *mgr, const char * /*signal*/, void (TClass::*m)(const TQString&,const TQString&) ) : manager(mgr), method(m){} void exec( const TQString &id,const TQString &arg, const TQString &arg2 ) { TClass *c = (TClass*)manager->findContact( id ); if( c ) { void (TClass::*tmp)(const TQString&,const TQString&) = (void (TClass::*)(const TQString&,const TQString&))method; (*c.*tmp)(arg,arg2); } } private: IRCContactManager *manager; void (TClass::*method)(const TQString &,const TQString &); }; template class IRCSignalMappingTriple : public IRCSignalMappingTripleT { public: IRCSignalMappingTriple( IRCContactManager *mgr, const char * /*signal*/, void (TClass::*m)(const TQString&,const TQString&,const TQString&) ) : manager(mgr), method(m){} void exec( const TQString &id,const TQString&arg, const TQString &arg2, const TQString &arg3 ) { TClass *c = (TClass*)manager->findContact( id ); if( c ) { void (TClass::*tmp)(const TQString&,const TQString&,const TQString&) = (void (TClass::*)(const TQString&,const TQString&,const TQString&))method; (*c.*tmp)(arg,arg2,arg3); } } private: IRCContactManager *manager; void (TClass::*method)(const TQString &,const TQString &,const TQString &); }; class IRCSignalHandler : public TQObject { Q_OBJECT public: IRCSignalHandler( IRCContactManager *manager ); ~IRCSignalHandler(); private slots: /**** Slots for signals with non-TQString types */ //Channel contact slots void slotNamesList( const TQString &, const TQStringList & ); void slotEndOfNames( const TQString & ); void slotTopicUser( const TQString &, const TQString&, const TQDateTime &); //User contact slots void slotNewWhoIsIdle(const TQString &, unsigned long ); void slotNewWhoReply(const TQString &, const TQString &, const TQString &, const TQString &, const TQString &, bool , const TQString &, uint , const TQString & ); private: IRCContactManager *manager; TQValueList mappings; /**** Signal mapping functions */ template inline void map( IRCContactManager *m, const char* signal, void (TClass::*method)() ) { IRCSignalMappingT *mapping = new IRCSignalMapping( m, signal, method ); mappings.append(mapping); TQObject::connect( static_cast( m->mySelf()->account() )->engine(), signal, new QMember( mapping, this), TQT_SLOT( slotEmit( const TQString &) ) ); } template inline void mapSingle( IRCContactManager *m, const char* signal, void (TClass::*method)(const TQString&) ) { IRCSignalMappingSingleT *mapping = new IRCSignalMappingSingle( m, signal, method ); mappings.append(mapping); TQObject::connect( static_cast( m->mySelf()->account() )->engine(), signal, new QMemberSingle( mapping, this), TQT_SLOT( slotEmit( const TQString &, const TQString &) ) ); } template inline void mapDouble( IRCContactManager *m, const char* signal, void (TClass::*method)(const TQString&,const TQString&) ) { IRCSignalMappingDoubleT *mapping = new IRCSignalMappingDouble( m, signal, method ); mappings.append(mapping); TQObject::connect( static_cast( m->mySelf()->account() )->engine(), signal, new QMemberDouble( mapping, this), TQT_SLOT( slotEmit( const TQString &, const TQString &,const TQString &) ) ); } template inline void mapTriple( IRCContactManager *m, const char* signal, void (TClass::*method)(const TQString&,const TQString &, const TQString &) ) { IRCSignalMappingTripleT *mapping = new IRCSignalMappingTriple( m, signal, method ); mappings.append(mapping); TQObject::connect( static_cast( m->mySelf()->account() )->engine(), signal, new QMemberTriple( mapping, this), TQT_SLOT( slotEmit( const TQString &, const TQString &,const TQString &,const TQString &) ) ); } }; #endif