summaryrefslogtreecommitdiffstats
path: root/doc/src
diff options
context:
space:
mode:
authorAlexis Menard <alexis.menard@nokia.com>2009-05-12 12:51:15 (GMT)
committerAlexis Menard <alexis.menard@nokia.com>2009-05-12 12:51:15 (GMT)
commit90d801f05f64c645f0899e3d81b23ecf53bf4835 (patch)
tree14362a48f6c74709972ab1a92d7be81d910f788d /doc/src
parent1898c46452beae9e28cf9be7851099b4b4d2779e (diff)
parentc6add575d50ee30b19580fc2c1ebda5316a2f51b (diff)
downloadQt-90d801f05f64c645f0899e3d81b23ecf53bf4835.zip
Qt-90d801f05f64c645f0899e3d81b23ecf53bf4835.tar.gz
Qt-90d801f05f64c645f0899e3d81b23ecf53bf4835.tar.bz2
Merge branch 'kinetic-statemachine' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-statemachine
Conflicts: src/gui/graphicsview/qgraphicsitem.cpp
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/examples/trafficlight.qdoc79
-rw-r--r--doc/src/images/statemachine-button-history.pngbin91677 -> 8493 bytes
-rw-r--r--doc/src/images/statemachine-button-nested.pngbin73774 -> 7051 bytes
-rw-r--r--doc/src/images/statemachine-button.pngbin32767 -> 4233 bytes
-rw-r--r--doc/src/images/statemachine-customevents.pngbin0 -> 2544 bytes
-rw-r--r--doc/src/images/statemachine-finished.pngbin37907 -> 5518 bytes
-rw-r--r--doc/src/images/statemachine-nonparallel.pngbin68482 -> 5350 bytes
-rw-r--r--doc/src/images/statemachine-parallel.pngbin99587 -> 8631 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.qdoc412
11 files changed, 435 insertions, 56 deletions
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/doc/src/images/statemachine-button-history.png b/doc/src/images/statemachine-button-history.png
index cd66478..7f51cae 100644
--- a/doc/src/images/statemachine-button-history.png
+++ b/doc/src/images/statemachine-button-history.png
Binary files differ
diff --git a/doc/src/images/statemachine-button-nested.png b/doc/src/images/statemachine-button-nested.png
index 60360d1..762ac14 100644
--- a/doc/src/images/statemachine-button-nested.png
+++ b/doc/src/images/statemachine-button-nested.png
Binary files differ
diff --git a/doc/src/images/statemachine-button.png b/doc/src/images/statemachine-button.png
index 75d9e53..10102bd 100644
--- a/doc/src/images/statemachine-button.png
+++ b/doc/src/images/statemachine-button.png
Binary files differ
diff --git a/doc/src/images/statemachine-customevents.png b/doc/src/images/statemachine-customevents.png
new file mode 100644
index 0000000..62a4222
--- /dev/null
+++ b/doc/src/images/statemachine-customevents.png
Binary files differ
diff --git a/doc/src/images/statemachine-finished.png b/doc/src/images/statemachine-finished.png
index 802621e..0ac081d 100644
--- a/doc/src/images/statemachine-finished.png
+++ b/doc/src/images/statemachine-finished.png
Binary files differ
diff --git a/doc/src/images/statemachine-nonparallel.png b/doc/src/images/statemachine-nonparallel.png
index 1fe60d8..f9850a7 100644
--- a/doc/src/images/statemachine-nonparallel.png
+++ b/doc/src/images/statemachine-nonparallel.png
Binary files differ
diff --git a/doc/src/images/statemachine-parallel.png b/doc/src/images/statemachine-parallel.png
index 1868792..a65c297 100644
--- a/doc/src/images/statemachine-parallel.png
+++ b/doc/src/images/statemachine-parallel.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 c79839f..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$
**
****************************************************************************/
@@ -13,6 +43,7 @@
\page statemachine-api.html
\title The State Machine Framework
\brief An overview of the State Machine framework for constructing and executing state graphs.
+ \ingroup architecture
\tableofcontents
@@ -33,10 +64,10 @@
The State Machine framework provides an API and execution model that can be
used to effectively embed the elements and semantics of statecharts in Qt
- applications. The framework integrates tightly with Qt's existing event
- system and meta-object system; for example, transitions between states can
- be triggered by signals, and states can be configured to set properties and
- invoke methods on QObjects.
+ applications. The framework integrates tightly with Qt's meta-object system;
+ for example, transitions between states can be triggered by signals, and
+ states can be configured to set properties and invoke methods on QObjects.
+ Qt's event system is used to drive the state machines.
\section1 A Simple State Machine
@@ -52,60 +83,79 @@
\endomit
The following snippet shows the code needed to create such a state machine.
+ First, we create the state machine and states:
\code
QStateMachine machine;
QState *s1 = new QState();
QState *s2 = new QState();
QState *s3 = new QState();
+ \endcode
+
+ Then, we create the transitions by using the QState::addTransition()
+ function:
+ \code
s1->addTransition(button, SIGNAL(clicked()), s2);
s2->addTransition(button, SIGNAL(clicked()), s3);
s3->addTransition(button, SIGNAL(clicked()), s1);
+ \endcode
+
+ Next, we add the states to the machine and set the machine's initial state:
+ \code
machine.addState(s1);
machine.addState(s2);
machine.addState(s3);
machine.setInitialState(s1);
+ \endcode
+ Finally, we start the state machine:
+
+ \code
machine.start();
\endcode
- Once the state machine has been set up, you need to start it by calling
- QStateMachine::start(). The state machine executes asynchronously, i.e. it
- becomes part of your application's event loop.
+ The state machine executes asynchronously, i.e. it becomes part of your
+ application's event loop.
+
+ \section1 Doing Useful Work on State Entry and Exit
- The above state machine is perfectly fine, but it doesn't \e do anything; it
- merely transitions from one state to another. The
- QState::setPropertyOnEntry() function can be used to have a state set a
- property of a QObject when the state is entered. In the following snippet,
- the value that should be assigned to a QLabel's text property is specified
- for each state:
+ The above state machine merely transitions from one state to another, it
+ doesn't perform any operations. The QState::assignProperty() function can be
+ used to have a state set a property of a QObject when the state is
+ entered. In the following snippet, the value that should be assigned to a
+ QLabel's text property is specified for each state:
\code
- s1->setPropertyOnEntry(label, "text", "In state s1");
- s2->setPropertyOnEntry(label, "text", "In state s2");
- s3->setPropertyOnEntry(label, "text", "In state s3");
+ s1->assignProperty(label, "text", "In state s1");
+ s2->assignProperty(label, "text", "In state s2");
+ s3->assignProperty(label, "text", "In state s3");
\endcode
When any of the states is entered, the label's text will be changed
accordingly.
- The QState::invokeMethodOnEntry() function can be used to have a state
- invoke a method (a slot) of a QObject when the state is entered. In the
+ The QState::entered() signal is emitted when the state is entered, and the
+ QState::exited() signal is emitted when the state is exited. In the
following snippet, the button's showMaximized() slot will be called when
- state \c s3 is entered:
+ state \c s3 is entered, and the button's showMinimized() slot will be called
+ when \c s3 is exited:
\code
- s2->invokeMethodOnEntry(button, "showMaximized");
+ QObject::connect(s3, SIGNAL(entered()), button, SLOT(showMaximized()));
+ QObject::connect(s3, SIGNAL(exited()), button, SLOT(showMinimized()));
\endcode
- \section1 Sharing Transitions By Grouping States
+ \section1 State Machines That Finish
The state machine defined in the previous section never finishes. In order
for a state machine to be able to finish, it needs to have a top-level \e
- final state. When the state machine enters a top-level final state, the
- machine will emit the finished() signal and halt.
+ final state (QFinalState object). When the state machine enters a top-level
+ final state, the machine will emit the QStateMachine::finished() signal and
+ halt.
+
+ \section1 Sharing Transitions By Grouping States
Assume we wanted the user to be able to quit the application at any time by
clicking a Quit button. In order to achieve this, we need to create a final
@@ -167,6 +217,9 @@
s12>addTransition(quitButton, SIGNAL(clicked()), s12);
\endcode
+ A transition can have any state as its target, i.e. the target state does
+ not have to be on the same level in the state hierarchy as the source state.
+
\section1 Using History States to Save and Restore the Current State
Imagine that we wanted to add an "interrupt" mechanism to the example
@@ -204,12 +257,12 @@
QHistoryState *s1h = s1->addHistoryState();
QState *s3 = new QState();
- s3->setPropertyOnEntry(label, "text", "In s3");
+ s3->assignProperty(label, "text", "In s3");
QMessageBox mbox;
mbox.addButton(QMessageBox::Ok);
mbox.setText("Interrupted!");
mbox.setIcon(QMessageBox::Information);
- s3->invokeMethodOnEntry(&mbox, "exec");
+ QObject::connect(s3, SIGNAL(entered()), &mbox, SLOT(exec()));
s3->addTransition(s1h);
machine.addState(s3);
@@ -243,21 +296,26 @@
\caption This is a caption
\endomit
- To create a parallel state group, pass QState::ParallelStateGroup to the
- QState constructor.
+ To create a parallel state group, pass QState::ParallelStates to the QState
+ constructor.
\code
- QState *s1 = new QState(QState::ParallelStateGroup);
+ QState *s1 = new QState(QState::ParallelStates);
// s11 and s12 will be entered in parallel
QState *s11 = new QState(s1);
QState *s12 = new QState(s1);
\endcode
+ When a parallel state group is entered, all its child states will be
+ simultaneously entered. Transitions within the individual child states
+ operate normally. However, any of the child states may take a transition
+ outside the parent state. When this happens, the parent state and all of its
+ child states are exited.
+
\section1 Detecting that a Composite State has Finished
- A child state can be final; when a final child state is entered, a
- QStateFinishedEvent is generated for the parent state. You can use the
- QStateFinishedTransition class to trigger a transition based on this event.
+ A child state can be final (a QFinalState object); when a final child state
+ is entered, the parent state emits the QState::finished() signal.
\img statemachine-finished.png
\omit
@@ -266,7 +324,287 @@
This is useful when you want to hide the internal details of a state;
i.e. the only thing the outside world should be able to do is enter the
- state, and get a notification when the state has finished (i.e. when a final
- child state has been entered).
+ state, and get a notification when the state has completed its work.
+
+ For parallel state groups, the QState::finished() signal is emitted when \e
+ all the child states have entered final states.
+
+ \section1 Events, Transitions and Guards
+
+ A QStateMachine runs its own event loop. For signal transitions
+ (QSignalTransition objects), QStateMachine automatically posts a
+ QSignalEvent to itself when it intercepts the corresponding signal;
+ similarly, for QObject event transitions (QEventTransition objects) a
+ QWrappedEvent is posted.
+
+ You can post your own events to the state machine using
+ QStateMachine::postEvent().
+
+ When posting a custom event to the state machine, you typically also have
+ one or more custom transitions that can be triggered from events of that
+ type. To create such a transition, you subclass QAbstractTransition and
+ reimplement QAbstractTransition::eventTest(), where you check if an event
+ matches your event type (and optionally other criteria, e.g. attributes of
+ the event object).
+
+ Here we define our own custom event type, \c StringEvent, for posting
+ strings to the state machine:
+
+ \code
+ struct StringEvent : public QEvent
+ {
+ StringEvent(const QString &val)
+ : QEvent(QEvent::Type(QEvent::User+1)),
+ value(val) {}
+
+ QString value;
+ };
+ \endcode
+
+ Next, we define a transition that only triggers when the event's string
+ matches a particular string (a \e guarded transition):
+
+ \code
+ class StringTransition : public QAbstractTransition
+ {
+ public:
+ StringTransition(const QString &value)
+ : m_value(value) {}
+
+ protected:
+ virtual bool eventTest(QEvent *e) const
+ {
+ if (e->type() != QEvent::Type(QEvent::User+1)) // StringEvent
+ return false;
+ StringEvent *se = static_cast<StringEvent*>(e);
+ return (m_value == se->value);
+ }
+
+ virtual void onTransition(QEvent *) {}
+
+ private:
+ QString m_value;
+ };
+ \endcode
+
+ In the eventTest() reimplementation, we first check if the event type is the
+ desired one; if so, we cast the event to a StringEvent and perform the
+ string comparison.
+
+ The following is a statechart that uses the custom event and transition:
+
+ \img statemachine-customevents.png
+ \omit
+ \caption This is a caption
+ \endomit
+
+ Here's what the implementation of the statechart looks like:
+
+ \code
+ QStateMachine machine;
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+ QFinalState *done = new QFinalState();
- */
+ StringTransition *t1 = new StringTransition("Hello");
+ t1->setTargetState(s2);
+ s1->addTransition(t1);
+ StringTransition *t2 = new StringTransition("world");
+ t2->setTargetState(done);
+ s2->addTransition(t2);
+
+ machine.addState(s1);
+ machine.addState(s2);
+ machine.addState(done);
+ machine.setInitialState(s1);
+ \endcode
+
+ Once the machine is started, we can post events to it.
+
+ \code
+ 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.
+*/