summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@theqtcompany.com>2015-06-04 12:58:52 +0200
committerErik Verbruggen <erik.verbruggen@theqtcompany.com>2015-06-04 14:05:41 +0300
commit4030fbd57502bbfa785c51dfd208ea0a84f9f5ac (patch)
treef88bfee642a6b55e591e815113c485e89edfed4d /src
parent447b2c45d247e70c6d1df78846d296fd64fd5bf8 (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.cpp2
-rw-r--r--src/qml-module/state.cpp58
-rw-r--r--src/qml-module/state.h13
-rw-r--r--src/qml-module/statemachine.cpp9
-rw-r--r--src/qscxmllib/scxmlstatetable.cpp22
-rw-r--r--src/qscxmllib/scxmlstatetable.h23
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);