diff options
author | Gabriel de Dietrich <gabriel.dietrich-de@nokia.com> | 2009-08-27 16:53:15 (GMT) |
---|---|---|
committer | Gabriel de Dietrich <gabriel.dietrich-de@nokia.com> | 2009-08-28 09:29:11 (GMT) |
commit | e88a947cd8ac7bd78922a5468cd8b631b8ccf479 (patch) | |
tree | 72828b88f6f2b6707c61e7f131fca6ad54ed84bb | |
parent | 399d7f19ea356a29933b5a08d66b791061586c87 (diff) | |
download | Qt-e88a947cd8ac7bd78922a5468cd8b631b8ccf479.zip Qt-e88a947cd8ac7bd78922a5468cd8b631b8ccf479.tar.gz Qt-e88a947cd8ac7bd78922a5468cd8b631b8ccf479.tar.bz2 |
Q_ASSERT failure in QStateMachinePrivate::handleTransitionSignal.
The signal index actually emitted was different from the signal index
registered. This was due to recent changes in the meta-object protocol, where
new indexes are being created (cloned) for signals with default parameters.
When registering the transition signal, we now look for the original (non
cloned) signal index. The transition keeps track of the user-specified signal
index, and sets it when calling onTransition.
Reviewed-by: Kent Hansen
Reviewed-by: Olivier Goffart
Task-number: 260403
-rw-r--r-- | src/corelib/statemachine/qabstracttransition_p.h | 2 | ||||
-rw-r--r-- | src/corelib/statemachine/qsignalevent.h | 2 | ||||
-rw-r--r-- | src/corelib/statemachine/qsignaltransition.cpp | 17 | ||||
-rw-r--r-- | src/corelib/statemachine/qsignaltransition_p.h | 3 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qstatemachine/tst_qstatemachine.cpp | 42 |
6 files changed, 72 insertions, 1 deletions
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h index 328be16..33e4474 100644 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ b/src/corelib/statemachine/qabstracttransition_p.h @@ -75,7 +75,7 @@ public: static QAbstractTransitionPrivate *get(QAbstractTransition *q); bool callEventTest(QEvent *e); - void callOnTransition(QEvent *e); + virtual void callOnTransition(QEvent *e); QState *sourceState() const; QStateMachine *machine() const; void emitTriggered(); diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index 7e5d888..de166f4 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -70,6 +70,8 @@ private: QObject *m_sender; int m_signalIndex; QList<QVariant> m_arguments; + + friend class QSignalTransitionPrivate; }; #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index e34448f..fb28c08 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -245,6 +245,23 @@ bool QSignalTransition::event(QEvent *e) return QAbstractTransition::event(e); } +void QSignalTransitionPrivate::callOnTransition(QEvent *e) +{ + Q_Q(QSignalTransition); + + QSignalEvent *se = static_cast<QSignalEvent *>(e); + int savedSignalIndex; + if (e->type() == QEvent::Signal) { + savedSignalIndex = se->m_signalIndex; + se->m_signalIndex = originalSignalIndex; + } + + q->onTransition(e); + + if (e->type() == QEvent::Signal) + se->m_signalIndex = savedSignalIndex; +} + QT_END_NAMESPACE #endif //QT_NO_STATEMACHINE diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h index 21082ab..69bbcc9 100644 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ b/src/corelib/statemachine/qsignaltransition_p.h @@ -69,9 +69,12 @@ public: void unregister(); void maybeRegister(); + virtual void callOnTransition(QEvent *e); + QObject *sender; QByteArray signal; int signalIndex; + int originalSignalIndex; }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index d6946de..e5bca2c 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1408,6 +1408,7 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio signal.remove(0, 1); const QMetaObject *meta = sender->metaObject(); int signalIndex = meta->indexOfSignal(signal); + int originalSignalIndex = signalIndex; if (signalIndex == -1) { signalIndex = meta->indexOfSignal(QMetaObject::normalizedSignature(signal)); if (signalIndex == -1) { @@ -1416,6 +1417,11 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio return; } } + // The signal index we actually want to connect to is the one + // that is going to be sent, i.e. the non-cloned original index. + while (meta->method(signalIndex).attributes() & QMetaMethod::Cloned) + --signalIndex; + QVector<int> &connectedSignalIndexes = connections[sender]; if (connectedSignalIndexes.size() <= signalIndex) connectedSignalIndexes.resize(signalIndex+1); @@ -1435,6 +1441,7 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio } ++connectedSignalIndexes[signalIndex]; QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex; + QSignalTransitionPrivate::get(transition)->originalSignalIndex = originalSignalIndex; #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": added signal transition from" << transition->sourceState() << ": ( sender =" << sender << ", signal =" << signal diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 20e69ce..643daa2 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -93,10 +93,13 @@ Q_OBJECT { emit signalWithIntArg(arg); } void emitSignalWithStringArg(const QString &arg) { emit signalWithStringArg(arg); } + void emitSignalWithDefaultArg() + { emit signalWithDefaultArg(); } Q_SIGNALS: void signalWithNoArg(); void signalWithIntArg(int); void signalWithStringArg(const QString &); + void signalWithDefaultArg(int i = 42); }; class tst_QStateMachine : public QObject @@ -193,6 +196,8 @@ private slots: void nestedStateMachines(); void goToState(); + + void task260403_clonedSignals(); }; tst_QStateMachine::tst_QStateMachine() @@ -3937,5 +3942,42 @@ void tst_QStateMachine::goToState() QVERIFY(machine.configuration().contains(s2_1)); } +class CloneSignalTransition : public QSignalTransition +{ +public: + CloneSignalTransition(QObject *sender, const char *signal, QAbstractState *target) + : QSignalTransition(sender, signal) + { + setTargetState(target); + } + + void onTransition(QEvent *e) + { + QSignalTransition::onTransition(e); + QSignalEvent *se = static_cast<QSignalEvent*>(e); + eventSignalIndex = se->signalIndex(); + } + + int eventSignalIndex; +}; + +void tst_QStateMachine::task260403_clonedSignals() +{ + SignalEmitter emitter; + QStateMachine machine; + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); + CloneSignalTransition *t1 = new CloneSignalTransition(&emitter, SIGNAL(signalWithDefaultArg()), s2); + s1->addTransition(t1); + + machine.setInitialState(s1); + machine.start(); + QTest::qWait(1); + + emitter.emitSignalWithDefaultArg(); + QTest::qWait(1); + QCOMPARE(t1->eventSignalIndex, emitter.metaObject()->indexOfSignal("signalWithDefaultArg()")); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" |