summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/examples-overview.qdoc8
-rw-r--r--doc/src/examples.qdoc3
-rw-r--r--doc/src/examples/eventtransitions.qdoc86
-rw-r--r--doc/src/examples/pingpong.qdoc107
-rw-r--r--doc/src/examples/trafficlight.qdoc79
-rw-r--r--doc/src/examples/twowaybutton.qdoc (renamed from examples/statemachine/helloworld/main.cpp)66
-rw-r--r--doc/src/images/pingpong-example.pngbin0 -> 7843 bytes
-rw-r--r--doc/src/images/trafficlight-example1.pngbin0 -> 3694 bytes
-rw-r--r--doc/src/images/trafficlight-example2.pngbin0 -> 7257 bytes
-rw-r--r--doc/src/statemachine.qdoc218
-rw-r--r--examples/statemachine/clockticking/clockticking.pro10
-rw-r--r--examples/statemachine/clockticking/main.cpp123
-rw-r--r--examples/statemachine/composition/composition.pro7
-rw-r--r--examples/statemachine/composition/main.cpp104
-rw-r--r--examples/statemachine/errorstateplugins/errorstateplugins.pro11
-rw-r--r--examples/statemachine/eventtransitions/main.cpp16
-rw-r--r--examples/statemachine/helloworld/helloworld.pro10
-rw-r--r--examples/statemachine/pauseandresume/main.cpp102
-rw-r--r--examples/statemachine/pauseandresume/pauseandresume.pro7
-rw-r--r--examples/statemachine/pingpong/main.cpp14
-rw-r--r--examples/statemachine/statemachine.pro8
-rw-r--r--examples/statemachine/tankgame/gameitem.cpp (renamed from examples/statemachine/errorstate/gameitem.cpp)0
-rw-r--r--examples/statemachine/tankgame/gameitem.h (renamed from examples/statemachine/errorstate/gameitem.h)0
-rw-r--r--examples/statemachine/tankgame/main.cpp (renamed from examples/statemachine/errorstate/main.cpp)0
-rw-r--r--examples/statemachine/tankgame/mainwindow.cpp (renamed from examples/statemachine/errorstate/mainwindow.cpp)7
-rw-r--r--examples/statemachine/tankgame/mainwindow.h (renamed from examples/statemachine/errorstate/mainwindow.h)0
-rw-r--r--examples/statemachine/tankgame/plugin.h (renamed from examples/statemachine/errorstate/plugin.h)0
-rw-r--r--examples/statemachine/tankgame/rocketitem.cpp (renamed from examples/statemachine/errorstate/rocketitem.cpp)0
-rw-r--r--examples/statemachine/tankgame/rocketitem.h (renamed from examples/statemachine/errorstate/rocketitem.h)0
-rw-r--r--examples/statemachine/tankgame/tankgame.pro (renamed from examples/statemachine/errorstate/errorstate.pro)2
-rw-r--r--examples/statemachine/tankgame/tankitem.cpp (renamed from examples/statemachine/errorstate/tankitem.cpp)0
-rw-r--r--examples/statemachine/tankgame/tankitem.h (renamed from examples/statemachine/errorstate/tankitem.h)2
-rw-r--r--examples/statemachine/tankgameplugins/random_ai/random_ai.pro (renamed from examples/statemachine/errorstateplugins/random_ai/random_ai.pro)6
-rw-r--r--examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp (renamed from examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp)0
-rw-r--r--examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.h (renamed from examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h)2
-rw-r--r--examples/statemachine/tankgameplugins/seek_ai/seek_ai.cpp (renamed from examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp)0
-rw-r--r--examples/statemachine/tankgameplugins/seek_ai/seek_ai.h (renamed from examples/statemachine/errorstateplugins/seek_ai/seek_ai.h)2
-rw-r--r--examples/statemachine/tankgameplugins/seek_ai/seek_ai.pro (renamed from examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro)6
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai/spin_ai.cpp (renamed from examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp)0
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai/spin_ai.h (renamed from examples/statemachine/errorstateplugins/spin_ai/spin_ai.h)2
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai/spin_ai.pro (renamed from examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro)6
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.cpp (renamed from examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp)0
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.h (renamed from examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h)2
-rw-r--r--examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.pro (renamed from examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro)6
-rw-r--r--examples/statemachine/tankgameplugins/tankgameplugins.pro11
-rw-r--r--examples/statemachine/trafficlight/main.cpp47
-rw-r--r--examples/statemachine/twowaybutton/main.cpp22
-rw-r--r--src/corelib/statemachine/qstate.cpp2
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp33
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp1
-rw-r--r--src/plugins/accessible/widgets/simplewidgets.h1
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp45
53 files changed, 689 insertions, 498 deletions
diff --git a/doc/src/examples-overview.qdoc b/doc/src/examples-overview.qdoc
index 549574d..92ccd4e 100644
--- a/doc/src/examples-overview.qdoc
+++ b/doc/src/examples-overview.qdoc
@@ -319,6 +319,14 @@
from displaying Web pages within a Qt user interface to an implementation of
a basic function Web browser.
+ \section1 \l{Qt Examples#State Machine}{State Machine}
+
+ Qt provides a powerful hierchical finite state machine through the Qt State
+ Machine classes.
+
+ These examples demonstrate the fundamental aspects of implementing
+ Statecharts with Qt.
+
\section1 \l{Qt Examples#Qt for Embedded Linux}{Qt for Embedded Linux}
\l{Qt Examples#Qt for Embedded Linux}{\inlineimage qt-embedded-examples.png
diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc
index 06d7727..0153252 100644
--- a/doc/src/examples.qdoc
+++ b/doc/src/examples.qdoc
@@ -311,7 +311,10 @@
\section1 State Machine
\list
+ \o \l{statemachine/eventtransitions}{Event Transitions}\raisedaster
+ \o \l{statemachine/pingpong}{Ping Pong States}\raisedaster
\o \l{statemachine/trafficlight}{Traffic Light}\raisedaster
+ \o \l{statemachine/twowaybutton}{Two-way Button}\raisedaster
\endlist
\section1 Threads
diff --git a/doc/src/examples/eventtransitions.qdoc b/doc/src/examples/eventtransitions.qdoc
new file mode 100644
index 0000000..3b956bb
--- /dev/null
+++ b/doc/src/examples/eventtransitions.qdoc
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example statemachine/eventtransitions
+ \title Event Transitions Example
+
+ The Event Transitions example shows how to use event transitions, a
+ feature of \l{The State Machine Framework}.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 0
+
+ The \c Window class's constructors begins by creating a button.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 1
+
+ Two states, \c s1 and \c s2, are created; upon entry they will assign
+ "Outside" and "Inside" to the button's text, respectively.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 2
+
+ When the button receives an event of type QEvent::Enter and the state
+ machine is in state \c s1, the machine will transition to state \c s2.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 3
+
+ When the button receives an event of type QEvent::Leave and the state
+ machine is in state \c s2, the machine will transition back to state \c
+ s1.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 4
+
+ Next, the state \c s3 is created. \c s3 will be entered when the button
+ receives an event of type QEvent::MouseButtonPress and the state machine
+ is in state \c s2. When the button receives an event of type
+ QEvent::MouseButtonRelease and the state machine is in state \c s3, the
+ machine will transition back to state \c s2.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 5
+
+ Finally, the states are added to the machine as top-level states, the
+ initial state is set to be \c s1 ("Outside"), and the machine is started.
+
+ \snippet examples/statemachine/eventtransitions/main.cpp 6
+
+ The main() function constructs a Window object and shows it.
+
+*/
diff --git a/doc/src/examples/pingpong.qdoc b/doc/src/examples/pingpong.qdoc
new file mode 100644
index 0000000..040e429
--- /dev/null
+++ b/doc/src/examples/pingpong.qdoc
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example statemachine/pingpong
+ \title Ping Pong States Example
+
+ The Ping Pong States example shows how to use parallel states together
+ with custom events and transitions in \l{The State Machine Framework}.
+
+ This example implements a statechart where two states communicate by
+ posting events to the state machine. The state chart looks as follows:
+
+ \img pingpong-example.png
+ \omit
+ \caption This is a caption
+ \endomit
+
+ The \c pinger and \c ponger states are parallel states, i.e. they are
+ entered simultaneously and will take transitions independently of
+ eachother.
+
+ The \c pinger state will post the first \c ping event upon entry; the \c
+ ponger state will respond by posting a \c pong event; this will cause the
+ \c pinger state to post a new \c ping event; and so on.
+
+ \snippet examples/statemachine/pingpong/main.cpp 0
+
+ Two custom events are defined, \c PingEvent and \c PongEvent.
+
+ \snippet examples/statemachine/pingpong/main.cpp 1
+
+ The \c Pinger class defines a state that posts a \c PingEvent to the state
+ machine when the state is entered.
+
+ \snippet examples/statemachine/pingpong/main.cpp 2
+
+ The \c PingTransition class defines a transition that is triggered by
+ events of type \c PingEvent, and that posts a \c PongEvent (with a delay
+ of 500 milliseconds) to the state machine when the transition is
+ triggered.
+
+ \snippet examples/statemachine/pingpong/main.cpp 3
+
+ The \c PongTransition class defines a transition that is triggered by
+ events of type \c PongEvent, and that posts a \c PingEvent (with a delay
+ of 500 milliseconds) to the state machine when the transition is
+ triggered.
+
+ \snippet examples/statemachine/pingpong/main.cpp 4
+
+ The main() function begins by creating a state machine and a parallel
+ state group.
+
+ \snippet examples/statemachine/pingpong/main.cpp 5
+
+ Next, the \c pinger and \c ponger states are created, with the parallel
+ state group as their parent state. Note that the transitions are \e
+ targetless. When such a transition is triggered, the source state won't be
+ exited and re-entered; only the transition's onTransition() function will
+ be called, and the state machine's configuration will remain the same,
+ which is precisely what we want in this case.
+
+ \snippet examples/statemachine/pingpong/main.cpp 6
+
+ Finally, the group is added to the state machine, the machine is started,
+ and the application event loop is entered.
+
+ */
diff --git a/doc/src/examples/trafficlight.qdoc b/doc/src/examples/trafficlight.qdoc
index 16ee8ad..ae62127 100644
--- a/doc/src/examples/trafficlight.qdoc
+++ b/doc/src/examples/trafficlight.qdoc
@@ -1,11 +1,41 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the documentation of the Qt Toolkit.
**
-** $TROLLTECH_DUAL_LICENSE$
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
**
****************************************************************************/
@@ -26,30 +56,41 @@
\snippet examples/statemachine/trafficlight/main.cpp 0
The LightWidget class represents a single light of the traffic light. It
- provides a setOn() function to turn the light on or off. It paints itself
- in the color that's passed to the constructor.
+ provides an \c on property and two slots, turnOn() and turnOff(), to turn
+ the light on and off, respectively. The widget paints itself in the color
+ that's passed to the constructor.
- \snippet examples/statemachine/trafficlight/main.cpp 2
+ \snippet examples/statemachine/trafficlight/main.cpp 1
The TrafficLightWidget class represents the visual part of the traffic
- light; it's a widget that contains three lights, and provides accessor
- functions for these.
+ light; it's a widget that contains three lights arranged vertically, and
+ provides accessor functions for these.
- \snippet examples/statemachine/trafficlight/main.cpp 1
+ \snippet examples/statemachine/trafficlight/main.cpp 2
- The LightState class represents a state that turns a light on when the
- state is entered, and off when the state is exited. The class is a timer,
- and as we shall see the timeout is used to transition from one LightState
- to another.
+ The createLightState() function creates a state that turns a light on when
+ the state is entered, and off when the state is exited. The state uses a
+ timer, and as we shall see the timeout is used to transition from one
+ LightState to another. Here is the statechart for the light state:
+
+ \img trafficlight-example1.png
+ \omit
+ \caption This is a caption
+ \endomit
\snippet examples/statemachine/trafficlight/main.cpp 3
- The TrafficLight class combines the TrafficLightWidget with control flow
- based on the LightState class. The state graph has four states:
- red-to-yellow, yellow-to-green, green-to-yellow and yellow-to-red. The
- initial state is red-to-yellow; when the state's timer times out, the
- state machine transitions to yellow-to-green. The same process repeats
- through the other states.
+ The TrafficLight class combines the TrafficLightWidget with a state
+ machine. The state graph has four states: red-to-yellow, yellow-to-green,
+ green-to-yellow and yellow-to-red. The initial state is red-to-yellow;
+ when the state's timer times out, the state machine transitions to
+ yellow-to-green. The same process repeats through the other states.
+ This is what the statechart looks like:
+
+ \img trafficlight-example2.png
+ \omit
+ \caption This is a caption
+ \endomit
\snippet examples/statemachine/trafficlight/main.cpp 4
diff --git a/examples/statemachine/helloworld/main.cpp b/doc/src/examples/twowaybutton.qdoc
index fbe34b5..87de2e8 100644
--- a/examples/statemachine/helloworld/main.cpp
+++ b/doc/src/examples/twowaybutton.qdoc
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the QtCore module of the Qt Toolkit.
+** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,40 +39,44 @@
**
****************************************************************************/
-#include <QtCore>
-#ifdef QT_STATEMACHINE_SOLUTION
-#include <qstatemachine.h>
-#include <qstate.h>
-#include <qfinalstate.h>
-#endif
+/*!
+ \example statemachine/twowaybutton
+ \title Two-way Button Example
-class S0 : public QState
-{
-public:
- S0(QState *parent = 0)
- : QState(parent) {}
+ The Two-way button example shows how to use \l{The State Machine
+ Framework} to implement a simple state machine that toggles the current
+ state when a button is clicked.
- virtual void onEntry(QEvent *)
- {
- fprintf(stdout, "Hello world!\n");
- }
-};
+ \snippet examples/statemachine/twowaybutton/main.cpp 0
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
+ The application's main() function begins by constructing the application
+ object, a button and a state machine.
- QStateMachine machine;
- QState *s0 = new S0();
- QFinalState *s1 = new QFinalState();
- s0->addTransition(s1);
+ \snippet examples/statemachine/twowaybutton/main.cpp 1
- machine.addState(s0);
- machine.addState(s1);
- machine.setInitialState(s0);
+ The state machine has two states; \c on and \c off. When either state is
+ entered, the text of the button will be set accordingly.
- QObject::connect(&machine, SIGNAL(finished()), QCoreApplication::instance(), SLOT(quit()));
- machine.start();
+ \snippet examples/statemachine/twowaybutton/main.cpp 2
- return app.exec();
-}
+ When the state machine is in the \c off state and the button is clicked,
+ it will transition to the \c on state; when the state machine is in the \c
+ on state and the button is clicked, it will transition to the \c off
+ state.
+
+ \snippet examples/statemachine/twowaybutton/main.cpp 3
+
+ The states are added to the state machine; they become top-level (sibling)
+ states.
+
+ \snippet examples/statemachine/twowaybutton/main.cpp 4
+
+ The initial state is \c off; this is the state the state machine will
+ immediately transition to once the state machine is started.
+
+ \snippet examples/statemachine/twowaybutton/main.cpp 5
+
+ Finally, the button is resized and made visible, and the application event
+ loop is entered.
+
+*/
diff --git a/doc/src/images/pingpong-example.png b/doc/src/images/pingpong-example.png
new file mode 100644
index 0000000..af707e4
--- /dev/null
+++ b/doc/src/images/pingpong-example.png
Binary files differ
diff --git a/doc/src/images/trafficlight-example1.png b/doc/src/images/trafficlight-example1.png
new file mode 100644
index 0000000..ec8c7ff
--- /dev/null
+++ b/doc/src/images/trafficlight-example1.png
Binary files differ
diff --git a/doc/src/images/trafficlight-example2.png b/doc/src/images/trafficlight-example2.png
new file mode 100644
index 0000000..a12e4db
--- /dev/null
+++ b/doc/src/images/trafficlight-example2.png
Binary files differ
diff --git a/doc/src/statemachine.qdoc b/doc/src/statemachine.qdoc
index 16eae39..27bd4f8 100644
--- a/doc/src/statemachine.qdoc
+++ b/doc/src/statemachine.qdoc
@@ -1,11 +1,41 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the documentation of the Qt Toolkit.
**
-** $TROLLTECH_DUAL_LICENSE$
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
**
****************************************************************************/
@@ -395,4 +425,186 @@
machine.postEvent(new StringEvent("Hello"));
machine.postEvent(new StringEvent("world"));
\endcode
+
+ \section1 Using Restore Policy To Automatically Restore Properties
+
+ In some state machines it can be useful to focus the attention on assigning properties in states,
+ not on restoring them when the state is no longer active. If you know that a property should
+ always be restored to its initial value when the machine enters a state that does not explicitly
+ give the property a value, you can set the global restore policy to
+ QStateMachine::RestoreProperties.
+
+ \code
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+ \endcode
+
+ When this restore policy is set, the machine will automatically restore all properties. If it
+ enters a state where a given property is not set, it will first search the hierarchy of ancestors
+ to see if the property is defined there. If it is, the property will be restored to the value
+ defined by the closest ancestor. If not, it will be restored to its initial value (i.e. the
+ value of the property before any property assignments in states were executed.)
+
+ Take the following code:
+ \code
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ QState *s1 = new QState();
+ s1->assignProperty(object, "fooBar", 1.0);
+ machine.addState(s1);
+ machine.setInitialState(s1);
+
+ QState *s2 = new QState();
+ machine.addState(s2);
+ \endcode
+
+ Lets say the property \c fooBar is 0.0 when the machine starts. When the machine is in state
+ \c s1, the property will be 1.0, since the state explicitly assigns this value to it. When the
+ machine is in state \c s2, no value is explicitly defined for the property, so it will implicitly
+ be restored to 0.0.
+
+ If we are using nested states, the parent defines a value for the property which is inherited by
+ all descendants that do not explicitly assign a value to the property.
+ \code
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ QState *s1 = new QState();
+ s1->assignProperty(object, "fooBar", 1.0);
+ machine.addState(s1);
+ machine.setInitialState(s1);
+
+ QState *s2 = new QState(s1);
+ s2->assignProperty(object, "fooBar", 2.0);
+ s1->setInitialState(s2);
+
+ QState *s3 = new QState(s1);
+ \endcode
+
+ Here \c s1 has two children: \c s2 and \c s3. When \c s2 is entered, the property \c fooBar
+ will have the value 2.0, since this is explicitly defined for the state. When the machine is in
+ state \c s3, no value is defined for the state, but \c s1 defines the property to be 1.0, so this
+ is the value that will be assigned to \c fooBar.
+
+ \section1 Animating Property Assignments
+
+ The State Machine API connects with the Animation API in Qt to allow automatically animating
+ properties as they are assigned in states.
+
+ Say we have the following code:
+ \code
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+
+ s1->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
+ s2->assignProperty(button, "geometry", QRectF(0, 0, 100, 100));
+
+ s1->addTransition(button, SIGNAL(clicked()), s2);
+ \endcode
+
+ Here we define two states of a user interface. In \c s1 the \c button is small, and in \c s2
+ it is bigger. If we click the button to transition from \c s1 to \c s2, the geometry of the button
+ will be set immediately when a given state has been entered. If we want the transition to be
+ smooth, however, all we need to do is make a QPropertyAnimation and add this to the transition
+ object.
+
+ \code
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+
+ s1->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
+ s2->assignProperty(button, "geometry", QRectF(0, 0, 100, 100));
+
+ QSignalTransition *transition = s1->addTransition(button, SIGNAL(clicked()), s2);
+ transition->addAnimation(new QPropertyAnimation(button, "geometry"));
+ \endcode
+
+ Adding an animation for the property in question means that the property assignment will no
+ longer take immediate effect when the state has been entered. Instead, the animation will start
+ playing when the state has been entered and smoothly animate the property assignment. Since we
+ do not set the start value or end value of the animation, these will be set implicitly. The
+ start value of the animation will be the property's current value when the animation starts, and
+ the end value will be set based on the property assignments defined for the state.
+
+ If the global restore policy of the state machine is set to QStateMachine::RestoreProperties,
+ it is possible to also add animations for the property restorations.
+
+ \section1 Detecting That All Properties Have Been Set In A State
+
+ When animations are used to assign properties, a state no longer defines the exact values that a
+ property will have when the machine is in the given state. While the animation is running, the
+ property can potentially have any value, depending on the animation.
+
+ In some cases, it can be useful to be able to detect when the property has actually been assigned
+ the value defined by a state. For this, we can use the state's polished() signal.
+ \code
+ QState *s1 = new QState();
+ s1->assignProperty(button, "geometry", QRectF(0, 0, 50, 50));
+
+ QState *s2 = new QState();
+
+ s1->addTransition(s1, SIGNAL(polished()), s2);
+ \endcode
+
+ The machine will be in state \c s1 until the \c geometry property has been set. Then it will
+ immediately transition into \c s2. If the transition into \c s1 has an animation for the \c
+ geometry property, then the machine will stay in \c s1 until the animation has finished. If there
+ is no animation, it will simply set the property and immediately enter state \c s2.
+
+ Either way, when the machine is in state \c s2, the property \c geometry has been assigned the
+ defined value.
+
+ If the global restore policy is set to QStateMachine::RestoreProperties, the state will not emit
+ the polished() signal until these have been executed as well.
+
+ \section1 What happens if a state is exited before the animation has finished
+
+ If a state has property assignments, and the transition into the state has animations for the
+ properties, the state can potentially be exited before the properties have been assigned to the
+ values defines by the state. This is true in particular when there are transitions out from the
+ state that do not depend on the state being polished, as described in the previous section.
+
+ The State Machine API guarantees that a property assigned by the state machine either:
+ \list
+ \o Has a value explicitly assigned to the property.
+ \o Is currently being animated into a value explicitly assigned to the property.
+ \endlist
+
+ When a state is exited prior to the animation finishing, the behavior of the state machine depends
+ on the target state of the transition. If the target state explicitly assigns a value to the
+ property, no additional action will be taken. The property will be assigned the value defined by
+ the target state.
+
+ If the target state does not assign any value to the property, there are two
+ options: By default, the property will be assigned the value defined by the state it is leaving
+ (the value it would have been assigned if the animation had been permitted to finish playing.) If
+ a global restore policy is set, however, this will take precedence, and the property will be
+ restored as usual.
+
+ \section1 Default Animations
+
+ As described earlier, you can add animations to transitions to make sure property assignments
+ in the target state are animated. If you want a specific animation to be used for a given property
+ regardless of which transition is taken, you can add it as a default animation to the state
+ machine. This is in particular useful when the properties assigned (or restored) by specific
+ states is not known when the machine is constructed.
+
+ \code
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+
+ s2->assignProperty(object, "fooBar", 2.0);
+ s1->addTransition(s2);
+
+ QStateMachine machine;
+ machine.setInitialState(s1);
+ machine.addDefaultAnimation(new QPropertyAnimation(object, "fooBar"));
+ \endcode
+
+ When the machine is in state \c s2, the machine will play the default animation for the
+ property \c fooBar since this property is assigned by \c s2.
+
+ Note that animations explicitly set on transitions will take precedence over any default
+ animation for the given property.
*/
diff --git a/examples/statemachine/clockticking/clockticking.pro b/examples/statemachine/clockticking/clockticking.pro
deleted file mode 100644
index bff9cb8..0000000
--- a/examples/statemachine/clockticking/clockticking.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-QT = core
-TEMPLATE = app
-TARGET =
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp
diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp
deleted file mode 100644
index ea8e692..0000000
--- a/examples/statemachine/clockticking/main.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore>
-#include <stdio.h>
-#ifdef QT_STATEMACHINE_SOLUTION
-#include <qstatemachine.h>
-#include <qstate.h>
-#include <qabstracttransition.h>
-#endif
-
-class ClockEvent : public QEvent
-{
-public:
- ClockEvent() : QEvent(QEvent::Type(QEvent::User+2))
- {}
-};
-
-class ClockState : public QState
-{
-public:
- ClockState(QState *parent)
- : QState(parent) {}
-
-protected:
- virtual void onEntry(QEvent *)
- {
- fprintf(stdout, "ClockState entered; posting the initial tick\n");
- machine()->postEvent(new ClockEvent());
- }
-};
-
-class ClockTransition : public QAbstractTransition
-{
-public:
- ClockTransition() {}
-
-protected:
- virtual bool eventTest(QEvent *e) const {
- return (e->type() == QEvent::User+2);
- }
- virtual void onTransition(QEvent *)
- {
- fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n");
- machine()->postEvent(new ClockEvent(), 1000);
- }
-};
-
-class ClockListener : public QAbstractTransition
-{
-public:
- ClockListener() {}
-
-protected:
- virtual bool eventTest(QEvent *e) const {
- return (e->type() == QEvent::User+2);
- }
- virtual void onTransition(QEvent *)
- {
- fprintf(stdout, "ClockListener heard a tick!\n");
- }
-};
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
-
- QStateMachine machine;
- QState *group = new QState(QState::ParallelStates);
- group->setObjectName("group");
-
- ClockState *clock = new ClockState(group);
- clock->setObjectName("clock");
- clock->addTransition(new ClockTransition());
-
- QState *listener = new QState(group);
- listener->setObjectName("listener");
- listener->addTransition(new ClockListener());
-
- machine.addState(group);
- machine.setInitialState(group);
- machine.start();
-
- return app.exec();
-}
diff --git a/examples/statemachine/composition/composition.pro b/examples/statemachine/composition/composition.pro
deleted file mode 100644
index 6a976cb..0000000
--- a/examples/statemachine/composition/composition.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = app
-TARGET =
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp
diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp
deleted file mode 100644
index 0afff66..0000000
--- a/examples/statemachine/composition/main.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-#ifdef QT_STATEMACHINE_SOLUTION
-#include <qstatemachine.h>
-#include <qstate.h>
-#include <qfinalstate.h>
-#endif
-
-int main(int argc, char **argv)
-{
- QApplication app(argc, argv);
- QLabel label;
- label.setAlignment(Qt::AlignCenter);
-
- QStateMachine machine;
-
- QState *s1 = new QState();
- s1->setObjectName("s1");
- s1->assignProperty(&label, "text", "In S1, hang on...");
- s1->assignProperty(&label, "geometry", QRect(100, 100, 200, 100));
-
- QState *s1_timer = new QState(s1);
- s1_timer->setObjectName("s1_timer");
- QTimer t1;
- t1.setInterval(2000);
- QObject::connect(s1_timer, SIGNAL(entered()), &t1, SLOT(start()));
- QFinalState *s1_done = new QFinalState(s1);
- s1_done->setObjectName("s1_done");
- s1_timer->addTransition(&t1, SIGNAL(timeout()), s1_done);
- s1->setInitialState(s1_timer);
-
- QState *s2 = new QState();
- s2->setObjectName("s2");
- s2->assignProperty(&label, "text", "In S2, I'm gonna quit on you...");
- s2->assignProperty(&label, "geometry", QRect(300, 300, 300, 100));
-// s2->invokeMethodOnEntry(&label, "setNum", QList<QVariant>() << 123);
-// s2->invokeMethodOnEntry(&label, "showMaximized");
-
- QState *s2_timer = new QState(s2);
- s2_timer->setObjectName("s2_timer");
- QTimer t2;
- t2.setInterval(2000);
- QObject::connect(s2_timer, SIGNAL(entered()), &t2, SLOT(start()));
- QFinalState *s2_done = new QFinalState(s2);
- s2_done->setObjectName("s2_done");
- s2_timer->addTransition(&t2, SIGNAL(timeout()), s2_done);
- s2->setInitialState(s2_timer);
-
- s1->addTransition(s1, SIGNAL(finished()), s2);
-
- QFinalState *s3 = new QFinalState();
- s3->setObjectName("s3");
- s2->addTransition(s2, SIGNAL(finished()), s3);
-
- machine.addState(s1);
- machine.addState(s2);
- machine.addState(s3);
- machine.setInitialState(s1);
- QObject::connect(&machine, SIGNAL(finished()), &app, SLOT(quit()));
- machine.start();
-
- label.show();
- return app.exec();
-}
diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro
deleted file mode 100644
index 5b6b758..0000000
--- a/examples/statemachine/errorstateplugins/errorstateplugins.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS = random_ai \
- spin_ai_with_error \
- spin_ai \
- seek_ai
-
-# install
-target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins
-sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS errorstateplugins.pro
-sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins
-INSTALLS += target sources
diff --git a/examples/statemachine/eventtransitions/main.cpp b/examples/statemachine/eventtransitions/main.cpp
index f564b7e..aba0c73 100644
--- a/examples/statemachine/eventtransitions/main.cpp
+++ b/examples/statemachine/eventtransitions/main.cpp
@@ -46,6 +46,7 @@
#include <qeventtransition.h>
#endif
+//! [0]
class Window : public QWidget
{
public:
@@ -54,7 +55,9 @@ public:
{
QPushButton *button = new QPushButton(this);
button->setGeometry(QRect(100, 100, 100, 100));
+//! [0]
+//! [1]
QStateMachine *machine = new QStateMachine(this);
QState *s1 = new QState();
@@ -62,15 +65,21 @@ public:
QState *s2 = new QState();
s2->assignProperty(button, "text", "Inside");
+//! [1]
+//! [2]
QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter);
enterTransition->setTargetState(s2);
s1->addTransition(enterTransition);
+//! [2]
+//! [3]
QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave);
leaveTransition->setTargetState(s1);
s2->addTransition(leaveTransition);
+//! [3]
+//! [4]
QState *s3 = new QState();
s3->assignProperty(button, "text", "Pressing...");
@@ -81,16 +90,20 @@ public:
QEventTransition *releaseTransition = new QEventTransition(button, QEvent::MouseButtonRelease);
releaseTransition->setTargetState(s2);
s3->addTransition(releaseTransition);
+//! [4]
+//! [5]
machine->addState(s1);
machine->addState(s2);
machine->addState(s3);
+
machine->setInitialState(s1);
- QObject::connect(machine, SIGNAL(finished()), qApp, SLOT(quit()));
machine->start();
}
};
+//! [5]
+//! [6]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
@@ -100,3 +113,4 @@ int main(int argc, char **argv)
return app.exec();
}
+//! [6]
diff --git a/examples/statemachine/helloworld/helloworld.pro b/examples/statemachine/helloworld/helloworld.pro
deleted file mode 100644
index ac79117..0000000
--- a/examples/statemachine/helloworld/helloworld.pro
+++ /dev/null
@@ -1,10 +0,0 @@
-TEMPLATE = app
-TARGET =
-QT = core
-win32: CONFIG += console
-mac:CONFIG -= app_bundle
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp
diff --git a/examples/statemachine/pauseandresume/main.cpp b/examples/statemachine/pauseandresume/main.cpp
deleted file mode 100644
index 5bacb41..0000000
--- a/examples/statemachine/pauseandresume/main.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-#ifdef QT_STATEMACHINE_SOLUTION
-#include <qstatemachine.h>
-#include <qstate.h>
-#include <qfinalstate.h>
-#include <qhistorystate.h>
-#endif
-
-class Window : public QWidget
-{
-public:
- Window(QWidget *parent = 0)
- : QWidget(parent)
- {
- QPushButton *pb = new QPushButton("Go");
- QPushButton *pauseButton = new QPushButton("Pause");
- QPushButton *quitButton = new QPushButton("Quit");
- QVBoxLayout *vbox = new QVBoxLayout(this);
- vbox->addWidget(pb);
- vbox->addWidget(pauseButton);
- vbox->addWidget(quitButton);
-
- QStateMachine *machine = new QStateMachine(this);
-
- QState *process = new QState(machine->rootState());
- process->setObjectName("process");
-
- QState *s1 = new QState(process);
- s1->setObjectName("s1");
- QState *s2 = new QState(process);
- s2->setObjectName("s2");
- s1->addTransition(pb, SIGNAL(clicked()), s2);
- s2->addTransition(pb, SIGNAL(clicked()), s1);
-
- QHistoryState *h = new QHistoryState(process);
- h->setDefaultState(s1);
-
- QState *interrupted = new QState(machine->rootState());
- interrupted->setObjectName("interrupted");
- QFinalState *terminated = new QFinalState(machine->rootState());
- terminated->setObjectName("terminated");
- interrupted->addTransition(pauseButton, SIGNAL(clicked()), h);
- interrupted->addTransition(quitButton, SIGNAL(clicked()), terminated);
-
- process->addTransition(pauseButton, SIGNAL(clicked()), interrupted);
- process->addTransition(quitButton, SIGNAL(clicked()), terminated);
-
- process->setInitialState(s1);
- machine->setInitialState(process);
- QObject::connect(machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
- machine->start();
- }
-};
-
-int main(int argc, char **argv)
-{
- QApplication app(argc, argv);
- Window win;
- win.show();
- return app.exec();
-}
diff --git a/examples/statemachine/pauseandresume/pauseandresume.pro b/examples/statemachine/pauseandresume/pauseandresume.pro
deleted file mode 100644
index 6a976cb..0000000
--- a/examples/statemachine/pauseandresume/pauseandresume.pro
+++ /dev/null
@@ -1,7 +0,0 @@
-TEMPLATE = app
-TARGET =
-DEPENDPATH += .
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp
diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp
index eb8fd5d..db66bfd 100644
--- a/examples/statemachine/pingpong/main.cpp
+++ b/examples/statemachine/pingpong/main.cpp
@@ -47,6 +47,7 @@
#include <qabstracttransition.h>
#endif
+//! [0]
class PingEvent : public QEvent
{
public:
@@ -60,7 +61,9 @@ public:
PongEvent() : QEvent(QEvent::Type(QEvent::User+3))
{}
};
+//! [0]
+//! [1]
class Pinger : public QState
{
public:
@@ -74,7 +77,9 @@ protected:
fprintf(stdout, "ping?\n");
}
};
+//! [1]
+//! [3]
class PongTransition : public QAbstractTransition
{
public:
@@ -90,7 +95,9 @@ protected:
fprintf(stdout, "ping?\n");
}
};
+//! [3]
+//! [2]
class PingTransition : public QAbstractTransition
{
public:
@@ -106,7 +113,9 @@ protected:
fprintf(stdout, "pong!\n");
}
};
+//! [2]
+//! [4]
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
@@ -114,7 +123,9 @@ int main(int argc, char **argv)
QStateMachine machine;
QState *group = new QState(QState::ParallelStates);
group->setObjectName("group");
+//! [4]
+//! [5]
Pinger *pinger = new Pinger(group);
pinger->setObjectName("pinger");
pinger->addTransition(new PongTransition());
@@ -122,10 +133,13 @@ int main(int argc, char **argv)
QState *ponger = new QState(group);
ponger->setObjectName("ponger");
ponger->addTransition(new PingTransition());
+//! [5]
+//! [6]
machine.addState(group);
machine.setInitialState(group);
machine.start();
return app.exec();
}
+//! [6]
diff --git a/examples/statemachine/statemachine.pro b/examples/statemachine/statemachine.pro
index ba32c12..5074a3c 100644
--- a/examples/statemachine/statemachine.pro
+++ b/examples/statemachine/statemachine.pro
@@ -1,14 +1,12 @@
TEMPLATE = subdirs
SUBDIRS = \
- clockticking \
- composition \
eventtransitions \
factorial \
- helloworld \
- pauseandresume \
pingpong \
trafficlight \
- twowaybutton
+ twowaybutton \
+ tankgame \
+ tankgameplugins
# install
target.path = $$[QT_INSTALL_EXAMPLES]/statemachine
diff --git a/examples/statemachine/errorstate/gameitem.cpp b/examples/statemachine/tankgame/gameitem.cpp
index 1a2af71..1a2af71 100644
--- a/examples/statemachine/errorstate/gameitem.cpp
+++ b/examples/statemachine/tankgame/gameitem.cpp
diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/tankgame/gameitem.h
index 43b8785..43b8785 100644
--- a/examples/statemachine/errorstate/gameitem.h
+++ b/examples/statemachine/tankgame/gameitem.h
diff --git a/examples/statemachine/errorstate/main.cpp b/examples/statemachine/tankgame/main.cpp
index 26fc1bb..26fc1bb 100644
--- a/examples/statemachine/errorstate/main.cpp
+++ b/examples/statemachine/tankgame/main.cpp
diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/tankgame/mainwindow.cpp
index 07719bc..3bc9bbe 100644
--- a/examples/statemachine/errorstate/mainwindow.cpp
+++ b/examples/statemachine/tankgame/mainwindow.cpp
@@ -140,7 +140,9 @@ void MainWindow::init()
stoppedState->setInitialState(hs);
+//! [0]
m_runningState = new QState(QState::ParallelStates, m_machine->rootState());
+//! [0]
m_runningState->setObjectName("runningState");
m_runningState->assignProperty(addTankAction, "enabled", false);
m_runningState->assignProperty(runGameAction, "enabled", false);
@@ -231,8 +233,10 @@ void MainWindow::addTank()
}
bool ok;
+//! [1]
QString selectedName = QInputDialog::getItem(this, "Select a tank type", "Tank types",
itemNames, 0, false, &ok);
+//! [1]
if (ok && !selectedName.isEmpty()) {
int idx = itemNames.indexOf(selectedName);
@@ -244,9 +248,12 @@ void MainWindow::addTank()
emit mapFull();
QState *region = new QState(m_runningState);
+//! [2]
QState *pluginState = plugin->create(region, tankItem);
+//! [2]
region->setInitialState(pluginState);
+
// If the plugin has an error it is disabled
QState *errorState = new QState(region);
errorState->assignProperty(tankItem, "enabled", false);
diff --git a/examples/statemachine/errorstate/mainwindow.h b/examples/statemachine/tankgame/mainwindow.h
index 622dabe..622dabe 100644
--- a/examples/statemachine/errorstate/mainwindow.h
+++ b/examples/statemachine/tankgame/mainwindow.h
diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/tankgame/plugin.h
index 2b48d43..2b48d43 100644
--- a/examples/statemachine/errorstate/plugin.h
+++ b/examples/statemachine/tankgame/plugin.h
diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/tankgame/rocketitem.cpp
index c324980..c324980 100644
--- a/examples/statemachine/errorstate/rocketitem.cpp
+++ b/examples/statemachine/tankgame/rocketitem.cpp
diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/tankgame/rocketitem.h
index 189a1dd..189a1dd 100644
--- a/examples/statemachine/errorstate/rocketitem.h
+++ b/examples/statemachine/tankgame/rocketitem.h
diff --git a/examples/statemachine/errorstate/errorstate.pro b/examples/statemachine/tankgame/tankgame.pro
index b93a691..f7b0760 100644
--- a/examples/statemachine/errorstate/errorstate.pro
+++ b/examples/statemachine/tankgame/tankgame.pro
@@ -5,7 +5,7 @@
TEMPLATE = app
TARGET =
DEPENDPATH += .
-INCLUDEPATH += C:/dev/kinetic/examples/statemachine/errorstate/. .
+INCLUDEPATH += C:/dev/kinetic/examples/statemachine/tankgame/. .
# Input
HEADERS += mainwindow.h plugin.h tankitem.h rocketitem.h gameitem.h
diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/tankgame/tankitem.cpp
index 5506a7e..5506a7e 100644
--- a/examples/statemachine/errorstate/tankitem.cpp
+++ b/examples/statemachine/tankgame/tankitem.cpp
diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/tankgame/tankitem.h
index cefed69..66f05aa 100644
--- a/examples/statemachine/errorstate/tankitem.h
+++ b/examples/statemachine/tankgame/tankitem.h
@@ -35,6 +35,7 @@ public:
qreal distanceToObstacle() const;
qreal distanceToObstacle(QGraphicsItem **item) const;
+//! [0]
signals:
void tankSpotted(qreal direction, qreal distance);
void collision(const QLineF &collidedLine);
@@ -48,6 +49,7 @@ public slots:
void turnTo(qreal degrees = 0.0);
void stop();
void fireCannon();
+//! [0]
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai.pro b/examples/statemachine/tankgameplugins/random_ai/random_ai.pro
index f290250..5bc0b26 100644
--- a/examples/statemachine/errorstateplugins/random_ai/random_ai.pro
+++ b/examples/statemachine/tankgameplugins/random_ai/random_ai.pro
@@ -4,10 +4,10 @@ INCLUDEPATH += ../..
HEADERS = random_ai_plugin.h
SOURCES = random_ai_plugin.cpp
TARGET = $$qtLibraryTarget(random_ai)
-DESTDIR = ../../errorstate/plugins
+DESTDIR = ../../tankgame/plugins
#! [0]
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgame/plugins
sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS random_ai.pro
-sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/random_ai \ No newline at end of file
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins/random_ai \ No newline at end of file
diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp
index c196247..c196247 100644
--- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp
+++ b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp
diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.h
index 10e6f48..f5e3b6f 100644
--- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h
+++ b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.h
@@ -4,7 +4,7 @@
#include <QObject>
#include <QState>
-#include <errorstate/plugin.h>
+#include <tankgame/plugin.h>
class SelectActionState: public QState
{
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.cpp
index 2fb05d4..2fb05d4 100644
--- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp
+++ b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.cpp
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.h
index a1b5749..2835988 100644
--- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h
+++ b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.h
@@ -1,7 +1,7 @@
#ifndef SEEK_AI_H
#define SEEK_AI_H
-#include <errorstate/plugin.h>
+#include <tankgame/plugin.h>
#include <QState>
#include <QFinalState>
diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.pro
index 11bd242..0d8bf2e 100644
--- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro
+++ b/examples/statemachine/tankgameplugins/seek_ai/seek_ai.pro
@@ -4,10 +4,10 @@ INCLUDEPATH += ../..
HEADERS = seek_ai.h
SOURCES = seek_ai.cpp
TARGET = $$qtLibraryTarget(seek_ai)
-DESTDIR = ../../errorstate/plugins
+DESTDIR = ../../tankgame/plugins
#! [0]
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgame/plugins
sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS seek_ai.pro
-sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/seek_ai \ No newline at end of file
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins/seek_ai \ No newline at end of file
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.cpp
index de95f41..de95f41 100644
--- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp
+++ b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.cpp
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.h
index 6e220ed..a331a3e 100644
--- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h
+++ b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.h
@@ -1,7 +1,7 @@
#ifndef SPIN_AI_H
#define SPIN_AI_H
-#include <errorstate/plugin.h>
+#include <tankgame/plugin.h>
#include <QObject>
#include <QState>
diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.pro
index c2fd937..8ab4da0 100644
--- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro
+++ b/examples/statemachine/tankgameplugins/spin_ai/spin_ai.pro
@@ -4,10 +4,10 @@ INCLUDEPATH += ../..
HEADERS = spin_ai.h
SOURCES = spin_ai.cpp
TARGET = $$qtLibraryTarget(spin_ai)
-DESTDIR = ../../errorstate/plugins
+DESTDIR = ../../tankgame/plugins
#! [0]
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgame/plugins
sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai.pro
-sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai \ No newline at end of file
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins/spin_ai \ No newline at end of file
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.cpp
index 5499ba3..5499ba3 100644
--- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp
+++ b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.cpp
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.h
index d520455..5cfb364 100644
--- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h
+++ b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.h
@@ -1,7 +1,7 @@
#ifndef SPIN_AI_WITH_ERROR_H
#define SPIN_AI_WITH_ERROR_H
-#include <errorstate/plugin.h>
+#include <tankgame/plugin.h>
#include <QObject>
#include <QState>
diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.pro
index 31f4c7f..124cf98 100644
--- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro
+++ b/examples/statemachine/tankgameplugins/spin_ai_with_error/spin_ai_with_error.pro
@@ -4,10 +4,10 @@ INCLUDEPATH += ../..
HEADERS = spin_ai_with_error.h
SOURCES = spin_ai_with_error.cpp
TARGET = $$qtLibraryTarget(spin_ai_with_error)
-DESTDIR = ../../errorstate/plugins
+DESTDIR = ../../tankgame/plugins
#! [0]
# install
-target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgame/plugins
sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai_with_error.pro
-sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai_with_error \ No newline at end of file
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins/spin_ai_with_error \ No newline at end of file
diff --git a/examples/statemachine/tankgameplugins/tankgameplugins.pro b/examples/statemachine/tankgameplugins/tankgameplugins.pro
new file mode 100644
index 0000000..a098e03
--- /dev/null
+++ b/examples/statemachine/tankgameplugins/tankgameplugins.pro
@@ -0,0 +1,11 @@
+TEMPLATE = subdirs
+SUBDIRS = random_ai \
+ spin_ai_with_error \
+ spin_ai \
+ seek_ai
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins
+sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS tankgameplugins.pro
+sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/tankgameplugins
+INSTALLS += target sources
diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp
index 3c47a51..8a46fff 100644
--- a/examples/statemachine/trafficlight/main.cpp
+++ b/examples/statemachine/trafficlight/main.cpp
@@ -87,27 +87,6 @@ private:
//! [0]
//! [1]
-class LightState : public QState
-{
-public:
- LightState(LightWidget *light, int duration, QState *parent = 0)
- : QState(parent)
- {
- QTimer *timer = new QTimer(this);
- timer->setInterval(duration);
- timer->setSingleShot(true);
- QState *timing = new QState(this);
- QObject::connect(timing, SIGNAL(entered()), light, SLOT(turnOn()));
- QObject::connect(timing, SIGNAL(entered()), timer, SLOT(start()));
- QObject::connect(timing, SIGNAL(exited()), light, SLOT(turnOff()));
- QFinalState *done = new QFinalState(this);
- timing->addTransition(timer, SIGNAL(timeout()), done);
- setInitialState(timing);
- }
-};
-//! [1]
-
-//! [2]
class TrafficLightWidget : public QWidget
{
public:
@@ -139,6 +118,24 @@ private:
LightWidget *m_yellow;
LightWidget *m_green;
};
+//! [1]
+
+//! [2]
+QState *createLightState(LightWidget *light, int duration, QState *parent = 0)
+{
+ QState *lightState = new QState(parent);
+ QTimer *timer = new QTimer(lightState);
+ timer->setInterval(duration);
+ timer->setSingleShot(true);
+ QState *timing = new QState(lightState);
+ QObject::connect(timing, SIGNAL(entered()), light, SLOT(turnOn()));
+ QObject::connect(timing, SIGNAL(entered()), timer, SLOT(start()));
+ QObject::connect(timing, SIGNAL(exited()), light, SLOT(turnOff()));
+ QFinalState *done = new QFinalState(lightState);
+ timing->addTransition(timer, SIGNAL(timeout()), done);
+ lightState->setInitialState(timing);
+ return lightState;
+}
//! [2]
//! [3]
@@ -154,15 +151,15 @@ public:
vbox->setMargin(0);
QStateMachine *machine = new QStateMachine(this);
- LightState *redGoingYellow = new LightState(widget->redLight(), 3000);
+ QState *redGoingYellow = createLightState(widget->redLight(), 3000);
redGoingYellow->setObjectName("redGoingYellow");
- LightState *yellowGoingGreen = new LightState(widget->yellowLight(), 1000);
+ QState *yellowGoingGreen = createLightState(widget->yellowLight(), 1000);
yellowGoingGreen->setObjectName("yellowGoingGreen");
redGoingYellow->addTransition(redGoingYellow, SIGNAL(finished()), yellowGoingGreen);
- LightState *greenGoingYellow = new LightState(widget->greenLight(), 3000);
+ QState *greenGoingYellow = createLightState(widget->greenLight(), 3000);
greenGoingYellow->setObjectName("greenGoingYellow");
yellowGoingGreen->addTransition(yellowGoingGreen, SIGNAL(finished()), greenGoingYellow);
- LightState *yellowGoingRed = new LightState(widget->yellowLight(), 1000);
+ QState *yellowGoingRed = createLightState(widget->yellowLight(), 1000);
yellowGoingRed->setObjectName("yellowGoingRed");
greenGoingYellow->addTransition(greenGoingYellow, SIGNAL(finished()), yellowGoingRed);
yellowGoingRed->addTransition(yellowGoingRed, SIGNAL(finished()), redGoingYellow);
diff --git a/examples/statemachine/twowaybutton/main.cpp b/examples/statemachine/twowaybutton/main.cpp
index 61a0f32..a2c6e45 100644
--- a/examples/statemachine/twowaybutton/main.cpp
+++ b/examples/statemachine/twowaybutton/main.cpp
@@ -45,34 +45,42 @@
#include <qstatemachine.h>
#endif
+//! [0]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
-
QPushButton button;
-
QStateMachine machine;
- QState *first = new QState();
- first->setObjectName("first");
+//! [0]
+//! [1]
QState *off = new QState();
off->assignProperty(&button, "text", "Off");
off->setObjectName("off");
- first->addTransition(off);
QState *on = new QState();
on->setObjectName("on");
on->assignProperty(&button, "text", "On");
+//! [1]
+
+//! [2]
off->addTransition(&button, SIGNAL(clicked()), on);
on->addTransition(&button, SIGNAL(clicked()), off);
+//! [2]
- machine.addState(first);
+//! [3]
machine.addState(off);
machine.addState(on);
- machine.setInitialState(first);
+//! [3]
+
+//! [4]
+ machine.setInitialState(off);
machine.start();
+//! [4]
+//! [5]
button.resize(100, 50);
button.show();
return app.exec();
}
+//! [5]
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index 3a3bfc3..f1528b8 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -327,6 +327,8 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
}
}
transition->setParent(this);
+ if (machine() != 0 && machine()->configuration().contains(this))
+ QStateMachinePrivate::get(machine())->registerTransitions(this);
return transition;
}
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 42e965a..52b0a89 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1341,8 +1341,10 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
sender->metaObject()->className(), signal.constData());
return;
}
- QList<int> &connectedSignalIndexes = connections[sender];
- if (!connectedSignalIndexes.contains(signalIndex)) {
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ if (connectedSignalIndexes.size() <= signalIndex)
+ connectedSignalIndexes.resize(signalIndex+1);
+ if (connectedSignalIndexes.at(signalIndex) == 0) {
#ifndef QT_STATEMACHINE_SOLUTION
if (!signalEventGenerator)
signalEventGenerator = new QSignalEventGenerator(q);
@@ -1359,8 +1361,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()
@@ -1375,17 +1377,20 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit
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
}
@@ -1450,8 +1455,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();
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index 47b139c..4bf9ce2 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -61,6 +61,7 @@
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
#include <QtCore/qset.h>
+#include <QtCore/qvector.h>
#include "qstate.h"
#include "qstate_p.h"
@@ -202,7 +203,7 @@ public:
#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;
#endif
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index ce4b443..5ff2acf 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -2791,7 +2791,6 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
return;
// Notify the item that the transformation matrix is changing.
- // Notify the item that the matrix is changing.
QVariant newTransformVariant(itemChange(ItemMatrixChange,
qVariantFromValue<QMatrix>(newTransform.toAffine())));
newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant));
diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/plugins/accessible/widgets/simplewidgets.h
index d4552e3..d1fd0da 100644
--- a/src/plugins/accessible/widgets/simplewidgets.h
+++ b/src/plugins/accessible/widgets/simplewidgets.h
@@ -115,6 +115,7 @@ public:
class QAccessibleLineEdit : public QAccessibleWidgetEx, public QAccessibleTextInterface,
public QAccessibleSimpleEditableTextInterface
{
+ Q_ACCESSIBLE_OBJECT
public:
explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString());
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
index 9058cb6..3f94ad9 100644
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp
@@ -1711,6 +1711,51 @@ void tst_QStateMachine::signalTransitions()
QTRY_COMPARE(finishedSpy.count(), 1);
}
+ // Multiple transitions for same (object,signal)
+ {
+ QStateMachine machine;
+ SignalEmitter emitter;
+ QState *s0 = new QState(machine.rootState());
+ QState *s1 = new QState(machine.rootState());
+ QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1);
+ QSignalTransition *t1 = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s0);
+
+ QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
+ machine.setInitialState(s0);
+ machine.start();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s0));
+
+ emitter.emitSignalWithNoArg();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s1));
+
+ s0->removeTransition(t0);
+ emitter.emitSignalWithNoArg();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s0));
+
+ emitter.emitSignalWithNoArg();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s0));
+
+ s1->removeTransition(t1);
+ emitter.emitSignalWithNoArg();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s0));
+
+ s0->addTransition(t0);
+ s1->addTransition(t1);
+ emitter.emitSignalWithNoArg();
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s1));
+ }
}
void tst_QStateMachine::eventTransitions()