/**************************************************************************** ** ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtTest module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QSIGNALSPY_H #define QSIGNALSPY_H #include #include #include #include #include QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Test) class QVariant; /* ### Qt5: change the class to use regular BC mechanisms, such that we can * implement things like suggested in task 160192. */ class QSignalSpy: public QObject, public QList > { public: QSignalSpy(QObject *obj, const char *aSignal) { #ifdef Q_CC_BOR const int memberOffset = QObject::staticMetaObject.methodCount(); #else static const int memberOffset = QObject::staticMetaObject.methodCount(); #endif if (!obj) { qWarning("QSignalSpy: Cannot spy on a null object"); return; } if (!aSignal) { qWarning("QSignalSpy: Null signal name is not valid"); return; } if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) { qWarning("QSignalSpy: Not a valid signal, use the SIGNAL macro"); return; } QByteArray ba = QMetaObject::normalizedSignature(aSignal + 1); const QMetaObject *mo = obj->metaObject(); int sigIndex = mo->indexOfMethod(ba.constData()); if (sigIndex < 0) { qWarning("QSignalSpy: No such signal: '%s'", ba.constData()); return; } if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0)) { qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect."); return; } sig = ba; initArgs(mo->method(sigIndex)); } inline bool isValid() const { return !sig.isEmpty(); } inline QByteArray signal() const { return sig; } int qt_metacall(QMetaObject::Call call, int methodId, void **a) { methodId = QObject::qt_metacall(call, methodId, a); if (methodId < 0) return methodId; if (call == QMetaObject::InvokeMetaMethod) { if (methodId == 0) { appendArgs(a); } --methodId; } return methodId; } private: void initArgs(const QMetaMethod &member) { QList params = member.parameterTypes(); for (int i = 0; i < params.count(); ++i) { int tp = QMetaType::type(params.at(i).constData()); if (tp == QMetaType::Void) qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.", params.at(i).constData()); args << tp; } } void appendArgs(void **a) { QList list; for (int i = 0; i < args.count(); ++i) { QMetaType::Type type = static_cast(args.at(i)); list << QVariant(type, a[i + 1]); } append(list); } // the full, normalized signal name QByteArray sig; // holds the QMetaType types for the argument list of the signal QList args; }; QT_END_NAMESPACE QT_END_HEADER #endif