summaryrefslogtreecommitdiffstats
path: root/src/corelib/statemachine
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/statemachine')
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp27
-rw-r--r--src/corelib/statemachine/qabstractstate.h3
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h8
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp88
-rw-r--r--src/corelib/statemachine/qabstracttransition.h5
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h13
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp6
-rw-r--r--src/corelib/statemachine/qeventtransition.h8
-rw-r--r--src/corelib/statemachine/qfinalstate.h4
-rw-r--r--src/corelib/statemachine/qhistorystate.h4
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h9
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp6
-rw-r--r--src/corelib/statemachine/qsignaltransition.h6
-rw-r--r--src/corelib/statemachine/qstate.cpp44
-rw-r--r--src/corelib/statemachine/qstate.h4
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp288
-rw-r--r--src/corelib/statemachine/qstatemachine.h9
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h17
18 files changed, 222 insertions, 327 deletions
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
index 3f84314..7e59a7d 100644
--- a/src/corelib/statemachine/qabstractstate.cpp
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -129,36 +129,16 @@ void QAbstractStatePrivate::emitExited()
Constructs a new state with the given \a parent state.
*/
QAbstractState::QAbstractState(QState *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- *new QAbstractStatePrivate,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(new QAbstractStatePrivate)
-#endif
+ : QObject(*new QAbstractStatePrivate, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
\internal
*/
QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- dd,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(&dd)
-#endif
+ : QObject(dd, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
@@ -166,9 +146,6 @@ QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent)
*/
QAbstractState::~QAbstractState()
{
-#ifdef QT_STATEMACHINE_SOLUTION
- delete d_ptr;
-#endif
}
/*!
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
index f6b4b21..d0ebb52 100644
--- a/src/corelib/statemachine/qabstractstate.h
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -76,9 +76,6 @@ protected:
bool event(QEvent *e);
protected:
-#ifdef QT_STATEMACHINE_SOLUTION
- QAbstractStatePrivate *d_ptr;
-#endif
QAbstractState(QAbstractStatePrivate &dd, QState *parent);
private:
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
index 6c09696..1a99d6c 100644
--- a/src/corelib/statemachine/qabstractstate_p.h
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -53,9 +53,7 @@
// We mean it.
//
-#ifndef QT_STATEMACHINE_SOLUTION
#include <private/qobject_p.h>
-#endif
QT_BEGIN_NAMESPACE
@@ -63,9 +61,7 @@ class QStateMachine;
class QAbstractState;
class Q_CORE_EXPORT QAbstractStatePrivate
-#ifndef QT_STATEMACHINE_SOLUTION
: public QObjectPrivate
-#endif
{
Q_DECLARE_PUBLIC(QAbstractState)
@@ -82,10 +78,6 @@ public:
void emitEntered();
void emitExited();
-
-#ifdef QT_STATEMACHINE_SOLUTION
- QAbstractState *q_ptr;
-#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index 1897aa6..a930581 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -125,9 +125,9 @@ QStateMachine *QAbstractTransitionPrivate::machine() const
return 0;
}
-bool QAbstractTransitionPrivate::callEventTest(QEvent *e) const
+bool QAbstractTransitionPrivate::callEventTest(QEvent *e)
{
- Q_Q(const QAbstractTransition);
+ Q_Q(QAbstractTransition);
return q->eventTest(e);
}
@@ -147,18 +147,8 @@ QState *QAbstractTransitionPrivate::sourceState() const
Constructs a new QAbstractTransition object with the given \a sourceState.
*/
QAbstractTransition::QAbstractTransition(QState *sourceState)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- *new QAbstractTransitionPrivate,
-#endif
- sourceState)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(new QAbstractTransitionPrivate)
-#endif
+ : QObject(*new QAbstractTransitionPrivate, sourceState)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
@@ -167,20 +157,9 @@ QAbstractTransition::QAbstractTransition(QState *sourceState)
*/
QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets,
QState *sourceState)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- *new QAbstractTransitionPrivate,
-#endif
- sourceState)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(new QAbstractTransitionPrivate)
-#endif
+ : QObject(*new QAbstractTransitionPrivate, sourceState)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
- Q_D(QAbstractTransition);
- d->targetStates = targets;
+ setTargetStates(targets);
}
/*!
@@ -188,18 +167,8 @@ QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets,
*/
QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
QState *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- dd,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(&dd)
-#endif
+ : QObject(dd, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
@@ -208,20 +177,9 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
const QList<QAbstractState*> &targets,
QState *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- dd,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(&dd)
-#endif
+ : QObject(dd, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
- Q_D(QAbstractTransition);
- d->targetStates = targets;
+ setTargetStates(targets);
}
/*!
@@ -229,9 +187,6 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
*/
QAbstractTransition::~QAbstractTransition()
{
-#ifdef QT_STATEMACHINE_SOLUTION
- delete d_ptr;
-#endif
}
/*!
@@ -265,7 +220,7 @@ void QAbstractTransition::setTargetState(QAbstractState* target)
if (!target)
d->targetStates.clear();
else
- d->targetStates = QList<QAbstractState*>() << target;
+ setTargetStates(QList<QAbstractState*>() << target);
}
/*!
@@ -275,7 +230,13 @@ void QAbstractTransition::setTargetState(QAbstractState* target)
QList<QAbstractState*> QAbstractTransition::targetStates() const
{
Q_D(const QAbstractTransition);
- return d->targetStates;
+ QList<QAbstractState*> result;
+ for (int i = 0; i < d->targetStates.size(); ++i) {
+ QAbstractState *target = d->targetStates.at(i);
+ if (target)
+ result.append(target);
+ }
+ return result;
}
/*!
@@ -284,7 +245,22 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const
void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
{
Q_D(QAbstractTransition);
- d->targetStates = targets;
+
+ for (int i=0; i<targets.size(); ++i) {
+ QAbstractState *target = targets.at(i);
+ if (!target) {
+ qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
+ return;
+ }
+ if (target->machine() != 0 && target->machine()->rootState() == target) {
+ qWarning("QAbstractTransition::setTargetStates: root state cannot be target of transition");
+ return;
+ }
+ }
+
+ d->targetStates.clear();
+ for (int i = 0; i < targets.size(); ++i)
+ d->targetStates.append(targets.at(i));
}
/*!
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index e207944..c63d55a 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -88,16 +88,13 @@ public:
#endif
protected:
- virtual bool eventTest(QEvent *event) const = 0;
+ virtual bool eventTest(QEvent *event) = 0;
virtual void onTransition(QEvent *event) = 0;
bool event(QEvent *e);
protected:
-#ifdef QT_STATEMACHINE_SOLUTION
- QAbstractTransitionPrivate *d_ptr;
-#endif
QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent);
QAbstractTransition(QAbstractTransitionPrivate &dd,
const QList<QAbstractState*> &targets, QState *parent);
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
index b4e1c88..a6db220 100644
--- a/src/corelib/statemachine/qabstracttransition_p.h
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -53,11 +53,10 @@
// We mean it.
//
-#ifndef QT_STATEMACHINE_SOLUTION
#include <private/qobject_p.h>
-#endif
#include <QtCore/qlist.h>
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -67,9 +66,7 @@ class QStateMachine;
class QAbstractTransition;
class Q_CORE_EXPORT QAbstractTransitionPrivate
-#ifndef QT_STATEMACHINE_SOLUTION
: public QObjectPrivate
-#endif
{
Q_DECLARE_PUBLIC(QAbstractTransition)
public:
@@ -78,20 +75,16 @@ public:
static QAbstractTransitionPrivate *get(QAbstractTransition *q);
static const QAbstractTransitionPrivate *get(const QAbstractTransition *q);
- bool callEventTest(QEvent *e) const;
+ bool callEventTest(QEvent *e);
void callOnTransition(QEvent *e);
QState *sourceState() const;
QStateMachine *machine() const;
- QList<QAbstractState*> targetStates;
+ QList<QPointer<QAbstractState> > targetStates;
#ifndef QT_NO_ANIMATION
QList<QAbstractAnimation*> animations;
#endif
-
-#ifdef QT_STATEMACHINE_SOLUTION
- QAbstractTransition *q_ptr;
-#endif
};
QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
index 86259e4..74eb577 100644
--- a/src/corelib/statemachine/qeventtransition.cpp
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -252,14 +252,10 @@ void QEventTransition::setEventObject(QObject *object)
/*!
\reimp
*/
-bool QEventTransition::eventTest(QEvent *event) const
+bool QEventTransition::eventTest(QEvent *event)
{
Q_D(const QEventTransition);
-#ifdef QT_STATEMACHINE_SOLUTION
- if (event->type() == QEvent::Type(QEvent::User-3)) {
-#else
if (event->type() == QEvent::Wrapped) {
-#endif
QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
return (we->object() == d->object)
&& (we->event()->type() == d->eventType);
diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h
index a128cee..3530bdd 100644
--- a/src/corelib/statemachine/qeventtransition.h
+++ b/src/corelib/statemachine/qeventtransition.h
@@ -42,11 +42,7 @@
#ifndef QEVENTTRANSITION_H
#define QEVENTTRANSITION_H
-#ifndef QT_STATEMACHINE_SOLUTION
#include <QtCore/qabstracttransition.h>
-#else
-#include "qabstracttransition.h"
-#endif
#include <QtCore/qcoreevent.h>
QT_BEGIN_HEADER
@@ -60,9 +56,7 @@ class Q_CORE_EXPORT QEventTransition : public QAbstractTransition
{
Q_OBJECT
Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject)
-#ifndef QT_STATEMACHINE_SOLUTION
Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType)
-#endif
public:
QEventTransition(QState *sourceState = 0);
QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0);
@@ -77,7 +71,7 @@ public:
void setEventType(QEvent::Type type);
protected:
- bool eventTest(QEvent *event) const;
+ bool eventTest(QEvent *event);
void onTransition(QEvent *event);
bool event(QEvent *e);
diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h
index eb8aa0f..fa68394 100644
--- a/src/corelib/statemachine/qfinalstate.h
+++ b/src/corelib/statemachine/qfinalstate.h
@@ -42,11 +42,7 @@
#ifndef QFINALSTATE_H
#define QFINALSTATE_H
-#ifndef QT_STATEMACHINE_SOLUTION
#include <QtCore/qabstractstate.h>
-#else
-#include "qabstractstate.h"
-#endif
QT_BEGIN_HEADER
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
index d0f75de..a0682bd 100644
--- a/src/corelib/statemachine/qhistorystate.h
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -42,11 +42,7 @@
#ifndef QHISTORYSTATE_H
#define QHISTORYSTATE_H
-#ifndef QT_STATEMACHINE_SOLUTION
#include <QtCore/qabstractstate.h>
-#else
-#include "qabstractstate.h"
-#endif
QT_BEGIN_HEADER
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
index d18def8..cf0ea1e 100644
--- a/src/corelib/statemachine/qsignaleventgenerator_p.h
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -62,11 +62,7 @@ class QStateMachine;
class QSignalEventGenerator : public QObject
{
public:
- QSignalEventGenerator(
-#ifdef QT_STATEMACHINE_SOLUTION
- int signalIndex,
-#endif
- QStateMachine *parent);
+ QSignalEventGenerator(QStateMachine *parent);
static const QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const;
@@ -74,9 +70,6 @@ public:
virtual int qt_metacall(QMetaObject::Call, int, void **argv);
private:
-#ifdef QT_STATEMACHINE_SOLUTION
- int signalIndex;
-#endif
Q_DISABLE_COPY(QSignalEventGenerator)
};
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
index d5833bd..4caa917 100644
--- a/src/corelib/statemachine/qsignaltransition.cpp
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -225,14 +225,10 @@ void QSignalTransition::setSignal(const QByteArray &signal)
true if the event's sender and signal index match this transition, and
returns false otherwise.
*/
-bool QSignalTransition::eventTest(QEvent *event) const
+bool QSignalTransition::eventTest(QEvent *event)
{
Q_D(const QSignalTransition);
-#ifndef QT_STATEMACHINE_SOLUTION
if (event->type() == QEvent::Signal) {
-#else
- if (event->type() == QEvent::Type(QEvent::User-1)) {
-#endif
if (d->signalIndex == -1)
return false;
QSignalEvent *se = static_cast<QSignalEvent*>(event);
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
index 98a9ae7..b485785 100644
--- a/src/corelib/statemachine/qsignaltransition.h
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -42,11 +42,7 @@
#ifndef QSIGNALTRANSITION_H
#define QSIGNALTRANSITION_H
-#ifndef QT_STATEMACHINE_SOLUTION
#include <QtCore/qabstracttransition.h>
-#else
-#include "qabstracttransition.h"
-#endif
QT_BEGIN_HEADER
@@ -76,7 +72,7 @@ public:
void setSignal(const QByteArray &signal);
protected:
- bool eventTest(QEvent *event) const;
+ bool eventTest(QEvent *event);
void onTransition(QEvent *event);
bool event(QEvent *e);
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index 4c9e033..e42e463 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -193,9 +193,6 @@ QList<QAbstractState*> QStatePrivate::childStates() const
{
QList<QAbstractState*> result;
QList<QObject*>::const_iterator it;
-#ifdef QT_STATEMACHINE_SOLUTION
- const QObjectList &children = q_func()->children();
-#endif
for (it = children.constBegin(); it != children.constEnd(); ++it) {
QAbstractState *s = qobject_cast<QAbstractState*>(*it);
if (!s || qobject_cast<QHistoryState*>(s))
@@ -209,9 +206,6 @@ QList<QHistoryState*> QStatePrivate::historyStates() const
{
QList<QHistoryState*> result;
QList<QObject*>::const_iterator it;
-#ifdef QT_STATEMACHINE_SOLUTION
- const QObjectList &children = q_func()->children();
-#endif
for (it = children.constBegin(); it != children.constEnd(); ++it) {
QHistoryState *h = qobject_cast<QHistoryState*>(*it);
if (h)
@@ -224,9 +218,6 @@ QList<QAbstractTransition*> QStatePrivate::transitions() const
{
QList<QAbstractTransition*> result;
QList<QObject*>::const_iterator it;
-#ifdef QT_STATEMACHINE_SOLUTION
- const QObjectList &children = q_func()->children();
-#endif
for (it = children.constBegin(); it != children.constEnd(); ++it) {
QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it);
if (t)
@@ -280,11 +271,15 @@ QAbstractState *QState::errorState() const
void QState::setErrorState(QAbstractState *state)
{
Q_D(QState);
- if (state != 0 && QAbstractStatePrivate::get(state)->machine() != d->machine()) {
+ if (state != 0 && state->machine() != machine()) {
qWarning("QState::setErrorState: error state cannot belong "
"to a different state machine");
return;
}
+ if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) {
+ qWarning("QStateMachine::setErrorState: root state cannot be error state");
+ return;
+ }
d->errorState = state;
}
@@ -301,7 +296,14 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
qWarning("QState::addTransition: cannot add null transition");
return 0;
}
- const QList<QAbstractState*> &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
+
+ // machine() will always be non-null for root state
+ if (machine() != 0 && machine()->rootState() == this) {
+ qWarning("QState::addTransition: cannot add transition from root state");
+ return 0;
+ }
+
+ const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
for (int i = 0; i < targets.size(); ++i) {
QAbstractState *t = targets.at(i);
if (!t) {
@@ -316,6 +318,8 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
}
}
transition->setParent(this);
+ if (machine() != 0 && machine()->configuration().contains(this))
+ QStateMachinePrivate::get(machine())->registerTransitions(this);
return transition;
}
@@ -335,6 +339,15 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal,
qWarning("QState::addTransition: signal cannot be null");
return 0;
}
+ if (!target) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ if (*signal && sender->metaObject()->indexOfSignal(signal+1) == -1) {
+ qWarning("QState::addTransition: no such signal %s::%s",
+ sender->metaObject()->className(), signal+1);
+ return 0;
+ }
QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target);
addTransition(trans);
return trans;
@@ -350,7 +363,7 @@ public:
: QAbstractTransition(QList<QAbstractState*>() << target) {}
protected:
void onTransition(QEvent *) {}
- bool eventTest(QEvent *) const { return true; }
+ bool eventTest(QEvent *) { return true; }
};
} // namespace
@@ -361,9 +374,12 @@ protected:
*/
QAbstractTransition *QState::addTransition(QAbstractState *target)
{
+ if (!target) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
UnconditionalTransition *trans = new UnconditionalTransition(target);
- addTransition(trans);
- return trans;
+ return addTransition(trans);
}
/*!
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
index 73955d7..6729c69 100644
--- a/src/corelib/statemachine/qstate.h
+++ b/src/corelib/statemachine/qstate.h
@@ -42,11 +42,7 @@
#ifndef QSTATE_H
#define QSTATE_H
-#ifndef QT_STATEMACHINE_SOLUTION
#include <QtCore/qabstractstate.h>
-#else
-#include "qabstractstate.h"
-#endif
QT_BEGIN_HEADER
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index ff3fb7d..744515b 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -54,10 +54,8 @@
#include "qfinalstate.h"
#include "qhistorystate.h"
#include "qhistorystate_p.h"
-#ifndef QT_STATEMACHINE_SOLUTION
#include "private/qobject_p.h"
#include "private/qthread_p.h"
-#endif
#ifndef QT_NO_STATEMACHINE_EVENTFILTER
#include "qeventtransition.h"
@@ -68,11 +66,7 @@
#ifndef QT_NO_ANIMATION
#include "qpropertyanimation.h"
#include "qanimationgroup.h"
-# ifndef QT_STATEMACHINE_SOLUTION
-# include <private/qvariantanimation_p.h>
-# else
-# include "qvariantanimation_p.h"
-# endif
+#include <private/qvariantanimation_p.h>
#endif
#include <QtCore/qmetaobject.h>
@@ -89,68 +83,98 @@ QT_BEGIN_NAMESPACE
\since 4.6
\ingroup statemachine
- The QStateMachine class provides a hierarchical finite state machine based
- on \l{Statecharts: A visual formalism for complex systems}{Statecharts}
- concepts and notation. QStateMachine is part of \l{The State Machine
- Framework}.
-
- A state machine manages a set of states (QAbstractState objects) and
- transitions (QAbstractTransition objects) between those states; the states
- and the transitions collectively define a state graph. Once a state graph
- has been defined, the state machine can execute it. QStateMachine's
- execution algorithm is based on the \l{State Chart XML: State Machine
- Notation for Control Abstraction}{State Chart XML (SCXML)} algorithm.
-
- The QState class provides a state that you can use to set properties and
- invoke methods on QObjects when the state is entered or exited. This is
+ QStateMachine is based on the concepts and notation of
+ \l{Statecharts: A visual formalism for complex
+ systems}{Statecharts}. QStateMachine is part of \l{The State
+ Machine Framework}.
+
+ A state machine manages a set of states (classes that inherit from
+ QAbstractState) and transitions (descendants of
+ QAbstractTransition) between those states; these states and
+ transitions define a state graph. Once a state graph has been
+ built, the state machine can execute it. \l{QStateMachine}'s
+ execution algorithm is based on the \l{State Chart XML: State
+ Machine Notation for Control Abstraction}{State Chart XML (SCXML)}
+ algorithm. The framework's \l{The State Machine
+ Framework}{overview} gives several state graphs and the code to
+ build them.
+
+ The rootState() is the parent of all top-level states in the
+ machine; it is used, for instance, when the state graph is
+ deleted. It is created by the machine.
+
+ Use the addState() function to add a state to the state machine.
+ All top-level states are added to the root state. States are
+ removed with the removeState() function. Removing states while the
+ machine is running is discouraged.
+
+ Before the machine can be started, the \l{initialState}{initial
+ state} must be set. The initial state is the state that the
+ machine enters when started. You can then start() the state
+ machine. The started() signal is emitted when the initial state is
+ entered.
+
+ The machine is event driven and keeps its own event loop. Events
+ are posted to the machine through postEvent(). Note that this
+ means that it executes asynchronously, and that it will not
+ progress without a running event loop. You will normally not have
+ to post events to the machine directly as Qt's transitions, e.g.,
+ QEventTransition and its subclasses, handle this. But for custom
+ transitions triggered by events, postEvent() is useful.
+
+ The state machine processes events and takes transitions until a
+ top-level final state is entered; the state machine then emits the
+ finished() signal. You can also stop() the state machine
+ explicitly. The stopped() signal is emitted in this case.
+
+ The following snippet shows a state machine that will finish when a button
+ is clicked:
+
+ \code
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *s1 = new QState();
+ s1->assignProperty(&button, "text", "Click me");
+
+ QFinalState *s2 = new QFinalState();
+ s1->addTransition(&button, SIGNAL(clicked()), s2);
+
+ machine.addState(s1);
+ machine.addState(s2);
+ machine.setInitialState(s1);
+ machine.start();
+ \endcode
+
+ This code example uses QState, which inherits QAbstractState. The
+ QState class provides a state that you can use to set properties
+ and invoke methods on \l{QObject}s when the state is entered or
+ exited. It also contains convenience functions for adding
+ transitions, e.g., \l{QSignalTransition}s as in this example. See
+ the QState class description for further details.
+
+ If an error is encountered, the machine will enter the
+ \l{errorState}{error state}, which is a special state created by
+ the machine. The types of errors possible are described by the
+ \l{QStateMachine::}{Error} enum. After the error state is entered,
+ the type of the error can be retrieved with error(). The execution
+ of the state graph will not stop when the error state is entered.
+ So it is possible to handle the error, for instance, by connecting
+ to the \l{QAbstractState::}{entered()} signal of the error state.
+ It is also possible to set a custom error state with
+ setErrorState().
+
+ \omit This stuff will be moved elsewhere
+This is
typically used in conjunction with \l{Signals and Slots}{signals}; the
signals determine the flow of the state graph, whereas the states' property
assignments and method invocations are the actions.
- Use the addState() function to add a state to the state machine;
- alternatively, pass the machine's rootState() to the state constructor. Use
- the removeState() function to remove a state from the state machine.
-
- The following snippet shows a state machine that will finish when a button
- is clicked:
-
- \code
- QPushButton button;
-
- QStateMachine machine;
- QState *s1 = new QState();
- s1->assignProperty(&button, "text", "Click me");
-
- QFinalState *s2 = new QFinalState();
- s1->addTransition(&button, SIGNAL(clicked()), s2);
-
- machine.addState(s1);
- machine.addState(s2);
- machine.setInitialState(s1);
- machine.start();
- \endcode
-
- The setInitialState() function sets the state machine's initial state; this
- state is entered when the state machine is started.
-
- The start() function starts the state machine. The state machine executes
- asynchronously, i.e. you need to run an event loop in order for it to make
- progress. The started() signal is emitted when the state machine has entered
- the initial state.
-
- The state machine processes events and takes transitions until a top-level
- final state is entered; the state machine then emits the finished() signal.
-
- The stop() function stops the state machine. The stopped() signal is emitted
- when the state machine has stopped.
-
The postEvent() function posts an event to the state machine. This is useful
when you are using custom events to trigger transitions.
+ \endomit
- The rootState() function returns the state machine's root state. All
- top-level states have the root state as their parent.
-
- \sa QAbstractState, QAbstractTransition
+ \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework}
*/
/*!
@@ -212,9 +236,7 @@ QStateMachinePrivate::QStateMachinePrivate()
globalRestorePolicy = QStateMachine::DoNotRestoreProperties;
rootState = 0;
initialErrorStateForRoot = 0;
-#ifndef QT_STATEMACHINE_SOLUTION
signalEventGenerator = 0;
-#endif
#ifndef QT_NO_ANIMATION
animationsEnabled = true;
#endif
@@ -1011,6 +1033,8 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta
}
Q_ASSERT(currentErrorState != 0);
+ Q_ASSERT(currentErrorState != rootState);
+
QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
}
@@ -1100,7 +1124,7 @@ public:
InitialTransition(QAbstractState *target)
: QAbstractTransition(QList<QAbstractState*>() << target) {}
protected:
- virtual bool eventTest(QEvent *) const { return true; }
+ virtual bool eventTest(QEvent *) { return true; }
virtual void onTransition(QEvent *) {}
};
@@ -1222,10 +1246,12 @@ void QStateMachinePrivate::_q_process()
break;
case Finished:
state = NotRunning;
+ unregisterAllTransitions();
emit q->finished();
break;
case Stopped:
state = NotRunning;
+ unregisterAllTransitions();
emit q->stopped();
break;
}
@@ -1270,8 +1296,6 @@ void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
#endif
}
-#ifndef QT_STATEMACHINE_SOLUTION
-
static int senderSignalIndex(const QObject *sender)
{
QObjectPrivate *d = QObjectPrivate::get(const_cast<QObject*>(sender));
@@ -1288,8 +1312,6 @@ static int senderSignalIndex(const QObject *sender)
return d->currentSender->signal;
}
-#endif
-
void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
{
Q_Q(QStateMachine);
@@ -1307,14 +1329,12 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
sender->metaObject()->className(), signal.constData());
return;
}
- QList<int> &connectedSignalIndexes = connections[sender];
- if (!connectedSignalIndexes.contains(signalIndex)) {
-#ifndef QT_STATEMACHINE_SOLUTION
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ if (connectedSignalIndexes.size() <= signalIndex)
+ connectedSignalIndexes.resize(signalIndex+1);
+ if (connectedSignalIndexes.at(signalIndex) == 0) {
if (!signalEventGenerator)
signalEventGenerator = new QSignalEventGenerator(q);
-#else
- QSignalEventGenerator *signalEventGenerator = new QSignalEventGenerator(signalIndex, q);
-#endif
bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
signalEventGenerator->metaObject()->methodOffset());
if (!ok) {
@@ -1325,8 +1345,8 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
#endif
return;
}
- connectedSignalIndexes.append(signalIndex);
}
+ ++connectedSignalIndexes[signalIndex];
QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex;
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": added signal transition from" << transition->sourceState()
@@ -1340,20 +1360,35 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit
int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
if (signalIndex == -1)
return; // not registered
-#ifndef QT_STATEMACHINE_SOLUTION
+ QSignalTransitionPrivate::get(transition)->signalIndex = -1;
const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
- QList<int> &connectedSignalIndexes = connections[sender];
- Q_ASSERT(connectedSignalIndexes.contains(signalIndex));
- Q_ASSERT(signalEventGenerator != 0);
- bool ok = QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
- signalEventGenerator->metaObject()->methodOffset());
- if (ok) {
- connectedSignalIndexes.removeOne(signalIndex);
- if (connectedSignalIndexes.isEmpty())
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
+ Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
+ if (--connectedSignalIndexes[signalIndex] == 0) {
+ Q_ASSERT(signalEventGenerator != 0);
+ QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ int sum = 0;
+ for (int i = 0; i < connectedSignalIndexes.size(); ++i)
+ sum += connectedSignalIndexes.at(i);
+ if (sum == 0)
connections.remove(sender);
- QSignalTransitionPrivate::get(transition)->signalIndex = -1;
}
-#endif
+}
+
+void QStateMachinePrivate::unregisterAllTransitions()
+{
+ {
+ QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState);
+ for (int i = 0; i < transitions.size(); ++i)
+ unregisterSignalTransition(transitions.at(i));
+ }
+ {
+ QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState);
+ for (int i = 0; i < transitions.size(); ++i)
+ unregisterEventTransition(transitions.at(i));
+ }
}
#ifndef QT_NO_STATEMACHINE_EVENTFILTER
@@ -1369,12 +1404,10 @@ void QStateMachinePrivate::registerEventTransition(QEventTransition *transition)
QObject *object = QEventTransitionPrivate::get(transition)->object;
if (!object)
return;
-#ifndef QT_STATEMACHINE_SOLUTION
QObjectPrivate *od = QObjectPrivate::get(object);
if (!od->eventFilters.contains(q))
-#endif
object->installEventFilter(q);
- qobjectEvents[object].insert(transition->eventType());
+ ++qobjectEvents[object][transition->eventType()];
QEventTransitionPrivate::get(transition)->registered = true;
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": added event transition from" << transition->sourceState()
@@ -1389,11 +1422,18 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio
if (!QEventTransitionPrivate::get(transition)->registered)
return;
QObject *object = QEventTransitionPrivate::get(transition)->object;
- QSet<QEvent::Type> &events = qobjectEvents[object];
- events.remove(transition->eventType());
- if (events.isEmpty()) {
- qobjectEvents.remove(object);
- object->removeEventFilter(q);
+ QHash<QEvent::Type, int> &events = qobjectEvents[object];
+ Q_ASSERT(events.value(transition->eventType()) > 0);
+ if (--events[transition->eventType()] == 0) {
+ events.remove(transition->eventType());
+ int sum = 0;
+ QHash<QEvent::Type, int>::const_iterator it;
+ for (it = events.constBegin(); it != events.constEnd(); ++it)
+ sum += it.value();
+ if (sum == 0) {
+ qobjectEvents.remove(object);
+ object->removeEventFilter(q);
+ }
}
QEventTransitionPrivate::get(transition)->registered = false;
}
@@ -1402,8 +1442,8 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio
void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex,
void **argv)
{
- const QList<int> &connectedSignalIndexes = connections[sender];
- Q_ASSERT(connectedSignalIndexes.contains(signalIndex));
+ const QVector<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
const QMetaObject *meta = sender->metaObject();
QMetaMethod method = meta->method(signalIndex);
QList<QByteArray> parameterTypes = method.parameterTypes();
@@ -1426,36 +1466,16 @@ void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int sig
Constructs a new state machine with the given \a parent.
*/
QStateMachine::QStateMachine(QObject *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- *new QStateMachinePrivate,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(new QStateMachinePrivate)
-#endif
+ : QObject(*new QStateMachinePrivate, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
\internal
*/
QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
- : QObject(
-#ifndef QT_STATEMACHINE_SOLUTION
- dd,
-#endif
- parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , d_ptr(&dd)
-#endif
+ : QObject(dd, parent)
{
-#ifdef QT_STATEMACHINE_SOLUTION
- d_ptr->q_ptr = this;
-#endif
}
/*!
@@ -1463,9 +1483,6 @@ QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
*/
QStateMachine::~QStateMachine()
{
-#ifdef QT_STATEMACHINE_SOLUTION
- delete d_ptr;
-#endif
}
namespace {
@@ -2065,11 +2082,9 @@ int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: {
-#ifndef QT_STATEMACHINE_SOLUTION
// ### in Qt 4.6 we can use QObject::senderSignalIndex()
int signalIndex = senderSignalIndex(this);
Q_ASSERT(signalIndex != -1);
-#endif
QStateMachine *machine = qobject_cast<QStateMachine*>(parent());
QStateMachinePrivate::get(machine)->handleTransitionSignal(sender(), signalIndex, _a);
break;
@@ -2081,15 +2096,8 @@ int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
return _id;
}
-QSignalEventGenerator::QSignalEventGenerator(
-#ifdef QT_STATEMACHINE_SOLUTION
- int sigIdx,
-#endif
- QStateMachine *parent)
+QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
: QObject(parent)
-#ifdef QT_STATEMACHINE_SOLUTION
- , signalIndex(sigIdx)
-#endif
{
}
@@ -2120,13 +2128,8 @@ QSignalEventGenerator::QSignalEventGenerator(
*/
QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex,
const QList<QVariant> &arguments)
- :
-#ifndef QT_STATEMACHINE_SOLUTION
- QEvent(QEvent::Signal)
-#else
- QEvent(QEvent::Type(QEvent::User-1))
-#endif
- , m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments)
+ : QEvent(QEvent::Signal), m_sender(sender),
+ m_signalIndex(signalIndex), m_arguments(arguments)
{
}
@@ -2185,12 +2188,7 @@ QSignalEvent::~QSignalEvent()
and \a event.
*/
QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event)
-#ifdef QT_STATEMACHINE_SOLUTION
- : QEvent(QEvent::Type(QEvent::User-3))
-#else
- : QEvent(QEvent::Wrapped)
-#endif
- , m_object(object), m_event(event)
+ : QEvent(QEvent::Wrapped), m_object(object), m_event(event)
{
}
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index 5dc6c0b..2a98a9a 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -42,11 +42,7 @@
#ifndef QSTATEMACHINE_H
#define QSTATEMACHINE_H
-#ifndef QT_STATEMACHINE_SOLUTION
-# include <QtCore/qabstractstate.h>
-#else
-# include "qabstractstate.h"
-#endif
+#include <QtCore/qabstractstate.h>
#include <QtCore/qlist.h>
#include <QtCore/qobject.h>
@@ -151,9 +147,6 @@ protected:
bool event(QEvent *e);
protected:
-#ifdef QT_STATEMACHINE_SOLUTION
- QStateMachinePrivate *d_ptr;
-#endif
QStateMachine(QStateMachinePrivate &dd, QObject *parent);
private:
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index bb4a78c..dfa5575 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -53,14 +53,13 @@
// We mean it.
//
-#ifndef QT_STATEMACHINE_SOLUTION
#include <private/qobject_p.h>
-#endif
#include <QtCore/qcoreevent.h>
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qset.h>
+#include <QtCore/qvector.h>
#include "qstate.h"
#include "qstate_p.h"
@@ -83,9 +82,7 @@ class QAbstractAnimation;
class QStateMachine;
class Q_CORE_EXPORT QStateMachinePrivate
-#ifndef QT_STATEMACHINE_SOLUTION
: public QObjectPrivate
-#endif
{
Q_DECLARE_PUBLIC(QStateMachine)
public:
@@ -150,6 +147,7 @@ public:
void unregisterEventTransition(QEventTransition *transition);
#endif
void unregisterTransition(QAbstractTransition *transition);
+ void unregisterAllTransitions();
void handleTransitionSignal(const QObject *sender, int signalIndex,
void **args);
void scheduleProcess();
@@ -198,12 +196,11 @@ public:
#endif // QT_NO_ANIMATION
-#ifndef QT_STATEMACHINE_SOLUTION
QSignalEventGenerator *signalEventGenerator;
-#endif
- QHash<const QObject*, QList<int> > connections;
+
+ QHash<const QObject*, QVector<int> > connections;
#ifndef QT_NO_STATEMACHINE_EVENTFILTER
- QHash<QObject*, QSet<QEvent::Type> > qobjectEvents;
+ QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents;
#endif
QHash<int, QEvent*> delayedEvents;
@@ -213,10 +210,6 @@ public:
};
static const Handler *handler;
-
-#ifdef QT_STATEMACHINE_SOLUTION
- QStateMachine *q_ptr;
-#endif
};
QT_END_NAMESPACE