diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2017-06-12 16:19:08 +0200 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@qt.io> | 2017-08-14 09:08:05 +0000 |
commit | 8af8db3810ec2d8d2d923f39e23512d30ae234d9 (patch) | |
tree | 1d7e2fb3e27eecc3a8868b17494cc3a5c259e63d | |
parent | cbcd1b0c432089777377fb0190a7d86195367bb6 (diff) |
Fix emission of state changed signals
The state index is not the same as its changed signal index.
The changed signal is not being generated for history states.
The current fix is that we create a hash cache of state index
into the signal index of its appropriate signal just
after we set the table data for the state machine.
Task-number: QTBUG-61243
Change-Id: I778adaf6c2d626be17c50b558f93ec0035ea3325
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | src/scxml/qscxmlstatemachine.cpp | 26 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine_p.h | 4 | ||||
-rw-r--r-- | tests/auto/statemachine/historystate.scxml | 13 | ||||
-rw-r--r-- | tests/auto/statemachine/tst_statemachine.cpp | 19 | ||||
-rw-r--r-- | tests/auto/statemachine/tst_statemachine.qrc | 1 |
5 files changed, 62 insertions, 1 deletions
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp index e57630f..9767a03 100644 --- a/src/scxml/qscxmlstatemachine.cpp +++ b/src/scxml/qscxmlstatemachine.cpp @@ -731,7 +731,9 @@ void QScxmlStateMachinePrivate::emitStateActive(int stateIndex, bool active) { Q_Q(QScxmlStateMachine); void *args[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&active)) }; - QMetaObject::activate(q, m_metaObject, stateIndex, args); + const int signalIndex = m_stateIndexToSignalIndex.value(stateIndex, -1); + if (signalIndex >= 0) + QMetaObject::activate(q, m_metaObject, signalIndex, args); } void QScxmlStateMachinePrivate::emitInvokedServicesChanged() @@ -755,6 +757,26 @@ void QScxmlStateMachinePrivate::attach(QScxmlStateMachineInfo *info) info, &QScxmlStateMachineInfo::transitionsTriggered); } +void QScxmlStateMachinePrivate::updateMetaCache() +{ + m_stateIndexToSignalIndex.clear(); + + if (!m_tableData) + return; + + if (!m_stateTable) + return; + + int signalIndex = 0; + for (int i = 0; i < m_stateTable->stateCount; ++i) { + const auto &s = m_stateTable->state(i); + if (!s.isHistoryState() && s.type != StateTable::State::Invalid) { + m_stateIndexToSignalIndex.insert(i, signalIndex); + ++signalIndex; + } + } +} + QStringList QScxmlStateMachinePrivate::stateNames(const std::vector<int> &stateIndexes) const { QStringList names; @@ -1767,6 +1789,8 @@ void QScxmlStateMachine::setTableData(QScxmlTableData *tableData) == QScxmlExecutableContent::StateTable::terminator); } + d->updateMetaCache(); + emit tableDataChanged(tableData); } diff --git a/src/scxml/qscxmlstatemachine_p.h b/src/scxml/qscxmlstatemachine_p.h index bfa7bc1..388dd8d 100644 --- a/src/scxml/qscxmlstatemachine_p.h +++ b/src/scxml/qscxmlstatemachine_p.h @@ -283,6 +283,8 @@ public: void attach(QScxmlStateMachineInfo *info); const OrderedSet &configuration() const { return m_configuration; } + void updateMetaCache(); + private: QStringList stateNames(const std::vector<int> &stateIndexes) const; std::vector<int> historyStates(int stateIdx) const; @@ -379,6 +381,8 @@ private: bool isPaused() const { return m_runningState == Paused; } QScxmlInternal::StateMachineInfoProxy *m_infoSignalProxy; + + QHash<int, int> m_stateIndexToSignalIndex; }; QT_END_NAMESPACE diff --git a/tests/auto/statemachine/historystate.scxml b/tests/auto/statemachine/historystate.scxml new file mode 100644 index 0000000..4b3a5e4 --- /dev/null +++ b/tests/auto/statemachine/historystate.scxml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" binding="early" name="HistoryState"> + <state id="Working"> + <state id="State1"> + <onentry> + <send event="timeout" delay="1s"/> + </onentry> + </state> + <history type="shallow" id="HistoryState"/> + <transition type="external" event="timeout" target="State2"/> + </state> + <state id="State2"/> +</scxml> diff --git a/tests/auto/statemachine/tst_statemachine.cpp b/tests/auto/statemachine/tst_statemachine.cpp index ed1f424..69d38b6 100644 --- a/tests/auto/statemachine/tst_statemachine.cpp +++ b/tests/auto/statemachine/tst_statemachine.cpp @@ -48,6 +48,7 @@ private Q_SLOTS: void activeStateNames_data(); void activeStateNames(); void connections(); + void historyState(); void onExit(); void eventOccurred(); @@ -251,6 +252,24 @@ void tst_StateMachine::connections() #endif } +void tst_StateMachine::historyState() +{ + QScopedPointer<QScxmlStateMachine> stateMachine( + QScxmlStateMachine::fromFile(QString(":/tst_statemachine/historystate.scxml"))); + QVERIFY(!stateMachine.isNull()); + + bool state2Reached = false; + QMetaObject::Connection state2Connection = stateMachine->connectToState("State2", + [&state2Reached](bool enabled) { + state2Reached = state2Reached || enabled; + }); + QVERIFY(state2Connection); + + stateMachine->start(); + + QTRY_VERIFY(state2Reached); +} + void tst_StateMachine::onExit() { #if defined(__cpp_return_type_deduction) && __cpp_return_type_deduction == 201304 diff --git a/tests/auto/statemachine/tst_statemachine.qrc b/tests/auto/statemachine/tst_statemachine.qrc index c31fe4c..78c1f00 100644 --- a/tests/auto/statemachine/tst_statemachine.qrc +++ b/tests/auto/statemachine/tst_statemachine.qrc @@ -6,5 +6,6 @@ <file>ids1.scxml</file> <file>stateDotDoneEvent.scxml</file> <file>invoke.scxml</file> + <file>historystate.scxml</file> </qresource> </RCC> |