diff options
author | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-06-04 12:58:52 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-06-04 14:05:41 +0300 |
commit | 4030fbd57502bbfa785c51dfd208ea0a84f9f5ac (patch) | |
tree | f88bfee642a6b55e591e815113c485e89edfed4d /src | |
parent | 447b2c45d247e70c6d1df78846d296fd64fd5bf8 (diff) |
Changed the way how a connection is made to a state.
Change-Id: If60487601a9ad6fcdbcdee6a0f8528da372f5fe7
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml-module/signalevent.cpp | 2 | ||||
-rw-r--r-- | src/qml-module/state.cpp | 58 | ||||
-rw-r--r-- | src/qml-module/state.h | 13 | ||||
-rw-r--r-- | src/qml-module/statemachine.cpp | 9 | ||||
-rw-r--r-- | src/qscxmllib/scxmlstatetable.cpp | 22 | ||||
-rw-r--r-- | src/qscxmllib/scxmlstatetable.h | 23 |
6 files changed, 99 insertions, 28 deletions
diff --git a/src/qml-module/signalevent.cpp b/src/qml-module/signalevent.cpp index 5b3d7e8..a9c3739 100644 --- a/src/qml-module/signalevent.cpp +++ b/src/qml-module/signalevent.cpp @@ -75,7 +75,7 @@ void SignalEvent::setSignal(const QJSValue &signal) void SignalEvent::invoke() { if (Scxml::StateTable *table = qobject_cast<StateMachine *>(parent())->stateMachine()) { - table->submitEvent(m_eventName); + QMetaObject::invokeMethod(table, "submitEvent", Q_ARG(QByteArray, m_eventName)); } else { qmlInfo(this) << QStringLiteral("No state table found to submit event '%1'.").arg(QString::fromUtf8(m_eventName)); } diff --git a/src/qml-module/state.cpp b/src/qml-module/state.cpp index b42a7e0..4d41cf4 100644 --- a/src/qml-module/state.cpp +++ b/src/qml-module/state.cpp @@ -24,28 +24,24 @@ State::State(StateMachine *parent) : QObject(parent) + , completed(false) + , active(false) {} void State::componentComplete() { - if (Scxml::StateTable *table = qobject_cast<StateMachine *>(parent())->stateMachine()) { - if (Scxml::ScxmlState *state = table->findState(m_scxmlName)) { - if (state != m_state) { - m_state = state; - connect(m_state, SIGNAL(activeChanged(bool)), this, SIGNAL(activeChanged(bool))); - connect(m_state, SIGNAL(didEnter()), this, SIGNAL(didEnter())); - connect(m_state, SIGNAL(willExit()), this, SIGNAL(willExit())); - } - } - } + completed = true; + establishConnections(); - if (m_state == nullptr) - qmlInfo(this) << QStringLiteral("No state '%1' found.").arg(m_scxmlName); + if (Scxml::StateTable *table = qobject_cast<StateMachine *>(parent())->stateMachine()) + active = table->currentStates().contains(m_scxmlName); + if (active) + emit activeChanged(active); } bool State::isActive() const { - return m_state && m_state->active(); + return active; } QString State::scxmlName() const @@ -57,6 +53,42 @@ void State::setScxmlName(const QString &scxmlName) { if (m_scxmlName != scxmlName) { m_scxmlName = scxmlName; + breakConnections(); + establishConnections(); emit scxmlNameChanged(); } } + +void State::setActive(bool active) +{ + this->active = active; + emit activeChanged(active); +} + +void State::breakConnections() +{ + disconnect(activeConnection); + disconnect(didEnterConnection); + disconnect(willExitConnection); +} + +void State::establishConnections() +{ + if (!completed) + return; + + Scxml::StateTable *table = qobject_cast<StateMachine *>(parent())->stateMachine(); + if (table == nullptr) { + qmlInfo(this) << QStringLiteral("State is not part of a StateTable."); + return; + } + + if (!table->hasState(m_scxmlName)) { + qmlInfo(this) << QStringLiteral("No state '%1' found.").arg(m_scxmlName); + return; + } + + activeConnection = table->connect(m_scxmlName, SIGNAL(activeChanged(bool)), this, SLOT(setActive(bool))); + didEnterConnection = table->connect(m_scxmlName, SIGNAL(didEnter()), this, SIGNAL(didEnter())); + willExitConnection = table->connect(m_scxmlName, SIGNAL(willExit()), this, SIGNAL(willExit())); +} diff --git a/src/qml-module/state.h b/src/qml-module/state.h index b0581c7..53c3e37 100644 --- a/src/qml-module/state.h +++ b/src/qml-module/state.h @@ -53,9 +53,20 @@ Q_SIGNALS: void didEnter(); void willExit(); +private Q_SLOTS: + void setActive(bool active); + +private: + void breakConnections(); + void establishConnections(); + private: QString m_scxmlName; - Scxml::ScxmlState *m_state = nullptr; + QMetaObject::Connection activeConnection; + QMetaObject::Connection didEnterConnection; + QMetaObject::Connection willExitConnection; + bool completed; + bool active; }; QT_END_NAMESPACE diff --git a/src/qml-module/statemachine.cpp b/src/qml-module/statemachine.cpp index bb359bc..a2534a8 100644 --- a/src/qml-module/statemachine.cpp +++ b/src/qml-module/statemachine.cpp @@ -72,8 +72,13 @@ void StateMachine::componentComplete() return; } - m_table->init(); - m_table->start(); + bool ok = false; + bool moreOk = QMetaObject::invokeMethod(m_table, "init", Qt::DirectConnection, Q_RETURN_ARG(bool, ok)); + if (ok && moreOk) { + QMetaObject::invokeMethod(m_table, "start"); + } else { + qmlInfo(this) << "Failed to initialize the state machine."; + } } QQmlListProperty<QObject> StateMachine::states() diff --git a/src/qscxmllib/scxmlstatetable.cpp b/src/qscxmllib/scxmlstatetable.cpp index e1f8e1b..5ffa56a 100644 --- a/src/qscxmllib/scxmlstatetable.cpp +++ b/src/qscxmllib/scxmlstatetable.cpp @@ -331,10 +331,11 @@ QStringList StateTable::currentStates(bool compress) return res; } -ScxmlState *StateTable::findState(const QString &scxmlName) const +static ScxmlState *findState(const QString &scxmlName, StateTable *parent) { - QVector<QObject *> worklist; - worklist.append(const_cast<StateTable *>(this)); + QList<QObject *> worklist; + worklist.reserve(parent->children().size() + parent->configuration().size()); + worklist.append(parent); while (!worklist.isEmpty()) { QObject *obj = worklist.takeLast(); @@ -342,12 +343,25 @@ ScxmlState *StateTable::findState(const QString &scxmlName) const if (state->objectName() == scxmlName) return state; } - worklist.append(obj->children().toVector()); + worklist.append(obj->children()); } return nullptr; } +bool StateTable::hasState(const QString &scxmlStateName) const +{ + return findState(scxmlStateName, const_cast<StateTable *>(this)) != nullptr; +} + +QMetaObject::Connection StateTable::connect(const QString &scxmlStateName, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) +{ + ScxmlState *state = findState(scxmlStateName, this); + return QObject::connect(state, signal, receiver, method, type); +} + void StateTable::setName(const QString &name) { Q_D(StateTable); diff --git a/src/qscxmllib/scxmlstatetable.h b/src/qscxmllib/scxmlstatetable.h index 59824e1..8e35f8c 100644 --- a/src/qscxmllib/scxmlstatetable.h +++ b/src/qscxmllib/scxmlstatetable.h @@ -105,22 +105,31 @@ public: void setTableData(TableData *tableData); void doLog(const QString &label, const QString &msg); - virtual bool init(); + + Q_INVOKABLE bool init(); QString name() const; QStringList currentStates(bool compress = true); - ScxmlState *findState(const QString &scxmlName) const; + bool hasState(const QString &scxmlStateName) const; + + using QObject::connect; + QMetaObject::Connection connect(const QString &scxmlStateName, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type = Qt::AutoConnection); Q_INVOKABLE void submitError(const QByteArray &type, const QString &msg, const QByteArray &sendid); Q_INVOKABLE void submitEvent1(const QString &event); Q_INVOKABLE void submitEvent2(const QString &event, QVariant data); void submitEvent(ScxmlEvent *e); - void submitEvent(const QByteArray &event, const QVariantList &dataValues = QVariantList(), - const QStringList &dataNames = QStringList(), - ScxmlEvent::EventType type = ScxmlEvent::External, - const QByteArray &sendid = QByteArray(), const QString &origin = QString(), - const QString &origintype = QString(), const QByteArray &invokeid = QByteArray()); + Q_INVOKABLE void submitEvent(const QByteArray &event, + const QVariantList &dataValues = QVariantList(), + const QStringList &dataNames = QStringList(), + ScxmlEvent::EventType type = ScxmlEvent::External, + const QByteArray &sendid = QByteArray(), + const QString &origin = QString(), + const QString &origintype = QString(), + const QByteArray &invokeid = QByteArray()); void submitDelayedEvent(int delayInMiliSecs, ScxmlEvent *e); void cancelDelayedEvent(const QByteArray &event); |