Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / QtCollider / QcSignalSpy.h
blob59d698d2fadddc21d89df483f090a0862d741015
1 /************************************************************************
3 * Copyright 2010 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ************************************************************************/
22 #ifndef QC_SIGNALSPY_H
23 #define QC_SIGNALSPY_H
25 #include "Common.h"
26 #include "QObjectProxy.h"
28 #include <PyrKernel.h>
29 #include <PyrSymbol.h>
30 #include <VMGlobals.h>
31 #include <SCBase.h>
33 #include <QByteArray>
34 #include <QList>
35 #include <QObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
38 #include <QVariant>
40 class QcSignalSpy: public QObject
43 public:
45 QcSignalSpy( QObjectProxy *proxy, const char *sigName,
46 Qt::ConnectionType conType = Qt::QueuedConnection )
47 : QObject( proxy ), _proxy( proxy ), _sigId( -1 )
50 Q_ASSERT( sigName );
52 const QMetaObject *mo = _proxy->object()->metaObject();
54 QByteArray signal = QMetaObject::normalizedSignature( sigName );
55 int sigId = mo->indexOfSignal( signal );
57 if( sigId < 0 ) {
58 qcDebugMsg( 0, QString("WARNING: No such signal to connect: '%1'").arg(signal.constData()) );
59 return;
62 int slotId = QObject::staticMetaObject.methodCount();
64 if( !QMetaObject::connect( _proxy->object(), sigId, this, slotId,
65 conType, 0) )
67 qcErrorMsg( "QMetaObject::connect returned false. Unable to connect." );
68 return;
71 QMetaMethod mm = mo->method( sigId );
73 QList<QByteArray> params = mm.parameterTypes();
75 for( int i = 0; i < params.count(); ++i ) {
76 int type = QMetaType::type( params.at(i).constData() );
77 if( type == QMetaType::Void )
78 qcErrorMsg( QString("QObject:connect: Don't know how to handle '%1', "
79 "use qRegisterMetaType to register it.")
80 .arg(params.at(i).constData()) );
81 _argTypes << type;
84 _sigId = sigId;
87 int qt_metacall( QMetaObject::Call call, int methodId, void **argData )
89 methodId = QObject::qt_metacall( call, methodId, argData );
91 if( methodId < 0 )
92 return methodId;
94 if( call == QMetaObject::InvokeMetaMethod ) {
95 Q_ASSERT( methodId == 0 );
97 QList<QVariant> args;
98 #if QT_VERSION >= 0x040700
99 args.reserve( _argTypes.count() );
100 #endif
102 for (int i = 0; i < _argTypes.count(); ++i) {
103 QMetaType::Type type = static_cast<QMetaType::Type>(_argTypes.at(i));
104 args << QVariant( type, argData[i + 1] );
107 react( args );
109 methodId = -1;
112 return methodId;
115 inline int indexOfSignal () const { return _sigId; }
117 inline bool isValid () const { return _sigId > 0; }
119 protected:
121 virtual void react( QList<QVariant> & args ) = 0;
123 QObjectProxy *_proxy;
124 int _sigId;
125 QList<int> _argTypes;
128 class QcMethodSignalHandler : public QcSignalSpy
130 public:
131 QcMethodSignalHandler( QObjectProxy *proxy, const char *sigName, PyrSymbol *handler,
132 Qt::ConnectionType conType = Qt::QueuedConnection )
133 : QcSignalSpy( proxy, sigName, conType ), _handler( handler )
136 inline PyrSymbol *method() { return _handler; }
138 protected:
140 virtual void react( QList<QVariant> & args ) {
142 qcDebugMsg( 1, QString("SIGNAL: '%1' handled by method '%2'")
143 .arg( _proxy->object() ?
144 _proxy->object()->metaObject()->method( _sigId ).signature() :
145 "unknown" )
146 .arg(_handler->name)
149 _proxy->invokeScMethod( _handler, args );
152 PyrSymbol * _handler;
155 class QcFunctionSignalHandler : public QcSignalSpy
157 public:
158 QcFunctionSignalHandler( QObjectProxy *proxy, const char *sigName, PyrObject *handler,
159 Qt::ConnectionType conType = Qt::QueuedConnection )
160 : QcSignalSpy( proxy, sigName, conType ), _handler( handler )
163 inline PyrObject *function() { return _handler; }
165 protected:
167 virtual void react( QList<QVariant> & args ) {
169 qcDebugMsg( 1, QString("SIGNAL: '%1' handled by a Function")
170 .arg( _proxy->object() ?
171 _proxy->object()->metaObject()->method( _sigId ).signature() :
172 "unknown" )
175 args.prepend( QVariant::fromValue( _handler ) );
177 _proxy->invokeScMethod( SC_SYM(doFunction), args );
180 PyrObject * _handler;
184 #endif //QC_SIGNALSPY_H