diff options
author | Alexis Menard <alexis.menard@nokia.com> | 2009-05-12 12:51:15 (GMT) |
---|---|---|
committer | Alexis Menard <alexis.menard@nokia.com> | 2009-05-12 12:51:15 (GMT) |
commit | 90d801f05f64c645f0899e3d81b23ecf53bf4835 (patch) | |
tree | 14362a48f6c74709972ab1a92d7be81d910f788d | |
parent | 1898c46452beae9e28cf9be7851099b4b4d2779e (diff) | |
parent | c6add575d50ee30b19580fc2c1ebda5316a2f51b (diff) | |
download | Qt-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
209 files changed, 8072 insertions, 5230 deletions
diff --git a/bin/snapshot b/bin/snapshot index ffad857..b9a64e1 100644 --- a/bin/snapshot +++ b/bin/snapshot @@ -14,6 +14,40 @@ use strict; my $targetPath = ""; my $qtdir = $ENV{"QTDIR"}; +my @class_renames = ( + "QAbstractAnimation", + "QAnimationGroup", + "QParallelAnimationGroup", + "QSequentialAnimationGroup", + "QEasingCurve", + "QVariantAnimation", + "QPropertyAnimation", + "QItemAnimation", + "QPauseAnimation", + "QAbstractState", + "QAbstractStateGroup", + "QAbstractTransition", + "QActionState", + "QEventTransition", + "QFinalState", + "QHistoryState", + "QParallelStateGroup", + "QSignalEvent", + "QSignalTransition", + "QState", + "QStateAction", + "QStateInvokeMethodAction", + "QStateFinishedEvent", + "QStateFinishedTransition", + "QStateMachine", + "QTransition", + "QMouseEventTransition", + "QBasicMouseEventTransition", + "QKeyEventTransition", + "QBasicKeyEventTransition", + "QGraphicsWidget", + "QBoundEvent"); + my @files = ( "3rdparty/easing/easing.cpp", "corelib/tools/qeasingcurve.h", @@ -39,6 +73,9 @@ my @files = ( "corelib/animation/qsequentialanimationgroup.cpp", "corelib/animation/qsequentialanimationgroup.h", "corelib/animation/qsequentialanimationgroup_p.h", + "gui/animation/qguivariantanimation.cpp", + "gui/animation/animation.pri", + "corelib/statemachine/statemachine.pri", "corelib/statemachine/qabstractstate.cpp", "corelib/statemachine/qabstractstate.h", @@ -75,9 +112,9 @@ my @files = ( "corelib/statemachine/qstatemachine.h", "corelib/statemachine/qstatemachine_p.h", "corelib/statemachine/qstate_p.h", - "corelib/statemachine/qtransition.cpp", - "corelib/statemachine/qtransition.h", - "corelib/statemachine/qtransition_p.h", + "corelib/statemachine/qactiontransition.cpp", + "corelib/statemachine/qactiontransition.h", + "corelib/statemachine/qactiontransition_p.h", "gui/statemachine/qkeyeventtransition.h", "gui/statemachine/qkeyeventtransition.cpp", "gui/statemachine/qbasickeyeventtransition.cpp", @@ -109,13 +146,13 @@ open(OXML, "> " . $projectXML) || die "Could not open $projectXML for writing (n print "COPYING SOURCES...\n"; foreach my $files(@files) { - copyFile("$qtdir/src/$files","$targetPath/src"); + copyFile("$qtdir/src/$files","$targetPath/src", 1); } -copyFile("$qtdir/doc/src/animation.qdoc","$targetPath/doc"); -copyFile("$qtdir/doc/src/statemachine.qdoc","$targetPath/doc"); -copyFile("$qtdir/src/3rdparty/easing/legal.qdoc","$targetPath/doc"); +copyFile("$qtdir/doc/src/animation.qdoc","$targetPath/doc", 0); +copyFile("$qtdir/doc/src/statemachine.qdoc","$targetPath/doc", 0); +copyFile("$qtdir/src/3rdparty/easing/legal.qdoc","$targetPath/doc", 0); -copyFile("$qtdir/doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp","$targetPath/doc/src/snippets/code"); +copyFile("$qtdir/doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp","$targetPath/doc/src/snippets/code", 0); my %animation_examples = ( @@ -142,7 +179,6 @@ my %animation_examples = ( "bomb.cpp", "bomb.h", "custompropertyanimation.h", - "custompropertyanimation_p.h", "custompropertyanimation.cpp", "graphicsscene.cpp", "graphicsscene.h", @@ -150,7 +186,9 @@ my %animation_examples = ( "mainwindow.cpp", "mainwindow.h", "pics/scalable/*", - "pics/big/*", + "pics/big/*.png", + "pics/big/explosion/boat/*", + "pics/big/explosion/submarine/*", "pics/small/*", "pics/welcome/*", "pixmapitem.cpp", @@ -161,8 +199,11 @@ my %animation_examples = ( "submarine_p.h", "states.cpp", "states.h", + "qanimationstate.cpp", + "qanimationstate.h", "torpedo.cpp", - "torpedo.h"], + "torpedo.h", + "data.xml"], "stickman" => ["stickman.pro", "main.cpp", "animation.cpp", @@ -175,6 +216,7 @@ my %animation_examples = ( "node.h", "stickman.cpp", "stickman.h", + "editor/*", "animations/chilling", "animations/dancing", "animations/dead", @@ -193,7 +235,7 @@ for $exDir ( keys %animation_examples ) { my $glob = 0; if (index($ex_file,"/") > 0) { my($basefile, $fullPath) = fileparse("$targetPath/examples/$exDir/$ex_file"); - if ($basefile eq "*") { + if (index($basefile, "*") >= 0) { $glob = 1; } mkpath "$fullPath", 0777 unless(-e "$fullPath"); @@ -209,20 +251,25 @@ for $exDir ( keys %animation_examples ) { if ($glob eq 1) { my @globFiles = < $qtdir/examples/animation/$exDir/$ex_file >; foreach my $globFile(@globFiles) { - copyFile("$globFile", "$copyTargetPath"); + copyFile("$globFile", "$copyTargetPath", 0); } } else { - copyFile("$qtdir/examples/animation/$exDir/$ex_file", "$copyTargetPath"); + copyFile("$qtdir/examples/animation/$exDir/$ex_file", "$copyTargetPath", 0); } } } close OXML; print("Finished!"); + + ###################################################################### # Syntax: copyFile(gitfile, destinationPath) # Params: gitfile, string, filename to create duplicate for # destinationPath, string, destination name of duplicate +# autoRename, int, 0: Don't rename +# 1: The file should be renamed to have the "qt" prefix +# # # Purpose: Copies to the solutions area. # Returns: -- @@ -230,7 +277,7 @@ print("Finished!"); ###################################################################### sub copyFile { - my ($gitfile, $destinationPath) = @_; + my ($gitfile, $destinationPath, $autoRename) = @_; # Bi-directional synchronization open( I, "< " . $gitfile ) || die "Could not open $gitfile for reading"; local $/; @@ -239,44 +286,20 @@ sub copyFile my ($baseFileName, $path, $ext) = fileparse($gitfile, qr/\.[^.]*/); if ($ext eq ".h" or $ext eq ".cpp" or $ext eq ".qdoc") { # both public and private classes - $filecontents =~s/QAbstractAnimation/QtAbstractAnimation/g; - $filecontents =~s/QAnimationGroup/QtAnimationGroup/g; - $filecontents =~s/QParallelAnimationGroup/QtParallelAnimationGroup/g; - $filecontents =~s/QSequentialAnimationGroup/QtSequentialAnimationGroup/g; - $filecontents =~s/QEasingCurve/QtEasingCurve/g; - $filecontents =~s/QVariantAnimation/QtVariantAnimation/g; - $filecontents =~s/QPropertyAnimation/QtPropertyAnimation/g; - $filecontents =~s/QItemAnimation/QtItemAnimation/g; - $filecontents =~s/QPauseAnimation/QtPauseAnimation/g; - $filecontents =~s/QAbstractState/QtAbstractState/g; - $filecontents =~s/QAbstractStateGroup/QtAbstractStateGroup/g; - $filecontents =~s/QAbstractTransition/QtAbstractTransition/g; - $filecontents =~s/QActionState/QtActionState/g; - $filecontents =~s/QEventTransition/QtEventTransition/g; - $filecontents =~s/QFinalState/QtFinalState/g; - $filecontents =~s/QHistoryState/QtHistoryState/g; - $filecontents =~s/QParallelStateGroup/QtParallelStateGroup/g; - $filecontents =~s/QSignalEvent/QtSignalEvent/g; - $filecontents =~s/QSignalTransition/QtSignalTransition/g; - $filecontents =~s/QState/QtState/g; - $filecontents =~s/QStateAction/QtStateAction/g; - $filecontents =~s/QStateInvokeMethodAction/QtStateInvokeMethodAction/g; - $filecontents =~s/QStateFinishedEvent/QtStateFinishedEvent/g; - $filecontents =~s/QStateFinishedTransition/QtStateFinishedTransition/g; - $filecontents =~s/QStateMachine/QtStateMachine/g; - $filecontents =~s/QTransition/QtTransition/g; - $filecontents =~s/QMouseEventTransition/QtMouseEventTransition/g; - $filecontents =~s/QKeyEventTransition/QtKeyEventTransition/g; - $filecontents =~s/QGraphicsWidget/QtGraphicsWidget/g; + foreach my $qtClass(@class_renames) { + my $solutionClass = $qtClass; + $solutionClass =~s/^Q/Qt/g; + $filecontents =~s/$qtClass/$solutionClass/g; + my $qtFilename = lc($qtClass); + my $solutionFilename = lc($solutionClass); + $filecontents =~s/(#\s*include\s+["])$qtFilename/${1}$solutionFilename/g; + } + $filecontents =~s/Q_CORE_EXPORT/Q_ANIMATION_EXPORT/g; $filecontents =~s/Q_GUI_EXPORT/Q_ANIMATION_EXPORT/g; - $filecontents =~s/QBoundEvent/QtBoundEvent/g; - $filecontents =~s/class Q_GUI_EXPORT/class/g; $filecontents =~s/class Q_AUTOTEST_EXPORT/class/g; - $filecontents =~s/(#\s*include\s+["])q/${1}qt/g; - # moc stuff $filecontents =~s/(#\s*include\s+["])moc_q/${1}moc_qt/g; @@ -300,7 +323,14 @@ sub copyFile if (index($gitfile, "gui/statemachine") >= 0) { $baseFileName = "gui_statemachine"; } - + } + if ($baseFileName eq "animation") { + if (index($gitfile, "corelib/animation") >= 0) { + $baseFileName = "corelib_animation"; + } + if (index($gitfile, "gui/animation") >= 0) { + $baseFileName = "gui_animation"; + } } } @@ -312,7 +342,7 @@ sub copyFile mkpath $destinationPath, 0777 unless(-e "$destinationPath"); - if ($ext eq ".h" or $ext eq ".cpp" or $ext eq ".qdoc") { + if ($autoRename eq 1 and ($ext eq ".h" or $ext eq ".cpp" or $ext eq ".qdoc")) { $baseFileName =~s/^q/qt/g; } my $targetFile = "$destinationPath/$baseFileName$ext"; 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 Binary files differindex cd66478..7f51cae 100644 --- a/doc/src/images/statemachine-button-history.png +++ b/doc/src/images/statemachine-button-history.png diff --git a/doc/src/images/statemachine-button-nested.png b/doc/src/images/statemachine-button-nested.png Binary files differindex 60360d1..762ac14 100644 --- a/doc/src/images/statemachine-button-nested.png +++ b/doc/src/images/statemachine-button-nested.png diff --git a/doc/src/images/statemachine-button.png b/doc/src/images/statemachine-button.png Binary files differindex 75d9e53..10102bd 100644 --- a/doc/src/images/statemachine-button.png +++ b/doc/src/images/statemachine-button.png diff --git a/doc/src/images/statemachine-customevents.png b/doc/src/images/statemachine-customevents.png Binary files differnew file mode 100644 index 0000000..62a4222 --- /dev/null +++ b/doc/src/images/statemachine-customevents.png diff --git a/doc/src/images/statemachine-finished.png b/doc/src/images/statemachine-finished.png Binary files differindex 802621e..0ac081d 100644 --- a/doc/src/images/statemachine-finished.png +++ b/doc/src/images/statemachine-finished.png diff --git a/doc/src/images/statemachine-nonparallel.png b/doc/src/images/statemachine-nonparallel.png Binary files differindex 1fe60d8..f9850a7 100644 --- a/doc/src/images/statemachine-nonparallel.png +++ b/doc/src/images/statemachine-nonparallel.png diff --git a/doc/src/images/statemachine-parallel.png b/doc/src/images/statemachine-parallel.png Binary files differindex 1868792..a65c297 100644 --- a/doc/src/images/statemachine-parallel.png +++ b/doc/src/images/statemachine-parallel.png diff --git a/doc/src/images/trafficlight-example1.png b/doc/src/images/trafficlight-example1.png Binary files differnew file mode 100644 index 0000000..ec8c7ff --- /dev/null +++ b/doc/src/images/trafficlight-example1.png diff --git a/doc/src/images/trafficlight-example2.png b/doc/src/images/trafficlight-example2.png Binary files differnew file mode 100644 index 0000000..a12e4db --- /dev/null +++ b/doc/src/images/trafficlight-example2.png 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. +*/ diff --git a/examples/animation/animatedtiles/main.cpp b/examples/animation/animatedtiles/main.cpp index cfaa4ce..a97eaf3 100644 --- a/examples/animation/animatedtiles/main.cpp +++ b/examples/animation/animatedtiles/main.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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_EXPERIMENTAL_SOLUTION # include "qgraphicswidget.h" @@ -7,6 +48,7 @@ # include "qgraphicswidget.h" # include "qparallelanimationgroup.h" # include "qpropertyanimation.h" +# include "qsignaltransition.h" #else #include <QtCore/qstate.h> #endif diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp index 1a43ed7..1c63aba 100644 --- a/examples/animation/appchooser/main.cpp +++ b/examples/animation/appchooser/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ @@ -60,15 +90,16 @@ void createStates(const QObjectList &objects, for (int i = 0; i < objects.size(); ++i) { QState *state = new QState(parent); state->assignProperty(objects.at(i), "geometry", selectedRect); - QAbstractTransition *trans = parent->addTransition(objects.at(i), SIGNAL(clicked()), state); - for (int j = 0; j < objects.size(); ++j) { - QPropertyAnimation *animation = new QPropertyAnimation(objects.at(j), "geometry"); - animation->setDuration(2000); - trans->addAnimation(animation); - } + parent->addTransition(objects.at(i), SIGNAL(clicked()), state); } } +void createAnimations(const QObjectList &objects, QStateMachine *machine) +{ + for (int i=0; i<objects.size(); ++i) + machine->addDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry")); +} + int main(int argc, char **argv) { Q_INIT_RESOURCE(appchooser); @@ -104,7 +135,7 @@ int main(int argc, char **argv) window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QState *group = new QState(machine.rootState()); group->setObjectName("group"); @@ -113,7 +144,10 @@ int main(int argc, char **argv) QState *idleState = new QState(group); group->setInitialState(idleState); - createStates(QObjectList() << p1 << p2 << p3 << p4, selectedRect, group); + QObjectList objects; + objects << p1 << p2 << p3 << p4; + createStates(objects, selectedRect, group); + createAnimations(objects, &machine); machine.setInitialState(group); machine.start(); diff --git a/examples/animation/easing/animation.h b/examples/animation/easing/animation.h index db67810..c9472e1 100644 --- a/examples/animation/easing/animation.h +++ b/examples/animation/easing/animation.h @@ -3,9 +3,39 @@ ** 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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/easing/main.cpp b/examples/animation/easing/main.cpp index 139f2da..487fa86 100644 --- a/examples/animation/easing/main.cpp +++ b/examples/animation/easing/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/easing/window.cpp b/examples/animation/easing/window.cpp index c6ea360..cf4be15 100644 --- a/examples/animation/easing/window.cpp +++ b/examples/animation/easing/window.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ @@ -88,7 +118,7 @@ void Window::startAnimation() m_anim->setStartValue(QPointF(0, 0)); m_anim->setEndValue(QPointF(100, 100)); m_anim->setDuration(2000); - m_anim->setIterationCount(-1); // forever + m_anim->setLoopCount(-1); // forever m_anim->start(); } diff --git a/examples/animation/easing/window.h b/examples/animation/easing/window.h index 4ba6eb6..f3a8cb3 100644 --- a/examples/animation/easing/window.h +++ b/examples/animation/easing/window.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/example/main.cpp b/examples/animation/example/main.cpp index d5f5607..1180b4f 100644 --- a/examples/animation/example/main.cpp +++ b/examples/animation/example/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/example/mainwindow.cpp b/examples/animation/example/mainwindow.cpp index 2b0e035..4aff384 100644 --- a/examples/animation/example/mainwindow.cpp +++ b/examples/animation/example/mainwindow.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ @@ -173,9 +203,9 @@ MainWindow::MainWindow() : QMainWindow(0) setCentralWidget(view); - state3->invokeMethodOnEntry(this, "onEnterState3"); - state2->invokeMethodOnEntry(this, "onEnterState2"); - state1->invokeMethodOnEntry(this, "onEnterState1"); + QObject::connect(state3, SIGNAL(entered()), this, SLOT(onEnterState3())); + QObject::connect(state2, SIGNAL(entered()), this, SLOT(onEnterState2())); + QObject::connect(state1, SIGNAL(entered()), this, SLOT(onEnterState1())); connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*))); connect(button3, SIGNAL(clicked()), this, SLOT(onRemoveClicked())); diff --git a/examples/animation/example/mainwindow.h b/examples/animation/example/mainwindow.h index 6be7463..163eb89 100644 --- a/examples/animation/example/mainwindow.h +++ b/examples/animation/example/mainwindow.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp index 1f253f3..06ed3dd 100644 --- a/examples/animation/moveblocks/main.cpp +++ b/examples/animation/moveblocks/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ @@ -71,7 +101,7 @@ protected: && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand); } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} private: int m_rand; @@ -86,7 +116,7 @@ public: m_stateCount(0), m_lastIndex(0) { } - virtual void onEntry() + virtual void onEntry(QEvent *) { int n; while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) @@ -94,7 +124,7 @@ public: m_lastIndex = n; m_machine->postEvent(new StateSwitchEvent(n)); } - virtual void onExit() {} + virtual void onExit(QEvent *) {} void addState(QState *state, QAbstractAnimation *animation) { StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); @@ -172,7 +202,7 @@ int main(int argc, char **argv) QTimer timer; timer.setInterval(1250); timer.setSingleShot(true); - group->invokeMethodOnEntry(&timer, "start"); + QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start())); QState *state1; QState *state2; diff --git a/examples/animation/padnavigator-ng/main.cpp b/examples/animation/padnavigator-ng/main.cpp index 5b35b62..f8b167f 100644 --- a/examples/animation/padnavigator-ng/main.cpp +++ b/examples/animation/padnavigator-ng/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/panel.cpp b/examples/animation/padnavigator-ng/panel.cpp index 94dbdec..e61be0e 100644 --- a/examples/animation/padnavigator-ng/panel.cpp +++ b/examples/animation/padnavigator-ng/panel.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/panel.h b/examples/animation/padnavigator-ng/panel.h index cbceed1..35d0db5 100644 --- a/examples/animation/padnavigator-ng/panel.h +++ b/examples/animation/padnavigator-ng/panel.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/roundrectitem.cpp b/examples/animation/padnavigator-ng/roundrectitem.cpp index e498538..7e7d423 100644 --- a/examples/animation/padnavigator-ng/roundrectitem.cpp +++ b/examples/animation/padnavigator-ng/roundrectitem.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/roundrectitem.h b/examples/animation/padnavigator-ng/roundrectitem.h index 56a6d3c..fb142c6 100644 --- a/examples/animation/padnavigator-ng/roundrectitem.h +++ b/examples/animation/padnavigator-ng/roundrectitem.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/splashitem.cpp b/examples/animation/padnavigator-ng/splashitem.cpp index 84a8945..1264987 100644 --- a/examples/animation/padnavigator-ng/splashitem.cpp +++ b/examples/animation/padnavigator-ng/splashitem.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/padnavigator-ng/splashitem.h b/examples/animation/padnavigator-ng/splashitem.h index 6428b69..05ff040 100644 --- a/examples/animation/padnavigator-ng/splashitem.h +++ b/examples/animation/padnavigator-ng/splashitem.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/photobrowser/main.cpp b/examples/animation/photobrowser/main.cpp deleted file mode 100644 index 98f2a9e..0000000 --- a/examples/animation/photobrowser/main.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#include <QtGui> - -#include "river.h" -#include "menu.h" - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - if (app.arguments().size() == 1) { - qWarning("you have to specifiy a path to look for the photos"); - return 0; - } - - - QGraphicsScene scene; - scene.setSceneRect(QRectF(QPointF(), River::fixedSize())); - - QGraphicsView view(&scene); - view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - const int fw = view.frameWidth() * 2; - view.setFixedSize(River::fixedSize() + QSize(fw,fw)); - - River river(app.arguments()[1]); - scene.addItem(&river); - - Menu menu(&river); - menu.addAction(QLatin1String("River Mode"), &river, SLOT(setRiverMode())); - menu.addAction(QLatin1String("Grid Mode"), &river, SLOT(setGridMode())); - menu.addAction(QLatin1String("Cover Flow"), &river, SLOT(setCoverMode())); - menu.addAction(QLatin1String("Hide Menu"), &menu, SLOT(hide())); - menu.addAction(QLatin1String("Exit"), &app, SLOT(quit())); - menu.setZValue(2); - menu.setFocus(); - - river.menu = &menu; - view.show(); - - return app.exec(); -} diff --git a/examples/animation/photobrowser/menu.h b/examples/animation/photobrowser/menu.h deleted file mode 100644 index 9514cfe..0000000 --- a/examples/animation/photobrowser/menu.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef __MENU__H__ -#define __MENU__H__ - -#include <QtGui> - -class MenuAction; - -class Menu : public QGraphicsWidget -{ - Q_OBJECT -public: - Menu(QGraphicsItem *parent); - ~Menu(); - - MenuAction *addAction(const QString&, QObject *receiver = 0, const char* slot = 0 ); - - QRectF boundingRect() const; - void keyPressEvent ( QKeyEvent * event ); -public slots: - void show(); - void hide(); -private: - QList<MenuAction*> m_actions; - QGraphicsRectItem *m_selection; - int m_selected; -}; - -class MenuAction : public QGraphicsTextItem -{ - Q_OBJECT -public: - MenuAction(const QString &text, Menu * parent); - void trigger(); -signals: - void triggered(); -}; - - -#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/river.h b/examples/animation/photobrowser/river.h deleted file mode 100644 index 25bf62a..0000000 --- a/examples/animation/photobrowser/river.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef __RIVER__H__ -#define __RIVER__H__ - -#include <QtCore/QDirIterator> -#include <QtGui/QGraphicsWidget> - -#include "menu.h" - -class RiverItem; - -class River : public QGraphicsWidget -{ - Q_OBJECT -public: - enum Mode - { - RiverMode, - GridMode, - GridFullScreenMode, - CoverMode - }; - - River(const QString &path); - void addUnusedRiverItem(RiverItem * item); - - static QSize fixedSize(); - - void switchPaused(); - - void setMode(Mode m); - Mode mode() const; - - Menu *menu; - -protected: - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - void keyPressEvent ( QKeyEvent * keyEvent ); - void makeCenterAvailable(qreal size); - QPointF gridItemPosition(int row, int col) const; - QPixmap pixmap(int index) const; - -protected slots: - void animationFinished(); -public slots: - void setRiverMode(); - void setGridMode(); - void setCoverMode(); - -private: - const QFileInfoList m_images; - int m_currentImage; - mutable QVector<QPixmap> m_pixmaps; - QHash<int, RiverItem*> m_items; - QList<RiverItem*> m_gridItem; - QList<QItemAnimation*> m_pausedAnimations; - Mode m_mode; - - void adjustGrid(int topRight); - RiverItem *currentItem() { return m_items.value(m_selectedItem); } - RiverItem *createItem(int imageIndex); - void setCurrentItem(int currentItem); - void navigateBy(int offset); - - int m_selectedItem; - int m_topLeftIndex; - -}; - - -#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/riveritem.h b/examples/animation/photobrowser/riveritem.h deleted file mode 100644 index 39fdcc2..0000000 --- a/examples/animation/photobrowser/riveritem.h +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef __RIVERITEM__H__ -#define __RIVERITEM__H__ - -#include <QtGui/QGraphicsPixmapItem> - -class RiverItemAnimator; - -class RiverItem : public QGraphicsPixmapItem -{ -public: - RiverItem(QGraphicsItem *parent); - ~RiverItem(); - - void setPixmap(const QPixmap &); - void setFullScreen(bool b, qreal originScaleFactor); - -protected: - void mousePressEvent(QGraphicsSceneMouseEvent*); - -private: - QPointF m_nonFSPos; //to save the position when not in fullscreen - bool m_fullscreen; -}; - -#endif //__RIVERITEM__H__ diff --git a/examples/animation/piemenu/main.cpp b/examples/animation/piemenu/main.cpp deleted file mode 100644 index 28f62d0..0000000 --- a/examples/animation/piemenu/main.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#include <QtGui> -#include "scene.h" -#include "qgraphicspiemenu.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - Scene scene; - - QGraphicsView view(&scene); - view.show(); - - return app.exec(); -} diff --git a/examples/animation/piemenu/qgraphicspiemenu_p.h b/examples/animation/piemenu/qgraphicspiemenu_p.h deleted file mode 100644 index 87a749c..0000000 --- a/examples/animation/piemenu/qgraphicspiemenu_p.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSPIEMENU_P_H -#define QGRAPHICSPIEMENU_P_H - -#include "qgraphicspiemenu.h" -#include "qgraphicspiemenusection_p.h" - -#include <QtGui/qicon.h> -#include <QtCore/qstate.h> -#include <QtCore/qtransition.h> -#include <QtCore/qstatemachine.h> - -class QAction; -class QEventLoop; -class QGraphicsPieMenuSection; - -class QGraphicsPieMenuPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsPieMenu); -public: - void init(const QIcon &icon = QIcon(), const QString &title = QString()); - - QIcon icon; - QString title; - QStateMachine *machine; - QState *popupState; - //QTransition *transition; - QList<QGraphicsPieMenuSection *> sections; - - QEventLoop *eventLoop; - - QAction *menuAction; - QGraphicsPieMenu *q_ptr; - - void updatePopupState(); -}; - -#endif diff --git a/examples/animation/piemenu/qgraphicspiemenusection_p.h b/examples/animation/piemenu/qgraphicspiemenusection_p.h deleted file mode 100644 index 328f742..0000000 --- a/examples/animation/piemenu/qgraphicspiemenusection_p.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSPIEMENUSECTION_H -#define QGRAPHICSPIEMENUSECTION_H - -#include <QtGui/qgraphicswidget.h> -#include <QtGui/qpainter.h> - -class QGraphicsPieMenuSection : public QGraphicsWidget -{ - Q_OBJECT - Q_PROPERTY(qreal rotation READ rotation WRITE setRotation) -public: - QGraphicsPieMenuSection(QGraphicsItem *parent = 0) - : QGraphicsWidget(parent), rot(0) - { } - - qreal rotation() const - { - return rot; - } - void setRotation(qreal rotation) - { - rot = rotation; - setTransform(QTransform().rotate(rot)); - } - - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) - { - Q_UNUSED(option); - Q_UNUSED(widget); - painter->setPen(QPen(Qt::black, 1)); - painter->setBrush(QBrush(Qt::gray)); - painter->drawPie(QRectF(-100, -100, 200, 200), 0, -30 * 16); - } - -protected: - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &size = QSizeF()) const - { - Q_UNUSED(which); - Q_UNUSED(size); - return QSizeF(100, 30); - } - -private: - qreal rot; -}; - -#endif diff --git a/examples/animation/piemenu/scene.cpp b/examples/animation/piemenu/scene.cpp deleted file mode 100644 index 08aad06..0000000 --- a/examples/animation/piemenu/scene.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#include "qgraphicspiemenu.h" -#include "scene.h" - -#include <QtGui/qaction.h> -#include <QtGui/qgraphicssceneevent.h> - -Scene::Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent) - : QGraphicsScene(x, y, width, height, parent) -{ -} - -Scene::Scene(const QRectF &sceneRect, QObject *parent) - : QGraphicsScene(sceneRect, parent) -{ -} - -Scene::Scene(QObject *parent) - : QGraphicsScene(parent) -{ -} - -Scene::~Scene() -{ -} - -void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - QGraphicsPieMenu *menu = new QGraphicsPieMenu; - for (int i = 0; i < 5; ++i) - menu->addAction(new QAction(QString("Item %1").arg(i), menu)); - menu->popup(event->scenePos()); -} diff --git a/examples/animation/piemenu/scene.h b/examples/animation/piemenu/scene.h deleted file mode 100644 index 676f55f..0000000 --- a/examples/animation/piemenu/scene.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 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. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef SCENE_H -#define SCENE_H - -#include <QtGui/qgraphicsscene.h> - -class Scene : public QGraphicsScene -{ - Q_OBJECT -public: - Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent = 0); - Scene(const QRectF &sceneRect, QObject *parent = 0); - Scene(QObject *parent = 0); - ~Scene(); - -protected: - void mousePressEvent(QGraphicsSceneMouseEvent *event); -}; - -#endif diff --git a/examples/animation/research/memberfunctions/main.cpp b/examples/animation/research/memberfunctions/main.cpp index 9142f29..2663f9c 100644 --- a/examples/animation/research/memberfunctions/main.cpp +++ b/examples/animation/research/memberfunctions/main.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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> #include "qvalueanimation.h" diff --git a/examples/animation/research/memberfunctions/qvalueanimation.cpp b/examples/animation/research/memberfunctions/qvalueanimation.cpp index 2fe9be9..de0b8ff 100644 --- a/examples/animation/research/memberfunctions/qvalueanimation.cpp +++ b/examples/animation/research/memberfunctions/qvalueanimation.cpp @@ -1,16 +1,44 @@ /**************************************************************************** ** -** 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 QtCore module 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$ ** ****************************************************************************/ - - #include "qvalueanimation.h" #include "qvalueanimation_p.h" @@ -21,8 +49,8 @@ void QValueAnimationPrivate::initDefaultStartValue() { Q_Q(QValueAnimation); if (animProp && !q->startValue().isValid() - && ((currentTime == 0 && (currentIteration || currentIteration == 0)) - || (currentTime == duration && currentIteration == (iterationCount - 1)))) { + && (currentTime == 0 + || (currentTime == duration && currentLoop == (loopCount - 1)))) { setDefaultStartValue(animProp->read()); } } diff --git a/examples/animation/research/memberfunctions/qvalueanimation.h b/examples/animation/research/memberfunctions/qvalueanimation.h index a4aa213..55c4993 100644 --- a/examples/animation/research/memberfunctions/qvalueanimation.h +++ b/examples/animation/research/memberfunctions/qvalueanimation.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/research/memberfunctions/qvalueanimation_p.h b/examples/animation/research/memberfunctions/qvalueanimation_p.h index e6e7682..55c8ce1 100644 --- a/examples/animation/research/memberfunctions/qvalueanimation_p.h +++ b/examples/animation/research/memberfunctions/qvalueanimation_p.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/src/corelib/statemachine/qactionstate_p.h b/examples/animation/research/photobrowser/main.cpp index a06dde2..d5ab2a3 100644 --- a/src/corelib/statemachine/qactionstate_p.h +++ b/examples/animation/research/photobrowser/main.cpp @@ -39,45 +39,44 @@ ** ****************************************************************************/ -#ifndef QACTIONSTATE_P_H -#define QACTIONSTATE_P_H +#include <QtGui> -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +#include "river.h" +#include "menu.h" -#include "qabstractstate_p.h" -#include "qactionstate.h" - -#include <QtCore/qlist.h> - -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QActionState; -class Q_CORE_EXPORT QActionStatePrivate : public QAbstractStatePrivate +int main(int argc, char **argv) { - Q_DECLARE_PUBLIC(QActionState) + QApplication app(argc, argv); + if (app.arguments().size() == 1) { + qWarning("you have to specifiy a path to look for the photos"); + return 0; + } + + + QGraphicsScene scene; + scene.setSceneRect(QRectF(QPointF(), River::fixedSize())); -public: - QActionStatePrivate(); - ~QActionStatePrivate(); + QGraphicsView view(&scene); + view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - static QActionStatePrivate *get(QActionState *q); - static const QActionStatePrivate *get(const QActionState *q); + const int fw = view.frameWidth() * 2; + view.setFixedSize(River::fixedSize() + QSize(fw,fw)); - QList<QStateAction*> entryActions() const; - QList<QStateAction*> exitActions() const; -}; + River river(app.arguments()[1]); + scene.addItem(&river); + + Menu menu(&river); + menu.addAction(QLatin1String("River Mode"), &river, SLOT(setRiverMode())); + menu.addAction(QLatin1String("Grid Mode"), &river, SLOT(setGridMode())); + menu.addAction(QLatin1String("Cover Flow"), &river, SLOT(setCoverMode())); + menu.addAction(QLatin1String("Hide Menu"), &menu, SLOT(hide())); + menu.addAction(QLatin1String("Exit"), &app, SLOT(quit())); + menu.setZValue(2); + menu.setFocus(); -QT_END_NAMESPACE + river.menu = &menu; + view.show(); -#endif + return app.exec(); +} diff --git a/examples/animation/photobrowser/menu.cpp b/examples/animation/research/photobrowser/menu.cpp index d4efe9c..97493ba 100644 --- a/examples/animation/photobrowser/menu.cpp +++ b/examples/animation/research/photobrowser/menu.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/research/photobrowser/menu.h b/examples/animation/research/photobrowser/menu.h new file mode 100644 index 0000000..3bdfe45 --- /dev/null +++ b/examples/animation/research/photobrowser/menu.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef __MENU__H__ +#define __MENU__H__ + +#include <QtGui> + +class MenuAction; + +class Menu : public QGraphicsWidget +{ + Q_OBJECT +public: + Menu(QGraphicsItem *parent); + ~Menu(); + + MenuAction *addAction(const QString&, QObject *receiver = 0, const char* slot = 0 ); + + QRectF boundingRect() const; + void keyPressEvent ( QKeyEvent * event ); +public slots: + void show(); + void hide(); +private: + QList<MenuAction*> m_actions; + QGraphicsRectItem *m_selection; + int m_selected; +}; + +class MenuAction : public QGraphicsTextItem +{ + Q_OBJECT +public: + MenuAction(const QString &text, Menu * parent); + void trigger(); +signals: + void triggered(); +}; + + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/photobrowser.pro b/examples/animation/research/photobrowser/photobrowser.pro index 21f03d6..21f03d6 100644 --- a/examples/animation/photobrowser/photobrowser.pro +++ b/examples/animation/research/photobrowser/photobrowser.pro diff --git a/examples/animation/photobrowser/river.cpp b/examples/animation/research/photobrowser/river.cpp index f3dd0746..6760066 100644 --- a/examples/animation/photobrowser/river.cpp +++ b/examples/animation/research/photobrowser/river.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/src/corelib/statemachine/qactionstate.h b/examples/animation/research/photobrowser/river.h index 517b4b2..d6bfc76 100644 --- a/src/corelib/statemachine/qactionstate.h +++ b/examples/animation/research/photobrowser/river.h @@ -39,64 +39,73 @@ ** ****************************************************************************/ -#ifndef QACTIONSTATE_H -#define QACTIONSTATE_H +#ifndef __RIVER__H__ +#define __RIVER__H__ -#ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qabstractstate.h> -#else -#include "qabstractstate.h" -#endif +#include <QtCore/QDirIterator> +#include <QtGui/QGraphicsWidget> -#include <QtCore/qlist.h> -#include <QtCore/qvariant.h> +#include "menu.h" -QT_BEGIN_HEADER +class RiverItem; -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateAction; - -class QActionStatePrivate; -class Q_CORE_EXPORT QActionState : public QAbstractState +class River : public QGraphicsWidget { Q_OBJECT public: - QActionState(QState *parent = 0); - ~QActionState(); + enum Mode + { + RiverMode, + GridMode, + GridFullScreenMode, + CoverMode + }; - void invokeMethodOnEntry(QObject *object, const char *method, - const QList<QVariant> &args = QList<QVariant>()); - void invokeMethodOnExit(QObject *object, const char *method, - const QList<QVariant> &args = QList<QVariant>()); + River(const QString &path); + void addUnusedRiverItem(RiverItem * item); - void addEntryAction(QStateAction *action); - void addExitAction(QStateAction *action); + static QSize fixedSize(); - void removeEntryAction(QStateAction *action); - void removeExitAction(QStateAction *action); + void switchPaused(); - QList<QStateAction*> entryActions() const; - QList<QStateAction*> exitActions() const; + void setMode(Mode m); + Mode mode() const; -protected: - void onEntry(); - void onExit(); - - bool event(QEvent *e); + Menu *menu; protected: - QActionState(QActionStatePrivate &dd, QState *parent); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void keyPressEvent ( QKeyEvent * keyEvent ); + void makeCenterAvailable(qreal size); + QPointF gridItemPosition(int row, int col) const; + QPixmap pixmap(int index) const; + +protected slots: + void animationFinished(); +public slots: + void setRiverMode(); + void setGridMode(); + void setCoverMode(); private: - Q_DISABLE_COPY(QActionState) - Q_DECLARE_PRIVATE(QActionState) -}; + const QFileInfoList m_images; + int m_currentImage; + mutable QVector<QPixmap> m_pixmaps; + QHash<int, RiverItem*> m_items; + QList<RiverItem*> m_gridItem; + QList<QItemAnimation*> m_pausedAnimations; + Mode m_mode; + + void adjustGrid(int topRight); + RiverItem *currentItem() { return m_items.value(m_selectedItem); } + RiverItem *createItem(int imageIndex); + void setCurrentItem(int currentItem); + void navigateBy(int offset); + + int m_selectedItem; + int m_topLeftIndex; -QT_END_NAMESPACE +}; -QT_END_HEADER -#endif +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/riveritem.cpp b/examples/animation/research/photobrowser/riveritem.cpp index f6523a7..9692d30 100644 --- a/examples/animation/photobrowser/riveritem.cpp +++ b/examples/animation/research/photobrowser/riveritem.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/research/photobrowser/riveritem.h b/examples/animation/research/photobrowser/riveritem.h new file mode 100644 index 0000000..2023c44 --- /dev/null +++ b/examples/animation/research/photobrowser/riveritem.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef __RIVERITEM__H__ +#define __RIVERITEM__H__ + +#include <QtGui/QGraphicsPixmapItem> + +class RiverItemAnimator; + +class RiverItem : public QGraphicsPixmapItem +{ +public: + RiverItem(QGraphicsItem *parent); + ~RiverItem(); + + void setPixmap(const QPixmap &); + void setFullScreen(bool b, qreal originScaleFactor); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); + +private: + QPointF m_nonFSPos; //to save the position when not in fullscreen + bool m_fullscreen; +}; + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/research/piemenu/main.cpp b/examples/animation/research/piemenu/main.cpp new file mode 100644 index 0000000..8076da8 --- /dev/null +++ b/examples/animation/research/piemenu/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** 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> +#include "scene.h" +#include "qgraphicspiemenu.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + Scene scene; + + QGraphicsView view(&scene); + view.show(); + + return app.exec(); +} diff --git a/examples/animation/piemenu/piemenu.pro b/examples/animation/research/piemenu/piemenu.pro index 4d7a067..4d7a067 100644 --- a/examples/animation/piemenu/piemenu.pro +++ b/examples/animation/research/piemenu/piemenu.pro diff --git a/examples/animation/piemenu/qgraphicspiemenu.cpp b/examples/animation/research/piemenu/qgraphicspiemenu.cpp index c913423..a199119 100644 --- a/examples/animation/piemenu/qgraphicspiemenu.cpp +++ b/examples/animation/research/piemenu/qgraphicspiemenu.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/piemenu/qgraphicspiemenu.h b/examples/animation/research/piemenu/qgraphicspiemenu.h index 68b4ba9..d784f93 100644 --- a/examples/animation/piemenu/qgraphicspiemenu.h +++ b/examples/animation/research/piemenu/qgraphicspiemenu.h @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/src/corelib/statemachine/qtransition_p.h b/examples/animation/research/piemenu/qgraphicspiemenu_p.h index d43a4d4..458b8f1 100644 --- a/src/corelib/statemachine/qtransition_p.h +++ b/examples/animation/research/piemenu/qgraphicspiemenu_p.h @@ -39,42 +39,40 @@ ** ****************************************************************************/ -#ifndef QTRANSITION_P_H -#define QTRANSITION_P_H +#ifndef QGRAPHICSPIEMENU_P_H +#define QGRAPHICSPIEMENU_P_H -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +#include "qgraphicspiemenu.h" +#include "qgraphicspiemenusection_p.h" -#include "qabstracttransition_p.h" +#include <QtGui/qicon.h> +#include <QtCore/qstate.h> +#include <QtCore/qtransition.h> +#include <QtCore/qstatemachine.h> -#include <QtCore/qlist.h> +class QAction; +class QEventLoop; +class QGraphicsPieMenuSection; -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QTransition; -class Q_CORE_EXPORT QTransitionPrivate : public QAbstractTransitionPrivate +class QGraphicsPieMenuPrivate { - Q_DECLARE_PUBLIC(QTransition) + Q_DECLARE_PUBLIC(QGraphicsPieMenu); public: - QTransitionPrivate(); - ~QTransitionPrivate(); + void init(const QIcon &icon = QIcon(), const QString &title = QString()); - static QTransitionPrivate *get(QTransition *q); - static const QTransitionPrivate *get(const QTransition *q); + QIcon icon; + QString title; + QStateMachine *machine; + QState *popupState; + //QTransition *transition; + QList<QGraphicsPieMenuSection *> sections; - QList<QStateAction*> actions() const; -}; + QEventLoop *eventLoop; -QT_END_NAMESPACE + QAction *menuAction; + QGraphicsPieMenu *q_ptr; + + void updatePopupState(); +}; #endif diff --git a/src/corelib/statemachine/qstatefinishedtransition.h b/examples/animation/research/piemenu/qgraphicspiemenusection_p.h index eae3143..2d71a06 100644 --- a/src/corelib/statemachine/qstatefinishedtransition.h +++ b/examples/animation/research/piemenu/qgraphicspiemenusection_p.h @@ -39,49 +39,50 @@ ** ****************************************************************************/ -#ifndef QSTATEFINISHEDTRANSITION_H -#define QSTATEFINISHEDTRANSITION_H +#ifndef QGRAPHICSPIEMENUSECTION_H +#define QGRAPHICSPIEMENUSECTION_H -#ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qtransition.h> -#else -#include "qtransition.h" -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QState; +#include <QtGui/qgraphicswidget.h> +#include <QtGui/qpainter.h> -class QStateFinishedTransitionPrivate; -class Q_CORE_EXPORT QStateFinishedTransition : public QTransition +class QGraphicsPieMenuSection : public QGraphicsWidget { Q_OBJECT - Q_PROPERTY(QState* state READ state WRITE setState) + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation) public: - QStateFinishedTransition(QState *sourceState = 0); - QStateFinishedTransition(QState *state, const QList<QAbstractState*> &targets, - QState *sourceState = 0); - ~QStateFinishedTransition(); + QGraphicsPieMenuSection(QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), rot(0) + { } - QState *state() const; // ### name - void setState(QState *state); + qreal rotation() const + { + return rot; + } + void setRotation(qreal rotation) + { + rot = rotation; + setTransform(QTransform().rotate(rot)); + } -protected: - bool eventTest(QEvent *event) const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) + { + Q_UNUSED(option); + Q_UNUSED(widget); + painter->setPen(QPen(Qt::black, 1)); + painter->setBrush(QBrush(Qt::gray)); + painter->drawPie(QRectF(-100, -100, 200, 200), 0, -30 * 16); + } - bool event(QEvent *e); +protected: + QSizeF sizeHint(Qt::SizeHint which, const QSizeF &size = QSizeF()) const + { + Q_UNUSED(which); + Q_UNUSED(size); + return QSizeF(100, 30); + } private: - Q_DISABLE_COPY(QStateFinishedTransition) - Q_DECLARE_PRIVATE(QStateFinishedTransition) + qreal rot; }; -QT_END_NAMESPACE - -QT_END_HEADER - #endif diff --git a/examples/animation/research/piemenu/scene.cpp b/examples/animation/research/piemenu/scene.cpp new file mode 100644 index 0000000..6309975 --- /dev/null +++ b/examples/animation/research/piemenu/scene.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 "qgraphicspiemenu.h" +#include "scene.h" + +#include <QtGui/qaction.h> +#include <QtGui/qgraphicssceneevent.h> + +Scene::Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent) + : QGraphicsScene(x, y, width, height, parent) +{ +} + +Scene::Scene(const QRectF &sceneRect, QObject *parent) + : QGraphicsScene(sceneRect, parent) +{ +} + +Scene::Scene(QObject *parent) + : QGraphicsScene(parent) +{ +} + +Scene::~Scene() +{ +} + +void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsPieMenu *menu = new QGraphicsPieMenu; + for (int i = 0; i < 5; ++i) + menu->addAction(new QAction(QString("Item %1").arg(i), menu)); + menu->popup(event->scenePos()); +} diff --git a/examples/animation/sub-attaq/custompropertyanimation_p.h b/examples/animation/research/piemenu/scene.h index 89fc757..bbfe6d3 100644 --- a/examples/animation/sub-attaq/custompropertyanimation_p.h +++ b/examples/animation/research/piemenu/scene.h @@ -39,26 +39,22 @@ ** ****************************************************************************/ -#ifndef CUSTOMPROPERTYANIMATION_P_H -#define CUSTOMPROPERTYANIMATION_P_H +#ifndef SCENE_H +#define SCENE_H -#ifdef QT_EXPERIMENTAL_SOLUTION -# include "qvariantanimation_p.h" -#else -# include <private/qvariantanimation_p.h> -#endif +#include <QtGui/qgraphicsscene.h> -class CustomPropertyAnimationPrivate : public QVariantAnimationPrivate +class Scene : public QGraphicsScene { - Q_DECLARE_PUBLIC(CustomPropertyAnimation) + Q_OBJECT public: - CustomPropertyAnimationPrivate() : QVariantAnimationPrivate(), animProp(0) - { - } - - void initDefaultStartValue(); + Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent = 0); + Scene(const QRectF &sceneRect, QObject *parent = 0); + Scene(QObject *parent = 0); + ~Scene(); - AbstractProperty *animProp; +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); }; -#endif //QTCUSTOMPROPERTYANIMATION_P_H +#endif diff --git a/examples/animation/research/propertytransform/main.cpp b/examples/animation/research/propertytransform/main.cpp index 80002c9..99cd769 100644 --- a/examples/animation/research/propertytransform/main.cpp +++ b/examples/animation/research/propertytransform/main.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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> #include "qpropertytransform.h" diff --git a/examples/animation/research/propertytransform/qpropertytransform.h b/examples/animation/research/propertytransform/qpropertytransform.h index e052625..e27987f 100644 --- a/examples/animation/research/propertytransform/qpropertytransform.h +++ b/examples/animation/research/propertytransform/qpropertytransform.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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/QObject> #include <QtCore/QPoint> #include <QtGui/QGraphicsItem> diff --git a/examples/animation/research/sound/main.cpp b/examples/animation/research/sound/main.cpp index 2c9fa47..ffbc44c 100644 --- a/examples/animation/research/sound/main.cpp +++ b/examples/animation/research/sound/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ @@ -71,4 +101,4 @@ int main(int argc, char **argv) anim.start(); return app.exec(); -}
\ No newline at end of file +} diff --git a/examples/animation/states/main.cpp b/examples/animation/states/main.cpp index da50519..06b0667 100644 --- a/examples/animation/states/main.cpp +++ b/examples/animation/states/main.cpp @@ -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 QtCore module 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$ ** ****************************************************************************/ diff --git a/examples/animation/stickman/animation.cpp b/examples/animation/stickman/animation.cpp index 998632a..c2c6bd1 100644 --- a/examples/animation/stickman/animation.cpp +++ b/examples/animation/stickman/animation.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "animation.h" #include <QPointF> @@ -149,4 +190,4 @@ void Animation::load(QIODevice *device) m_frames.append(frame); } -}
\ No newline at end of file +} diff --git a/examples/animation/stickman/animation.h b/examples/animation/stickman/animation.h index 22afab6..e6c375e 100644 --- a/examples/animation/stickman/animation.h +++ b/examples/animation/stickman/animation.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef ANIMATION_H #define ANIMATION_H diff --git a/examples/animation/stickman/editor/animationdialog.cpp b/examples/animation/stickman/editor/animationdialog.cpp index ca0daf0..441517d 100644 --- a/examples/animation/stickman/editor/animationdialog.cpp +++ b/examples/animation/stickman/editor/animationdialog.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "animationdialog.h" #include "stickman.h" #include "animation.h" @@ -148,4 +189,4 @@ void AnimationDialog::totalFramesChanged(int totalFrames) void AnimationDialog::setCurrentAnimationName(const QString &name) { m_animation->setName(name); -}
\ No newline at end of file +} diff --git a/examples/animation/stickman/editor/animationdialog.h b/examples/animation/stickman/editor/animationdialog.h index c144fd8..764cdaf 100644 --- a/examples/animation/stickman/editor/animationdialog.h +++ b/examples/animation/stickman/editor/animationdialog.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef ANIMATIONDIALOG_H #define ANIMATIONDIALOG_H diff --git a/examples/animation/stickman/editor/mainwindow.cpp b/examples/animation/stickman/editor/mainwindow.cpp index 158c9b7..c6464c6 100644 --- a/examples/animation/stickman/editor/mainwindow.cpp +++ b/examples/animation/stickman/editor/mainwindow.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "mainwindow.h" #include "animationdialog.h" #include "stickman.h" diff --git a/examples/animation/stickman/editor/mainwindow.h b/examples/animation/stickman/editor/mainwindow.h index 279fc07..4c2b949 100644 --- a/examples/animation/stickman/editor/mainwindow.h +++ b/examples/animation/stickman/editor/mainwindow.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef MAINWINDOW_H #define MAINWINDOW_H diff --git a/examples/animation/stickman/graphicsview.cpp b/examples/animation/stickman/graphicsview.cpp index d4f0e3a..754f3bc 100644 --- a/examples/animation/stickman/graphicsview.cpp +++ b/examples/animation/stickman/graphicsview.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "graphicsview.h" #include "editor/mainwindow.h" #include "stickman.h" diff --git a/examples/animation/stickman/graphicsview.h b/examples/animation/stickman/graphicsview.h index 58ed95b..2515418 100644 --- a/examples/animation/stickman/graphicsview.h +++ b/examples/animation/stickman/graphicsview.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef GRAPHICSVIEW_H #define GRAPHICSVIEW diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp index 9233760..b22af55 100644 --- a/examples/animation/stickman/lifecycle.cpp +++ b/examples/animation/stickman/lifecycle.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "lifecycle.h" #include "stickman.h" #include "node.h" @@ -70,14 +111,12 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) // Set up intial state graph m_machine = new QStateMachine(); - m_machine->setGlobalRestorePolicy(QState::RestoreProperties); m_alive = new QState(m_machine->rootState()); m_alive->setObjectName("alive"); // Make it blink when lightning strikes before entering dead animation QState *lightningBlink = new QState(m_machine->rootState()); - lightningBlink->setRestorePolicy(QState::DoNotRestoreProperties); lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white); lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black); lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white); @@ -86,11 +125,10 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) QTimer *timer = new QTimer(lightningBlink); timer->setSingleShot(true); timer->setInterval(100); - lightningBlink->invokeMethodOnEntry(timer, "start"); - lightningBlink->invokeMethodOnExit(timer, "stop"); + QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start())); + QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop())); m_dead = new QState(m_machine->rootState()); - m_dead->setRestorePolicy(QState::DoNotRestoreProperties); m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black); m_dead->assignProperty(m_stickMan, "penColor", Qt::white); m_dead->assignProperty(m_stickMan, "fillColor", Qt::black); @@ -110,15 +148,6 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) m_machine->setInitialState(m_alive); } -void LifeCycle::setResetKey(Qt::Key resetKey) -{ - // When resetKey is pressed, enter the idle state and do a restoration animation - // (requires no animation pointer, since no property is being set in the idle state) - KeyPressTransition *trans = new KeyPressTransition(m_keyReceiver, resetKey, m_idle); - trans->addAnimation(m_animationGroup); - m_alive->addTransition(trans); -} - void LifeCycle::setDeathAnimation(const QString &fileName) { QState *deathAnimation = makeState(m_dead, fileName); @@ -174,14 +203,14 @@ QState *LifeCycle::makeState(QState *parentState, const QString &animationFileNa topLevel->setInitialState(frameState); } else { connectByAnimation(previousState, frameState, - new QSignalTransition(m_machine, SIGNAL(animationsFinished()))); + new QSignalTransition(previousState, SIGNAL(polished()))); } previousState = frameState; } // Loop connectByAnimation(previousState, topLevel->initialState(), - new QSignalTransition(m_machine, SIGNAL(animationsFinished()))); + new QSignalTransition(previousState, SIGNAL(polished()))); return topLevel; diff --git a/examples/animation/stickman/lifecycle.h b/examples/animation/stickman/lifecycle.h index 437e935..e520402 100644 --- a/examples/animation/stickman/lifecycle.h +++ b/examples/animation/stickman/lifecycle.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef LIFECYCLE_H #define LIFECYCLE_H @@ -17,7 +58,6 @@ public: ~LifeCycle(); void setDeathAnimation(const QString &fileName); - void setResetKey(Qt::Key key); void addActivity(const QString &fileName, Qt::Key key); void start(); diff --git a/examples/animation/stickman/main.cpp b/examples/animation/stickman/main.cpp index 62860ec..62d8252 100644 --- a/examples/animation/stickman/main.cpp +++ b/examples/animation/stickman/main.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "animation.h" #include "node.h" #include "lifecycle.h" @@ -23,7 +64,6 @@ int main(int argc, char **argv) "<li>Press <font color=\"purple\">J</font> to make the stickman jump.</li>" "<li>Press <font color=\"purple\">D</font> to make the stickman dance.</li>" "<li>Press <font color=\"purple\">C</font> to make him chill out.</li>" - "<li>Press <font color=\"purple\">Return</font> to make him return to his original position.</li>" "<li>When you are done, press <font color=\"purple\">Escape</font>.</li>" "</i></p>" "<p>If he is unlucky, the stickman will get struck by lightning, and never jump, dance or chill out again." @@ -46,7 +86,6 @@ int main(int argc, char **argv) view->setSceneRect(scene->sceneRect()); LifeCycle *cycle = new LifeCycle(stickMan, view); - cycle->setResetKey(Qt::Key_Return); cycle->setDeathAnimation("animations/dead"); cycle->addActivity("animations/jumping", Qt::Key_J); diff --git a/examples/animation/stickman/node.cpp b/examples/animation/stickman/node.cpp index 5932b60..ed18108 100644 --- a/examples/animation/stickman/node.cpp +++ b/examples/animation/stickman/node.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "node.h" #include "stickman.h" @@ -48,4 +89,4 @@ void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { m_dragging = false; -}
\ No newline at end of file +} diff --git a/examples/animation/stickman/node.h b/examples/animation/stickman/node.h index e9e9190..72eae87 100644 --- a/examples/animation/stickman/node.h +++ b/examples/animation/stickman/node.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef NODE_H #define NODE_H diff --git a/examples/animation/stickman/stickman.cpp b/examples/animation/stickman/stickman.cpp index 1393836..5eb392f 100644 --- a/examples/animation/stickman/stickman.cpp +++ b/examples/animation/stickman/stickman.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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 "stickman.h" #include "node.h" diff --git a/examples/animation/stickman/stickman.h b/examples/animation/stickman/stickman.h index e659cdb..46863a3 100644 --- a/examples/animation/stickman/stickman.h +++ b/examples/animation/stickman/stickman.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + #ifndef STICKMAN_H #define STICKMAN_H diff --git a/examples/animation/sub-attaq/animationmanager.cpp b/examples/animation/sub-attaq/animationmanager.cpp index 9f99426..5b9282a 100644 --- a/examples/animation/sub-attaq/animationmanager.cpp +++ b/examples/animation/sub-attaq/animationmanager.cpp @@ -48,7 +48,7 @@ #else # include <QtCore/QAbstractAnimation> #endif -#include <QDebug> +#include <QtCore/QDebug> // the universe's only animation manager AnimationManager *AnimationManager::instance = 0; diff --git a/examples/animation/sub-attaq/animationmanager.h b/examples/animation/sub-attaq/animationmanager.h index fe92680..69ec3d7 100644 --- a/examples/animation/sub-attaq/animationmanager.h +++ b/examples/animation/sub-attaq/animationmanager.h @@ -42,7 +42,7 @@ #ifndef ANIMATIONMANAGER_H #define ANIMATIONMANAGER_H -#include <QObject> +#include <QtCore/QObject> class QAbstractAnimation; diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp index 633e1b1..143cf94 100644 --- a/examples/animation/sub-attaq/boat.cpp +++ b/examples/animation/sub-attaq/boat.cpp @@ -56,14 +56,15 @@ # include "qhistorystate.h" # include "qfinalstate.h" # include "qstate.h" +# include "qpauseanimation.h" #include "qsequentialanimationgroup.h" #else -#include <QPropertyAnimation> -#include <QStateMachine> -#include <QHistoryState> -#include <QFinalState> -#include <QState> -#include <QSequentialAnimationGroup> +#include <QtCore/QPropertyAnimation> +#include <QtCore/QStateMachine> +#include <QtCore/QHistoryState> +#include <QtCore/QFinalState> +#include <QtCore/QState> +#include <QtCore/QSequentialAnimationGroup> #endif static QAbstractAnimation *setupDestroyAnimation(Boat *boat) @@ -98,10 +99,30 @@ static QAbstractAnimation *setupDestroyAnimation(Boat *boat) anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); anim4->setDuration(100); anim4->setEndValue(1); + CustomPropertyAnimation *anim5 = new CustomPropertyAnimation(boat); + anim5->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim5->setDuration(100); + anim5->setEndValue(0); + CustomPropertyAnimation *anim6 = new CustomPropertyAnimation(boat); + anim6->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim6->setDuration(100); + anim6->setEndValue(0); + CustomPropertyAnimation *anim7 = new CustomPropertyAnimation(boat); + anim7->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim7->setDuration(100); + anim7->setEndValue(0); + CustomPropertyAnimation *anim8 = new CustomPropertyAnimation(boat); + anim8->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim8->setDuration(100); + anim8->setEndValue(0); group->addAnimation(anim1); group->addAnimation(anim2); group->addAnimation(anim3); group->addAnimation(anim4); + group->addAnimation(anim5); + group->addAnimation(anim6); + group->addAnimation(anim7); + group->addAnimation(anim8); #else // work around for a bug where we don't transition if the duration is zero. QtPauseAnimation *anim = new QtPauseAnimation(group); @@ -125,37 +146,39 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //The movement animation used to animate the boat movementAnimation = new QPropertyAnimation(this, "pos"); - AnimationManager::self()->registerAnimation(movementAnimation); + + //The movement animation used to animate the boat + destroyAnimation = setupDestroyAnimation(this); //We setup the state machien of the boat - QStateMachine *machine = new QStateMachine(this); + machine = new QStateMachine(this); QState *moving = new QState(machine->rootState()); - StopState *stopState = new StopState(this,moving); + StopState *stopState = new StopState(this, moving); machine->setInitialState(moving); moving->setInitialState(stopState); - MoveStateRight *moveStateRight = new MoveStateRight(this,moving); - MoveStateLeft *moveStateLeft = new MoveStateLeft(this,moving); - LaunchStateRight *launchStateRight = new LaunchStateRight(this,machine->rootState()); - LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this,machine->rootState()); + MoveStateRight *moveStateRight = new MoveStateRight(this, moving); + MoveStateLeft *moveStateLeft = new MoveStateLeft(this, moving); + LaunchStateRight *launchStateRight = new LaunchStateRight(this, machine->rootState()); + LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this, machine->rootState()); //then setup the transitions for the rightMove state - KeyStopTransition *leftStopRight = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyStopTransition *leftStopRight = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Left); leftStopRight->setTargetState(stopState); - KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Left); leftMoveRight->setTargetState(moveStateRight); - KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveRight->setTargetState(moveStateRight); - KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveStop->setTargetState(moveStateRight); //then setup the transitions for the leftMove state - KeyStopTransition *rightStopLeft = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyStopTransition *rightStopLeft = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Right); rightStopLeft->setTargetState(stopState); - KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveLeft->setTargetState(moveStateLeft); - KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); leftMoveLeft->setTargetState(moveStateLeft); - KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); leftMoveStop->setTargetState(moveStateLeft); //We set up the right move state @@ -175,17 +198,17 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) moveStateRight->addTransition(movementAnimation, SIGNAL(finished()), stopState); //We set up the keys for dropping bombs - KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireLeft->setTargetState(launchStateRight); - KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireRight->setTargetState(launchStateRight); - KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireStop->setTargetState(launchStateRight); - KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireLeft->setTargetState(launchStateLeft); - KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireRight->setTargetState(launchStateLeft); - KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireMove->setTargetState(launchStateLeft); //We set up transitions for fire up @@ -199,7 +222,7 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) stopState->addTransition(downFireMove); //Finally the launch state should come back to its original state - QHistoryState *historyState = moving->addHistoryState(); + QHistoryState *historyState = new QHistoryState(moving); launchStateLeft->addTransition(historyState); launchStateRight->addTransition(historyState); @@ -207,7 +230,7 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //This state play the destroyed animation QAnimationState *destroyedState = new QAnimationState(machine->rootState()); - destroyedState->setAnimation(setupDestroyAnimation(this)); + destroyedState->setAnimation(destroyAnimation); //Play a nice animation when the boat is destroyed moving->addTransition(this, SIGNAL(boatDestroyed()),destroyedState); @@ -218,9 +241,22 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //The machine has finished to be executed, then the boat is dead connect(machine,SIGNAL(finished()),this, SIGNAL(boatExecutionFinished())); +} + +void Boat::run() +{ + //We register animations + AnimationManager::self()->registerAnimation(movementAnimation); + AnimationManager::self()->registerAnimation(destroyAnimation); machine->start(); } +void Boat::stop() +{ + movementAnimation->stop(); + machine->stop(); +} + void Boat::updateBoatMovement() { if (speed == 0 || direction == Boat::None) { diff --git a/examples/animation/sub-attaq/boat.h b/examples/animation/sub-attaq/boat.h index 4c4a737..b28cf20 100644 --- a/examples/animation/sub-attaq/boat.h +++ b/examples/animation/sub-attaq/boat.h @@ -43,13 +43,11 @@ #define __BOAT__H__ //Qt -#include <QObject> -#include <QKeyEvent> - -#include <QDebug> +#include <QtCore/QObject> +#include <QtGui/QKeyEvent> #if defined(QT_EXPERIMENTAL_SOLUTION) -# include "qgraphicswidget.h" +# include "qtgraphicswidget.h" #else # include <QtGui/QGraphicsWidget> #endif @@ -57,6 +55,8 @@ class PixmapItem; class Bomb; class QVariantAnimation; +class QAbstractAnimation; +class QStateMachine; class Boat : public QGraphicsWidget { @@ -71,6 +71,8 @@ public: enum { Type = UserType + 2 }; Boat(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); void destroy(); + void run(); + void stop(); int bombsLaunched() const; void setBombsLaunched(int number); @@ -94,6 +96,8 @@ private: int bombsAlreadyLaunched; Movement direction; QVariantAnimation *movementAnimation; + QAbstractAnimation *destroyAnimation; + QStateMachine *machine; PixmapItem *pixmapItem; }; diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h index 8dacaba..17fbe5c 100644 --- a/examples/animation/sub-attaq/boat_p.h +++ b/examples/animation/sub-attaq/boat_p.h @@ -61,13 +61,10 @@ class KeyStopTransition : public QKeyEventTransition { public: KeyStopTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const @@ -90,13 +87,10 @@ private: { public: KeyMoveTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const @@ -110,7 +104,7 @@ protected: return false; } - void onTransition() + void onTransition(QEvent *) { //We decrease the speed if needed if (key == Qt::Key_Left && boat->currentDirection() == Boat::Right) @@ -131,13 +125,10 @@ private: { public: KeyLaunchTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const @@ -165,7 +156,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentDirection(Boat::Right); boat->updateBoatMovement(); @@ -183,7 +174,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentDirection(Boat::Left); boat->updateBoatMovement(); @@ -201,7 +192,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentSpeed(0); boat->setCurrentDirection(Boat::None); @@ -220,7 +211,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { Bomb *b = new Bomb(); b->setPos(boat->x()+boat->size().width(),boat->y()); @@ -242,7 +233,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { Bomb *b = new Bomb(); b->setPos(boat->x() - b->size().width(), boat->y()); diff --git a/examples/animation/sub-attaq/custompropertyanimation.cpp b/examples/animation/sub-attaq/custompropertyanimation.cpp index 45997af..f7ab269 100644 --- a/examples/animation/sub-attaq/custompropertyanimation.cpp +++ b/examples/animation/sub-attaq/custompropertyanimation.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "custompropertyanimation.h" -#include "custompropertyanimation_p.h" // Qt #include <QtCore/qdebug.h> @@ -48,23 +47,8 @@ QT_BEGIN_NAMESPACE -void CustomPropertyAnimationPrivate::initDefaultStartValue() -{ - if (!animProp) - return; - QVariant def = animProp->read(); - if (def.isValid()) - convertValues(def.userType()); - if (animProp && !defaultStartValue.isValid() - && ((currentTime == 0 && (currentIteration || currentIteration == 0)) - || (currentTime == duration && currentIteration == (iterationCount - 1)))) { - setDefaultStartValue(def); - } -} - - CustomPropertyAnimation::CustomPropertyAnimation(QObject *parent) : - QVariantAnimation(*new CustomPropertyAnimationPrivate, parent) + QVariantAnimation(parent), animProp(0) { } @@ -72,13 +56,12 @@ CustomPropertyAnimation::~CustomPropertyAnimation() { } -void CustomPropertyAnimation::setProperty(AbstractProperty *animProp) +void CustomPropertyAnimation::setProperty(AbstractProperty *_animProp) { - Q_D(CustomPropertyAnimation); - if (d->animProp == animProp) + if (animProp == _animProp) return; - delete d->animProp; - d->animProp = animProp; + delete animProp; + animProp = _animProp; } /*! @@ -86,11 +69,10 @@ void CustomPropertyAnimation::setProperty(AbstractProperty *animProp) */ void CustomPropertyAnimation::updateCurrentValue(const QVariant &value) { - Q_D(CustomPropertyAnimation); - if (!d->animProp || state() == QAbstractAnimation::Stopped) + if (!animProp || state() == QAbstractAnimation::Stopped) return; - d->animProp->write(value); + animProp->write(value); } @@ -99,10 +81,29 @@ void CustomPropertyAnimation::updateCurrentValue(const QVariant &value) */ void CustomPropertyAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState) { - Q_D(CustomPropertyAnimation); // Initialize start value - if (oldState == QAbstractAnimation::Stopped) - d->initDefaultStartValue(); + if (oldState == QAbstractAnimation::Stopped) { + if (!animProp) + return; + QVariant def = animProp->read(); + if (def.isValid()) { + const int t = def.userType(); + KeyValues values = keyValues(); + //this ensures that all the keyValues are of type t + for (int i = 0; i < values.count(); ++i) { + QVariantAnimation::KeyValue &pair = values[i]; + if (pair.second.userType() != t) + pair.second.convert(static_cast<QVariant::Type>(t)); + } + //let's now update the key values + setKeyValues(values); + } + + if (animProp && !startValue().isValid() && currentTime() == 0 + || (currentTime() == duration() && currentLoop() == (loopCount() - 1))) { + setStartValue(def); + } + } QVariantAnimation::updateState(oldState, newState); } diff --git a/examples/animation/sub-attaq/custompropertyanimation.h b/examples/animation/sub-attaq/custompropertyanimation.h index ba6ef55..48a50c9 100644 --- a/examples/animation/sub-attaq/custompropertyanimation.h +++ b/examples/animation/sub-attaq/custompropertyanimation.h @@ -49,7 +49,6 @@ #endif class QGraphicsItem; -class CustomPropertyAnimationPrivate; struct AbstractProperty { @@ -111,7 +110,7 @@ public: private: Q_DISABLE_COPY(CustomPropertyAnimation); - Q_DECLARE_PRIVATE(CustomPropertyAnimation); + AbstractProperty *animProp; }; #endif // CUSTOMPROPERTYANIMATION_H diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp index 5dcc034..2a6f83c 100644 --- a/examples/animation/sub-attaq/graphicsscene.cpp +++ b/examples/animation/sub-attaq/graphicsscene.cpp @@ -50,6 +50,7 @@ #include "custompropertyanimation.h" #include "animationmanager.h" #include "qanimationstate.h" +#include "progressitem.h" //Qt #if defined(QT_EXPERIMENTAL_SOLUTION) @@ -60,20 +61,20 @@ #include "qfinalstate.h" #include "qpauseanimation.h" #else -#include <QPropertyAnimation> -#include <QSequentialAnimationGroup> -#include <QParallelAnimationGroup> -#include <QStateMachine> -#include <QFinalState> -#include <QPauseAnimation> +#include <QtCore/QPropertyAnimation> +#include <QtCore/QSequentialAnimationGroup> +#include <QtCore/QParallelAnimationGroup> +#include <QtCore/QStateMachine> +#include <QtCore/QFinalState> +#include <QtCore/QPauseAnimation> #endif -#include <QAction> -#include <QDir> -#include <QApplication> -#include <QMessageBox> -#include <QGraphicsView> -#include <QGraphicsSceneMouseEvent> -#include <QXmlStreamReader> +#include <QtGui/QAction> +#include <QtCore/QDir> +#include <QtGui/QApplication> +#include <QtGui/QMessageBox> +#include <QtGui/QGraphicsView> +#include <QtGui/QGraphicsSceneMouseEvent> +#include <QtCore/QXmlStreamReader> //helper function that creates an animation for position and inserts it into group static CustomPropertyAnimation *addGraphicsItemPosAnimation(QSequentialAnimationGroup *group, @@ -117,6 +118,15 @@ GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode) surfaceItem->setPos(0,sealLevel() - surfaceItem->boundingRect().height()/2); addItem(surfaceItem); + //The item that display score and level + progressItem = new ProgressItem(backgroundItem); + + //We create the boat + boat = new Boat(); + addItem(boat); + boat->setPos(this->width()/2, sealLevel() - boat->size().height()); + boat->hide(); + //parse the xml that contain all data of the game QXmlStreamReader reader; QFile file(QDir::currentPath() + "/data.xml"); @@ -335,17 +345,17 @@ void GraphicsScene::clearScene() { foreach (SubMarine *sub,submarines) { sub->destroy(); - delete sub; + sub->deleteLater(); } foreach (Torpedo *torpedo,torpedos) { torpedo->destroy(); - delete torpedo; + torpedo->deleteLater(); } foreach (Bomb *bomb,bombs) { bomb->destroy(); - delete bomb; + bomb->deleteLater(); } submarines.clear(); @@ -354,10 +364,8 @@ void GraphicsScene::clearScene() AnimationManager::self()->unregisterAllAnimations(); - if (boat) { - delete boat; - boat = 0; - } + boat->stop(); + boat->hide(); } QGraphicsPixmapItem *GraphicsScene::addWelcomeItem(const QPixmap &pm) diff --git a/examples/animation/sub-attaq/graphicsscene.h b/examples/animation/sub-attaq/graphicsscene.h index 875f59f..0840564 100644 --- a/examples/animation/sub-attaq/graphicsscene.h +++ b/examples/animation/sub-attaq/graphicsscene.h @@ -43,13 +43,13 @@ #define __GRAPHICSSCENE__H__ //Qt -#include <QGraphicsScene> -#include <QSet> +#include <QtGui/QGraphicsScene> +#include <QtCore/QSet> #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qstate.h" #else -# include <QState> +# include <QtCore/QState> #endif @@ -58,6 +58,7 @@ class SubMarine; class Torpedo; class Bomb; class PixmapItem; +class ProgressItem; class QAction; class GraphicsScene : public QGraphicsScene @@ -109,6 +110,7 @@ private slots: private: Mode mode; PixmapItem *backgroundItem; + ProgressItem *progressItem; QAction * newAction; QAction * quitAction; Boat *boat; @@ -121,8 +123,11 @@ private: friend class PauseState; friend class PlayState; + friend class LevelState; friend class LostState; friend class WinState; + friend class WinTransition; + friend class UpdateScoreTransition; }; #endif //__GRAPHICSSCENE__H__ diff --git a/examples/animation/sub-attaq/mainwindow.cpp b/examples/animation/sub-attaq/mainwindow.cpp index c25b9ef..a166241 100644 --- a/examples/animation/sub-attaq/mainwindow.cpp +++ b/examples/animation/sub-attaq/mainwindow.cpp @@ -47,7 +47,7 @@ #include <QtOpenGL/QtOpenGL> #endif //Qt -#include <QGraphicsView> +#include <QtGui/QGraphicsView> MainWindow::MainWindow() : QMainWindow(0) { diff --git a/examples/animation/sub-attaq/mainwindow.h b/examples/animation/sub-attaq/mainwindow.h index 6289b3f..72d1324 100644 --- a/examples/animation/sub-attaq/mainwindow.h +++ b/examples/animation/sub-attaq/mainwindow.h @@ -43,7 +43,7 @@ #define __MAINWINDOW__H__ //Qt -#include <QMainWindow> +#include <QtGui/QMainWindow> class GraphicsScene; class QGraphicsView; diff --git a/examples/animation/sub-attaq/pixmapitem.cpp b/examples/animation/sub-attaq/pixmapitem.cpp index aa8b552..22a363f 100644 --- a/examples/animation/sub-attaq/pixmapitem.cpp +++ b/examples/animation/sub-attaq/pixmapitem.cpp @@ -43,7 +43,7 @@ #include "pixmapitem.h" //Qt -#include <QDir> +#include <QtCore/QDir> PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent) : QGraphicsPixmapItem(parent),name(fileName) { diff --git a/examples/animation/sub-attaq/pixmapitem.h b/examples/animation/sub-attaq/pixmapitem.h index f3c1a41..31022c1 100644 --- a/examples/animation/sub-attaq/pixmapitem.h +++ b/examples/animation/sub-attaq/pixmapitem.h @@ -46,7 +46,7 @@ #include "graphicsscene.h" //Qt -#include <QGraphicsPixmapItem> +#include <QtGui/QGraphicsPixmapItem> class PixmapItem : public QGraphicsPixmapItem { diff --git a/examples/animation/sub-attaq/progressitem.cpp b/examples/animation/sub-attaq/progressitem.cpp new file mode 100644 index 0000000..59ccb9a --- /dev/null +++ b/examples/animation/sub-attaq/progressitem.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 "progressitem.h" +#include "pixmapitem.h" + +ProgressItem::ProgressItem (QGraphicsItem * parent) + : QGraphicsTextItem(parent), currentLevel(1), currentScore(0) +{ + setFont(QFont("Comic Sans MS")); + setPos(parentItem()->boundingRect().topRight() - QPointF(180, -5)); +} + +void ProgressItem::setLevel(int level) +{ + currentLevel = level; + updateProgress(); +} + +void ProgressItem::setScore(int score) +{ + currentScore = score; + updateProgress(); +} + +void ProgressItem::updateProgress() +{ + setHtml(QString("Level : %1 Score : %2").arg(currentLevel).arg(currentScore)); +} diff --git a/src/corelib/statemachine/qstatefinishedevent.h b/examples/animation/sub-attaq/progressitem.h index c2f81f7..7b8db4d 100644 --- a/src/corelib/statemachine/qstatefinishedevent.h +++ b/examples/animation/sub-attaq/progressitem.h @@ -39,32 +39,23 @@ ** ****************************************************************************/ -#ifndef QSTATEFINISHEDEVENT_H -#define QSTATEFINISHEDEVENT_H +#ifndef PROGRESSITEM_H +#define PROGRESSITEM_H -#include <QtCore/qcoreevent.h> +//Qt +#include <QtGui/QGraphicsTextItem> -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QState; - -class Q_CORE_EXPORT QStateFinishedEvent : public QEvent +class ProgressItem : public QGraphicsTextItem { public: - QStateFinishedEvent(QState *state); - ~QStateFinishedEvent(); - - QState *state() const; + ProgressItem(QGraphicsItem * parent = 0); + void setLevel(int level); + void setScore(int score); private: - QState *m_state; - void *d; + void updateProgress(); + int currentLevel; + int currentScore; }; -QT_END_NAMESPACE - -#endif +#endif // PROGRESSITEM_H diff --git a/examples/animation/sub-attaq/qanimationstate.cpp b/examples/animation/sub-attaq/qanimationstate.cpp index 70285a8..0f30ac2 100644 --- a/examples/animation/sub-attaq/qanimationstate.cpp +++ b/examples/animation/sub-attaq/qanimationstate.cpp @@ -43,11 +43,12 @@ #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qstate.h" +# include "qstate_p.h" #else # include <QtCore/qstate.h> +# include <private/qstate_p.h> #endif -#include <private/qstate_p.h> QT_BEGIN_NAMESPACE @@ -145,7 +146,7 @@ QAbstractAnimation* QAnimationState::animation() const /*! \reimp */ -void QAnimationState::onEntry() +void QAnimationState::onEntry(QEvent *) { Q_D(QAnimationState); if (d->animation) @@ -155,7 +156,7 @@ void QAnimationState::onEntry() /*! \reimp */ -void QAnimationState::onExit() +void QAnimationState::onExit(QEvent *) { Q_D(QAnimationState); if (d->animation) diff --git a/examples/animation/sub-attaq/qanimationstate.h b/examples/animation/sub-attaq/qanimationstate.h index fda1534..88c0a6d 100644 --- a/examples/animation/sub-attaq/qanimationstate.h +++ b/examples/animation/sub-attaq/qanimationstate.h @@ -60,7 +60,7 @@ QT_MODULE(Gui) class QAnimationStatePrivate; -class Q_GUI_EXPORT QAnimationState : public QState +class QAnimationState : public QState { Q_OBJECT public: @@ -74,8 +74,8 @@ Q_SIGNALS: void animationFinished(); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *); + void onExit(QEvent *); bool event(QEvent *e); private: diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index f476f55..c6af924 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -46,10 +46,11 @@ #include "submarine.h" #include "torpedo.h" #include "animationmanager.h" +#include "progressitem.h" //Qt -#include <QMessageBox> -#include <QGraphicsView> +#include <QtGui/QMessageBox> +#include <QtGui/QGraphicsView> #if defined(QT_EXPERIMENTAL_SOLUTION) #include "qstatemachine.h" #include "qkeyeventtransition.h" @@ -59,7 +60,7 @@ #include <QtCore/QStateMachine> #include <QtGui/QKeyEventTransition> #include <QtCore/QSignalEvent> -#include <QFinalState> +#include <QtCore/QFinalState> #endif PlayState::PlayState(GraphicsScene *scene, QState *parent) @@ -75,33 +76,37 @@ PlayState::~PlayState() { } -void PlayState::onEntry() +void PlayState::onEntry(QEvent *) { //We are now playing? if (machine) { machine->stop(); scene->clearScene(); + currentLevel = 0; + score = 0; delete machine; } machine = new QStateMachine(this); //This state is when player is playing - QState *playState = new QState(machine->rootState()); + LevelState *levelState = new LevelState(scene, this, machine->rootState()); - initializeLevel(); + //This state is when the player is actually playing but the game is not paused + QState *playingState = new QState(levelState); + levelState->setInitialState(playingState); //This state is when the game is paused - PauseState *pauseState = new PauseState(scene, machine->rootState()); + PauseState *pauseState = new PauseState(scene, levelState); //We have one view, it receive the key press event QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); pressPplay->setTargetState(pauseState); QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); - pressPpause->setTargetState(playState); + pressPpause->setTargetState(playingState); //Pause "P" is triggered, the player pause the game - playState->addTransition(pressPplay); + playingState->addTransition(pressPplay); //To get back playing when the game has been paused pauseState->addTransition(pressPpause); @@ -113,49 +118,67 @@ void PlayState::onEntry() WinState *winState = new WinState(scene, this, machine->rootState()); //The boat has been destroyed then the game is finished - playState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState); + levelState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState); //This transition check if we won or not WinTransition *winTransition = new WinTransition(scene, this, winState); //The boat has been destroyed then the game is finished - playState->addTransition(winTransition); + levelState->addTransition(winTransition); //This state is an animation when the score changed - UpdateScoreState *scoreState = new UpdateScoreState(this, machine->rootState()); + UpdateScoreState *scoreState = new UpdateScoreState(this, levelState); //This transition update the score when a submarine die - UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, scoreState); + UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, levelState); + scoreTransition->setTargetState(scoreState); //The boat has been destroyed then the game is finished - playState->addTransition(scoreTransition); + playingState->addTransition(scoreTransition); //We go back to play state - scoreState->addTransition(playState); + scoreState->addTransition(playingState); //We start playing!!! - machine->setInitialState(playState); + machine->setInitialState(levelState); //Final state QFinalState *final = new QFinalState(machine->rootState()); - //We win we should reach the final state - winState->addFinishedTransition(final); + //This transition is triggered when the player press space after completing a level + CustomSpaceTransition *spaceTransition = new CustomSpaceTransition(scene->views().at(0), this, QEvent::KeyPress, Qt::Key_Space); + spaceTransition->setTargetState(levelState); + winState->addTransition(spaceTransition); //We lost we should reach the final state - lostState->addFinishedTransition(final); + lostState->addTransition(lostState, SIGNAL(finished()), final); machine->start(); } -void PlayState::initializeLevel() +LevelState::LevelState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) { - scene->boat = new Boat(); - scene->addItem(scene->boat); - scene->setFocusItem(scene->boat,Qt::OtherFocusReason); +} +void LevelState::onEntry(QEvent *) +{ + initializeLevel(); +} + +void LevelState::initializeLevel() +{ + //we re-init the boat scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height()); + scene->boat->setCurrentSpeed(0); + scene->boat->setCurrentDirection(Boat::None); + scene->boat->setBombsLaunched(0); + scene->boat->show(); + scene->setFocusItem(scene->boat,Qt::OtherFocusReason); + scene->boat->run(); + + scene->progressItem->setScore(game->score); + scene->progressItem->setLevel(game->currentLevel + 1); - GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(currentLevel); + GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(game->currentLevel); for (int i = 0; i < currentLevelDescription.submarines.size(); ++i ) { @@ -179,12 +202,12 @@ void PlayState::initializeLevel() PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent),scene(scene) { } -void PauseState::onEntry() +void PauseState::onEntry(QEvent *) { AnimationManager::self()->pauseAll(); scene->boat->setEnabled(false); } -void PauseState::onExit() +void PauseState::onExit(QEvent *) { AnimationManager::self()->resumeAll(); scene->boat->setEnabled(true); @@ -196,7 +219,7 @@ LostState::LostState(GraphicsScene *scene, PlayState *game, QState *parent) : QS { } -void LostState::onEntry() +void LostState::onEntry(QEvent *) { //The message to display QString message = QString("You lose on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); @@ -219,14 +242,14 @@ WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QSta { } -void WinState::onEntry() +void WinState::onEntry(QEvent *) { //We clear the scene scene->clearScene(); QString message; if (scene->levelsData.size() - 1 != game->currentLevel) { - message = QString("You win the level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); + message = QString("You win the level %1. Your score is %2.\nPress Space to continue after closing this dialog.").arg(game->currentLevel+1).arg(game->score); //We increment the level number game->currentLevel++; } else { @@ -246,16 +269,15 @@ UpdateScoreState::UpdateScoreState(PlayState *game, QState *parent) : QState(par { this->game = game; } -void UpdateScoreState::onEntry() +void UpdateScoreState::onEntry(QEvent *e) { - //### Make a nice anim to update the score in the scene - QState::onEntry(); + QState::onEntry(e); } /** Win transition */ UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int)), QList<QAbstractState*>() << target), - game(game) + game(game), scene(scene) { } @@ -266,6 +288,7 @@ bool UpdateScoreTransition::eventTest(QEvent *event) const else { QSignalEvent *se = static_cast<QSignalEvent*>(event); game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); return true; } } @@ -273,7 +296,7 @@ bool UpdateScoreTransition::eventTest(QEvent *event) const /** Win transition */ WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int)), QList<QAbstractState*>() << target), - game(game) + game(game), scene(scene) { } @@ -284,6 +307,26 @@ bool WinTransition::eventTest(QEvent *event) const else { QSignalEvent *se = static_cast<QSignalEvent*>(event); game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); return true; } } + +/** Space transition */ +CustomSpaceTransition::CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key) + : QKeyEventTransition(widget, type, key), + game(game) +{ +} + +bool CustomSpaceTransition::eventTest(QEvent *event) const +{ + Q_UNUSED(event); + if (!QKeyEventTransition::eventTest(event)) + return false; + if (game->currentLevel != 0) + return true; + else + return false; + +} diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h index 52d4ffa..27beb71 100644 --- a/examples/animation/sub-attaq/states.h +++ b/examples/animation/sub-attaq/states.h @@ -47,12 +47,14 @@ #include "qstate.h" #include "qsignaltransition.h" #include "qpropertyanimation.h" +#include "qkeyeventtransition.h" #else -#include <QState> -#include <QSignalTransition> -#include <QPropertyAnimation> +#include <QtCore/QState> +#include <QtCore/QSignalTransition> +#include <QtCore/QPropertyAnimation> +# include <QtGui/QKeyEventTransition> #endif -#include <QSet> +#include <QtCore/QSet> class GraphicsScene; class Boat; @@ -64,10 +66,9 @@ class PlayState : public QState public: PlayState(GraphicsScene *scene, QState *parent = 0); ~PlayState(); - void initializeLevel(); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; @@ -79,8 +80,22 @@ private : friend class UpdateScoreState; friend class UpdateScoreTransition; friend class WinTransition; + friend class CustomSpaceTransition; friend class WinState; friend class LostState; + friend class LevelState; +}; + +class LevelState : public QState +{ +public: + LevelState(GraphicsScene *scene, PlayState *game, QState *parent = 0); +protected: + void onEntry(QEvent *); +private : + void initializeLevel(); + GraphicsScene *scene; + PlayState *game; }; class PauseState : public QState @@ -89,8 +104,8 @@ public: PauseState(GraphicsScene *scene, QState *parent = 0); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *); + void onExit(QEvent *); private : GraphicsScene *scene; Boat *boat; @@ -102,7 +117,7 @@ public: LostState(GraphicsScene *scene, PlayState *game, QState *parent = 0); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; PlayState *game; @@ -114,7 +129,7 @@ public: WinState(GraphicsScene *scene, PlayState *game, QState *parent = 0); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; PlayState *game; @@ -125,7 +140,7 @@ class UpdateScoreState : public QState public: UpdateScoreState(PlayState *game, QState *parent); protected: - void onEntry(); + void onEntry(QEvent *); private: QPropertyAnimation *scoreAnimation; PlayState *game; @@ -140,6 +155,7 @@ protected: virtual bool eventTest(QEvent *event) const; private: PlayState * game; + GraphicsScene *scene; }; //These transtion test if we have won the game @@ -151,6 +167,19 @@ protected: virtual bool eventTest(QEvent *event) const; private: PlayState * game; + GraphicsScene *scene; +}; + +//These transtion is true if one level has been completed and the player want to continue + class CustomSpaceTransition : public QKeyEventTransition +{ +public: + CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key); +protected: + virtual bool eventTest(QEvent *event) const; +private: + PlayState *game; + int key; }; #endif // STATES_H diff --git a/examples/animation/sub-attaq/sub-attaq.pro b/examples/animation/sub-attaq/sub-attaq.pro index 07c4d06..961a9b5 100644 --- a/examples/animation/sub-attaq/sub-attaq.pro +++ b/examples/animation/sub-attaq/sub-attaq.pro @@ -2,10 +2,10 @@ # Automatically generated by qmake (2.01a) Thu Oct 9 10:53:30 2008 # ##################################################################### TEMPLATE = app -TARGET = +TARGET = DEPENDPATH += . INCLUDEPATH += . -QT+= xml +QT += xml contains(QT_CONFIG, opengl):QT += opengl # Input @@ -20,10 +20,9 @@ HEADERS += boat.h \ states.h \ boat_p.h \ submarine_p.h \ - custompropertyanimation_p.h \ custompropertyanimation.h \ - qanimationstate.h - + qanimationstate.h \ + progressitem.h SOURCES += boat.cpp \ bomb.cpp \ main.cpp \ @@ -35,6 +34,6 @@ SOURCES += boat.cpp \ animationmanager.cpp \ states.cpp \ custompropertyanimation.cpp \ - qanimationstate.cpp - + qanimationstate.cpp \ + progressitem.cpp RESOURCES += subattaq.qrc diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp index e64ffdd..0f03efc 100644 --- a/examples/animation/sub-attaq/submarine.cpp +++ b/examples/animation/sub-attaq/submarine.cpp @@ -50,15 +50,16 @@ #include "qanimationstate.h" #if defined(QT_EXPERIMENTAL_SOLUTION) -#include "qpropertyanimation.h" -#include "qstatemachine.h" -#include "qfinalstate.h" -#include "qsequentialanimationgroup.h" +# include "qpropertyanimation.h" +# include "qstatemachine.h" +# include "qfinalstate.h" +# include "qsequentialanimationgroup.h" +# include "qpauseanimation.h" #else -#include <QPropertyAnimation> -#include <QStateMachine> -#include <QFinalState> -#include <QSequentialAnimationGroup> +#include <QtCore/QPropertyAnimation> +#include <QtCore/QStateMachine> +#include <QtCore/QFinalState> +#include <QtCore/QSequentialAnimationGroup> #endif static QAbstractAnimation *setupDestroyAnimation(SubMarine *sub) @@ -125,15 +126,15 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * QState *moving = new QState(machine->rootState()); //This state is when the boat is moving from left to right - MovementState *movement = new MovementState(this,moving); + MovementState *movement = new MovementState(this, moving); //This state is when the boat is moving from left to right - ReturnState *rotation = new ReturnState(this,moving); + ReturnState *rotation = new ReturnState(this, moving); //This is the initial state of the moving root state moving->setInitialState(movement); - movement->addTransition(this, SIGNAL(subMarineStateChanged()),moving); + movement->addTransition(this, SIGNAL(subMarineStateChanged()), moving); //This is the initial state of the machine machine->setInitialState(moving); @@ -152,7 +153,7 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * destroyedState->setAnimation(setupDestroyAnimation(this)); //Play a nice animation when the submarine is destroyed - moving->addTransition(this, SIGNAL(subMarineDestroyed()),destroyedState); + moving->addTransition(this, SIGNAL(subMarineDestroyed()), destroyedState); //Transition to final state when the destroyed animation is finished destroyedState->addTransition(destroyedState, SIGNAL(animationFinished()), final); diff --git a/examples/animation/sub-attaq/submarine.h b/examples/animation/sub-attaq/submarine.h index 562b4cf..7ee587d 100644 --- a/examples/animation/sub-attaq/submarine.h +++ b/examples/animation/sub-attaq/submarine.h @@ -47,8 +47,8 @@ #include "qvariantanimation.h" #include "qgraphicswidget.h" #else -#include <QVariantAnimation> -#include <QGraphicsWidget> +#include <QtCore/QVariantAnimation> +#include <QtGui/QGraphicsWidget> #endif class PixmapItem; diff --git a/examples/animation/sub-attaq/submarine_p.h b/examples/animation/sub-attaq/submarine_p.h index 354a406..c76d991 100644 --- a/examples/animation/sub-attaq/submarine_p.h +++ b/examples/animation/sub-attaq/submarine_p.h @@ -51,9 +51,9 @@ #if defined(QT_EXPERIMENTAL_SOLUTION) #include "qpropertyanimation.h" #else -#include <QPropertyAnimation> +#include <QtCore/QPropertyAnimation> #endif -#include <QGraphicsScene> +#include <QtGui/QGraphicsScene> //This state is describing when the boat is moving right class MovementState : public QAnimationState @@ -77,7 +77,7 @@ protected slots: } protected: - void onEntry() + void onEntry(QEvent *e) { if (submarine->currentDirection() == SubMarine::Left) { movementAnimation->setEndValue(QPointF(0,submarine->y())); @@ -88,7 +88,7 @@ protected: movementAnimation->setDuration((submarine->scene()->width()-submarine->size().width()-submarine->x())/submarine->currentSpeed()*12); } movementAnimation->setStartValue(submarine->pos()); - QAnimationState::onEntry(); + QAnimationState::onEntry(e); } private: @@ -109,19 +109,19 @@ public: } protected: - void onEntry() + void onEntry(QEvent *e) { returnAnimation->stop(); returnAnimation->setStartValue(submarine->yRotation()); returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.); returnAnimation->setDuration(500); - QAnimationState::onEntry(); + QAnimationState::onEntry(e); } - void onExit() + void onExit(QEvent *e) { submarine->currentDirection() == SubMarine::Right ? submarine->setCurrentDirection(SubMarine::Left) : submarine->setCurrentDirection(SubMarine::Right); - QAnimationState::onExit(); + QAnimationState::onExit(e); } private: diff --git a/examples/animation/sub-attaq/torpedo.cpp b/examples/animation/sub-attaq/torpedo.cpp index b24948d..88f1112 100644 --- a/examples/animation/sub-attaq/torpedo.cpp +++ b/examples/animation/sub-attaq/torpedo.cpp @@ -52,9 +52,9 @@ #include "qstatemachine.h" #include "qfinalstate.h" #else -#include <QPropertyAnimation> -#include <QStateMachine> -#include <QFinalState> +#include <QtCore/QPropertyAnimation> +#include <QtCore/QStateMachine> +#include <QtCore/QFinalState> #endif Torpedo::Torpedo(QGraphicsItem * parent, Qt::WindowFlags wFlags) diff --git a/examples/animation/sub-attaq/torpedo.h b/examples/animation/sub-attaq/torpedo.h index 33bbc04..2e44e41 100644 --- a/examples/animation/sub-attaq/torpedo.h +++ b/examples/animation/sub-attaq/torpedo.h @@ -43,13 +43,13 @@ #define __TORPEDO__H__ //Qt -#include <QObject> +#include <QtCore/QObject> #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qvariantanimation.h" # include "qgraphicswidget.h" #else -# include <QVariantAnimation> +# include <QtCore/QVariantAnimation> # include <QtGui/QGraphicsWidget> #endif diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp index d01822f..ea8e692 100644 --- a/examples/statemachine/clockticking/main.cpp +++ b/examples/statemachine/clockticking/main.cpp @@ -44,7 +44,7 @@ #ifdef QT_STATEMACHINE_SOLUTION #include <qstatemachine.h> #include <qstate.h> -#include <qtransition.h> +#include <qabstracttransition.h> #endif class ClockEvent : public QEvent @@ -57,51 +57,43 @@ public: class ClockState : public QState { public: - ClockState(QStateMachine *machine, QState *parent) - : QState(parent), m_machine(machine) {} + ClockState(QState *parent) + : QState(parent) {} protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { fprintf(stdout, "ClockState entered; posting the initial tick\n"); - m_machine->postEvent(new ClockEvent()); + machine()->postEvent(new ClockEvent()); } - -private: - QStateMachine *m_machine; }; class ClockTransition : public QAbstractTransition { public: - ClockTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) { } + ClockTransition() {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n"); - m_machine->postEvent(new ClockEvent(), 1000); + machine()->postEvent(new ClockEvent(), 1000); } - -private: - QStateMachine *m_machine; }; class ClockListener : public QAbstractTransition { public: - ClockListener() - : QAbstractTransition() {} + ClockListener() {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "ClockListener heard a tick!\n"); } @@ -112,12 +104,12 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); QStateMachine machine; - QState *group = new QState(QState::ParallelGroup); + QState *group = new QState(QState::ParallelStates); group->setObjectName("group"); - ClockState *clock = new ClockState(&machine, group); + ClockState *clock = new ClockState(group); clock->setObjectName("clock"); - clock->addTransition(new ClockTransition(&machine)); + clock->addTransition(new ClockTransition()); QState *listener = new QState(group); listener->setObjectName("listener"); diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp index 24b823c..0afff66 100644 --- a/examples/statemachine/composition/main.cpp +++ b/examples/statemachine/composition/main.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) s1_timer->setObjectName("s1_timer"); QTimer t1; t1.setInterval(2000); - s1_timer->invokeMethodOnEntry(&t1, "start"); + 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); @@ -80,17 +80,17 @@ int main(int argc, char **argv) s2_timer->setObjectName("s2_timer"); QTimer t2; t2.setInterval(2000); - s2_timer->invokeMethodOnEntry(&t2, "start"); + 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->addFinishedTransition(s2); + s1->addTransition(s1, SIGNAL(finished()), s2); QFinalState *s3 = new QFinalState(); s3->setObjectName("s3"); - s2->addFinishedTransition(s3); + s2->addTransition(s2, SIGNAL(finished()), s3); machine.addState(s1); machine.addState(s2); diff --git a/examples/statemachine/errorstate/errorstate.pro b/examples/statemachine/errorstate/errorstate.pro new file mode 100644 index 0000000..b93a691 --- /dev/null +++ b/examples/statemachine/errorstate/errorstate.pro @@ -0,0 +1,13 @@ +###################################################################### +# Automatically generated by qmake (2.01a) on 22. apr 14:11:33 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += C:/dev/kinetic/examples/statemachine/errorstate/. . + +# Input +HEADERS += mainwindow.h plugin.h tankitem.h rocketitem.h gameitem.h +SOURCES += main.cpp mainwindow.cpp tankitem.cpp rocketitem.cpp gameitem.cpp +CONFIG += console diff --git a/examples/statemachine/errorstate/gameitem.cpp b/examples/statemachine/errorstate/gameitem.cpp new file mode 100644 index 0000000..1a2af71 --- /dev/null +++ b/examples/statemachine/errorstate/gameitem.cpp @@ -0,0 +1,88 @@ +#include "gameitem.h" + +#include <QGraphicsScene> +#include <QDebug> + +GameItem::GameItem(QObject *parent) : QObject(parent) +{ +} + +QPointF GameItem::tryMove(const QPointF &requestedPosition, QLineF *collidedLine, + QGraphicsItem **collidedItem) const +{ + QLineF movementPath(pos(), requestedPosition); + + qreal cannonLength = 0.0; + { + QPointF p1 = boundingRect().center(); + QPointF p2 = QPointF(boundingRect().right() + 10.0, p1.y()); + + cannonLength = QLineF(mapToScene(p1), mapToScene(p2)).length(); + } + + movementPath.setLength(movementPath.length() + cannonLength); + + QRectF boundingRectPath(QPointF(qMin(movementPath.x1(), movementPath.x2()), qMin(movementPath.y1(), movementPath.y2())), + QPointF(qMax(movementPath.x1(), movementPath.x2()), qMax(movementPath.y1(), movementPath.y2()))); + + QList<QGraphicsItem *> itemsInRect = scene()->items(boundingRectPath, Qt::IntersectsItemBoundingRect); + + QPointF nextPoint = requestedPosition; + QRectF sceneRect = scene()->sceneRect(); + + foreach (QGraphicsItem *item, itemsInRect) { + if (item == static_cast<const QGraphicsItem *>(this)) + continue; + + QPolygonF mappedBoundingRect = item->mapToScene(item->boundingRect()); + for (int i=0; i<mappedBoundingRect.size(); ++i) { + QPointF p1 = mappedBoundingRect.at(i == 0 ? mappedBoundingRect.size()-1 : i-1); + QPointF p2 = mappedBoundingRect.at(i); + + QLineF rectLine(p1, p2); + QPointF intersectionPoint; + QLineF::IntersectType intersectType = movementPath.intersect(rectLine, &intersectionPoint); + + if (intersectType == QLineF::BoundedIntersection) { + movementPath.setP2(intersectionPoint); + movementPath.setLength(movementPath.length() - cannonLength); + nextPoint = movementPath.p2(); + + if (collidedLine != 0) + *collidedLine = rectLine; + + if (collidedItem != 0) + *collidedItem = item; + } + } + } + + + // Don't go outside of map + if (nextPoint.x() < sceneRect.left()) { + nextPoint.rx() = sceneRect.left(); + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topLeft(), scene()->sceneRect().bottomLeft()); + } + + if (nextPoint.x() > sceneRect.right()) { + nextPoint.rx() = sceneRect.right(); + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topRight(), scene()->sceneRect().bottomRight()); + } + + if (nextPoint.y() < sceneRect.top()) { + nextPoint.ry() = sceneRect.top(); + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topLeft(), scene()->sceneRect().topRight()); + } + + if (nextPoint.y() > sceneRect.bottom()) { + nextPoint.ry() = sceneRect.bottom(); + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().bottomLeft(), scene()->sceneRect().bottomRight()); + } + + return nextPoint; +} + diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/errorstate/gameitem.h new file mode 100644 index 0000000..43b8785 --- /dev/null +++ b/examples/statemachine/errorstate/gameitem.h @@ -0,0 +1,23 @@ +#ifndef GAMEITEM_H +#define GAMEITEM_H + +#include <QGraphicsItem> + +class QLineF; +class GameItem: public QObject, public QGraphicsItem +{ + Q_OBJECT +public: + enum { Type = UserType + 1 }; + int type() const { return Type; } + + GameItem(QObject *parent = 0); + + virtual void idle(qreal elapsed) = 0; + +protected: + QPointF tryMove(const QPointF &requestedPosition, QLineF *collidedLine = 0, + QGraphicsItem **collidedItem = 0) const; +}; + +#endif diff --git a/examples/statemachine/errorstate/main.cpp b/examples/statemachine/errorstate/main.cpp new file mode 100644 index 0000000..26fc1bb --- /dev/null +++ b/examples/statemachine/errorstate/main.cpp @@ -0,0 +1,12 @@ +#include <QApplication> +#include "mainwindow.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + MainWindow mainWindow; + mainWindow.show(); + + return app.exec(); +} diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp new file mode 100644 index 0000000..07719bc --- /dev/null +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -0,0 +1,257 @@ +#include "mainwindow.h" +#include "tankitem.h" +#include "rocketitem.h" +#include "plugin.h" + +#include <QStateMachine> +#include <QGraphicsView> +#include <QAction> +#include <QMenuBar> +#include <QState> +#include <QHistoryState> +#include <QTimer> +#include <QFileDialog> +#include <QPluginLoader> +#include <QApplication> +#include <QInputDialog> +#include <QMessageBox> + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), m_scene(0), m_machine(0), m_runningState(0), m_started(false) +{ + init(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::addWall(const QRectF &wall) +{ + QGraphicsRectItem *item = new QGraphicsRectItem; + item->setRect(wall); + item->setBrush(Qt::darkGreen); + item->setPen(QPen(Qt::black, 0)); + + m_scene->addItem(item); +} + +void MainWindow::init() +{ + setWindowTitle("Pluggable Tank Game"); + + QGraphicsView *view = new QGraphicsView(this); + view->setRenderHints(QPainter::Antialiasing); + setCentralWidget(view); + + m_scene = new QGraphicsScene(this); + view->setScene(m_scene); + + QRectF sceneRect = QRectF(-200.0, -200.0, 400.0, 400.0); + m_scene->setSceneRect(sceneRect); + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().topLeft() + QPointF(15.0, 15.0)); + item->setDirection(45.0); + item->setColor(Qt::red); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().topRight() + QPointF(-15.0, 15.0)); + item->setDirection(135.0); + item->setColor(Qt::green); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().bottomRight() + QPointF(-15.0, -15.0)); + item->setDirection(225.0); + item->setColor(Qt::blue); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().bottomLeft() + QPointF(15.0, -15.0)); + item->setDirection(315.0); + item->setColor(Qt::yellow); + + m_spawns.append(item); + } + + QPointF centerOfMap = sceneRect.center(); + + addWall(QRectF(centerOfMap + QPointF(-50.0, -60.0), centerOfMap + QPointF(50.0, -50.0))); + addWall(QRectF(centerOfMap - QPointF(-50.0, -60.0), centerOfMap - QPointF(50.0, -50.0))); + addWall(QRectF(centerOfMap + QPointF(-50.0, -50.0), centerOfMap + QPointF(-40.0, 50.0))); + addWall(QRectF(centerOfMap - QPointF(-50.0, -50.0), centerOfMap - QPointF(-40.0, 50.0))); + + addWall(QRectF(sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, -10.0), + sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, 100.0))); + addWall(QRectF(sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 10.0), + sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, -100.0))); + addWall(QRectF(sceneRect.topLeft() + QPointF(-10.0, sceneRect.height() / 2.0 - 5.0), + sceneRect.topLeft() + QPointF(100.0, sceneRect.height() / 2.0 + 5.0))); + addWall(QRectF(sceneRect.topRight() + QPointF(10.0, sceneRect.height() / 2.0 - 5.0), + sceneRect.topRight() + QPointF(-100.0, sceneRect.height() / 2.0 + 5.0))); + + + QAction *addTankAction = menuBar()->addAction("&Add tank"); + QAction *runGameAction = menuBar()->addAction("&Run game"); + runGameAction->setObjectName("runGameAction"); + QAction *stopGameAction = menuBar()->addAction("&Stop game"); + menuBar()->addSeparator(); + QAction *quitAction = menuBar()->addAction("&Quit"); + + connect(addTankAction, SIGNAL(triggered()), this, SLOT(addTank())); + connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); + + m_machine = new QStateMachine(this); + QState *stoppedState = new QState(m_machine->rootState()); + stoppedState->setObjectName("stoppedState"); + stoppedState->assignProperty(runGameAction, "enabled", true); + stoppedState->assignProperty(stopGameAction, "enabled", false); + stoppedState->assignProperty(this, "started", false); + m_machine->setInitialState(stoppedState); + + QState *spawnsAvailable = new QState(stoppedState); + spawnsAvailable->setObjectName("spawnsAvailable"); + spawnsAvailable->assignProperty(addTankAction, "enabled", true); + + QState *noSpawnsAvailable = new QState(stoppedState); + noSpawnsAvailable->setObjectName("noSpawnsAvailable"); + noSpawnsAvailable->assignProperty(addTankAction, "enabled", false); + + spawnsAvailable->addTransition(this, SIGNAL(mapFull()), noSpawnsAvailable); + + QHistoryState *hs = new QHistoryState(stoppedState); + hs->setDefaultState(spawnsAvailable); + + stoppedState->setInitialState(hs); + + m_runningState = new QState(QState::ParallelStates, m_machine->rootState()); + m_runningState->setObjectName("runningState"); + m_runningState->assignProperty(addTankAction, "enabled", false); + m_runningState->assignProperty(runGameAction, "enabled", false); + m_runningState->assignProperty(stopGameAction, "enabled", true); + + stoppedState->addTransition(runGameAction, SIGNAL(triggered()), m_runningState); + m_runningState->addTransition(stopGameAction, SIGNAL(triggered()), stoppedState); + + QTimer *timer = new QTimer(this); + timer->setInterval(100); + connect(timer, SIGNAL(timeout()), this, SLOT(runStep())); + connect(m_runningState, SIGNAL(entered()), timer, SLOT(start())); + connect(m_runningState, SIGNAL(exited()), timer, SLOT(stop())); + + m_machine->start(); + m_time.start(); +} + +void MainWindow::runStep() +{ + if (!m_started) { + m_time.restart(); + m_started = true; + } else { + int elapsed = m_time.elapsed(); + if (elapsed > 0) { + m_time.restart(); + qreal elapsedSecs = elapsed / 1000.0; + QList<QGraphicsItem *> items = m_scene->items(); + foreach (QGraphicsItem *item, items) { + if (GameItem *gameItem = qgraphicsitem_cast<GameItem *>(item)) + gameItem->idle(elapsedSecs); + } + } + } +} + +void MainWindow::addRocket() +{ + TankItem *tankItem = qobject_cast<TankItem *>(sender()); + if (tankItem != 0) { + RocketItem *rocketItem = new RocketItem; + + QPointF s = tankItem->mapToScene(QPointF(tankItem->boundingRect().right() + 10.0, + tankItem->boundingRect().center().y())); + rocketItem->setPos(s); + rocketItem->setDirection(tankItem->direction()); + m_scene->addItem(rocketItem); + } +} + +void MainWindow::addTank() +{ + Q_ASSERT(!m_spawns.isEmpty()); + + QDir pluginsDir(qApp->applicationDirPath()); +#if defined(Q_OS_WIN) + if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") + pluginsDir.cdUp(); +#elif defined(Q_OS_MAC) + if (pluginsDir.dirName() == "MacOS") { + pluginsDir.cdUp(); + pluginsDir.cdUp(); + pluginsDir.cdUp(); + } +#endif + + pluginsDir.cd("plugins"); + + QStringList itemNames; + QList<Plugin *> items; + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *possiblePlugin = loader.instance(); + if (Plugin *plugin = qobject_cast<Plugin *>(possiblePlugin)) { + QString objectName = possiblePlugin->objectName(); + if (objectName.isEmpty()) + objectName = fileName; + + itemNames.append(objectName); + items.append(plugin); + } + } + + if (items.isEmpty()) { + QMessageBox::information(this, "No tank types found", "Please build the errorstateplugins directory"); + return; + } + + bool ok; + QString selectedName = QInputDialog::getItem(this, "Select a tank type", "Tank types", + itemNames, 0, false, &ok); + + if (ok && !selectedName.isEmpty()) { + int idx = itemNames.indexOf(selectedName); + if (Plugin *plugin = idx >= 0 ? items.at(idx) : 0) { + TankItem *tankItem = m_spawns.takeLast(); + m_scene->addItem(tankItem); + connect(tankItem, SIGNAL(cannonFired()), this, SLOT(addRocket())); + if (m_spawns.isEmpty()) + emit mapFull(); + + QState *region = new QState(m_runningState); + QState *pluginState = plugin->create(region, tankItem); + region->setInitialState(pluginState); + + // If the plugin has an error it is disabled + QState *errorState = new QState(region); + errorState->assignProperty(tankItem, "enabled", false); + pluginState->setErrorState(errorState); + } + } +} + diff --git a/examples/statemachine/errorstate/mainwindow.h b/examples/statemachine/errorstate/mainwindow.h new file mode 100644 index 0000000..622dabe --- /dev/null +++ b/examples/statemachine/errorstate/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> +#include <QTime> + +class QGraphicsScene; +class QStateMachine; +class QState; +class TankItem; +class MainWindow: public QMainWindow +{ + Q_OBJECT + Q_PROPERTY(bool started READ started WRITE setStarted) +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + + void setStarted(bool b) { m_started = b; } + bool started() const { return m_started; } + +public slots: + void addTank(); + void addRocket(); + void runStep(); + +signals: + void mapFull(); + +private: + void init(); + void addWall(const QRectF &wall); + + QGraphicsScene *m_scene; + + QStateMachine *m_machine; + QState *m_runningState; + + QList<TankItem *> m_spawns; + QTime m_time; + + bool m_started : 1; +}; + +#endif + diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/errorstate/plugin.h new file mode 100644 index 0000000..2b48d43 --- /dev/null +++ b/examples/statemachine/errorstate/plugin.h @@ -0,0 +1,17 @@ +#ifndef PLUGIN_H +#define PLUGIN_H + +#include <QtPlugin> + +class QState; +class Plugin +{ +public: + virtual ~Plugin() {} + + virtual QState *create(QState *parentState, QObject *tank) = 0; +}; + +Q_DECLARE_INTERFACE(Plugin, "TankPlugin") + +#endif diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/errorstate/rocketitem.cpp new file mode 100644 index 0000000..c324980 --- /dev/null +++ b/examples/statemachine/errorstate/rocketitem.cpp @@ -0,0 +1,60 @@ +#include "rocketitem.h" +#include "tankitem.h" + +#include <QPainter> +#include <QGraphicsScene> + +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +RocketItem::RocketItem(QObject *parent) + : GameItem(parent), m_direction(0.0), m_distance(300.0) +{ +} + +QRectF RocketItem::boundingRect() const +{ + return QRectF(-1.0, -1.0, 2.0, 2.0); +} + +void RocketItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setBrush(Qt::black); + painter->drawEllipse(boundingRect()); +} + +void RocketItem::idle(qreal elapsed) +{ + qreal dist = elapsed * speed(); + + m_distance -= dist; + if (m_distance < 0.0) { + scene()->removeItem(this); + delete this; + return; + } + + qreal a = m_direction * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); + + QPointF requestedPosition = pos() + QPointF(xd, yd); + QGraphicsItem *collidedItem = 0; + QPointF nextPosition = tryMove(requestedPosition, 0, &collidedItem); + if (requestedPosition == nextPosition) { + setPos(nextPosition); + } else { + if (GameItem *gameItem = qgraphicsitem_cast<GameItem *>(collidedItem)) { + TankItem *tankItem = qobject_cast<TankItem *>(gameItem); + if (tankItem != 0) + tankItem->hitByRocket(); + } + + scene()->removeItem(this); + delete this; + } +} diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/errorstate/rocketitem.h new file mode 100644 index 0000000..189a1dd --- /dev/null +++ b/examples/statemachine/errorstate/rocketitem.h @@ -0,0 +1,26 @@ +#ifndef ROCKETITEM_H +#define ROCKETITEM_H + +#include "gameitem.h" + +class RocketItem: public GameItem +{ + Q_OBJECT +public: + RocketItem(QObject *parent = 0); + + virtual void idle(qreal elapsed); + qreal speed() const { return 100.0; } + void setDirection(qreal direction) { m_direction = direction; } + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; + +private: + qreal m_direction; + qreal m_distance; +}; + + +#endif diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp new file mode 100644 index 0000000..5506a7e --- /dev/null +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -0,0 +1,262 @@ +#include "tankitem.h" + +#include <QPainter> +#include <QGraphicsScene> +#include <QDebug> + +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +class Action +{ +public: + Action(TankItem *item) : m_item(item) + { + } + + TankItem *item() const { return m_item; } + void setItem(TankItem *item) { m_item = item; } + + virtual bool apply(qreal timeDelta) = 0; + +private: + TankItem *m_item; +}; + +class MoveAction: public Action +{ +public: + MoveAction(TankItem *item, qreal distance) + : Action(item), m_distance(distance) + { + m_reverse = m_distance < 0.0; + } + + bool apply(qreal timeDelta) + { + qreal dist = timeDelta * item()->speed() * (m_reverse ? -1.0 : 1.0); + + bool done = false; + if (qAbs(m_distance) < qAbs(dist)) { + done = true; + dist = m_distance; + } + m_distance -= dist; + + qreal a = item()->direction() * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); + + item()->setPos(item()->pos() + QPointF(xd, yd)); + return !done; + } + +private: + qreal m_distance; + bool m_reverse; +}; + +class TurnAction: public Action +{ +public: + TurnAction(TankItem *item, qreal distance) + : Action(item), m_distance(distance) + { + m_reverse = m_distance < 0.0; + } + + bool apply(qreal timeDelta) + { + qreal dist = timeDelta * item()->angularSpeed() * (m_reverse ? -1.0 : 1.0); + bool done = false; + if (qAbs(m_distance) < qAbs(dist)) { + done = true; + dist = m_distance; + } + m_distance -= dist; + + item()->setDirection(item()->direction() + dist); + return !done; + } + +private: + qreal m_distance; + bool m_reverse; +}; + +TankItem::TankItem(QObject *parent) + : GameItem(parent), m_currentAction(0), m_currentDirection(0.0), m_enabled(true) +{ + connect(this, SIGNAL(cannonFired()), this, SIGNAL(actionCompleted())); +} + +void TankItem::idle(qreal elapsed) +{ + if (m_enabled) { + if (m_currentAction != 0) { + if (!m_currentAction->apply(elapsed)) { + setAction(0); + emit actionCompleted(); + } + + QGraphicsItem *item = 0; + qreal distance = distanceToObstacle(&item); + if (TankItem *tankItem = qgraphicsitem_cast<TankItem *>(item)) + emit tankSpotted(tankItem->direction(), distance); + } + } +} + +void TankItem::hitByRocket() +{ + deleteLater(); +} + +void TankItem::setAction(Action *newAction) +{ + if (m_currentAction != 0) + delete m_currentAction; + + m_currentAction = newAction; +} + +void TankItem::fireCannon() +{ + emit cannonFired(); +} + +void TankItem::moveForwards(qreal length) +{ + setAction(new MoveAction(this, length)); +} + +void TankItem::moveBackwards(qreal length) +{ + setAction(new MoveAction(this, -length)); +} + +void TankItem::turn(qreal degrees) +{ + setAction(new TurnAction(this, degrees)); +} + +void TankItem::turnTo(qreal degrees) +{ + setAction(new TurnAction(this, degrees - direction())); +} + +void TankItem::stop() +{ + setAction(0); +} + +QVariant TankItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionChange && scene()) { + QPointF requestedPosition = value.toPointF(); + QLineF collidedLine; + QPointF nextPoint = tryMove(requestedPosition, &collidedLine); + if (nextPoint != requestedPosition) + emit collision(collidedLine); + return nextPoint; + } else { + return QGraphicsItem::itemChange(change, value); + } +} + + +void TankItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + QRectF brect = boundingRect(); + + painter->setBrush(m_color); + painter->setPen(Qt::black); + + // body + painter->drawRect(brect.adjusted(0.0, 4.0, -2.0, -4.0)); + + // cannon + QRectF cannonBase = brect.adjusted(10.0, 6.0, -12.0, -6.0); + painter->drawEllipse(cannonBase); + + painter->drawRect(QRectF(QPointF(cannonBase.center().x(), cannonBase.center().y() - 2.0), + QPointF(brect.right(), cannonBase.center().y() + 2.0))); + + // left track + painter->setBrush(QBrush(Qt::black, Qt::VerPattern)); + QRectF leftTrackRect = QRectF(brect.topLeft(), QPointF(brect.right() - 2.0, brect.top() + 4.0)); + painter->fillRect(leftTrackRect, Qt::darkYellow); + painter->drawRect(leftTrackRect); + + // right track + QRectF rightTrackRect = QRectF(QPointF(brect.left(), brect.bottom() - 4.0), + QPointF(brect.right() - 2.0, brect.bottom())); + painter->fillRect(rightTrackRect, Qt::darkYellow); + painter->drawRect(rightTrackRect); + + if (!m_enabled) { + painter->setPen(QPen(Qt::red, 5)); + + painter->drawEllipse(brect); + + QPainterPath path; + path.addEllipse(brect); + painter->setClipPath(path); + painter->drawLine(brect.topRight(), brect.bottomLeft()); + } +} + +QRectF TankItem::boundingRect() const +{ + return QRectF(-20.0, -10.0, 40.0, 20.0); +} + +qreal TankItem::direction() const +{ + return m_currentDirection; +} + +void TankItem::setDirection(qreal newDirection) +{ + int fullRotations = int(newDirection) / 360; + newDirection -= fullRotations * 360.0; + + qreal diff = newDirection - m_currentDirection; + m_currentDirection = newDirection; + rotate(diff); +} + +qreal TankItem::distanceToObstacle(QGraphicsItem **obstacle) const +{ + qreal dist = sqrt(pow(scene()->sceneRect().width(), 2) + pow(scene()->sceneRect().height(), 2)); + + qreal a = m_currentDirection * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); + + QPointF requestedPosition = pos() + QPointF(xd, yd); + QGraphicsItem *collidedItem = 0; + QPointF nextPosition = tryMove(requestedPosition, 0, &collidedItem); + if (collidedItem != 0) { + if (obstacle != 0) + *obstacle = collidedItem; + + QPointF d = nextPosition - pos(); + return sqrt(pow(d.x(), 2) + pow(d.y(), 2)); + } else { + return 0.0; + } +} + +qreal TankItem::distanceToObstacle() const +{ + return distanceToObstacle(0); +} + + + diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h new file mode 100644 index 0000000..cefed69 --- /dev/null +++ b/examples/statemachine/errorstate/tankitem.h @@ -0,0 +1,65 @@ +#ifndef TANKITEM_H +#define TANKITEM_H + +#include "gameitem.h" + +#include <QColor> + +class Action; +class TankItem: public GameItem +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) + Q_PROPERTY(qreal direction READ direction WRITE turnTo) + Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle) +public: + TankItem(QObject *parent = 0); + + void setColor(const QColor &color) { m_color = color; } + QColor color() const { return m_color; } + + void idle(qreal elapsed); + void setDirection(qreal newDirection); + + qreal speed() const { return 90.0; } + qreal angularSpeed() const { return 90.0; } + + QRectF boundingRect() const; + + void hitByRocket(); + + void setEnabled(bool b) { m_enabled = b; } + bool enabled() const { return m_enabled; } + + qreal direction() const; + qreal distanceToObstacle() const; + qreal distanceToObstacle(QGraphicsItem **item) const; + +signals: + void tankSpotted(qreal direction, qreal distance); + void collision(const QLineF &collidedLine); + void actionCompleted(); + void cannonFired(); + +public slots: + void moveForwards(qreal length = 10.0); + void moveBackwards(qreal length = 10.0); + void turn(qreal degrees = 30.0); + void turnTo(qreal degrees = 0.0); + void stop(); + void fireCannon(); + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private: + void setAction(Action *newAction); + + Action *m_currentAction; + qreal m_currentDirection; + QColor m_color; + bool m_enabled; +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro new file mode 100644 index 0000000..5b6b758 --- /dev/null +++ b/examples/statemachine/errorstateplugins/errorstateplugins.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/errorstateplugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS errorstateplugins.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins +INSTALLS += target sources diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai.pro b/examples/statemachine/errorstateplugins/random_ai/random_ai.pro new file mode 100644 index 0000000..f290250 --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = random_ai_plugin.h +SOURCES = random_ai_plugin.cpp +TARGET = $$qtLibraryTarget(random_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/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 diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp new file mode 100644 index 0000000..c196247 --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp @@ -0,0 +1,38 @@ +#include "random_ai_plugin.h" + +#include <QState> +#include <QtPlugin> + +#include <time.h> + +QState *RandomAiPlugin::create(QState *parentState, QObject *tank) +{ + qsrand(uint(time(NULL))); + + QState *topLevel = new QState(parentState); + + QState *selectNextActionState = new SelectActionState(topLevel); + topLevel->setInitialState(selectNextActionState); + + QState *fireState = new RandomDistanceState(topLevel); + connect(fireState, SIGNAL(distanceComputed(qreal)), tank, SLOT(fireCannon())); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(fireSelected()), fireState); + + QState *moveForwardsState = new RandomDistanceState(topLevel); + connect(moveForwardsState, SIGNAL(distanceComputed(qreal)), tank, SLOT(moveForwards(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(moveForwardsSelected()), moveForwardsState); + + QState *moveBackwardsState = new RandomDistanceState(topLevel); + connect(moveBackwardsState, SIGNAL(distanceComputed(qreal)), tank, SLOT(moveBackwards(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(moveBackwardsSelected()), moveBackwardsState); + + QState *turnState = new RandomDistanceState(topLevel); + connect(turnState, SIGNAL(distanceComputed(qreal)), tank, SLOT(turn(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(turnSelected()), turnState); + + topLevel->addTransition(tank, SIGNAL(actionCompleted()), selectNextActionState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(random_ai, RandomAiPlugin) diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h new file mode 100644 index 0000000..10e6f48 --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h @@ -0,0 +1,64 @@ +#ifndef RANDOM_AI_PLUGIN_H +#define RANDOM_AI_PLUGIN_H + +#include <QObject> +#include <QState> + +#include <errorstate/plugin.h> + +class SelectActionState: public QState +{ + Q_OBJECT +public: + SelectActionState(QState *parent = 0) : QState(parent) + { + } + +signals: + void fireSelected(); + void moveForwardsSelected(); + void moveBackwardsSelected(); + void turnSelected(); + +protected: + void onEntry(QEvent *) + { + int rand = qrand() % 4; + switch (rand) { + case 0: emit fireSelected(); break; + case 1: emit moveForwardsSelected(); break; + case 2: emit moveBackwardsSelected(); break; + case 3: emit turnSelected(); break; + }; + } +}; + +class RandomDistanceState: public QState +{ + Q_OBJECT +public: + RandomDistanceState(QState *parent = 0) : QState(parent) + { + } + +signals: + void distanceComputed(qreal distance); + +protected: + void onEntry(QEvent *) + { + emit distanceComputed(qreal(qrand() % 180)); + } +}; + +class RandomAiPlugin: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + RandomAiPlugin() { setObjectName("Random"); } + + virtual QState *create(QState *parentState, QObject *tank); +}; + +#endif // RANDOM_AI_PLUGIN_H diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp new file mode 100644 index 0000000..2fb05d4 --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp @@ -0,0 +1,48 @@ +#include "seek_ai.h" + +QState *SeekAi::create(QState *parentState, QObject *tank) +{ + QState *topLevel = new QState(parentState); + topLevel->setObjectName("topLevel"); + + QState *seek = new QState(topLevel); + seek->setObjectName("seek"); + topLevel->setInitialState(seek); + + QState *lookForNearestWall = new SearchState(tank, seek); + lookForNearestWall->setObjectName("lookForNearestWall"); + seek->setInitialState(lookForNearestWall); + + QState *driveToFirstObstacle = new QState(seek); + driveToFirstObstacle->setObjectName("driveToFirstObstacle"); + lookForNearestWall->addTransition(lookForNearestWall, SIGNAL(nearestObstacleStraightAhead()), + driveToFirstObstacle); + + QState *drive = new QState(driveToFirstObstacle); + drive->setObjectName("drive"); + driveToFirstObstacle->setInitialState(drive); + connect(drive, SIGNAL(entered()), tank, SLOT(moveForwards())); + connect(drive, SIGNAL(exited()), tank, SLOT(stop())); + + // Go in loop + QState *finishedDriving = new QState(driveToFirstObstacle); + finishedDriving->setObjectName("finishedDriving"); + drive->addTransition(tank, SIGNAL(actionCompleted()), finishedDriving); + finishedDriving->addTransition(drive); + + QState *turnTo = new QState(seek); + turnTo->setObjectName("turnTo"); + driveToFirstObstacle->addTransition(new CollisionTransition(tank, turnTo)); + + turnTo->addTransition(tank, SIGNAL(actionCompleted()), driveToFirstObstacle); + + ChaseState *chase = new ChaseState(tank, topLevel); + chase->setObjectName("chase"); + seek->addTransition(new TankSpottedTransition(tank, chase)); + chase->addTransition(chase, SIGNAL(finished()), driveToFirstObstacle); + chase->addTransition(new TankSpottedTransition(tank, chase)); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(seek_ai, SeekAi) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h new file mode 100644 index 0000000..a1b5749 --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -0,0 +1,204 @@ +#ifndef SEEK_AI_H +#define SEEK_AI_H + +#include <errorstate/plugin.h> + +#include <QState> +#include <QFinalState> +#include <QSignalTransition> +#include <QSignalEvent> +#include <QVariant> +#include <QLineF> +#include <QDebug> + +class SearchState: public QState +{ + Q_OBJECT +public: + SearchState(QObject *tank, QState *parentState = 0) + : QState(parentState), + m_tank(tank), + m_distanceToTurn(360.0), + m_nearestDistance(-1.0), + m_directionOfNearestObstacle(0.0) + { + } + +public slots: + void turnAlittle() + { + qreal dist = m_tank->property("distanceToObstacle").toDouble(); + + if (m_nearestDistance < 0.0 || dist < m_nearestDistance) { + m_nearestDistance = dist; + m_directionOfNearestObstacle = m_tank->property("direction").toDouble(); + } + + m_distanceToTurn -= 10.0; + if (m_distanceToTurn < 0.0) { + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + connect(m_tank, SIGNAL(actionCompleted()), this, SIGNAL(nearestObstacleStraightAhead())); + m_tank->setProperty("direction", m_directionOfNearestObstacle); + } + + qreal currentDirection = m_tank->property("direction").toDouble(); + m_tank->setProperty("direction", currentDirection + 10.0); + } + +signals: + void nearestObstacleStraightAhead(); + +protected: + void onEntry(QEvent *) + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + turnAlittle(); + } + + void onExit(QEvent *) + { + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(nearestObstacleStraightAhead())); + } + +private: + QObject *m_tank; + + qreal m_distanceToTurn; + qreal m_nearestDistance; + qreal m_directionOfNearestObstacle; +}; + +class CollisionTransition: public QSignalTransition +{ +public: + CollisionTransition(QObject *tank, QState *turnTo) + : QSignalTransition(tank, SIGNAL(collision(QLineF))), + m_tank(tank), + m_turnTo(turnTo) + { + setTargetState(turnTo); + } + +protected: + bool eventTest(QEvent *event) const + { + bool b = QSignalTransition::eventTest(event); + if (b) { + QSignalEvent *se = static_cast<QSignalEvent *>(event); + m_lastLine = se->arguments().at(0).toLineF(); + } + return b; + } + + void onTransition(QEvent *) + { + qreal angleOfWall = m_lastLine.angle(); + + qreal newDirection; + if (qrand() % 2 == 0) + newDirection = angleOfWall; + else + newDirection = angleOfWall - 180.0; + + m_turnTo->assignProperty(m_tank, "direction", newDirection); + } + +private: + mutable QLineF m_lastLine; + QObject *m_tank; + QState *m_turnTo; +}; + +class ChaseState: public QState +{ + class GoToLocationState: public QState + { + public: + GoToLocationState(QObject *tank, QState *parentState = 0) + : QState(parentState), m_tank(tank), m_distance(0.0) + { + } + + void setDistance(qreal distance) { m_distance = distance; } + + protected: + void onEntry() + { + QMetaObject::invokeMethod(m_tank, "moveForwards", Q_ARG(qreal, m_distance)); + } + + private: + QObject *m_tank; + qreal m_distance; + }; + +public: + ChaseState(QObject *tank, QState *parentState = 0) : QState(parentState), m_tank(tank) + { + QState *fireCannon = new QState(this); + connect(fireCannon, SIGNAL(entered()), tank, SLOT(fireCannon())); + setInitialState(fireCannon); + + m_goToLocation = new GoToLocationState(this); + fireCannon->addTransition(tank, SIGNAL(actionCompleted()), m_goToLocation); + + m_turnToDirection = new QState(this); + m_goToLocation->addTransition(tank, SIGNAL(actionCompleted()), m_turnToDirection); + + QFinalState *finalState = new QFinalState(this); + m_turnToDirection->addTransition(tank, SIGNAL(actionCompleted()), finalState); + } + + void setDirection(qreal direction) + { + m_turnToDirection->assignProperty(m_tank, "direction", direction); + } + + void setDistance(qreal distance) + { + m_goToLocation->setDistance(distance); + } + +private: + QObject *m_tank; + GoToLocationState *m_goToLocation; + QState *m_turnToDirection; + +}; + +class TankSpottedTransition: public QSignalTransition +{ +public: + TankSpottedTransition(QObject *tank, ChaseState *target) : QSignalTransition(tank, SIGNAL(tankSpotted(qreal,qreal))), m_chase(target) + { + setTargetState(target); + } + +protected: + bool eventTest(QEvent *event) const + { + bool b = QSignalTransition::eventTest(event); + if (b) { + QSignalEvent *se = static_cast<QSignalEvent *>(event); + m_chase->setDirection(se->arguments().at(0).toDouble()); + m_chase->setDistance(se->arguments().at(1).toDouble()); + } + return b; + } + +private: + ChaseState *m_chase; +}; + +class SeekAi: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + SeekAi() { setObjectName("Seek and destroy"); } + + virtual QState *create(QState *parentState, QObject *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro new file mode 100644 index 0000000..11bd242 --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = seek_ai.h +SOURCES = seek_ai.cpp +TARGET = $$qtLibraryTarget(seek_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/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 diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp new file mode 100644 index 0000000..de95f41 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp @@ -0,0 +1,29 @@ +#include "spin_ai.h" + +#include <QtPlugin> + +QState *SpinAi::create(QState *parentState, QObject *tank) +{ + QState *topLevel = new QState(parentState); + QState *spinState = new SpinState(tank, topLevel); + topLevel->setInitialState(spinState); + + // When tank is spotted, fire two times and go back to spin state + QState *fireState = new QState(topLevel); + + QState *fireOnce = new QState(fireState); + fireState->setInitialState(fireOnce); + connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon())); + + QState *fireTwice = new QState(fireState); + connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon())); + + fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice); + fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState); + + spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(spin_ai, SpinAi) diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h new file mode 100644 index 0000000..6e220ed --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h @@ -0,0 +1,46 @@ +#ifndef SPIN_AI_H +#define SPIN_AI_H + +#include <errorstate/plugin.h> + +#include <QObject> +#include <QState> +#include <QVariant> + +class SpinState: public QState +{ + Q_OBJECT +public: + SpinState(QObject *tank, QState *parent) : QState(parent), m_tank(tank) + { + } + +public slots: + void spin() + { + m_tank->setProperty("direction", 90.0); + } + +protected: + void onEntry(QEvent *) + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); + spin(); + } + +private: + QObject *m_tank; + +}; + +class SpinAi: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + SpinAi() { setObjectName("Spin and destroy"); } + + virtual QState *create(QState *parentState, QObject *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro new file mode 100644 index 0000000..c2fd937 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = spin_ai.h +SOURCES = spin_ai.cpp +TARGET = $$qtLibraryTarget(spin_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/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 diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp new file mode 100644 index 0000000..5499ba3 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp @@ -0,0 +1,29 @@ +#include "spin_ai_with_error.h" + +#include <QtPlugin> + +QState *SpinAiWithError::create(QState *parentState, QObject *tank) +{ + QState *topLevel = new QState(parentState); + QState *spinState = new SpinState(tank, topLevel); + topLevel->setInitialState(spinState); + + // When tank is spotted, fire two times and go back to spin state + // (no initial state set for fireState will lead to run-time error in machine) + QState *fireState = new QState(topLevel); + + QState *fireOnce = new QState(fireState); + connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon())); + + QState *fireTwice = new QState(fireState); + connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon())); + + fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice); + fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState); + + spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(spin_ai_with_error, SpinAiWithError) diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h new file mode 100644 index 0000000..d520455 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h @@ -0,0 +1,46 @@ +#ifndef SPIN_AI_WITH_ERROR_H +#define SPIN_AI_WITH_ERROR_H + +#include <errorstate/plugin.h> + +#include <QObject> +#include <QState> +#include <QVariant> + +class SpinState: public QState +{ + Q_OBJECT +public: + SpinState(QObject *tank, QState *parent) : QState(parent), m_tank(tank) + { + } + +public slots: + void spin() + { + m_tank->setProperty("direction", 90.0); + } + +protected: + void onEntry(QEvent *) + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); + spin(); + } + +private: + QObject *m_tank; + +}; + +class SpinAiWithError: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + SpinAiWithError() { setObjectName("Spin and destroy with runtime error in state machine"); } + + virtual QState *create(QState *parentState, QObject *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro new file mode 100644 index 0000000..31f4c7f --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = spin_ai_with_error.h +SOURCES = spin_ai_with_error.cpp +TARGET = $$qtLibraryTarget(spin_ai_with_error) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/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 diff --git a/examples/statemachine/factorial/main.cpp b/examples/statemachine/factorial/main.cpp index 9e39ced..2b63690 100644 --- a/examples/statemachine/factorial/main.cpp +++ b/examples/statemachine/factorial/main.cpp @@ -104,7 +104,7 @@ public: return m_fact->property("x").toInt() > 1; } - virtual void onTransition() + virtual void onTransition(QEvent *) { int x = m_fact->property("x").toInt(); int fac = m_fact->property("fac").toInt(); @@ -128,7 +128,7 @@ public: return m_fact->property("x").toInt() <= 1; } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "%d\n", m_fact->property("fac").toInt()); } diff --git a/examples/statemachine/helloworld/main.cpp b/examples/statemachine/helloworld/main.cpp index 13486d4..fbe34b5 100644 --- a/examples/statemachine/helloworld/main.cpp +++ b/examples/statemachine/helloworld/main.cpp @@ -52,7 +52,7 @@ public: S0(QState *parent = 0) : QState(parent) {} - virtual void onEntry() + virtual void onEntry(QEvent *) { fprintf(stdout, "Hello world!\n"); } diff --git a/examples/statemachine/pauseandresume/main.cpp b/examples/statemachine/pauseandresume/main.cpp index e0ebbff..5bacb41 100644 --- a/examples/statemachine/pauseandresume/main.cpp +++ b/examples/statemachine/pauseandresume/main.cpp @@ -73,7 +73,7 @@ public: s1->addTransition(pb, SIGNAL(clicked()), s2); s2->addTransition(pb, SIGNAL(clicked()), s1); - QHistoryState *h = process->addHistoryState(); + QHistoryState *h = new QHistoryState(process); h->setDefaultState(s1); QState *interrupted = new QState(machine->rootState()); diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp index 3272524..eb8fd5d 100644 --- a/examples/statemachine/pingpong/main.cpp +++ b/examples/statemachine/pingpong/main.cpp @@ -44,7 +44,7 @@ #ifdef QT_STATEMACHINE_SOLUTION #include <qstate.h> #include <qstatemachine.h> -#include <qtransition.h> +#include <qabstracttransition.h> #endif class PingEvent : public QEvent @@ -64,58 +64,47 @@ public: class Pinger : public QState { public: - Pinger(QStateMachine *machine, QState *parent) - : QState(parent), m_machine(machine) {} + Pinger(QState *parent) + : QState(parent) {} protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { - m_machine->postEvent(new PingEvent()); + machine()->postEvent(new PingEvent()); fprintf(stdout, "ping?\n"); } - -private: - QStateMachine *m_machine; }; class PongTransition : public QAbstractTransition { public: - PongTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) {} + PongTransition() {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+3); } - virtual void onTransition() + virtual void onTransition(QEvent *) { - m_machine->postEvent(new PingEvent(), 500); + machine()->postEvent(new PingEvent(), 500); fprintf(stdout, "ping?\n"); } - -private: - QStateMachine *m_machine; }; class PingTransition : public QAbstractTransition { public: - PingTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) {} + PingTransition() {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { - m_machine->postEvent(new PongEvent(), 500); + machine()->postEvent(new PongEvent(), 500); fprintf(stdout, "pong!\n"); } - -private: - QStateMachine *m_machine; }; int main(int argc, char **argv) @@ -123,16 +112,16 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); QStateMachine machine; - QState *group = new QState(QState::ParallelGroup); + QState *group = new QState(QState::ParallelStates); group->setObjectName("group"); - Pinger *pinger = new Pinger(&machine, group); + Pinger *pinger = new Pinger(group); pinger->setObjectName("pinger"); - pinger->addTransition(new PongTransition(&machine)); + pinger->addTransition(new PongTransition()); QState *ponger = new QState(group); ponger->setObjectName("ponger"); - ponger->addTransition(new PingTransition(&machine)); + ponger->addTransition(new PingTransition()); machine.addState(group); machine.setInitialState(group); diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp index 528ed00..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); - timing->invokeMethodOnEntry(light, "turnOn"); - timing->invokeMethodOnEntry(timer, "start"); - timing->invokeMethodOnExit(light, "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] @@ -151,20 +148,21 @@ public: QVBoxLayout *vbox = new QVBoxLayout(this); TrafficLightWidget *widget = new TrafficLightWidget(); vbox->addWidget(widget); + 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->addFinishedTransition(yellowGoingGreen); - LightState *greenGoingYellow = new LightState(widget->greenLight(), 3000); + redGoingYellow->addTransition(redGoingYellow, SIGNAL(finished()), yellowGoingGreen); + QState *greenGoingYellow = createLightState(widget->greenLight(), 3000); greenGoingYellow->setObjectName("greenGoingYellow"); - yellowGoingGreen->addFinishedTransition(greenGoingYellow); - LightState *yellowGoingRed = new LightState(widget->yellowLight(), 1000); + yellowGoingGreen->addTransition(yellowGoingGreen, SIGNAL(finished()), greenGoingYellow); + QState *yellowGoingRed = createLightState(widget->yellowLight(), 1000); yellowGoingRed->setObjectName("yellowGoingRed"); - greenGoingYellow->addFinishedTransition(yellowGoingRed); - yellowGoingRed->addFinishedTransition(redGoingYellow); + greenGoingYellow->addTransition(greenGoingYellow, SIGNAL(finished()), yellowGoingRed); + yellowGoingRed->addTransition(yellowGoingRed, SIGNAL(finished()), redGoingYellow); machine->addState(redGoingYellow); machine->addState(yellowGoingGreen); @@ -182,7 +180,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); TrafficLight widget; - widget.resize(120, 300); + widget.resize(110, 300); widget.show(); return app.exec(); diff --git a/src/3rdparty/easing/easing.cpp b/src/3rdparty/easing/easing.cpp index 6a98c98..5bd3997 100644 --- a/src/3rdparty/easing/easing.cpp +++ b/src/3rdparty/easing/easing.cpp @@ -37,36 +37,36 @@ static qreal easeNone(qreal progress) { return progress; } - + /** * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity. * * @param t Current time (in frames or seconds). * @return The correct value. */ -static qreal easeInQuad(qreal t) +static qreal easeInQuad(qreal t) { return t*t; } - + /** * Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity. * * @param t Current time (in frames or seconds). * @return The correct value. */ -static qreal easeOutQuad(qreal t) +static qreal easeOutQuad(qreal t) { return -t*(t-2); } - + /** * Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration. * * @param t Current time (in frames or seconds). * @return The correct value. */ -static qreal easeInOutQuad(qreal t) +static qreal easeInOutQuad(qreal t) { t*=2.0; if (t < 1) { @@ -76,7 +76,7 @@ static qreal easeInOutQuad(qreal t) return -0.5 * (t*(t-2) - 1); } } - + /** * Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration. * @@ -88,7 +88,7 @@ static qreal easeOutInQuad(qreal t) if (t < 0.5) return easeOutQuad (t*2)/2; return easeInQuad((2*t)-1)/2 + 0.5; } - + /** * Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity. * @@ -99,7 +99,7 @@ static qreal easeInCubic(qreal t) { return t*t*t; } - + /** * Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity. * @@ -111,7 +111,7 @@ static qreal easeOutCubic(qreal t) t-=1.0; return t*t*t + 1; } - + /** * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration. * @@ -151,7 +151,7 @@ static qreal easeInQuart(qreal t) { return t*t*t*t; } - + /** * Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity. * @@ -163,7 +163,7 @@ static qreal easeOutQuart(qreal t) t-= qreal(1.0); return - (t*t*t*t- 1); } - + /** * Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration. * @@ -178,7 +178,7 @@ static qreal easeInOutQuart(qreal t) t -= 2.0f; return -0.5 * (t*t*t*t- 2); } -} +} /** * Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration. @@ -186,12 +186,12 @@ static qreal easeInOutQuart(qreal t) * @param t Current time (in frames or seconds). * @return The correct value. */ -static qreal easeOutInQuart(qreal t) +static qreal easeOutInQuart(qreal t) { if (t < 0.5) return easeOutQuart (2*t)/2; return easeInQuart(2*t-1)/2 + 0.5; } - + /** * Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity. * @@ -202,7 +202,7 @@ static qreal easeInQuint(qreal t) { return t*t*t*t*t; } - + /** * Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity. * @@ -214,7 +214,7 @@ static qreal easeOutQuint(qreal t) t-=1.0; return t*t*t*t*t + 1; } - + /** * Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration. * @@ -230,7 +230,7 @@ static qreal easeInOutQuint(qreal t) return 0.5*(t*t*t*t*t + 2); } } - + /** * Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration. * @@ -242,7 +242,7 @@ static qreal easeOutInQuint(qreal t) if (t < 0.5) return easeOutQuint (2*t)/2; return easeInQuint(2*t - 1)/2 + 0.5; } - + /** * Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity. * @@ -253,7 +253,7 @@ static qreal easeInSine(qreal t) { return (t == 1.0) ? 1.0 : -::cos(t * M_PI_2) + 1.0; } - + /** * Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity. * @@ -264,7 +264,7 @@ static qreal easeOutSine(qreal t) { return ::sin(t* M_PI_2); } - + /** * Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration. * @@ -275,7 +275,7 @@ static qreal easeInOutSine(qreal t) { return -0.5 * (::cos(M_PI*t) - 1); } - + /** * Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration. * @@ -287,7 +287,7 @@ static qreal easeOutInSine(qreal t) if (t < 0.5) return easeOutSine (2*t)/2; return easeInSine(2*t - 1)/2 + 0.5; } - + /** * Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity. * @@ -321,7 +321,7 @@ static qreal easeInOutExpo(qreal t) if (t==0.0) return qreal(0.0); if (t==1.0) return qreal(1.0); t*=2.0; - if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 1.0 * 0.0005; + if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 0.0005; return 0.5 * 1.0005 * (-::qPow(qreal(2.0), -10 * (t - 1)) + 2); } @@ -336,7 +336,7 @@ static qreal easeOutInExpo(qreal t) if (t < 0.5) return easeOutExpo (2*t)/2; return easeInExpo(2*t - 1)/2 + 0.5; } - + /** * Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity. * @@ -471,8 +471,8 @@ static qreal easeInOutElastic(qreal t, qreal a, qreal p) s = p / (2 * M_PI) * ::asin(1.0 / a); } - if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( ((t-1)*1.0-s)*(2*M_PI)/p )); - return a*::qPow(2.0f,-10*(t-1)) * ::sin( ((t-1)*1.0-s)*(2*M_PI)/p )*.5 + 1.0; + if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )); + return a*::qPow(2.0f,-10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )*.5 + 1.0; } /** @@ -547,23 +547,23 @@ static qreal easeOutInBack(qreal t, qreal s) return easeInBack(2*t - 1, s)/2 + 0.5; } -static qreal easeOutBounce_helper(qreal t, qreal b, qreal c, qreal a) +static qreal easeOutBounce_helper(qreal t, qreal c, qreal a) { - if (t == 1.0) return 1.0; - if (t < (1/2.75)) { - return c*(7.5625*t*t) + b; - } else if (t < (2/2.75)) { - t -= (1.5f/2.75f); - return -a * (1. - (7.5625*t*t + .75)) + (b + c); - } else if (t < (2.5/2.75)) { - t -= (2.25f/2.75f); - return -a * (1. - (7.5625*t*t + .9375)) + (b + c); + if (t == 1.0) return c; + if (t < (4/11.0)) { + return c*(7.5625*t*t); + } else if (t < (8/11.0)) { + t -= (6/11.0); + return -a * (1. - (7.5625*t*t + .75)) + c; + } else if (t < (10/11.0)) { + t -= (9/11.0); + return -a * (1. - (7.5625*t*t + .9375)) + c; } else { - t -= (2.65f/2.75f); - return -a * (1. - (7.5625*t*t + .984375)) + (b + c); + t -= (21/22.0); + return -a * (1. - (7.5625*t*t + .984375)) + c; } } - + /** * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity. * @@ -573,7 +573,7 @@ static qreal easeOutBounce_helper(qreal t, qreal b, qreal c, qreal a) */ static qreal easeOutBounce(qreal t, qreal a) { - return easeOutBounce_helper(t, 0, 1, a); + return easeOutBounce_helper(t, 1, a); } /** @@ -585,10 +585,10 @@ static qreal easeOutBounce(qreal t, qreal a) */ static qreal easeInBounce(qreal t, qreal a) { - return 1.0 - easeOutBounce_helper(1.0-t, 0, 1.0, a); + return 1.0 - easeOutBounce_helper(1.0-t, 1.0, a); } - - + + /** * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration. * @@ -601,7 +601,7 @@ static qreal easeInOutBounce(qreal t, qreal a) if (t < 0.5) return easeInBounce (2*t, a)/2; else return (t == 1.0) ? 1.0 : easeOutBounce (2*t - 1, a)/2 + 0.5; } - + /** * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration. * @@ -611,8 +611,8 @@ static qreal easeInOutBounce(qreal t, qreal a) */ static qreal easeOutInBounce(qreal t, qreal a) { - if (t < 0.5) return easeOutBounce_helper(t*2, 0, 0.5, a); - return 1.0 - easeOutBounce_helper (2.0-2*t, 0.0, 0.5, a); + if (t < 0.5) return easeOutBounce_helper(t*2, 0.5, a); + return 1.0 - easeOutBounce_helper (2.0-2*t, 0.5, a); } static inline qreal qt_sinProgress(qreal value) @@ -633,7 +633,7 @@ static inline qreal qt_smoothBeginEndMixFactor(qreal value) /** * Easing function that starts growing slowly, then increases in speed. At the end of the curve the speed will be constant. */ -static qreal easeInCurve(qreal t) +static qreal easeInCurve(qreal t) { const qreal sinProgress = qt_sinProgress(t); const qreal mix = qt_smoothBeginEndMixFactor(t); @@ -643,7 +643,7 @@ static qreal easeInCurve(qreal t) /** * Easing function that starts growing steadily, then ends slowly. The speed will be constant at the beginning of the curve. */ -static qreal easeOutCurve(qreal t) +static qreal easeOutCurve(qreal t) { const qreal sinProgress = qt_sinProgress(t); const qreal mix = qt_smoothBeginEndMixFactor(1 - t); @@ -653,7 +653,7 @@ static qreal easeOutCurve(qreal t) /** * Easing function where the value grows sinusoidally. Note that the calculated end value will be 0 rather than 1. */ -static qreal easeSineCurve(qreal t) +static qreal easeSineCurve(qreal t) { return (qSin(((t * M_PI * 2)) - M_PI_2) + 1) / 2; } @@ -662,7 +662,7 @@ static qreal easeSineCurve(qreal t) * Easing function where the value grows cosinusoidally. Note that the calculated start value will be 0.5 and the end value will be 0.5 * contrary to the usual 0 to 1 easing curve. */ -static qreal easeCosineCurve(qreal t) +static qreal easeCosineCurve(qreal t) { return (qCos(((t * M_PI * 2)) - M_PI_2) + 1) / 2; } diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 2b9e77d..f5b9323 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -42,51 +42,58 @@ /*! \class QAbstractAnimation \ingroup animation - \brief The QAbstractAnimation class provides an abstract base class for animations. + \brief The QAbstractAnimation class is the base of all animations. \since 4.5 \preliminary - This class is part of \l{The Animation Framework}. It serves as a base class - for standard animations and groups, with functions for shared - functionality, and it also makes it easy for you to define custom + The class defines the functions for the functionality shared by + all animations. By inheriting this class, you can create custom animations that plug into the rest of the animation framework. - If you want to create an animation, you should look at the two subclasses, - QVariantAnimation and QAnimationGroup, instead. - - QAbstractAnimation provides an interface for the current time and - duration, the iteration count, and the state of an animation. These properties - define the base functionality common to all animations in Qt. The virtual - duration() function returns the local duration of the animation; i.e., for - how long the animation should update the current time before - looping. Subclasses can implement this function differently; for example, - QVariantAnimation returns the duration of a simple animated property, whereas - QAnimationGroup returns the duration of a set or sequence of - animations. You can also set a loop count by calling setIterationCount(); a - iteration count of 2 will let the animation run twice (the default value is - 1). - - Like QTimeLine, QAbstractAnimation also provides an interface for starting - and stopping an animation, and for tracking its progress. You can call the - start() slot to start the animation. When the animation starts, the - stateChanged() signal is emitted, and state() returns Running. If you call the - stop() slot, the stateChanged() signal is emitted, and state() returns - Stopped. If you call the pause() slot, the stateChanged() signal is emitted - and state() returns Paused. If the animation reaches the end, the finished() - signal is emitted. You can check the current state by calling state(). - - QAbstractAnimation provides two functions that are pure virtual, and must - be reimplemented in a subclass: duration(), and updateCurrentTime(). The - duration() function lets you report a duration for the animation (a return - value of -1 signals that the animation runs forever until explicitly - stopped). The current time is delivered by the framework through calls to - updateCurrentTime(). By reimplementing this function, you can track the - animation progress and update your target objects accordingly. By - reimplementing updateState(), you can track the animation's state - changes, which is particularily useful for animations that are not driven - by time. - - \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} + The progress of an animation is given by its current time + (currentTime()), which is measured in milliseconds from the start + of the animation (0) to its end (duration()). The value is updated + automatically while the animation is running. It can also be set + directly with setCurrentTime(). + + At any point an animation is in one of three states: + \l{QAbstractAnimation::}{Running}, + \l{QAbstractAnimation::}{Stopped}, or + \l{QAbstractAnimation::}{Paused}--as defined by the + \l{QAbstractAnimation::}{State} enum. The current state can be + changed by calling start(), stop(), pause(), or resume(). An + animation will always reset its \l{currentTime()}{current time} + when it is started. If paused, it will continue with the same + current time when resumed. When an animation is stopped, it cannot + be resumed, but will keep its current time (until started again). + QAbstractAnimation will emit stateChanged() whenever its state + changes. + + An animation can loop any number of times by setting the loopCount + property. When an animation's current time reaches its duration(), + it will reset the current time and keep running. A loop count of 1 + (the default value) means that the animation will run one time. + Note that a duration of -1 means that the animation will run until + stopped; the current time will increase indefinitely. When the + current time equals duration() and the animation is in its + final loop, the \l{QAbstractAnimation::}{Stopped} state is + entered, and the finished() signal is emitted. + + QAbstractAnimation provides pure virtual functions used by + subclasses to track the progress of the animation: duration() and + updateCurrentTime(). The duration() function lets you report a + duration for the animation (as discussed above). The current time + is delivered by the animation framework through calls to + updateCurrentTime(). By reimplementing this function, you can + track the animation progress. Note that neither the interval + between calls nor the number of calls to this function are + defined; though, it will normally be 60 updates per second. + + By reimplementing updateState(), you can track the animation's + state changes, which is particularly useful for animations that + are not driven by time. + + \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework} */ /*! @@ -119,12 +126,12 @@ */ /*! - \fn QAbstractAnimation::currentIterationChanged(int currentIteration) + \fn QAbstractAnimation::currentLoopChanged(int currentLoop) - QAbstractAnimation emits this signal whenever the current iteration - changes. \a currentIteration is the current iteration. + QAbstractAnimation emits this signal whenever the current loop + changes. \a currentLoop is the current loop. - \sa currentIteration(), iterationCount() + \sa currentLoop(), loopCount() */ /*! @@ -149,13 +156,13 @@ #include <QtCore/qcoreevent.h> #include <QtCore/qpointer.h> -#define TIMER_INTERVAL 16 +#define DEFAULT_TIMER_INTERVAL 16 QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer); -QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0) +QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false) { } @@ -182,12 +189,38 @@ void QUnifiedTimer::updateRecentlyStartedAnimations() animationsToStart.clear(); } +/* + defines the timing interval. Default is DEFAULT_TIMER_INTERVAL +*/ +void QUnifiedTimer::setTimingInterval(int interval) +{ + timingInterval = interval; + if (animationTimer.isActive()) { + //we changed the timing interval + animationTimer.start(timingInterval, this); + } +} + +/* + this allows to have a consistent timer interval at each tick from the timer + not taking the real time that passed into account. +*/ +void QUnifiedTimer::setConsistentTiming(bool b) +{ + consistentTiming = b; +} + +int QUnifiedTimer::elapsedTime() const +{ + return lastTick; +} + void QUnifiedTimer::timerEvent(QTimerEvent *event) { //this is simply the time we last received a tick - int oldLastTick = lastTick; + const int oldLastTick = lastTick; if (time.isValid()) - lastTick = time.elapsed(); + lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed(); //we transfer the waiting animations into the "really running" state updateRecentlyStartedAnimations(); @@ -198,7 +231,7 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) animationTimer.stop(); time = QTime(); } else { - animationTimer.start(TIMER_INTERVAL, this); + animationTimer.start(timingInterval, this); lastTick = 0; time.start(); } @@ -245,7 +278,7 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) QAbstractAnimation::State oldState = state; int oldCurrentTime = currentTime; - int oldCurrentIteration = currentIteration; + int oldCurrentLoop = currentLoop; QAbstractAnimation::Direction oldDirection = direction; state = newState; @@ -274,7 +307,7 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) if (direction == QAbstractAnimation::Forward) q->setCurrentTime(0); else - q->setCurrentTime(iterationCount == -1 ? q->duration() : q->totalDuration()); + q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration()); } // Check if the setCurrentTime() function called stop(). @@ -302,8 +335,8 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) QUnifiedTimer::instance()->unregisterAnimation(q); - if (dura == -1 || iterationCount < 0 - || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentIteration + 1)) == (dura * iterationCount)) + if (dura == -1 || loopCount < 0 + || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount)) || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) { if (guard) emit q->finished(); @@ -459,10 +492,10 @@ void QAbstractAnimation::setDirection(Direction direction) if (state() == Stopped) { if (direction == Backward) { d->currentTime = duration(); - d->currentIteration = d->iterationCount - 1; + d->currentLoop = d->loopCount - 1; } else { d->currentTime = 0; - d->currentIteration = 0; + d->currentLoop = 0; } } updateDirection(direction); @@ -474,14 +507,14 @@ void QAbstractAnimation::setDirection(Direction direction) \brief the duration of the animation. If the duration is -1, it means that the duration is undefined. - In this case, iterationCount is ignored. + In this case, loopCount is ignored. */ /*! - \property QAbstractAnimation::iterationCount - \brief the iteration count of the animation + \property QAbstractAnimation::loopCount + \brief the loop count of the animation - This property describes the iteration count of the animation as an integer. + This property describes the loop count of the animation as an integer. By default this value is 1, indicating that the animation should run once only, and then stop. By changing it you can let the animation loop several times. With a value of 0, the animation will not @@ -490,34 +523,34 @@ void QAbstractAnimation::setDirection(Direction direction) It is not supported to have loop on an animation that has an undefined duration. It will only run once. */ -int QAbstractAnimation::iterationCount() const +int QAbstractAnimation::loopCount() const { Q_D(const QAbstractAnimation); - return d->iterationCount; + return d->loopCount; } -void QAbstractAnimation::setIterationCount(int iterationCount) +void QAbstractAnimation::setLoopCount(int loopCount) { Q_D(QAbstractAnimation); - d->iterationCount = iterationCount; + d->loopCount = loopCount; } /*! - \property QAbstractAnimation::currentIteration - \brief the current iteration of the animation + \property QAbstractAnimation::currentLoop + \brief the current loop of the animation - This property describes the current iteration of the animation. By default, - the animation's iteration count is 1, and so the current iteration will - always be 0. If the iteration count is 2 and the animation runs past its + This property describes the current loop of the animation. By default, + the animation's loop count is 1, and so the current loop will + always be 0. If the loop count is 2 and the animation runs past its duration, it will automatically rewind and restart at current time 0, and - current iteration 1, and so on. + current loop 1, and so on. - When the current iteration changes, QAbstractAnimation emits the - currentIterationChanged() signal. + When the current loop changes, QAbstractAnimation emits the + currentLoopChanged() signal. */ -int QAbstractAnimation::currentIteration() const +int QAbstractAnimation::currentLoop() const { Q_D(const QAbstractAnimation); - return d->currentIteration; + return d->currentLoop; } /*! @@ -525,7 +558,7 @@ int QAbstractAnimation::currentIteration() const This pure virtual function returns the duration of the animation, and defines for how long QAbstractAnimation should update the current - time. This duration is local, and does not include the iteration count. + time. This duration is local, and does not include the loop count. A return value of -1 indicates that the animation has no defined duration; the animation should run forever until stopped. This is useful for @@ -535,24 +568,24 @@ int QAbstractAnimation::currentIteration() const If the animation is a parallel QAnimationGroup, the duration will be the longest duration of all its animations. If the animation is a sequential QAnimationGroup, the duration will be the sum of the duration of all its animations. - \sa iterationCount + \sa loopCount */ /*! Returns the total and effective duration of the animation, including the - iteration count. + loop count. \sa duration(), currentTime */ int QAbstractAnimation::totalDuration() const { Q_D(const QAbstractAnimation); - if (d->iterationCount < 0) + if (d->loopCount < 0) return -1; int dura = duration(); if (dura == -1) return -1; - return dura * d->iterationCount; + return dura * d->loopCount; } /*! @@ -565,11 +598,11 @@ int QAbstractAnimation::totalDuration() const progresses. The animation's current time starts at 0, and ends at duration(). If the - animation's iterationCount is larger than 1, the current time will rewind and + animation's loopCount is larger than 1, the current time will rewind and start at 0 again for the consecutive loops. If the animation has a pause. currentTime will also include the duration of the pause. - \sa iterationCount + \sa loopCount */ int QAbstractAnimation::currentTime() const { @@ -583,31 +616,31 @@ void QAbstractAnimation::setCurrentTime(int msecs) // Calculate new time and loop. int dura = duration(); - int totalDura = (d->iterationCount < 0 || dura == -1) ? -1 : dura * d->iterationCount; + int totalDura = (d->loopCount < 0 || dura == -1) ? -1 : dura * d->loopCount; if (totalDura != -1) msecs = qMin(totalDura, msecs); d->totalCurrentTime = msecs; // Update new values. - int oldLoop = d->currentIteration; - d->currentIteration = ((dura <= 0) ? 0 : (msecs / dura)); - if (d->currentIteration == d->iterationCount) { + int oldLoop = d->currentLoop; + d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura)); + if (d->currentLoop == d->loopCount) { //we're at the end d->currentTime = qMax(0, dura); - d->currentIteration = qMax(0, d->iterationCount - 1); + d->currentLoop = qMax(0, d->loopCount - 1); } else { if (d->direction == Forward) { d->currentTime = (dura <= 0) ? msecs : (msecs % dura); } else { d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1; if (d->currentTime == dura) - --d->currentIteration; + --d->currentLoop; } } updateCurrentTime(msecs); - if (d->currentIteration != oldLoop) - emit currentIterationChanged(d->currentIteration); + if (d->currentLoop != oldLoop) + emit currentLoopChanged(d->currentLoop); // All animations are responsible for stopping the animation when their // own end state is reached; in this case the animation is time driven, @@ -648,7 +681,7 @@ void QAbstractAnimation::start(DeletionPolicy policy) signal, and state() returns Stopped. The current time is not changed. If the animation stops by itself after reaching the end (i.e., - currentTime() == duration() and currentIteration() > iterationCount() - 1), the + currentTime() == duration() and currentLoop() > loopCount() - 1), the finished() signal is emitted. \sa start(), state() diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h index d6260cd..a7f0082 100644 --- a/src/corelib/animation/qabstractanimation.h +++ b/src/corelib/animation/qabstractanimation.h @@ -60,9 +60,9 @@ class Q_CORE_EXPORT QAbstractAnimation : public QObject { Q_OBJECT Q_PROPERTY(State state READ state NOTIFY stateChanged) - Q_PROPERTY(int iterationCount READ iterationCount WRITE setIterationCount) + Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount) Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime) - Q_PROPERTY(int currentIteration READ currentIteration NOTIFY currentIterationChanged) + Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged) Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged) Q_PROPERTY(int duration READ duration) @@ -93,9 +93,9 @@ public: Direction direction() const; void setDirection(Direction direction); - int iterationCount() const; - void setIterationCount(int iterationCount); - int currentIteration() const; + int loopCount() const; + void setLoopCount(int loopCount); + int currentLoop() const; virtual int duration() const = 0; int totalDuration() const; @@ -105,7 +105,7 @@ public: Q_SIGNALS: void finished(); void stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState); - void currentIterationChanged(int currentIteration); + void currentLoopChanged(int currentLoop); void directionChanged(QAbstractAnimation::Direction); public Q_SLOTS: diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 28d7d71..41983a5 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -77,8 +77,8 @@ public: deleteWhenStopped(false), totalCurrentTime(0), currentTime(0), - iterationCount(1), - currentIteration(0), + loopCount(1), + currentLoop(0), group(0) { } @@ -97,8 +97,8 @@ public: int totalCurrentTime; int currentTime; - int iterationCount; - int currentIteration; + int loopCount; + int currentLoop; QAnimationGroup *group; #ifdef QT_EXPERIMENTAL_SOLUTION @@ -110,7 +110,7 @@ private: }; -class QUnifiedTimer : public QObject +class Q_CORE_EXPORT QUnifiedTimer : public QObject { private: QUnifiedTimer(); @@ -118,11 +118,17 @@ private: public: static QUnifiedTimer *instance(); - void timerEvent(QTimerEvent *); - void updateTimer(); void registerAnimation(QAbstractAnimation *animation); void unregisterAnimation(QAbstractAnimation *animation); + void setTimingInterval(int interval); + void setConsistentTiming(bool consistent); + + int elapsedTime() const; + +protected: + void timerEvent(QTimerEvent *); + void updateTimer(); private: void updateRecentlyStartedAnimations(); @@ -130,6 +136,8 @@ private: QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; + int timingInterval; + bool consistentTiming; QList<QAbstractAnimation*> animations, animationsToStart; }; diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index f39738b..2f8cc28 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -46,18 +46,46 @@ \ingroup animation \preliminary - QAnimationGroup represents a group of animations, such as parallel or sequential, - and lets you combine different animations into one. The group manages any animation - that inherits QAbstractAnimation. By combining groups, you can easily construct - complex animation graphs. - - The QAnimationGroup base class provides methods for adding and retrieving animations. - Besides that, you can remove animations by calling remove(), and clear the animation - group by calling clearAnimations(). You may keep track of changes in the group's animations by - listening to QEvent::ChildAdded and QEvent::ChildRemoved events. - - QAnimationGroup takes ownership of the animations it manages, and ensures that they are - deleted when the animation group is deleted. + An animation group is a container for animations (subclasses of + QAbstractAnimation). A group is usually responsible for managing + the \l{QAbstractAnimation::State}{state} of its animations, i.e., + it decides when to start, stop, resume, and pause them. Currently, + Qt provides two such groups: QParallelAnimationGroup and + QSequentialAnimationGroup. Look up their class descriptions for + details. + + Since QAnimationGroup inherits from QAbstractAnimation, you can + combine groups, and easily construct complex animation graphs. + You can query QAbstractAnimation for the group it belongs to + (using the \l{QAbstractAnimation::}{group()} function). + + To start a top-level animation group, you simply use the + \l{QAbstractAnimation::}{start()} function from + QAbstractAnimation. By a top-level animation group, we think of a + group that itself is not contained within another group. Starting + sub groups directly is not supported, and may lead to unexpected + behavior. + + \omit OK, we'll put in a snippet on this here \endomit + + QAnimationGroup provides methods for adding and retrieving + animations. Besides that, you can remove animations by calling + remove(), and clear the animation group by calling + clearAnimations(). You may keep track of changes in the group's + animations by listening to QEvent::ChildAdded and + QEvent::ChildRemoved events. + + \omit OK, let's find a snippet here as well. \endomit + + QAnimationGroup takes ownership of the animations it manages, and + ensures that they are deleted when the animation group is deleted. + + You can also use a \l{The State Machine Framework}{state machine} + to create complex animations. The framework provides a special + state, QAnimationState, that plays an animation upon entry and + transitions to a new state when the animation has finished + playing. This technique can also be combined with using animation + groups. \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework} */ @@ -164,9 +192,10 @@ void QAnimationGroup::insertAnimationAt(int index, QAbstractAnimation *animation return; } - d->animations.insert(index, animation); if (QAnimationGroup *oldGroup = animation->group()) oldGroup->removeAnimation(animation); + + d->animations.insert(index, animation); QAbstractAnimationPrivate::get(animation)->group = this; // this will make sure that ChildAdded event is sent to 'this' animation->setParent(this); diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index 993c577..e4bce6a 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -46,8 +46,27 @@ \ingroup animation \preliminary - The animations are all started at the same time, and run in parallel. The animation group - finishes when the longest lasting animation has finished. + QParallelAnimationGroup--a \l{QAnimationGroup}{container for + animations}--starts all its animations when it is + \l{QAbstractAnimation::start()}{started} itself, i.e., runs all + animations in parallel. The animation group finishes when the + longest lasting animation has finished. + + You can treat QParallelAnimation as any other QAbstractAnimation, + e.g., pause, resume, or add it to other animation groups. + + \code + QParallelAnimationGroup *group = new QParallelAnimationGroup; + group->addAnimation(anim1); + group->addAnimation(anim2); + + group->start(); + \endcode + + In this example, \c anim1 and \c anim2 are two + \l{QPropertyAnimation}s that have already been set up. + + \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION @@ -111,7 +130,7 @@ void QParallelAnimationGroup::updateCurrentTime(int) if (d->animations.isEmpty()) return; - if (d->currentIteration > d->lastIteration) { + if (d->currentLoop > d->lastLoop) { // simulate completion of the loop int dura = duration(); if (dura > 0) { @@ -119,7 +138,7 @@ void QParallelAnimationGroup::updateCurrentTime(int) animation->setCurrentTime(dura); // will stop } } - } else if (d->currentIteration < d->lastIteration) { + } else if (d->currentLoop < d->lastLoop) { // simulate completion of the loop seeking backwards foreach (QAbstractAnimation *animation, d->animations) { animation->setCurrentTime(0); @@ -127,11 +146,11 @@ void QParallelAnimationGroup::updateCurrentTime(int) } } - bool timeFwd = ((d->currentIteration == d->lastIteration && d->currentTime >= d->lastCurrentTime) - || d->currentIteration > d->lastIteration); + bool timeFwd = ((d->currentLoop == d->lastLoop && d->currentTime >= d->lastCurrentTime) + || d->currentLoop > d->lastLoop); #ifdef QANIMATION_DEBUG qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d", - __LINE__, d->currentTime, d->currentIteration, d->lastIteration, timeFwd, d->lastCurrentTime, state()); + __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state()); #endif // finally move into the actual time of the current loop foreach (QAbstractAnimation *animation, d->animations) { @@ -139,7 +158,7 @@ void QParallelAnimationGroup::updateCurrentTime(int) if (dura == -1 && d->isUncontrolledAnimationFinished(animation)) continue; if (dura == -1 || (d->currentTime <= dura && dura != 0) - || (dura == 0 && d->currentIteration != d->lastIteration)) { + || (dura == 0 && d->currentLoop != d->lastLoop)) { switch (state()) { case Running: animation->start(); @@ -165,7 +184,7 @@ void QParallelAnimationGroup::updateCurrentTime(int) if (d->currentTime > dura) animation->stop(); } - d->lastIteration = d->currentIteration; + d->lastLoop = d->currentLoop; d->lastCurrentTime = d->currentTime; } @@ -207,7 +226,7 @@ void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished() Q_ASSERT(animation); int uncontrolledRunningCount = 0; - if (animation->duration() == -1 || animation->iterationCount() < 0) { + if (animation->duration() == -1 || animation->loopCount() < 0) { QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin(); while (it != uncontrolledFinishTime.end()) { if (it.key() == animation) { @@ -248,7 +267,7 @@ void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() Q_Q(QParallelAnimationGroup); foreach (QAbstractAnimation *animation, animations) { - if (animation->duration() == -1 || animation->iterationCount() < 0) { + if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); } @@ -273,11 +292,11 @@ void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction dire } } else { if (direction == Forward) { - d->lastIteration = 0; + d->lastLoop = 0; d->lastCurrentTime = 0; } else { - // Looping backwards with iterationCount == -1 does not really work well... - d->lastIteration = (d->iterationCount == -1 ? 0 : d->iterationCount - 1); + // Looping backwards with loopCount == -1 does not really work well... + d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1); d->lastCurrentTime = duration(); } } diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h index 8a4dc1b..f36d972 100644 --- a/src/corelib/animation/qparallelanimationgroup_p.h +++ b/src/corelib/animation/qparallelanimationgroup_p.h @@ -64,12 +64,12 @@ class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate Q_DECLARE_PUBLIC(QParallelAnimationGroup) public: QParallelAnimationGroupPrivate() - : lastIteration(0), lastCurrentTime(0) + : lastLoop(0), lastCurrentTime(0) { } QHash<QAbstractAnimation*, int> uncontrolledFinishTime; - int lastIteration; + int lastLoop; int lastCurrentTime; bool isUncontrolledAnimationFinished(QAbstractAnimation *anim) const; diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp index 30ea92c..685fa98 100644 --- a/src/corelib/animation/qpauseanimation.cpp +++ b/src/corelib/animation/qpauseanimation.cpp @@ -45,6 +45,22 @@ \since 4.5 \ingroup animation \preliminary + + If you wish to introduce a delay between animations in a + QSequentialAnimationGroup, you can insert a QPauseAnimation. This + class does not animate anything, but does not + \l{QAbstractAnimation::finished()}{finish} before a specified + number of milliseconds have elapsed from when it was started. You + specify the duration of the pause in the constructor. It can also + be set directly with setDuration(). + + It is not necessary to construct a QPauseAnimation yourself. + QSequentialAnimationGroup provides the convenience functions + \l{QSequentialAnimationGroup::}{addPause()} and + \l{QSequentialAnimationGroup::}{insertPauseAt()}. These functions + simply take the number of milliseconds the pause should last. + + \sa QSequentialAnimationGroup */ #ifndef QT_NO_ANIMATION diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index adf3527..96cfa6b 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -41,27 +41,48 @@ /*! \class QPropertyAnimation - \brief The QPropertyAnimation class animates properties for QObject(and QWidget) + \brief The QPropertyAnimation class animates Qt properties \ingroup animation \preliminary - This class is part of {The Animation Framework}. You can use QPropertyAnimation - by itself as a simple animation class, or as part of more complex - animations through QAnimationGroup. - - The most common way to use QPropertyAnimation is to construct an instance - of it by passing a pointer to a QObject or a QWidget, and the name of the - property you would like to animate to QPropertyAnimation's constructor. - - The start value of the animation is optional. If you do not set any start - value, the animation will operate on the target's current property value - at the point when the animation was started. You can call setStartValue() - to set the start value, and setEndValue() to set the target value for - the animated property. - - Animations can operate on QObjects and QWidgets. You can choose to assign a - target object by either calling setTargetObject() or by passing a QObject - pointer to QPropertyAnimation's constructor. + QPropertyAnimation interpolates over \l{Qt's Property System}{Qt + properties}. As property values are stored in \l{QVariant}s, the + class inherits QVariantAnimation, and supports animation of the + same \l{QVariant::Type}{variant types} as its super class. + + A class declaring properties must be a QObject. To make it + possible to animate a property, it must provide a setter (so that + QPropertyAnimation can set the property's value). Note that this + makes it possible to animate many of Qt's widgets. Let's look at + an example: + + \code + QPropertyAnimation animation(myWidget, "geometry"); + animation.setDuration(10000); + animation.setStartValue(QRect(0, 0, 100, 30)); + animation.setEndValue(QRect(250, 250, 100, 30)); + + animation.start(); + \endcode + + The property name and the QObject instance of which property + should be animated are passed to the constructor. You can then + specify the start and end value of the property. The procedure is + equal for properties in classes you have implemented + yourself--just check with QVariantAnimation that your QVariant + type is supported. + + The QVariantAnimation class description explains how to set up the + animation in detail. Note, however, that if a start value is not + set, the property will start at the value it had when the + QPropertyAnimation instance was created. + + QPropertyAnimation works like a charm on its own. For complex + animations that, for instance, contain several objects, + QAnimationGroup is provided. An animation group is an animation + that can contain other animations, and that can manage when its + animations are played. Look at QParallelAnimationGroup for an + example. \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} */ @@ -97,6 +118,8 @@ void QPropertyAnimationPrivate::updateMetaProperty() property = mo->property(propertyIndex); propertyType = property.userType(); } else { + if (!target->dynamicPropertyNames().contains(propertyName)) + qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData()); hasMetaProperty = 2; } } @@ -220,11 +243,20 @@ void QPropertyAnimation::updateCurrentValue(const QVariant &value) /*! \reimp + + If the startValue is not defined when the state of the animation changes from Stopped to Running, + the current property value is used as the initial value for the animation. */ void QPropertyAnimation::updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState) { Q_D(QPropertyAnimation); + + if (!d->target) { + qWarning("QPropertyAnimation::updateState: Changing state of an animation without target"); + return; + } + QVariantAnimation::updateState(oldState, newState); QMutexLocker locker(guardHashLock()); QPropertyAnimationHash * hash = _q_runningAnimations(); @@ -233,20 +265,21 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State oldState, d->updateMetaProperty(); QPropertyAnimation *oldAnim = hash->value(key, 0); if (oldAnim) { - //we try to stop the top level group + // try to stop the top level group QAbstractAnimation *current = oldAnim; - while(current->group() && current->state() != Stopped) current = current->group(); + while (current->group() && current->state() != Stopped) + current = current->group(); current->stop(); } hash->insert(key, this); - // Initialize start value - if (d->target && !d->defaultStartValue.isValid() && (d->atBeginning() || d->atEnd())) { + + // update the default start value + if (oldState == Stopped) { d->setDefaultStartValue(d->target->property(d->propertyName.constData())); } } else if (hash->value(key) == this) { hash->remove(key); } - } #include "moc_qpropertyanimation.cpp" diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h index e5d5305..b619256 100644 --- a/src/corelib/animation/qpropertyanimation.h +++ b/src/corelib/animation/qpropertyanimation.h @@ -47,7 +47,6 @@ #else # include <QtCore/qvariantanimation.h> #endif -#include <QtCore/qvariant.h> QT_BEGIN_HEADER diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 879532c..38f4818 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -46,13 +46,36 @@ \ingroup animation \preliminary - The first animation in the group is started first, and when it finishes, the next animation - is started, and so on. The animation group finishes when the last animation has finished. + QSequentialAnimationGroup is a QAnimationGroup that runs its + animations in sequence, i.e., it starts one animation after + another has finished playing. The animations are played in the + order they are added to the group (using + \l{QAnimationGroup::}{addAnimation()} or + \l{QAnimationGroup::}{insertAnimationAt()}). The animation group + finishes when its last animation has finished. - At each moment there is at most one animation that is active in the group, called currentAnimation. - An empty group has no current animation. + At each moment there is at most one animation that is active in + the group; it is returned by currentAnimation(). An empty group + has no current animation. - You can call addPause() or insertPause() to add a pause to a sequential animation group. + A sequential animation group can be treated as any other + animation, i.e., it can be started, stopped, and added to other + groups. You can also call addPause() or insertPauseAt() to add a + pause to a sequential animation group. + + \code + QSequentialAnimationGroup group; + + group.addAnimation(anim1); + group.addAnimation(anim2); + + group.start(); + \endcode + + In this example, \c anim1 and \c anim2 are two already set up + \l{QPropertyAnimation}s. + + \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework} */ #ifndef QT_NO_ANIMATION @@ -77,7 +100,7 @@ bool QSequentialAnimationGroupPrivate::atEnd() const // 3. the current animation is the last one // 4. the current animation has reached its end const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime; - return (currentIteration == iterationCount - 1 + return (currentLoop == loopCount - 1 && direction == QAbstractAnimation::Forward && currentAnimation == animations.last() && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex)); @@ -101,7 +124,7 @@ QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivat int duration = 0; // in case duration is -1, currentLoop will always be 0 - ret.timeOffset = currentIteration * q->duration(); + ret.timeOffset = currentLoop * q->duration(); for (int i = 0; i < animations.size(); ++i) { duration = animationActualTotalDuration(i); @@ -133,13 +156,13 @@ void QSequentialAnimationGroupPrivate::restart() { // restarting the group by making the first/last animation the current one if (direction == QAbstractAnimation::Forward) { - lastIteration = 0; + lastLoop = 0; if (currentAnimationIndex == 0) activateCurrentAnimation(); else setCurrentAnimation(0); } else { // direction == QAbstractAnimation::Backward - lastIteration = iterationCount - 1; + lastLoop = loopCount - 1; int index = animations.size() - 1; if (currentAnimationIndex == index) activateCurrentAnimation(); @@ -156,7 +179,7 @@ void QSequentialAnimationGroupPrivate::restart() */ void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex) { - if (lastIteration < currentIteration) { + if (lastLoop < currentLoop) { // we need to fast forward to the end for (int i = currentAnimationIndex; i < animations.size(); ++i) { QAbstractAnimation *anim = animations.at(i); @@ -188,7 +211,7 @@ void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &new */ void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex) { - if (lastIteration > currentIteration) { + if (lastLoop > currentLoop) { // we need to fast rewind to the beginning for (int i = currentAnimationIndex; i >= 0 ; --i) { QAbstractAnimation *anim = animations.at(i); @@ -329,12 +352,12 @@ void QSequentialAnimationGroup::updateCurrentTime(int msecs) d->actualDuration.removeLast(); // newAnimationIndex.index is the new current animation - if (d->lastIteration < d->currentIteration - || (d->lastIteration == d->currentIteration && d->currentAnimationIndex < newAnimationIndex.index)) { + if (d->lastLoop < d->currentLoop + || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) { // advancing with forward direction is the same as rewinding with backwards direction d->advanceForwards(newAnimationIndex); - } else if (d->lastIteration > d->currentIteration - || (d->lastIteration == d->currentIteration && d->currentAnimationIndex > newAnimationIndex.index)) { + } else if (d->lastLoop > d->currentLoop + || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) { // rewinding with forward direction is the same as advancing with backwards direction d->rewindForwards(newAnimationIndex); } @@ -358,7 +381,7 @@ void QSequentialAnimationGroup::updateCurrentTime(int msecs) stop(); } - d->lastIteration = d->currentIteration; + d->lastLoop = d->currentLoop; } /*! @@ -505,7 +528,7 @@ void QSequentialAnimationGroupPrivate::animationInsertedAt(int index) setCurrentAnimation(0); // initialize the current animation if (currentAnimationIndex == index - && currentAnimation->currentTime() == 0 && currentAnimation->currentIteration() == 0) { + && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) { //in this case we simply insert an animation before the current one has actually started setCurrentAnimation(index); } @@ -513,7 +536,7 @@ void QSequentialAnimationGroupPrivate::animationInsertedAt(int index) //we update currentAnimationIndex in case it has changed (the animation pointer is still valid) currentAnimationIndex = animations.indexOf(currentAnimation); - if (index < currentAnimationIndex || currentIteration != 0) { + if (index < currentAnimationIndex || currentLoop != 0) { qWarning("QSequentialGroup::insertAnimationAt only supports to add animations after the current one."); return; //we're not affected because it is added after the current one } @@ -562,7 +585,7 @@ void QSequentialAnimationGroupPrivate::animationRemovedAt(int index) } //let's also update the total current time - totalCurrentTime = currentTime + iterationCount * q->duration(); + totalCurrentTime = currentTime + loopCount * q->duration(); } QT_END_NAMESPACE diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index 05d2a40..3ac90f8 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -64,7 +64,7 @@ class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate Q_DECLARE_PUBLIC(QSequentialAnimationGroup) public: QSequentialAnimationGroupPrivate() - : currentAnimation(0), currentAnimationIndex(-1), lastIteration(0) + : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0) { } @@ -96,7 +96,7 @@ public: QList<int> actualDuration; void restart(); - int lastIteration; + int lastLoop; // handle time changes void rewindForwards(const AnimationIndex &newAnimationIndex); diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 6b162ae..73ed0df 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -59,26 +59,68 @@ QT_BEGIN_NAMESPACE \since 4.5 \preliminary - This class is part of {The Animation Framework}. It serves as a base class - for property and item animations, with functions for shared functionality. - - If you want to create an animation, you should look at QPropertyAnimation instead. - + This class is part of \l{The Animation Framework}. It serves as a + base class for property and item animations, with functions for + shared functionality. + + QVariantAnimation cannot be used directly as it is an abstract + class; it does not implement + \l{QAbstractAnimation::}{updateCurrentValue()} from + QAbstractAnimation. The class performs interpolation over + \l{QVariant}s, but leaves using the interpolated values to its + subclasses. Currently, Qt provides QPropertyAnimation, which + animates Qt \l{Qt's Property System}{properties}. See the + QPropertyAnimation class description if you wish to animate such + properties. + You can then set start and end values for the property by calling setStartValue() and setEndValue(), and finally call start() to - start the animation. When control goes back to the event loop, QVariantAnimation - will interpolate the property of the target object and emit the valueChanged - signal. To react to a change in the current value you have to reimplement the - updateCurrentValue virtual method. - - There are two ways to affect how QVariantAnimation interpolates the values. - You can set an easing curve by calling setEasingCurve(), and configure the - duration by calling setDuration(). You can change how the QVariants are - interpolated by creating a subclass of QVariantAnimation, and reimplementing the - virtual interpolated() function. - - - \sa QPropertyAnimation, {The Animation Framework} + start the animation. QVariantAnimation will interpolate the + property of the target object and emit valueChanged(). To react to + a change in the current value you have to reimplement the + updateCurrentValue() virtual function. + + It is also possible to set values at specified steps situated + between the start and end value. The interpolation will then + touch these points at the specified steps. Note that the start and + end values are defined as the key values at 0.0 and 1.0. + + There are two ways to affect how QVariantAnimation interpolates + the values. You can set an easing curve by calling + setEasingCurve(), and configure the duration by calling + setDuration(). You can change how the QVariants are interpolated + by creating a subclass of QVariantAnimation, and reimplementing + the virtual interpolated() function. + + Subclassing QVariantAnimation can be an alternative if you have + \l{QVariant}s that you do not wish to declare as Qt properties. + Note, however, that you in most cases will be better off declaring + your QVariant as a property. + + Not all QVariant types are supported. Below is a list of currently + supported QVariant types: + + \list + \o \l{QMetaType::}{Int} + \o \l{QMetaType::}{Double} + \o \l{QMetaType::}{Float} + \o \l{QMetaType::}{QLine} + \o \l{QMetaType::}{QLineF} + \o \l{QMetaType::}{QPoint} + \o \l{QMetaType::}{QSize} + \o \l{QMetaType::}{QSizeF} + \o \l{QMetaType::}{QRect} + \o \l{QMetaType::}{QRectF} + \endlist + + If you need to interpolate other variant types, including custom + types, you have to implement interpolation for these yourself. + You do this by reimplementing interpolated(), which returns + interpolation values for the value being interpolated. + + \omit We need some snippets around here. \endomit + + \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework} */ /*! @@ -175,26 +217,16 @@ void QVariantAnimationPrivate::updateCurrentValue() endProgress = currentInterval.end.first; const qreal localProgress = (progress - startProgress) / (endProgress - startProgress); - bool changed = false; - { - //we do that here in a limited scope so that ret is dereferenced and frees memory - //and the call to updateCurrentValue can recreate QVariant of the same type (for ex. in - //QGraphicsItem::setPos - QVariant ret = q->interpolated(currentInterval.start.second, - currentInterval.end.second, - localProgress); - if (currentValue != ret) { - changed = true; - qSwap(currentValue, ret); - } - } - - if (changed) { - //the value has changed - q->updateCurrentValue(currentValue); + QVariant ret = q->interpolated(currentInterval.start.second, + currentInterval.end.second, + localProgress); + qSwap(currentValue, ret); + q->updateCurrentValue(currentValue); #ifndef QT_EXPERIMENTAL_SOLUTION if (connectedSignals & changedSignalMask) #endif + if (currentValue != ret) { + //the value has changed emit q->valueChanged(currentValue); } } @@ -271,16 +303,16 @@ QVariantAnimation::~QVariantAnimation() \property QVariantAnimation::easingCurve \brief the easing curve of the animation - This property defines the easing curve of the animation. By default, a - linear easing curve is used, resulting in linear interpolation of the - end property. For many animations, it's useful to try different easing - curves, including QEasingCurve::InCirc, which provides a circular entry curve, - and QEasingCurve::InOutElastic, which provides an elastic effect on the values - of the interpolated property. + This property defines the easing curve of the animation. By + default, a linear easing curve is used, resulting in linear + interpolation. Other curves are provided, for instance, + QEasingCurve::InCirc, which provides a circular entry curve. + Another example is QEasingCurve::InOutElastic, which provides an + elastic effect on the values of the interpolated variant. - The easing curve is used with the interpolator, the interpolated() virtual - function, the animation's duration, and iterationCount, to control how the - current value changes as the animation progresses. + The easing curve is used with the interpolator, the interpolated() + virtual function, the animation's duration, and iterationCount, to + control how the current value changes as the animation progresses. */ QEasingCurve QVariantAnimation::easingCurve() const { @@ -340,7 +372,7 @@ template<typename T> static inline QVariantAnimation::Interpolator castToInterpo return reinterpret_cast<QVariantAnimation::Interpolator>(func); } -static QVariantAnimation::Interpolator getInterpolator(int interpolationType) +QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType) { QReadLocker locker(registeredInterpolatorsLock()); QVariantAnimation::Interpolator ret = 0; @@ -382,8 +414,8 @@ static QVariantAnimation::Interpolator getInterpolator(int interpolationType) \property QVariantAnimation::duration \brief the duration of the animation - This property describes the duration of the animation. The default - duration is 250 milliseconds. + This property describes the duration in milliseconds of the + animation. The default duration is 250 milliseconds. \sa QAbstractAnimation::duration() */ @@ -519,17 +551,22 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues) /*! \property QVariantAnimation::currentValue - \brief the current value of the animation + \brief the current value of the animation. - This property describes the current value; an interpolation between the - start value and the end value, using the current time for progress. + This property describes the current value; an interpolated value + between the \l{startValue}{start value} and the \l{endValue}{end + value}, using the current time for progress. The value itself is + obtained from interpolated(), which is called repeatedly as the + animation is running. - QVariantAnimation calls the virtual updateCurrentValue() function when the - current value changes. This is particularily useful for subclasses that - need to track updates. + QVariantAnimation calls the virtual updateCurrentValue() function + when the current value changes. This is particularly useful for + subclasses that need to track updates. For example, + QPropertyAnimation uses this function to animate Qt \l{Qt's + Property System}{properties}. \sa startValue, endValue - */ +*/ QVariant QVariantAnimation::currentValue() const { Q_D(const QVariantAnimation); @@ -559,13 +596,22 @@ void QVariantAnimation::updateState(QAbstractAnimation::State oldState, } /*! - This virtual function returns the linear interpolation between variants \a - from and \a to, at \a progress, usually a value between 0 and 1. You can reimplement - this function in a subclass of QVariantAnimation to provide your own interpolation - algorithm. Note that in order for the interpolation to work with a QEasingCurve - that return a value smaller than 0 or larger than 1 (such as QEasingCurve::InBack) - you should make sure that it can extrapolate. If the semantic of the datatype - does not allow extrapolation this function should handle that gracefully. + + This virtual function returns the linear interpolation between + variants \a from and \a to, at \a progress, usually a value + between 0 and 1. You can reimplement this function in a subclass + of QVariantAnimation to provide your own interpolation algorithm. + + Note that in order for the interpolation to work with a + QEasingCurve that return a value smaller than 0 or larger than 1 + (such as QEasingCurve::InBack) you should make sure that it can + extrapolate. If the semantic of the datatype does not allow + extrapolation this function should handle that gracefully. + + You should call the QVariantAnimation implementation of this + function if you want your class to handle the types already + supported by Qt (see class QVariantAnimation description for a + list of supported types). \sa QEasingCurve */ @@ -574,7 +620,7 @@ QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &t Q_D(const QVariantAnimation); if (d->interpolator == 0) { if (from.userType() == to.userType()) - d->interpolator = getInterpolator(from.userType()); + d->interpolator = QVariantAnimationPrivate::getInterpolator(from.userType()); if (d->interpolator == 0) //no interpolator found return QVariant(); } diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h index 7ce597f..69dbbf3 100644 --- a/src/corelib/animation/qvariantanimation.h +++ b/src/corelib/animation/qvariantanimation.h @@ -49,8 +49,7 @@ # include <QtCore/qeasingcurve.h> # include <QtCore/qabstractanimation.h> #endif -#include <QtCore/qlist.h> -#include <QtCore/qpoint.h> +#include <QtCore/qvector.h> #include <QtCore/qvariant.h> #include <QtCore/qpair.h> diff --git a/src/corelib/animation/qvariantanimation_p.h b/src/corelib/animation/qvariantanimation_p.h index e468ac9..14a3ef6 100644 --- a/src/corelib/animation/qvariantanimation_p.h +++ b/src/corelib/animation/qvariantanimation_p.h @@ -88,18 +88,6 @@ public: return q->d_func(); } - - //some helper functions - bool atBeginning() const - { - return currentTime == 0; - } - - bool atEnd() const - { - return currentTime == duration && currentIteration == (iterationCount - 1); - } - void setDefaultStartValue(const QVariant &value); int duration; @@ -109,7 +97,7 @@ public: QVariant currentValue; QVariant defaultStartValue; bool hasStartValue; - + //this is used to keep track of the KeyValue interval in which we currently are struct { @@ -124,6 +112,8 @@ public: void setValueAt(qreal, const QVariant &); QVariant valueAt(qreal step) const; void convertValues(int t); + + static QVariantAnimation::Interpolator getInterpolator(int interpolationType); }; //this should make the interpolation faster diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 11a2d3c..d6b0174 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -264,6 +264,8 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal + \omitvalue Wrapped + \omitvalue Signal */ /*! diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 5e76976..18188a8 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -269,9 +269,8 @@ public: CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear - Signal = 191, - StateFinished = 192, - Bound = 193, + Signal = 192, + Wrapped = 193, // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 1795bd6..3f84314 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -41,9 +41,10 @@ #include "qabstractstate.h" #include "qabstractstate_p.h" +#include "qstate.h" +#include "qstate_p.h" #include "qstatemachine.h" #include "qstatemachine_p.h" -#include "qstate.h" QT_BEGIN_NAMESPACE @@ -52,16 +53,18 @@ QT_BEGIN_NAMESPACE \brief The QAbstractState class is the base class of states of a QStateMachine. + \since 4.6 \ingroup statemachine The QAbstractState class is the abstract base class of states that are part of a QStateMachine. It defines the interface that all state objects have in common. QAbstractState is part of \l{The State Machine Framework}. - The assignProperty() function is used for defining property assignments that - should be performed when a state is entered. + The entered() signal is emitted when the state has been entered. The + exited() signal is emitted when the state has been exited. - The parentState() function returns the state's parent state. + The parentState() function returns the state's parent state. The machine() + function returns the state machine that the state is part of. \section1 Subclassing @@ -72,45 +75,7 @@ QT_BEGIN_NAMESPACE function to perform custom processing when the state is exited. */ -/*! - \enum QAbstractState::RestorePolicy - - This enum specifies the restore policy type for a state. The restore policy - takes effect when the machine enters a state which sets one or more - properties. If the restore policy of the state is set to RestoreProperties, - the state machine will save the original value of the property before the - new value is set. - - Later, when the machine either enters a state which has its restore policy - set to DoNotRestoreProperties or when it enters a state which does not set - a value for the given property, the property will automatically be restored - to its initial value. - - Only one initial value will be saved for any given property. If a value for a property has - already been saved by the state machine, it will not be overwritten until the property has been - successfully restored. Once the property has been restored, the state machine will clear the - initial value until it enters a new state which sets the property and which has RestoreProperties - as its restore policy. - - \value GlobalRestorePolicy The restore policy for the state should be retrieved using - QStateMachine::globalRestorePolicy() - \value DoNotRestoreProperties The state machine should not save the initial values of properties - set in the state and restore them later. - \value RestoreProperties The state machine should save the initial values of properties - set in the state and restore them later. - - - \sa setRestorePolicy(), restorePolicy() -*/ - -/*! - \property QAbstractState::restorePolicy - - \brief the restore policy of this state -*/ - -QAbstractStatePrivate::QAbstractStatePrivate() - : restorePolicy(QAbstractState::GlobalRestorePolicy) +QAbstractStatePrivate::QAbstractStatePrivate() { } @@ -136,16 +101,28 @@ QStateMachine *QAbstractStatePrivate::machine() const return 0; } -void QAbstractStatePrivate::callOnEntry() +void QAbstractStatePrivate::callOnEntry(QEvent *e) +{ + Q_Q(QAbstractState); + q->onEntry(e); +} + +void QAbstractStatePrivate::callOnExit(QEvent *e) { Q_Q(QAbstractState); - q->onEntry(); + q->onExit(e); } -void QAbstractStatePrivate::callOnExit() +void QAbstractStatePrivate::emitEntered() { Q_Q(QAbstractState); - q->onExit(); + emit q->entered(); +} + +void QAbstractStatePrivate::emitExited() +{ + Q_Q(QAbstractState); + emit q->exited(); } /*! @@ -203,55 +180,43 @@ QState *QAbstractState::parentState() const } /*! - Instructs this state to set the property with the given \a name of the given - \a object to the given \a value when the state is entered. + Returns the state machine that this state is part of, or 0 if the state is + not part of a state machine. */ -void QAbstractState::assignProperty(QObject *object, const char *name, - const QVariant &value) +QStateMachine *QAbstractState::machine() const { - Q_D(QAbstractState); - for (int i = 0; i < d->propertyAssignments.size(); ++i) { - QPropertyAssignment &assn = d->propertyAssignments[i]; - if ((assn.object == object) && (assn.propertyName == name)) { - assn.value = value; - return; - } - } - d->propertyAssignments.append(QPropertyAssignment(object, name, value)); + Q_D(const QAbstractState); + return d->machine(); } /*! - Sets the restore policy of this state to \a restorePolicy. - - The default restore policy is QAbstractState::GlobalRestorePolicy. + \fn QAbstractState::onExit(QEvent *event) + + This function is called when the state is exited. The given \a event is what + caused the state to be exited. Reimplement this function to perform custom + processing when the state is exited. */ -void QAbstractState::setRestorePolicy(RestorePolicy restorePolicy) -{ - Q_D(QAbstractState); - d->restorePolicy = restorePolicy; -} /*! - Returns the restore policy for this state. + \fn QAbstractState::onEntry(QEvent *event) + + This function is called when the state is entered. The given \a event is + what caused the state to be entered. Reimplement this function to perform + custom processing when the state is entered. */ -QAbstractState::RestorePolicy QAbstractState::restorePolicy() const -{ - Q_D(const QAbstractState); - return d->restorePolicy; -} /*! - \fn QAbstractState::onExit() + \fn QAbstractState::entered() - This function is called when the state is exited. Reimplement this function - to perform custom processing when the state is exited. + This signal is emitted when the state has been entered (after onEntry() has + been called). */ /*! - \fn QAbstractState::onEntry() + \fn QAbstractState::exited() - This function is called when the state is entered. Reimplement this function - to perform custom processing when the state is entered. + This signal is emitted when the state has been exited (after onExit() has + been called). */ /*! diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index b788a88..f6b4b21 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -51,35 +51,27 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QState; +class QStateMachine; class QAbstractStatePrivate; class Q_CORE_EXPORT QAbstractState : public QObject { Q_OBJECT - Q_ENUMS(RestorePolicy) - Q_PROPERTY(RestorePolicy restorePolicy READ restorePolicy WRITE setRestorePolicy) public: - enum RestorePolicy { - GlobalRestorePolicy, - DoNotRestoreProperties, - RestoreProperties - }; - ~QAbstractState(); QState *parentState() const; + QStateMachine *machine() const; - void assignProperty(QObject *object, const char *name, - const QVariant &value); - - void setRestorePolicy(RestorePolicy restorePolicy); - RestorePolicy restorePolicy() const; +Q_SIGNALS: + void entered(); + void exited(); protected: QAbstractState(QState *parent = 0); - virtual void onEntry() = 0; - virtual void onExit() = 0; + virtual void onEntry(QEvent *event) = 0; + virtual void onExit(QEvent *event) = 0; bool event(QEvent *e); diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index bf44116..6c09696 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -57,26 +57,10 @@ #include <private/qobject_p.h> #endif -#include <QtCore/qlist.h> - QT_BEGIN_NAMESPACE -class QAbstractTransition; -class QHistoryState; class QStateMachine; -struct QPropertyAssignment -{ - QPropertyAssignment(QObject *o, const QByteArray &n, - const QVariant &v, bool es = true) - : object(o), propertyName(n), value(v), explicitlySet(es) - {} - QObject *object; - QByteArray propertyName; - QVariant value; - bool explicitlySet; -}; - class QAbstractState; class Q_CORE_EXPORT QAbstractStatePrivate #ifndef QT_STATEMACHINE_SOLUTION @@ -93,11 +77,11 @@ public: QStateMachine *machine() const; - void callOnEntry(); - void callOnExit(); + void callOnEntry(QEvent *e); + void callOnExit(QEvent *e); - QAbstractState::RestorePolicy restorePolicy; - QList<QPropertyAssignment> propertyAssignments; + void emitEntered(); + void emitExited(); #ifdef QT_STATEMACHINE_SOLUTION QAbstractState *q_ptr; diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 36de7f5..6ddb416 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE \brief The QAbstractTransition class is the base class of transitions between QAbstractState objects. + \since 4.6 \ingroup statemachine The QAbstractTransition class is the abstract base class of transitions @@ -59,11 +60,9 @@ QT_BEGIN_NAMESPACE QStateMachine. QAbstractTransition is part of \l{The State Machine Framework}. - The QTransition class provides a default (action-based) implementation of - the QAbstractTransition interface. - The sourceState() function returns the source of the transition. The - targetStates() function returns the targets of the transition. + targetStates() function returns the targets of the transition. The machine() + function returns the state machine that the transition is part of. Transitions can cause animations to be played. Use the addAnimation() function to add an animation to the transition. @@ -80,19 +79,19 @@ QT_BEGIN_NAMESPACE */ /*! - \property QAbstractTransition::source + \property QAbstractTransition::sourceState \brief the source state (parent) of this transition */ /*! - \property QAbstractTransition::target + \property QAbstractTransition::targetState \brief the target state of this transition */ /*! - \property QAbstractTransition::targets + \property QAbstractTransition::targetStates \brief the target states of this transition @@ -132,10 +131,10 @@ bool QAbstractTransitionPrivate::callEventTest(QEvent *e) const return q->eventTest(e); } -void QAbstractTransitionPrivate::callOnTransition() +void QAbstractTransitionPrivate::callOnTransition(QEvent *e) { Q_Q(QAbstractTransition); - q->onTransition(); + q->onTransition(e); } QState *QAbstractTransitionPrivate::sourceState() const @@ -180,8 +179,7 @@ QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets, #ifdef QT_STATEMACHINE_SOLUTION d_ptr->q_ptr = this; #endif - Q_D(QAbstractTransition); - d->targetStates = targets; + setTargetStates(targets); } /*! @@ -221,8 +219,7 @@ QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd, #ifdef QT_STATEMACHINE_SOLUTION d_ptr->q_ptr = this; #endif - Q_D(QAbstractTransition); - d->targetStates = targets; + setTargetStates(targets); } /*! @@ -266,7 +263,7 @@ void QAbstractTransition::setTargetState(QAbstractState* target) if (!target) d->targetStates.clear(); else - d->targetStates = QList<QAbstractState*>() << target; + setTargetStates(QList<QAbstractState*>() << target); } /*! @@ -276,7 +273,13 @@ void QAbstractTransition::setTargetState(QAbstractState* target) QList<QAbstractState*> QAbstractTransition::targetStates() const { Q_D(const QAbstractTransition); - return d->targetStates; + QList<QAbstractState*> result; + for (int i = 0; i < d->targetStates.size(); ++i) { + QAbstractState *target = d->targetStates.at(i); + if (target) + result.append(target); + } + return result; } /*! @@ -285,7 +288,32 @@ QList<QAbstractState*> QAbstractTransition::targetStates() const void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets) { Q_D(QAbstractTransition); - d->targetStates = targets; + + for (int i=0; i<targets.size(); ++i) { + QAbstractState *target = targets.at(i); + if (!target) { + qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null"); + return; + } + if (target->machine() != 0 && target->machine()->rootState() == target) { + qWarning("QAbstractTransition::setTargetStates: root state cannot be target of transition"); + return; + } + } + + d->targetStates.clear(); + for (int i = 0; i < targets.size(); ++i) + d->targetStates.append(targets.at(i)); +} + +/*! + Returns the state machine that this transition is part of, or 0 if the + transition is not part of a state machine. +*/ +QStateMachine *QAbstractTransition::machine() const +{ + Q_D(const QAbstractTransition); + return d->machine(); } #ifndef QT_NO_ANIMATION @@ -344,10 +372,11 @@ QList<QAbstractAnimation*> QAbstractTransition::animations() const */ /*! - \fn QAbstractTransition::onTransition() + \fn QAbstractTransition::onTransition(QEvent *event) - This function is called when the transition is triggered. Reimplement this - function to perform custom processing when the transition is triggered. + This function is called when the transition is triggered. The given \a event + is what caused the transition to trigger. Reimplement this function to + perform custom processing when the transition is triggered. */ /*! diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index c49731f..e207944 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -55,6 +55,7 @@ QT_MODULE(Core) class QEvent; class QAbstractState; class QState; +class QStateMachine; #ifndef QT_NO_ANIMATION class QAbstractAnimation; @@ -64,9 +65,9 @@ class QAbstractTransitionPrivate; class Q_CORE_EXPORT QAbstractTransition : public QObject { Q_OBJECT - Q_PROPERTY(QState* source READ sourceState) - Q_PROPERTY(QAbstractState* target READ targetState WRITE setTargetState) - Q_PROPERTY(QList<QAbstractState*> targets READ targetStates WRITE setTargetStates) + Q_PROPERTY(QState* sourceState READ sourceState) + Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState) + Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates) public: QAbstractTransition(QState *sourceState = 0); QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0); @@ -78,6 +79,8 @@ public: QList<QAbstractState*> targetStates() const; void setTargetStates(const QList<QAbstractState*> &targets); + QStateMachine *machine() const; + #ifndef QT_NO_ANIMATION void addAnimation(QAbstractAnimation *animation); void removeAnimation(QAbstractAnimation *animation); @@ -87,7 +90,7 @@ public: protected: virtual bool eventTest(QEvent *event) const = 0; - virtual void onTransition() = 0; + virtual void onTransition(QEvent *event) = 0; bool event(QEvent *e); diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h index a48a09c..eb0ec21 100644 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ b/src/corelib/statemachine/qabstracttransition_p.h @@ -58,6 +58,7 @@ #endif #include <QtCore/qlist.h> +#include <QtCore/qpointer.h> QT_BEGIN_NAMESPACE @@ -79,11 +80,11 @@ public: static const QAbstractTransitionPrivate *get(const QAbstractTransition *q); bool callEventTest(QEvent *e) const; - void callOnTransition(); + void callOnTransition(QEvent *e); QState *sourceState() const; QStateMachine *machine() const; - QList<QAbstractState*> targetStates; + QList<QPointer<QAbstractState> > targetStates; #ifndef QT_NO_ANIMATION QList<QAbstractAnimation*> animations; diff --git a/src/corelib/statemachine/qactionstate.cpp b/src/corelib/statemachine/qactionstate.cpp deleted file mode 100644 index 77fd036..0000000 --- a/src/corelib/statemachine/qactionstate.cpp +++ /dev/null @@ -1,292 +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 "qactionstate.h" -#include "qactionstate_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QActionState - - \brief The QActionState class provides an action-based state. - - \ingroup statemachine - - QActionState executes \l{QStateAction}{state actions} when the state is - entered and exited. QActionState is part of \l{The State Machine Framework}. - - You can add actions to a state with the addEntryAction() and addExitAction() - functions. The state executes the actions when the state is entered and - exited, respectively. - - The invokeMethodOnEntry() and invokeMethodOnExit() functions are used for - defining method invocations that should be performed when a state is entered - and exited, respectively. - - \code - QState *s2 = new QState(); - s2->invokeMethodOnEntry(&label, "showMaximized"); - machine.addState(s2); - \endcode - - \sa QStateAction -*/ - -QActionStatePrivate::QActionStatePrivate() -{ -} - -QActionStatePrivate::~QActionStatePrivate() -{ -} - -QActionStatePrivate *QActionStatePrivate::get(QActionState *q) -{ - return q->d_func(); -} - -const QActionStatePrivate *QActionStatePrivate::get(const QActionState *q) -{ - return q->d_func(); -} - -QList<QStateAction*> QActionStatePrivate::entryActions() const -{ - QList<QStateAction*> result; - QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *act = qobject_cast<QStateAction*>(*it); - if (act && (QStateActionPrivate::get(act)->when == QStateActionPrivate::ExecuteOnEntry)) - result.append(act); - } - return result; -} - -QList<QStateAction*> QActionStatePrivate::exitActions() const -{ - QList<QStateAction*> result; - QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *act = qobject_cast<QStateAction*>(*it); - if (act && (QStateActionPrivate::get(act)->when == QStateActionPrivate::ExecuteOnExit)) - result.append(act); - } - return result; -} - -/*! - Constructs a new action state with the given \a parent state. -*/ -QActionState::QActionState(QState *parent) - : QAbstractState(*new QActionStatePrivate, parent) -{ -} - -/*! - \internal -*/ -QActionState::QActionState(QActionStatePrivate &dd, - QState *parent) - : QAbstractState(dd, parent) -{ -} - -/*! - Destroys this action state. -*/ -QActionState::~QActionState() -{ -} - -/*! - Instructs this state to invoke the given \a method of the given \a object - with the given \a arguments when the state is entered. This function will - create a QStateInvokeMethodAction object and add it to the entry actions of - the state. - - \sa invokeMethodOnExit(), setPropertyOnEntry(), addEntryAction() -*/ -void QActionState::invokeMethodOnEntry(QObject *object, const char *method, - const QList<QVariant> &arguments) -{ - addEntryAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Instructs this state to invoke the given \a method of the given \a object - with the given \a arguments when the state is exited. This function will - create a QStateInvokeMethodAction object and add it to the exit actions of - the state. - - \sa invokeMethodOnEntry(), addExitAction() -*/ -void QActionState::invokeMethodOnExit(QObject *object, const char *method, - const QList<QVariant> &arguments) -{ - addExitAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Adds the given \a action to this state. The action will be executed when - this state is entered. The state takes ownership of the action. - - \sa addExitAction(), removeEntryAction() -*/ -void QActionState::addEntryAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::addEntryAction: cannot add null action"); - return; - } - action->setParent(this); - QStateActionPrivate::get(action)->when = QStateActionPrivate::ExecuteOnEntry; -} - -/*! - Adds the given \a action to this state. The action will be executed when - this state is exited. The state takes ownership of the action. - - \sa addEntryAction(), removeExitAction() -*/ -void QActionState::addExitAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::addExitAction: cannot add null action"); - return; - } - action->setParent(this); - QStateActionPrivate::get(action)->when = QStateActionPrivate::ExecuteOnExit; -} - -/*! - Removes the given entry \a action from this state. The state releases - ownership of the action. - - \sa addEntryAction() -*/ -void QActionState::removeEntryAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::removeEntryAction: cannot remove null action"); - return; - } - if (action->parent() == this) - action->setParent(0); -} - -/*! - Removes the given exit \a action from this state. The state releases - ownership of the action. - - \sa addExitAction() -*/ -void QActionState::removeExitAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::removeExitAction: cannot remove null action"); - return; - } - if (action->parent() == this) - action->setParent(0); -} - -/*! - Returns this state's entry actions. - - \sa addEntryAction(), exitActions() -*/ -QList<QStateAction*> QActionState::entryActions() const -{ - Q_D(const QActionState); - return d->entryActions(); -} - -/*! - Returns this state's exit actions. - - \sa addExitAction(), entryActions() -*/ -QList<QStateAction*> QActionState::exitActions() const -{ - Q_D(const QActionState); - return d->exitActions(); -} - -/*! - \reimp -*/ -void QActionState::onEntry() -{ - Q_D(QActionState); - QList<QStateAction*> actions = d->entryActions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -void QActionState::onExit() -{ - Q_D(QActionState); - QList<QStateAction*> actions = d->exitActions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -bool QActionState::event(QEvent *e) -{ - return QAbstractState::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index b03074d..86259e4 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -41,7 +41,7 @@ #include "qeventtransition.h" #include "qeventtransition_p.h" -#include "qboundevent_p.h" +#include "qwrappedevent.h" #include "qstate.h" #include "qstate_p.h" #include "qstatemachine.h" @@ -55,10 +55,11 @@ QT_BEGIN_NAMESPACE \brief The QEventTransition class provides a QObject-specific transition for Qt events. + \since 4.6 \ingroup statemachine - A QEventTransition object binds an event or transition to a particular - QObject. QEventTransition is part of \l{The State Machine Framework}. + A QEventTransition object binds an event to a particular QObject. + QEventTransition is part of \l{The State Machine Framework}. Example: @@ -78,16 +79,17 @@ QT_BEGIN_NAMESPACE \section1 Subclassing - Many event classes have attributes in addition to the event type itself. - The testEventCondition() function can be reimplemented to check attributes - of an event instance in order to determine whether the transition should be - triggered or not. + When reimplementing the eventTest() function, you should first call the base + implementation to verify that the event is a QWrappedEvent for the proper + object and event type. You may then cast the event to a QWrappedEvent and + get the original event by calling QWrappedEvent::event(), and perform + additional checks on that object. \sa QState::addTransition() */ /*! - \property QEventTransition::object + \property QEventTransition::eventObject \brief the event source that this event transition is associated with */ @@ -128,7 +130,7 @@ void QEventTransitionPrivate::invalidate() Constructs a new QEventTransition object with the given \a sourceState. */ QEventTransition::QEventTransition(QState *sourceState) - : QTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { } @@ -138,7 +140,7 @@ QEventTransition::QEventTransition(QState *sourceState) */ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QState *sourceState) - : QTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -154,7 +156,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QEventTransition::QEventTransition(QObject *object, QEvent::Type type, const QList<QAbstractState*> &targets, QState *sourceState) - : QTransition(*new QEventTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -166,7 +168,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) - : QTransition(dd, parent) + : QAbstractTransition(dd, parent) { } @@ -175,7 +177,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent) - : QTransition(dd, parent) + : QAbstractTransition(dd, parent) { Q_D(QEventTransition); d->registered = false; @@ -189,7 +191,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, const QList<QAbstractState*> &targets, QState *parent) - : QTransition(dd, targets, parent) + : QAbstractTransition(dd, targets, parent) { Q_D(QEventTransition); d->registered = false; @@ -228,7 +230,7 @@ void QEventTransition::setEventType(QEvent::Type type) /*! Returns the event source associated with this event transition. */ -QObject *QEventTransition::eventSource() const +QObject *QEventTransition::eventObject() const { Q_D(const QEventTransition); return d->object; @@ -238,7 +240,7 @@ QObject *QEventTransition::eventSource() const Sets the event source associated with this event transition to be the given \a object. */ -void QEventTransition::setEventSource(QObject *object) +void QEventTransition::setEventObject(QObject *object) { Q_D(QEventTransition); if (d->object == object) @@ -256,28 +258,21 @@ bool QEventTransition::eventTest(QEvent *event) const #ifdef QT_STATEMACHINE_SOLUTION if (event->type() == QEvent::Type(QEvent::User-3)) { #else - if (event->type() == QEvent::Bound) { + if (event->type() == QEvent::Wrapped) { #endif - QBoundEvent *oe = static_cast<QBoundEvent*>(event); - return (oe->object() == d->object) - && (oe->event()->type() == d->eventType) - && testEventCondition(oe->event()); + QWrappedEvent *we = static_cast<QWrappedEvent*>(event); + return (we->object() == d->object) + && (we->event()->type() == d->eventType); } return false; } /*! - Tests an instance of an event associated with this event transition and - returns true if the transition should be taken, otherwise returns false. - The type of the given \a event will be eventType(). - - Reimplement this function if you have custom conditions associated with - the transition. The default implementation always returns true. + \reimp */ -bool QEventTransition::testEventCondition(QEvent *event) const +void QEventTransition::onTransition(QEvent *event) { Q_UNUSED(event); - return true; } /*! @@ -285,7 +280,7 @@ bool QEventTransition::testEventCondition(QEvent *event) const */ bool QEventTransition::event(QEvent *e) { - return QTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index edd7f8a..a128cee 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -42,7 +42,11 @@ #ifndef QEVENTTRANSITION_H #define QEVENTTRANSITION_H -#include "qtransition.h" +#ifndef QT_STATEMACHINE_SOLUTION +#include <QtCore/qabstracttransition.h> +#else +#include "qabstracttransition.h" +#endif #include <QtCore/qcoreevent.h> QT_BEGIN_HEADER @@ -52,10 +56,10 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QEventTransitionPrivate; -class Q_CORE_EXPORT QEventTransition : public QTransition +class Q_CORE_EXPORT QEventTransition : public QAbstractTransition { Q_OBJECT - Q_PROPERTY(QObject* object READ eventSource WRITE setEventSource) + Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject) #ifndef QT_STATEMACHINE_SOLUTION Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType) #endif @@ -66,16 +70,15 @@ public: const QList<QAbstractState*> &targets, QState *sourceState = 0); ~QEventTransition(); - QObject *eventSource() const; - void setEventSource(QObject *object); + QObject *eventObject() const; + void setEventObject(QObject *object); QEvent::Type eventType() const; void setEventType(QEvent::Type type); protected: - virtual bool testEventCondition(QEvent *event) const; // ### name - bool eventTest(QEvent *event) const; + void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h index 568e35e..fca8c0d 100644 --- a/src/corelib/statemachine/qeventtransition_p.h +++ b/src/corelib/statemachine/qeventtransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qtransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QEventTransition; -class Q_CORE_EXPORT QEventTransitionPrivate : public QTransitionPrivate +class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QEventTransition) public: diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index 5219b1b..0980336 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "qfinalstate.h" -#include "qactionstate_p.h" +#include "qabstractstate_p.h" QT_BEGIN_NAMESPACE @@ -49,14 +49,15 @@ QT_BEGIN_NAMESPACE \brief The QFinalState class provides a final state. + \since 4.6 \ingroup statemachine A final state is used to communicate that (part of) a QStateMachine has finished its work. When a final top-level state is entered, the state machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In - general, when a final substate (a child of a QState) is entered, a - QStateFinishedEvent is generated for the final state's parent - state. QFinalState is part of \l{The State Machine Framework}. + general, when a final substate (a child of a QState) is entered, the parent + state's \l{QState::finished()}{finished}() signal is emitted. QFinalState + is part of \l{The State Machine Framework}. To use a final state, you create a QFinalState object and add a transition to it from another state. Example: @@ -76,10 +77,10 @@ QT_BEGIN_NAMESPACE machine.start(); \endcode - \sa QStateFinishedTransition + \sa QStateMachine::finished(), QState::finished() */ -class QFinalStatePrivate : public QActionStatePrivate +class QFinalStatePrivate : public QAbstractStatePrivate { Q_DECLARE_PUBLIC(QFinalState) @@ -95,7 +96,7 @@ QFinalStatePrivate::QFinalStatePrivate() Constructs a new QFinalState object with the given \a parent state. */ QFinalState::QFinalState(QState *parent) - : QActionState(*new QFinalStatePrivate, parent) + : QAbstractState(*new QFinalStatePrivate, parent) { } @@ -109,17 +110,17 @@ QFinalState::~QFinalState() /*! \reimp */ -void QFinalState::onEntry() +void QFinalState::onEntry(QEvent *event) { - QActionState::onEntry(); + Q_UNUSED(event); } /*! \reimp */ -void QFinalState::onExit() +void QFinalState::onExit(QEvent *event) { - QActionState::onExit(); + Q_UNUSED(event); } /*! @@ -127,7 +128,7 @@ void QFinalState::onExit() */ bool QFinalState::event(QEvent *e) { - return QActionState::event(e); + return QAbstractState::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h index 36813f5..eb8aa0f 100644 --- a/src/corelib/statemachine/qfinalstate.h +++ b/src/corelib/statemachine/qfinalstate.h @@ -43,9 +43,9 @@ #define QFINALSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qactionstate.h> +#include <QtCore/qabstractstate.h> #else -#include "qactionstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QFinalStatePrivate; -class Q_CORE_EXPORT QFinalState : public QActionState +class Q_CORE_EXPORT QFinalState : public QAbstractState { Q_OBJECT public: @@ -63,8 +63,8 @@ public: ~QFinalState(); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index a0c933c..d1b2391 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE \brief The QHistoryState class provides a means of returning to a previously active substate. + \since 4.6 \ingroup statemachine A history state is a pseudo-state that represents the child state that the @@ -57,9 +58,8 @@ QT_BEGIN_NAMESPACE other child states of the parent state. QHistoryState is part of \l{The State Machine Framework}. - Use QState::addHistoryState() to construct a history state. Use the - setDefaultState() function to set the state that should be entered if the - parent state has never been entered. Example: + Use the setDefaultState() function to set the state that should be entered + if the parent state has never been entered. Example: \code QStateMachine machine; @@ -68,7 +68,7 @@ QT_BEGIN_NAMESPACE QState *s11 = new QState(s1); QState *s12 = new QState(s1); - QState *s1h = s1->addHistoryState(); + QHistoryState *s1h = new QHistoryState(s1); s1h->setDefaultState(s11); machine.addState(s1); @@ -82,6 +82,38 @@ QT_BEGIN_NAMESPACE // state if s1 has never been entered. s1->addTransition(button, SIGNAL(clicked()), s1h); \endcode + + By default a history state is shallow, meaning that it won't remember nested + states. This can be configured through the historyType property. +*/ + +/*! + \property QHistoryState::defaultState + + \brief the default state of this history state +*/ + +/*! + \property QHistoryState::historyType + + \brief the type of history that this history state records + + The default value of this property is QHistoryState::ShallowHistory. +*/ + +/*! + \enum QHistoryState::HistoryType + + This enum specifies the type of history that a QHistoryState records. + + \value ShallowHistory Only the immediate child states of the parent state + are recorded. In this case a transition with the history state as its + target will end up in the immediate child state that the parent was in the + last time it was exited. This is the default. + + \value DeepHistory Nested states are recorded. In this case a transition + with the history state as its target will end up in the most deeply nested + descendant state the parent was in the last time it was exited. */ QHistoryStatePrivate::QHistoryStatePrivate() @@ -89,12 +121,6 @@ QHistoryStatePrivate::QHistoryStatePrivate() { } -QHistoryState *QHistoryStatePrivate::create(QState::HistoryType type, - QState *parent) -{ - return new QHistoryState(type, parent); -} - QHistoryStatePrivate *QHistoryStatePrivate::get(QHistoryState *q) { return q->d_func(); @@ -106,12 +132,19 @@ const QHistoryStatePrivate *QHistoryStatePrivate::get(const QHistoryState *q) } /*! - \internal - + Constructs a new shallow history state with the given \a parent state. +*/ +QHistoryState::QHistoryState(QState *parent) + : QAbstractState(*new QHistoryStatePrivate, parent) +{ + Q_D(QHistoryState); + d->historyType = ShallowHistory; +} +/*! Constructs a new history state of the given \a type, with the given \a parent state. */ -QHistoryState::QHistoryState(QState::HistoryType type, QState *parent) +QHistoryState::QHistoryState(HistoryType type, QState *parent) : QAbstractState(*new QHistoryStatePrivate, parent) { Q_D(QHistoryState); @@ -151,17 +184,37 @@ void QHistoryState::setDefaultState(QAbstractState *state) } /*! + Returns the type of history that this history state records. +*/ +QHistoryState::HistoryType QHistoryState::historyType() const +{ + Q_D(const QHistoryState); + return d->historyType; +} + +/*! + Sets the \a type of history that this history state records. +*/ +void QHistoryState::setHistoryType(HistoryType type) +{ + Q_D(QHistoryState); + d->historyType = type; +} + +/*! \reimp */ -void QHistoryState::onEntry() +void QHistoryState::onEntry(QEvent *event) { + Q_UNUSED(event); } /*! \reimp */ -void QHistoryState::onExit() +void QHistoryState::onExit(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index 9cd7f0b..d0f75de 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -43,9 +43,9 @@ #define QHISTORYSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qstate.h> +#include <QtCore/qabstractstate.h> #else -#include "qstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -58,23 +58,32 @@ class QHistoryStatePrivate; class Q_CORE_EXPORT QHistoryState : public QAbstractState { Q_OBJECT + Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState) + Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType) + Q_ENUMS(HistoryType) public: + enum HistoryType { + ShallowHistory, + DeepHistory + }; + + QHistoryState(QState *parent = 0); + QHistoryState(HistoryType type, QState *parent = 0); ~QHistoryState(); QAbstractState *defaultState() const; void setDefaultState(QAbstractState *state); + HistoryType historyType() const; + void setHistoryType(HistoryType type); + protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); private: - QHistoryState(QState::HistoryType type, - QState *parent = 0); - -private: Q_DISABLE_COPY(QHistoryState) Q_DECLARE_PRIVATE(QHistoryState) }; diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h index 84648b5..2f17496 100644 --- a/src/corelib/statemachine/qhistorystate_p.h +++ b/src/corelib/statemachine/qhistorystate_p.h @@ -67,14 +67,11 @@ class QHistoryStatePrivate : public QAbstractStatePrivate public: QHistoryStatePrivate(); - static QHistoryState *create(QState::HistoryType type, - QState *parent); - static QHistoryStatePrivate *get(QHistoryState *q); static const QHistoryStatePrivate *get(const QHistoryState *q); QAbstractState *defaultState; - QState::HistoryType historyType; + QHistoryState::HistoryType historyType; QList<QAbstractState*> configuration; }; diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index 5dcabc4..8221f68 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -72,4 +72,6 @@ private: QT_END_NAMESPACE +QT_END_HEADER + #endif diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 9c03b94..d5833bd 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE \brief The QSignalTransition class provides a transition based on a Qt signal. + \since 4.6 \ingroup statemachine Typically you would use the overload of QState::addTransition() that takes a @@ -95,7 +96,7 @@ QT_BEGIN_NAMESPACE */ /*! - \property QSignalTransition::object + \property QSignalTransition::senderObject \brief the sender object that this signal transition is associated with */ @@ -136,7 +137,7 @@ void QSignalTransitionPrivate::invalidate() Constructs a new signal transition with the given \a sourceState. */ QSignalTransition::QSignalTransition(QState *sourceState) - : QTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { } @@ -146,7 +147,7 @@ QSignalTransition::QSignalTransition(QState *sourceState) */ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QState *sourceState) - : QTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -161,7 +162,7 @@ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QSignalTransition::QSignalTransition(QObject *sender, const char *signal, const QList<QAbstractState*> &targets, QState *sourceState) - : QTransition(*new QSignalTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -232,8 +233,9 @@ bool QSignalTransition::eventTest(QEvent *event) const #else if (event->type() == QEvent::Type(QEvent::User-1)) { #endif + if (d->signalIndex == -1) + return false; QSignalEvent *se = static_cast<QSignalEvent*>(event); - Q_ASSERT(d->signalIndex != -1); return (se->sender() == d->sender) && (se->signalIndex() == d->signalIndex); } @@ -243,9 +245,17 @@ bool QSignalTransition::eventTest(QEvent *event) const /*! \reimp */ +void QSignalTransition::onTransition(QEvent *event) +{ + Q_UNUSED(event); +} + +/*! + \reimp +*/ bool QSignalTransition::event(QEvent *e) { - return QTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index ba4af17..98a9ae7 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -43,9 +43,9 @@ #define QSIGNALTRANSITION_H #ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qtransition.h> +#include <QtCore/qabstracttransition.h> #else -#include "qtransition.h" +#include "qabstracttransition.h" #endif QT_BEGIN_HEADER @@ -55,10 +55,10 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QSignalTransitionPrivate; -class Q_CORE_EXPORT QSignalTransition : public QTransition +class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition { Q_OBJECT - Q_PROPERTY(QObject* object READ senderObject WRITE setSenderObject) + Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject) Q_PROPERTY(QByteArray signal READ signal WRITE setSignal) public: QSignalTransition(QState *sourceState = 0); @@ -77,6 +77,7 @@ public: protected: bool eventTest(QEvent *event) const; + void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h index c5fbcfc..a23e58c 100644 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ b/src/corelib/statemachine/qsignaltransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qtransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QSignalTransition; -class QSignalTransitionPrivate : public QTransitionPrivate +class QSignalTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QSignalTransition) public: diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 944ca2c..3a3bfc3 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -46,7 +46,6 @@ #include "qabstracttransition.h" #include "qabstracttransition_p.h" #include "qsignaltransition.h" -#include "qstatefinishedtransition.h" #include "qstatemachine.h" #include "qstatemachine_p.h" @@ -57,6 +56,7 @@ QT_BEGIN_NAMESPACE \brief The QState class provides a general-purpose state for QStateMachine. + \since 4.6 \ingroup statemachine QState objects can have child states, and can have transitions to other @@ -65,50 +65,63 @@ QT_BEGIN_NAMESPACE The addTransition() function adds a transition. The removeTransition() function removes a transition. + The assignProperty() function is used for defining property assignments that + should be performed when a state is entered. + + Top-level states must be passed QStateMachine::rootState() as their parent + state, or added to a state machine using QStateMachine::addState(). + \section1 States with Child States - For non-parallel state groups, the setInitialState() function must be called - to set the initial state. The child states are mutually exclusive states, - and the state machine needs to know which child state to enter when the - parent state is the target of a transition. + The childMode property determines how child states are treated. For + non-parallel state groups, the setInitialState() function must be called to + set the initial state. The child states are mutually exclusive states, and + the state machine needs to know which child state to enter when the parent + state is the target of a transition. - The addHistoryState() function adds a history state. + The state emits the QState::finished() signal when a final child state + (QFinalState) is entered. The setErrorState() sets the state's error state. The error state is the state that the state machine will transition to if an error is detected when attempting to enter the state (e.g. because no initial state has been set). + */ /*! - \enum QState::Type + \property QState::initialState - This enum specifies the type of a state. + \brief the initial state of this state (one of its child states) +*/ - \value Normal A normal state. If the state has no child states, it is an - atomic state; otherwise, the child states are mutually exclusive and an - initial state must be set by calling QState::setInitialState(). +/*! + \property QState::errorState - \value ParallelGroup The state is a parallel group state. When a parallel - group state is entered, all its child states are entered in parallel. + \brief the error state of this state */ /*! - \enum QState::HistoryType + \property QState::childMode - This enum specifies the type of history that a QHistoryState records. + \brief the child mode of this state - \value ShallowHistory Only the immediate child states of the parent state - are recorded. In this case a transition with the history state as its - target will end up in the immediate child state that the parent was in the - last time it was exited. This is the default. + The default value of this property is QState::ExclusiveStates. +*/ + +/*! + \enum QState::ChildMode + + This enum specifies how a state's child states are treated. + + \value ExclusiveStates The child states are mutually exclusive and an + initial state must be set by calling QState::setInitialState(). - \value DeepHistory Nested states are recorded. In this case a transition - with the history state as its target will end up in the most deeply nested - descendant state the parent was in the last time it was exited. + \value ParallelStates The child states are parallel. When the parent state + is entered, all its child states are entered in parallel. */ QStatePrivate::QStatePrivate() - : errorState(0), isParallelGroup(false), initialState(0) + : errorState(0), initialState(0), childMode(QState::ExclusiveStates) { } @@ -130,29 +143,42 @@ const QStatePrivate *QStatePrivate::get(const QState *q) return q->d_func(); } +void QStatePrivate::emitFinished() +{ + Q_Q(QState); + emit q->finished(); +} + +void QStatePrivate::emitPolished() +{ + Q_Q(QState); + emit q->polished(); +} + /*! Constructs a new state with the given \a parent state. */ QState::QState(QState *parent) - : QActionState(*new QStatePrivate, parent) + : QAbstractState(*new QStatePrivate, parent) { } /*! - Constructs a new state of the given \a type with the given \a parent state. + Constructs a new state with the given \a childMode and the given \a parent + state. */ -QState::QState(Type type, QState *parent) - : QActionState(*new QStatePrivate, parent) +QState::QState(ChildMode childMode, QState *parent) + : QAbstractState(*new QStatePrivate, parent) { Q_D(QState); - d->isParallelGroup = (type == ParallelGroup); + d->childMode = childMode; } /*! \internal */ QState::QState(QStatePrivate &dd, QState *parent) - : QActionState(dd, parent) + : QAbstractState(dd, parent) { } @@ -210,6 +236,30 @@ QList<QAbstractTransition*> QStatePrivate::transitions() const } /*! + Instructs this state to set the property with the given \a name of the given + \a object to the given \a value when the state is entered. + + \sa polished() +*/ +void QState::assignProperty(QObject *object, const char *name, + const QVariant &value) +{ + Q_D(QState); + if (!object) { + qWarning("QState::assignProperty: cannot assign property '%s' of null object", name); + return; + } + for (int i = 0; i < d->propertyAssignments.size(); ++i) { + QPropertyAssignment &assn = d->propertyAssignments[i]; + if ((assn.object == object) && (assn.propertyName == name)) { + assn.value = value; + return; + } + } + d->propertyAssignments.append(QPropertyAssignment(object, name, value)); +} + +/*! Returns this state group's error state. \sa QStateMachine::errorState(), QStateMachine::setErrorState() @@ -230,41 +280,54 @@ QAbstractState *QState::errorState() const void QState::setErrorState(QAbstractState *state) { Q_D(QState); - if (state != 0 && QAbstractStatePrivate::get(state)->machine() != d->machine()) { + if (state != 0 && state->machine() != machine()) { qWarning("QState::setErrorState: error state cannot belong " "to a different state machine"); return; } + if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) { + qWarning("QStateMachine::setErrorState: root state cannot be error state"); + return; + } d->errorState = state; } /*! Adds the given \a transition. The transition has this state as the source. - This state takes ownership of the transition. + This state takes ownership of the transition. If the transition is successfully + added, the function will return the \a transition pointer. Otherwise it will return null. */ -void QState::addTransition(QAbstractTransition *transition) +QAbstractTransition *QState::addTransition(QAbstractTransition *transition) { Q_D(QState); if (!transition) { qWarning("QState::addTransition: cannot add null transition"); - return; + return 0; } - const QList<QAbstractState*> &targets = QAbstractTransitionPrivate::get(transition)->targetStates; + + // machine() will always be non-null for root state + if (machine() != 0 && machine()->rootState() == this) { + qWarning("QState::addTransition: cannot add transition from root state"); + return 0; + } + + const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates; for (int i = 0; i < targets.size(); ++i) { QAbstractState *t = targets.at(i); if (!t) { qWarning("QState::addTransition: cannot add transition to null state"); - return; + return 0; } if ((QAbstractStatePrivate::get(t)->machine() != d->machine()) && QAbstractStatePrivate::get(t)->machine() && d->machine()) { qWarning("QState::addTransition: cannot add transition " "to a state in a different state machine"); - return; + return 0; } } transition->setParent(this); + return transition; } /*! @@ -283,25 +346,20 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, qWarning("QState::addTransition: signal cannot be null"); return 0; } + if (!target) { + qWarning("QState::addTransition: cannot add transition to null state"); + return 0; + } + if (*signal && sender->metaObject()->indexOfSignal(signal+1) == -1) { + qWarning("QState::addTransition: no such signal %s::%s", + sender->metaObject()->className(), signal+1); + return 0; + } QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target); addTransition(trans); return trans; } -/*! - Adds a transition that's triggered by the finished event of this state, and - returns the new QStateFinishedTransition object. The transition has the - given \a target state. - - \sa QStateFinishedEvent -*/ -QStateFinishedTransition *QState::addFinishedTransition(QAbstractState *target) -{ - QStateFinishedTransition *trans = new QStateFinishedTransition(this, QList<QAbstractState*>() << target); - addTransition(trans); - return trans; -} - namespace { // ### Make public? @@ -311,7 +369,7 @@ public: UnconditionalTransition(QAbstractState *target) : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: - void onTransition() {} + void onTransition(QEvent *) {} bool eventTest(QEvent *) const { return true; } }; @@ -323,9 +381,12 @@ protected: */ QAbstractTransition *QState::addTransition(QAbstractState *target) { + if (!target) { + qWarning("QState::addTransition: cannot add transition to null state"); + return 0; + } UnconditionalTransition *trans = new UnconditionalTransition(target); - addTransition(trans); - return trans; + return addTransition(trans); } /*! @@ -354,40 +415,19 @@ void QState::removeTransition(QAbstractTransition *transition) } /*! - Returns the list of transitions from this state, or an empty list if there - are no transitions from this state. - - \sa addTransition(), removeTransition() -*/ -QList<QAbstractTransition*> QState::transitions() const -{ - Q_D(const QState); - return d->transitions(); -} - -/*! - Creates a history state of the given \a type for this state and returns the - new state. The history state becomes a child of this state. -*/ -QHistoryState *QState::addHistoryState(HistoryType type) -{ - return QHistoryStatePrivate::create(type, this); -} - -/*! \reimp */ -void QState::onEntry() +void QState::onEntry(QEvent *event) { - QActionState::onEntry(); + Q_UNUSED(event); } /*! \reimp */ -void QState::onExit() +void QState::onExit(QEvent *event) { - QActionState::onExit(); + Q_UNUSED(event); } /*! @@ -406,7 +446,7 @@ QAbstractState *QState::initialState() const void QState::setInitialState(QAbstractState *state) { Q_D(QState); - if (d->isParallelGroup) { + if (d->childMode == QState::ParallelStates) { qWarning("QState::setInitialState: ignoring attempt to set initial state " "of parallel state group %p", this); return; @@ -420,11 +460,45 @@ void QState::setInitialState(QAbstractState *state) } /*! + Returns the child mode of this state. +*/ +QState::ChildMode QState::childMode() const +{ + Q_D(const QState); + return d->childMode; +} + +/*! + Sets the child \a mode of this state. +*/ +void QState::setChildMode(ChildMode mode) +{ + Q_D(QState); + d->childMode = mode; +} + +/*! \reimp */ bool QState::event(QEvent *e) { - return QActionState::event(e); + return QAbstractState::event(e); } +/*! + \fn QState::finished() + + This signal is emitted when a final child state of this state is entered. + + \sa QFinalState +*/ + +/*! + \fn QState::polished() + + This signal is emitted when all properties have been assigned their final value. + + \sa QState::assignProperty(), QAbstractTransition::addAnimation() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 4c86e02..73955d7 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -43,9 +43,9 @@ #define QSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qactionstate.h> +#include <QtCore/qabstractstate.h> #else -#include "qactionstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -55,47 +55,50 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QAbstractTransition; -class QHistoryState; class QSignalTransition; -class QStateFinishedTransition; class QStatePrivate; -class Q_CORE_EXPORT QState : public QActionState +class Q_CORE_EXPORT QState : public QAbstractState { Q_OBJECT + Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) + Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) + Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode) + Q_ENUMS(ChildMode) public: - enum Type { - Normal, - ParallelGroup - }; - - enum HistoryType { - ShallowHistory, - DeepHistory + enum ChildMode { + ExclusiveStates, + ParallelStates }; QState(QState *parent = 0); - QState(Type type, QState *parent = 0); + QState(ChildMode childMode, QState *parent = 0); ~QState(); QAbstractState *errorState() const; void setErrorState(QAbstractState *state); - void addTransition(QAbstractTransition *transition); + QAbstractTransition *addTransition(QAbstractTransition *transition); QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target); QAbstractTransition *addTransition(QAbstractState *target); - QStateFinishedTransition *addFinishedTransition(QAbstractState *target); void removeTransition(QAbstractTransition *transition); - QList<QAbstractTransition*> transitions() const; - - QHistoryState *addHistoryState(HistoryType type = ShallowHistory); QAbstractState *initialState() const; void setInitialState(QAbstractState *state); + ChildMode childMode() const; + void setChildMode(ChildMode mode); + + void assignProperty(QObject *object, const char *name, + const QVariant &value); + +Q_SIGNALS: + void finished(); + void polished(); + protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 17b312a..1f913b4 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -53,14 +53,33 @@ // We mean it. // -#include "qactionstate_p.h" +#include "qabstractstate_p.h" #include <QtCore/qlist.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE +struct QPropertyAssignment +{ + QPropertyAssignment() + : object(0) {} + QPropertyAssignment(QObject *o, const QByteArray &n, + const QVariant &v, bool es = true) + : object(o), propertyName(n), value(v), explicitlySet(es) + {} + QObject *object; + QByteArray propertyName; + QVariant value; + bool explicitlySet; +}; + +class QAbstractTransition; +class QHistoryState; + class QState; -class Q_CORE_EXPORT QStatePrivate : public QActionStatePrivate +class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate { Q_DECLARE_PUBLIC(QState) public: @@ -74,9 +93,14 @@ public: QList<QHistoryState*> historyStates() const; QList<QAbstractTransition*> transitions() const; + void emitFinished(); + void emitPolished(); + QAbstractState *errorState; - bool isParallelGroup; QAbstractState *initialState; + QState::ChildMode childMode; + + QList<QPropertyAssignment> propertyAssignments; }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstateaction.cpp b/src/corelib/statemachine/qstateaction.cpp deleted file mode 100644 index b03aa19..0000000 --- a/src/corelib/statemachine/qstateaction.cpp +++ /dev/null @@ -1,354 +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 "qstateaction.h" -#include "qstateaction_p.h" -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qmetaobject.h> - -QT_BEGIN_NAMESPACE - -QStateActionPrivate::QStateActionPrivate() -{ - when = ExecuteOnEntry; -} - -QStateActionPrivate::~QStateActionPrivate() -{ -} - -QStateActionPrivate *QStateActionPrivate::get(QStateAction *q) -{ - return q->d_func(); -} - -void QStateActionPrivate::callExecute() -{ - Q_Q(QStateAction); - q->execute(); -} - -/*! - \class QStateAction - - \brief The QStateAction class is the base class of QState actions. - - \ingroup statemachine - - A state action is added to a state by calling QState::addEntryAction() or - QState::addExitAction(). QStateAction is part of \l{The State Machine - Framework}. - - \section1 Subclassing - - Subclasses must implement the execute() function. -*/ - -/*! - Constructs a new QStateAction object with the given \a parent. -*/ -QStateAction::QStateAction(QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QStateActionPrivate, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QStateActionPrivate) -#endif -{ -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif -} - -/*! - \internal -*/ -QStateAction::QStateAction(QStateActionPrivate &dd, QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif -{ -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif -} - -/*! - Destroys this QStateAction object. -*/ -QStateAction::~QStateAction() -{ -#ifdef QT_STATEMACHINE_SOLUTION - delete d_ptr; -#endif -} - -/*! - \fn QStateAction::execute() - - Executes this action. -*/ - -/*! - \reimp -*/ -bool QStateAction::event(QEvent *e) -{ - return QObject::event(e); -} - -QStateInvokeMethodActionPrivate *QStateInvokeMethodActionPrivate::get(QStateInvokeMethodAction *q) -{ - return q->d_func(); -} - -/*! - \class QStateInvokeMethodAction - - \brief The QStateInvokeMethodAction class provides an invoke method action for QObjects. - - \ingroup statemachine - - The QStateInvokeMethodAction class provides an action that calls a method of - a QObject when a QState is entered or exited. QStateInvokeMethodAction is - part of \l{The State Machine Framework}. - - Typically you don't construct QStateInvokeMethodAction objects directly, but - rather call the QState::invokeMethodOnEntry() function or the - QState::invokeMethodOnExit() function. -*/ - -/*! - \property QStateInvokeMethodAction::arguments - - \brief the arguments to the method this action invokes -*/ - -/*! - \property QStateInvokeMethodAction::methodName - - \brief the name of the method this action invokes -*/ - -/*! - \property QStateInvokeMethodAction::target - - \brief the object on which this action invokes a method -*/ - -/*! - Constructs a new QStateInvokeMethodAction object for the method named \a - methodName of the given \a target object, with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction( - QObject *target, const QByteArray &methodName, QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; - d->methodName = methodName; - d->methodIndex = -1; -} - -/*! - Constructs a new QStateInvokeMethodAction object for the method named \a - methodName of the given \a target object, with the given arguments, \a args, - and with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction( - QObject *target, const QByteArray &methodName, - const QList<QVariant> &args, QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; - d->methodName = methodName; - d->methodIndex = -1; - d->args = args; -} - -/*! - Constructs a new QStateInvokeMethodAction object with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction(QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = 0; - d->methodIndex = -1; -} - -/*! - Destroys this QStateInvokeMethodAction object. -*/ -QStateInvokeMethodAction::~QStateInvokeMethodAction() -{ -} - -/*! - \reimp -*/ -void QStateInvokeMethodAction::execute() -{ - Q_D(QStateInvokeMethodAction); - if (!d->target) - return; - - if (d->methodIndex == -1) { - QVarLengthArray<char, 512> sig; - int len = d->methodName.length(); - if (len <= 0) - return; - sig.append(d->methodName, len); - sig.append('('); - - int paramCount; - for (paramCount = 0; paramCount < d->args.size() && paramCount < 10; ++paramCount) { - const char *tn = d->args.at(paramCount).typeName(); - len = qstrlen(tn); - if (len <= 0) - break; - sig.append(tn, len); - sig.append(','); - } - if (paramCount == 0) - sig.append(')'); // no parameters - else - sig[sig.size() - 1] = ')'; - sig.append('\0'); - - const QMetaObject *meta = d->target->metaObject(); - int idx = meta->indexOfMethod(sig.constData()); - if (idx < 0) { - QByteArray norm = QMetaObject::normalizedSignature(sig.constData()); - idx = meta->indexOfMethod(norm.constData()); - if ((idx < 0) || (idx >= meta->methodCount())) { - qWarning("InvokeMethodAction: unable to find method '%s' of %s(%p)", - sig.constData(), meta->className(), d->target); - return; - } - } - d->methodIndex = idx; - } - - void *param[11]; - param[0] = 0; // return value - for (int i = 0; i < 10; ++i) - param[i+1] = (i < d->args.size()) ? const_cast<void*>(d->args.at(i).constData()) : (void*)0; - (void)d->target->qt_metacall(QMetaObject::InvokeMetaMethod, d->methodIndex, param); -} - -/*! - Returns the object on which this action invokes a method. -*/ -QObject *QStateInvokeMethodAction::targetObject() const -{ - Q_D(const QStateInvokeMethodAction); - return d->target; -} - -/*! - Sets the object on which this action invokes a method. -*/ -void QStateInvokeMethodAction::setTargetObject(QObject *target) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; -} - -/*! - Returns the name of the method this action will invoke. -*/ -QByteArray QStateInvokeMethodAction::methodName() const -{ - Q_D(const QStateInvokeMethodAction); - return d->methodName; -} - -/*! - Sets the name of the method this action will invoke. -*/ -void QStateInvokeMethodAction::setMethodName(const QByteArray &methodName) -{ - Q_D(QStateInvokeMethodAction); - if (methodName != d->methodName) { - d->methodName = methodName; - d->methodIndex = -1; - } -} - -/*! - Returns the arguments to the method this action will invoke. -*/ -QVariantList QStateInvokeMethodAction::arguments() const -{ - Q_D(const QStateInvokeMethodAction); - return d->args; -} - -/*! - Sets the arguments to the method this action will invoke. -*/ -void QStateInvokeMethodAction::setArguments(const QVariantList &arguments) -{ - Q_D(QStateInvokeMethodAction); - if (d->args != arguments) { - d->args = arguments; - d->methodIndex = -1; - } -} - -/*! - \reimp -*/ -bool QStateInvokeMethodAction::event(QEvent *e) -{ - return QStateAction::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstateaction.h b/src/corelib/statemachine/qstateaction.h deleted file mode 100644 index 6843080..0000000 --- a/src/corelib/statemachine/qstateaction.h +++ /dev/null @@ -1,119 +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$ -** -****************************************************************************/ - -#ifndef QSTATEACTION_H -#define QSTATEACTION_H - -#include <QtCore/qobject.h> - -#include <QtCore/qvariant.h> -#include <QtCore/qlist.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateActionPrivate; -class Q_CORE_EXPORT QStateAction : public QObject -{ - Q_OBJECT -public: - ~QStateAction(); - -protected: - QStateAction(QObject *parent = 0); - - virtual void execute() = 0; - - bool event(QEvent *e); - -protected: -#ifdef QT_STATEMACHINE_SOLUTION - QStateActionPrivate *d_ptr; -#endif - QStateAction(QStateActionPrivate &dd, QObject *parent); - -private: - Q_DISABLE_COPY(QStateAction) - Q_DECLARE_PRIVATE(QStateAction) -}; - -class QStateInvokeMethodActionPrivate; -class Q_CORE_EXPORT QStateInvokeMethodAction : public QStateAction -{ - Q_OBJECT - Q_PROPERTY(QObject* target READ targetObject WRITE setTargetObject) - Q_PROPERTY(QByteArray methodName READ methodName WRITE setMethodName) - Q_PROPERTY(QVariantList arguments READ arguments WRITE setArguments) -public: - QStateInvokeMethodAction(QObject *target, const QByteArray &methodName, - QObject *parent = 0); - QStateInvokeMethodAction(QObject *target, const QByteArray &methodName, - const QList<QVariant> &args, QObject *parent = 0); - QStateInvokeMethodAction(QObject *parent = 0); - ~QStateInvokeMethodAction(); - - QObject *targetObject() const; - void setTargetObject(QObject *target); - - QByteArray methodName() const; - void setMethodName(const QByteArray &methodName); - - QVariantList arguments() const; - void setArguments(const QVariantList &arguments); - -protected: - void execute(); - - bool event(QEvent *e); - -private: - Q_DISABLE_COPY(QStateInvokeMethodAction) - Q_DECLARE_PRIVATE(QStateInvokeMethodAction) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qstateaction_p.h b/src/corelib/statemachine/qstateaction_p.h deleted file mode 100644 index 4016b74..0000000 --- a/src/corelib/statemachine/qstateaction_p.h +++ /dev/null @@ -1,107 +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$ -** -****************************************************************************/ - -#ifndef QSTATEACTION_P_H -#define QSTATEACTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QT_STATEMACHINE_SOLUTION -#include <private/qobject_p.h> -#endif - -QT_BEGIN_NAMESPACE - -class QStateAction; -class QStateActionPrivate -#ifndef QT_STATEMACHINE_SOLUTION - : public QObjectPrivate -#endif -{ - Q_DECLARE_PUBLIC(QStateAction) -public: - QStateActionPrivate(); - ~QStateActionPrivate(); - - static QStateActionPrivate *get(QStateAction *q); - - void callExecute(); - - enum When { - ExecuteOnEntry, - ExecuteOnExit - }; - - When when; - -#ifdef QT_STATEMACHINE_SOLUTION - QStateAction *q_ptr; -#endif -}; - -class QStateInvokeMethodAction; -class QStateInvokeMethodActionPrivate : public QStateActionPrivate -{ - Q_DECLARE_PUBLIC(QStateInvokeMethodAction) -public: - QStateInvokeMethodActionPrivate() {} - ~QStateInvokeMethodActionPrivate() {} - - static QStateInvokeMethodActionPrivate *get(QStateInvokeMethodAction *q); - - QObject *target; - QByteArray methodName; - int methodIndex; - QList<QVariant> args; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstatefinishedtransition.cpp b/src/corelib/statemachine/qstatefinishedtransition.cpp deleted file mode 100644 index 24d2ca4..0000000 --- a/src/corelib/statemachine/qstatefinishedtransition.cpp +++ /dev/null @@ -1,175 +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 "qstatefinishedtransition.h" -#include "qstatefinishedevent.h" -#include "qtransition_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QStateFinishedTransition - - \brief The QStateFinishedTransition class provides a transition that triggers when a state is finished. - - \ingroup statemachine - - A state is finished when one of its final child states (a QFinalState) is - entered; this will cause a QStateFinishedEvent to be generated. The - QStateFinishedTransition class provides a way of associating a transition - with such an event. QStateFinishedTransition is part of \l{The State Machine - Framework}. - - \code - QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - QState *s11 = new QState(s1); - QFinalState *s12 = new QFinalState(s1); - s11->addTransition(s12); - - QState *s2 = new QState(machine.rootState()); - QStateFinishedTransition *finishedTransition = new QStateFinishedTransition(s1); - finishedTransition->setTargetState(s2); - s1->addTransition(finishedTransition); - \endcode - - \sa QState::addFinishedTransition(), QStateFinishedEvent -*/ - -/*! - \property QStateFinishedTransition::state - - \brief the state whose QStateFinishedEvent this transition is associated with -*/ - -class QStateFinishedTransitionPrivate : public QTransitionPrivate -{ - Q_DECLARE_PUBLIC(QStateFinishedTransition) -public: - QStateFinishedTransitionPrivate(); - - static QStateFinishedTransitionPrivate *get(QStateFinishedTransition *q); - - QState *state; -}; - -QStateFinishedTransitionPrivate::QStateFinishedTransitionPrivate() -{ - state = 0; -} - -QStateFinishedTransitionPrivate *QStateFinishedTransitionPrivate::get(QStateFinishedTransition *q) -{ - return q->d_func(); -} - -/*! - Constructs a new QStateFinishedTransition object that has the given \a - sourceState. -*/ -QStateFinishedTransition::QStateFinishedTransition(QState *sourceState) - : QTransition(*new QStateFinishedTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QStateFinishedTransition object associated with the given - \a state, and that has the given \a targets and \a sourceState. -*/ -QStateFinishedTransition::QStateFinishedTransition( - QState *state, const QList<QAbstractState*> &targets, QState *sourceState) - : QTransition(*new QStateFinishedTransitionPrivate, targets, sourceState) -{ - Q_D(QStateFinishedTransition); - d->state = state; -} - -/*! - Destroys this QStateFinishedTransition. -*/ -QStateFinishedTransition::~QStateFinishedTransition() -{ -} - -/*! - Returns the state associated with this QStateFinishedTransition. -*/ -QState *QStateFinishedTransition::state() const -{ - Q_D(const QStateFinishedTransition); - return d->state; -} - -/*! - Sets the \a state associated with this QStateFinishedTransition. -*/ -void QStateFinishedTransition::setState(QState *state) -{ - Q_D(QStateFinishedTransition); - d->state = state; -} - -/*! - \reimp -*/ -bool QStateFinishedTransition::eventTest(QEvent *event) const -{ - Q_D(const QStateFinishedTransition); -#ifndef QT_STATEMACHINE_SOLUTION - if (event->type() == QEvent::StateFinished) { -#else - if (event->type() == QEvent::Type(QEvent::User-2)) { -#endif - QStateFinishedEvent *sfe = static_cast<QStateFinishedEvent*>(event); - return (sfe->state() == d->state); - } - return false; -} - -/*! - \reimp -*/ -bool QStateFinishedTransition::event(QEvent *e) -{ - return QTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 90932f6..24af8e4 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "qstatemachine.h" +#include "qstate.h" +#include "qstate_p.h" #include "qstatemachine_p.h" #include "qabstracttransition.h" #include "qabstracttransition_p.h" @@ -49,17 +51,9 @@ #include "qsignaleventgenerator_p.h" #include "qabstractstate.h" #include "qabstractstate_p.h" -#include "qactionstate.h" -#include "qactionstate_p.h" #include "qfinalstate.h" #include "qhistorystate.h" #include "qhistorystate_p.h" -#include "qstatefinishedevent.h" -#include "qstatefinishedtransition.h" -#include "qstate.h" -#include "qstate_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" #ifndef QT_STATEMACHINE_SOLUTION #include "private/qobject_p.h" #include "private/qthread_p.h" @@ -68,7 +62,7 @@ #ifndef QT_NO_STATEMACHINE_EVENTFILTER #include "qeventtransition.h" #include "qeventtransition_p.h" -#include "qboundevent_p.h" +#include "qwrappedevent.h" #endif #ifndef QT_NO_ANIMATION @@ -92,6 +86,7 @@ QT_BEGIN_NAMESPACE \brief The QStateMachine class provides a hierarchical finite state machine. + \since 4.6 \ingroup statemachine The QStateMachine class provides a hierarchical finite state machine based @@ -110,7 +105,7 @@ QT_BEGIN_NAMESPACE invoke methods on QObjects when the state is entered or exited. This is typically used in conjunction with \l{Signals and Slots}{signals}; the signals determine the flow of the state graph, whereas the states' property - assigments and method invocations are the actions. + assignments and method invocations are the actions. Use the addState() function to add a state to the state machine; alternatively, pass the machine's rootState() to the state constructor. Use @@ -124,7 +119,7 @@ QT_BEGIN_NAMESPACE QStateMachine machine; QState *s1 = new QState(); - s1->setPropertyOnEntry(&button, "text", "Click me"); + s1->assignProperty(&button, "text", "Click me"); QFinalState *s2 = new QFinalState(); s1->addTransition(&button, SIGNAL(clicked()), s2); @@ -168,6 +163,8 @@ QT_BEGIN_NAMESPACE \property QStateMachine::initialState \brief the initial state of this state machine + + The initial state must be one of the rootState()'s child states. */ /*! @@ -182,6 +179,27 @@ QT_BEGIN_NAMESPACE \brief the error string of this state machine */ +/*! + \property QStateMachine::globalRestorePolicy + + \brief the restore policy for states of this state machine. + + The default value of this property is + QStateMachine::DoNotRestoreProperties. +*/ + +#ifndef QT_NO_ANIMATION +/*! + \property QStateMachine::animationsEnabled + + \brief whether animations are enabled + + The default value of this property is true. + + \sa QAbstractTransition::addAnimation() +*/ +#endif + // #define QSTATEMACHINE_DEBUG QStateMachinePrivate::QStateMachinePrivate() @@ -191,12 +209,15 @@ QStateMachinePrivate::QStateMachinePrivate() processingScheduled = false; stop = false; error = QStateMachine::NoError; - globalRestorePolicy = QAbstractState::DoNotRestoreProperties; + globalRestorePolicy = QStateMachine::DoNotRestoreProperties; rootState = 0; initialErrorStateForRoot = 0; #ifndef QT_STATEMACHINE_SOLUTION signalEventGenerator = 0; #endif +#ifndef QT_NO_ANIMATION + animationsEnabled = true; +#endif } QStateMachinePrivate::~QStateMachinePrivate() @@ -237,6 +258,18 @@ Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler() return &qt_kernel_statemachine_handler; } +static int indexOfDescendant(QState *s, QAbstractState *desc) +{ + QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates(); + for (int i = 0; i < childStates.size(); ++i) { + QAbstractState *c = childStates.at(i); + if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) { + return i; + } + } + return -1; +} + bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2) { if (s1->parent() == s2->parent()) { @@ -247,8 +280,9 @@ bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return true; } else { - // ### fixme - return s1 < s2; + QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(lca != 0); + return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } @@ -262,8 +296,9 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return false; } else { - // ### fixme - return s2 < s1; + QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(lca != 0); + return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } @@ -343,26 +378,26 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event return enabledTransitions; } -void QStateMachinePrivate::microstep(const QList<QAbstractTransition*> &enabledTransitions) +void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ")"; qDebug() << q_func() << ": configuration before exiting states:" << configuration; #endif - exitStates(enabledTransitions); + QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after exiting states:" << configuration; #endif - executeTransitionContent(enabledTransitions); - QList<QAbstractState*> enteredStates = enterStates(enabledTransitions); - applyProperties(enabledTransitions, enteredStates); + executeTransitionContent(event, enabledTransitions); + QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions); + applyProperties(enabledTransitions, exitedStates, enteredStates); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after entering states:" << configuration; qDebug() << q_func() << ": end microstep"; #endif } -QList<QAbstractState*> QStateMachinePrivate::exitStates(const QList<QAbstractTransition*> &enabledTransitions) +QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions) { // qDebug() << "exitStates(" << enabledTransitions << ")"; QSet<QAbstractState*> statesToExit; @@ -374,6 +409,15 @@ QList<QAbstractState*> QStateMachinePrivate::exitStates(const QList<QAbstractTra continue; lst.prepend(t->sourceState()); QAbstractState *lca = findLCA(lst); + if (lca == 0) { + setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); + lst = pendingErrorStates.toList(); + lst.prepend(t->sourceState()); + + lca = findLCA(lst); + Q_ASSERT(lca != 0); + } + { QSet<QAbstractState*>::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { @@ -395,7 +439,7 @@ QList<QAbstractState*> QStateMachinePrivate::exitStates(const QList<QAbstractTra QSet<QAbstractState*>::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { QAbstractState *s0 = *it; - if (QHistoryStatePrivate::get(h)->historyType == QState::DeepHistory) { + if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) { if (isAtomic(s0) && isDescendantOf(s0, s)) QHistoryStatePrivate::get(h)->configuration.append(s0); } else if (s0->parentState() == s) { @@ -403,7 +447,7 @@ QList<QAbstractState*> QStateMachinePrivate::exitStates(const QList<QAbstractTra } } #ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QState::DeepHistory) ? "deep" : "shallow") + qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") << "history for" << s << "in" << h << ":" << QHistoryStatePrivate::get(h)->configuration; #endif } @@ -414,24 +458,25 @@ QList<QAbstractState*> QStateMachinePrivate::exitStates(const QList<QAbstractTra #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": exiting" << s; #endif - QAbstractStatePrivate::get(s)->callOnExit(); + QAbstractStatePrivate::get(s)->callOnExit(event); configuration.remove(s); + QAbstractStatePrivate::get(s)->emitExited(); } return statesToExit_sorted; } -void QStateMachinePrivate::executeTransitionContent(const QList<QAbstractTransition*> &enabledTransitions) +void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions) { for (int i = 0; i < enabledTransitions.size(); ++i) { QAbstractTransition *t = enabledTransitions.at(i); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": triggering" << t; #endif - QAbstractTransitionPrivate::get(t)->callOnTransition(); + QAbstractTransitionPrivate::get(t)->callOnTransition(event); } } -QList<QAbstractState*> QStateMachinePrivate::enterStates(const QList<QAbstractTransition*> &enabledTransitions) +QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG Q_Q(QStateMachine); @@ -440,45 +485,24 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(const QList<QAbstractTr QSet<QAbstractState*> statesToEnter; QSet<QAbstractState*> statesForDefaultEntry; - for (int i = 0; i < enabledTransitions.size(); ++i) { - QAbstractTransition *t = enabledTransitions.at(i); - QList<QAbstractState*> lst = t->targetStates(); - if (lst.isEmpty()) - continue; - lst.prepend(t->sourceState()); - QState *lca = findLCA(lst); - for (int j = 1; j < lst.size(); ++j) { - QAbstractState *s = lst.at(j); - if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) { - QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration; - if (!hconf.isEmpty()) { - for (int k = 0; k < hconf.size(); ++k) { - QAbstractState *s0 = hconf.at(k); - addStatesToEnter(s0, lca, statesToEnter, statesForDefaultEntry); - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": restoring" - << ((QHistoryStatePrivate::get(h)->historyType == QState::DeepHistory) ? "deep" : "shallow") - << "history from" << s << ":" << hconf; -#endif - } else { - QList<QAbstractState*> hlst; - if (QHistoryStatePrivate::get(h)->defaultState) - hlst.append(QHistoryStatePrivate::get(h)->defaultState); - if (hlst.isEmpty()) { - setError(QStateMachine::NoDefaultStateInHistoryState, h); - } else { - for (int k = 0; k < hlst.size(); ++k) { - QAbstractState *s0 = hlst.at(k); - addStatesToEnter(s0, lca, statesToEnter, statesForDefaultEntry); - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": initial history targets for" << s << ":" << hlst; -#endif + if (pendingErrorStates.isEmpty()) { + for (int i = 0; i < enabledTransitions.size(); ++i) { + QAbstractTransition *t = enabledTransitions.at(i); + QList<QAbstractState*> lst = t->targetStates(); + if (lst.isEmpty()) + continue; + lst.prepend(t->sourceState()); + QState *lca = findLCA(lst); + for (int j = 1; j < lst.size(); ++j) { + QAbstractState *s = lst.at(j); + addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); + if (isParallel(lca)) { + QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates(); + foreach (QAbstractState* child,lcac) { + if (!statesToEnter.contains(child)) + addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); } } - } else { - addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); } } } @@ -502,7 +526,8 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(const QList<QAbstractTr #endif configuration.insert(s); registerTransitions(s); - QAbstractStatePrivate::get(s)->callOnEntry(); + QAbstractStatePrivate::get(s)->callOnEntry(event); + QAbstractStatePrivate::get(s)->emitEntered(); if (statesForDefaultEntry.contains(s)) { // ### executeContent(s.initial.transition.children()) } @@ -511,9 +536,9 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(const QList<QAbstractTr if (parent) { QState *grandparent = parent->parentState(); #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": posting finished event for" << parent; + qDebug() << q << ": emitting finished signal for" << parent; #endif - internalEventQueue.append(new QStateFinishedEvent(parent)); + QStatePrivate::get(parent)->emitFinished(); if (grandparent && isParallel(grandparent)) { bool allChildStatesFinal = true; QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates(); @@ -526,9 +551,9 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(const QList<QAbstractTr } if (allChildStatesFinal) { #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": posting finished event for" << grandparent; + qDebug() << q << ": emitting finished signal for" << grandparent; #endif - internalEventQueue.append(new QStateFinishedEvent(grandparent)); + QStatePrivate::get(grandparent)->emitFinished(); } } } @@ -552,135 +577,229 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry) { - statesToEnter.insert(s); - if (isParallel(s)) { - QState *grp = qobject_cast<QState*>(s); - QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates(); - for (int i = 0; i < lst.size(); ++i) { - QAbstractState *child = lst.at(i); - addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry); - } - } else if (isCompound(s)) { - statesForDefaultEntry.insert(s); - QState *grp = qobject_cast<QState*>(s); - QAbstractState *initial = grp->initialState(); - if (initial != 0) { - addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); - } else { - setError(QStateMachine::NoInitialStateError, grp); - return; - } - } - QList<QState*> ancs = properAncestors(s, root); - for (int i = 0; i < ancs.size(); ++i) { - QState *anc = ancs.at(i); - if (!anc->parentState()) - continue; - statesToEnter.insert(anc); - if (isParallel(anc)) { - QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates(); - for (int j = 0; j < lst.size(); ++j) { - QAbstractState *child = lst.at(j); - bool hasDescendantInList = false; - QSet<QAbstractState*>::const_iterator it; - for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { - if (isDescendantOf(*it, child)) { - hasDescendantInList = true; - break; - } - } - if (!hasDescendantInList) - addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry); - } - } - } + if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) { + QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration; + if (!hconf.isEmpty()) { + for (int k = 0; k < hconf.size(); ++k) { + QAbstractState *s0 = hconf.at(k); + addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry); + } + #ifdef QSTATEMACHINE_DEBUG + qDebug() <<q_func() << ": restoring" + << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") + << "history from" << s << ":" << hconf; + #endif + } else { + QList<QAbstractState*> hlst; + if (QHistoryStatePrivate::get(h)->defaultState) + hlst.append(QHistoryStatePrivate::get(h)->defaultState); + + if (hlst.isEmpty()) { + setError(QStateMachine::NoDefaultStateInHistoryStateError, h); + } else { + for (int k = 0; k < hlst.size(); ++k) { + QAbstractState *s0 = hlst.at(k); + addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry); + } + #ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": initial history targets for" << s << ":" << hlst; + #endif + } + } + } else { + statesToEnter.insert(s); + if (isParallel(s)) { + QState *grp = qobject_cast<QState*>(s); + QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates(); + for (int i = 0; i < lst.size(); ++i) { + QAbstractState *child = lst.at(i); + addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry); + } + } else if (isCompound(s)) { + statesForDefaultEntry.insert(s); + QState *grp = qobject_cast<QState*>(s); + QAbstractState *initial = grp->initialState(); + if (initial != 0) { + addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); + } else { + setError(QStateMachine::NoInitialStateError, grp); + return; + } + } + QList<QState*> ancs = properAncestors(s, root); + for (int i = 0; i < ancs.size(); ++i) { + QState *anc = ancs.at(i); + if (!anc->parentState()) + continue; + statesToEnter.insert(anc); + if (isParallel(anc)) { + QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates(); + for (int j = 0; j < lst.size(); ++j) { + QAbstractState *child = lst.at(j); + bool hasDescendantInList = false; + QSet<QAbstractState*>::const_iterator it; + for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { + if (isDescendantOf(*it, child)) { + hasDescendantInList = true; + break; + } + } + if (!hasDescendantInList) + addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry); + } + } + } + } } void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList, + const QList<QAbstractState*> &exitedStates, const QList<QAbstractState*> &enteredStates) { -#ifndef QT_NO_ANIMATION Q_Q(QStateMachine); - // Gracefully terminate playing animations. - for (int i = 0; i < playingAnimations.size(); ++i) - playingAnimations.at(i)->stop(); - playingAnimations.clear(); - for (int i = 0; i < resetEndValues.size(); ++i) - qobject_cast<QVariantAnimation*>(resetEndValues.at(i))->setEndValue(QVariant()); // ### generalize - resetEndValues.clear(); - - // Find the animations to use for the state change. - QList<QAbstractAnimation*> selectedAnimations; - for (int i = 0; i < transitionList.size(); ++i) - selectedAnimations << transitionList.at(i)->animations(); -#else +#ifdef QT_NO_ANIMATION Q_UNUSED(transitionList); #endif - - // Process the SetProperty definitions of the entered states. - QList<QPropertyAssignment> propertyAssignments; + // Process the property assignments of the entered states. + QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState; QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables; for (int i = 0; i < enteredStates.size(); ++i) { - QAbstractState *s = enteredStates.at(i); - - QAbstractState::RestorePolicy restorePolicy = s->restorePolicy(); - if (restorePolicy == QAbstractState::GlobalRestorePolicy) - restorePolicy = globalRestorePolicy; + QState *s = qobject_cast<QState*>(enteredStates.at(i)); + if (!s) + continue; - QList<QPropertyAssignment> assignments = QAbstractStatePrivate::get(s)->propertyAssignments; + QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments; for (int j = 0; j < assignments.size(); ++j) { const QPropertyAssignment &assn = assignments.at(j); - if (restorePolicy == QAbstractState::RestoreProperties) { + if (globalRestorePolicy == QStateMachine::RestoreProperties) { registerRestorable(assn.object, assn.propertyName); } pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); - propertyAssignments.append(assn); + propertyAssignmentsForState[s].append(assn); } + + // Remove pending restorables for all parent states to avoid restoring properties + // before the state that assigned them is exited. If state does not explicitly + // assign a property which is assigned by the parent, it inherits the parent's assignment. + QState *parentState = s; + while ((parentState = parentState->parentState()) != 0) { + assignments = QStatePrivate::get(parentState)->propertyAssignments; + for (int j=0; j<assignments.size(); ++j) { + const QPropertyAssignment &assn = assignments.at(j); + int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); + if (c > 0) + propertyAssignmentsForState[s].append(assn); + } + } + } + if (!pendingRestorables.isEmpty()) { + QAbstractState *s; + if (!enteredStates.isEmpty()) + s = enteredStates.last(); // ### handle if parallel + else + s = 0; + propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables); } - propertyAssignments << restorablesToPropertyList(pendingRestorables); #ifndef QT_NO_ANIMATION - // Set the animated properties that did not finish animating and that are not - // set in the new state. - for (int i = 0; i < propertiesForAnimations.size(); ++i) { - QPropertyAssignment assn = propertiesForAnimations.at(i).second; - bool found = false; - for (int j = 0; j < propertyAssignments.size(); ++j) { - if ((propertyAssignments.at(j).object == assn.object) - && (propertyAssignments.at(j).propertyName == assn.propertyName)) { - found = true; - break; + // Gracefully terminate playing animations for states that are exited. + for (int i = 0; i < exitedStates.size(); ++i) { + QAbstractState *s = exitedStates.at(i); + QList<QAbstractAnimation*> animations = animationsForState.take(s); + for (int j = 0; j < animations.size(); ++j) { + QAbstractAnimation *anim = animations.at(j); + QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + stateForAnimation.remove(anim); + + // Stop the (top-level) animation. + // ### Stopping nested animation has weird behavior. + QAbstractAnimation *topLevelAnim = anim; + while (QAnimationGroup *group = topLevelAnim->group()) + topLevelAnim = group; + topLevelAnim->stop(); + + if (resetAnimationEndValues.contains(anim)) { + qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize + resetAnimationEndValues.remove(anim); + } + QPropertyAssignment assn = propertyForAnimation.take(anim); + Q_ASSERT(assn.object != 0); + // If there is no property assignment that sets this property, + // set the property to its target value. + bool found = false; + QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it; + for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) { + const QList<QPropertyAssignment> &assignments = it.value(); + for (int k = 0; k < assignments.size(); ++k) { + if ((assignments.at(k).object == assn.object) + && (assignments.at(k).propertyName == assn.propertyName)) { + found = true; + break; + } + } + } + if (!found) { + assn.object->setProperty(assn.propertyName, assn.value); } } - if (!found) { - assn.object->setProperty(assn.propertyName, assn.value); + } + + // Find the animations to use for the state change. + QList<QAbstractAnimation*> selectedAnimations; + if (animationsEnabled) { + for (int i = 0; i < transitionList.size(); ++i) { + QAbstractTransition *transition = transitionList.at(i); + + selectedAnimations << transition->animations(); + selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); + + QList<QAbstractState *> targetStates = transition->targetStates(); + for (int j=0; j<targetStates.size(); ++j) + selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j)); } + selectedAnimations << defaultAnimations; } - // Initialize animations from SetProperty definitions. - propertiesForAnimations.clear(); + // Initialize animations from property assignments. for (int i = 0; i < selectedAnimations.size(); ++i) { QAbstractAnimation *anim = selectedAnimations.at(i); - QList<QPropertyAssignment>::iterator it; - for (it = propertyAssignments.begin(); it != propertyAssignments.end(); ) { - QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret; - ret = initializeAnimation(anim, *it); - QList<QAbstractAnimation*> handlers = ret.first; - if (!handlers.isEmpty()) { - for (int j = 0; j < handlers.size(); ++j) - propertiesForAnimations.append(qMakePair(handlers.at(j), *it)); - it = propertyAssignments.erase(it); - } else { - ++it; + QHash<QAbstractState*, QList<QPropertyAssignment> >::iterator it; + for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) { + QList<QPropertyAssignment>::iterator it2; + QAbstractState *s = it.key(); + QList<QPropertyAssignment> &assignments = it.value(); + for (it2 = assignments.begin(); it2 != assignments.end(); ) { + QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret; + ret = initializeAnimation(anim, *it2); + QList<QAbstractAnimation*> handlers = ret.first; + if (!handlers.isEmpty()) { + for (int j = 0; j < handlers.size(); ++j) { + QAbstractAnimation *a = handlers.at(j); + propertyForAnimation.insert(a, *it2); + stateForAnimation.insert(a, s); + animationsForState[s].append(a); + // ### connect to just the top-level animation? + QObject::disconnect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + } + it2 = assignments.erase(it2); + } else { + ++it2; + } + for (int j = 0; j < ret.second.size(); ++j) + resetAnimationEndValues.insert(ret.second.at(j)); } - resetEndValues << ret.second; + if (assignments.isEmpty()) + it = propertyAssignmentsForState.erase(it); + else + ++it; } - // We require that at least one animation is valid. // ### generalize QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim); if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim)) variantAnims.append(va); + bool hasValidEndValue = false; for (int j = 0; j < variantAnims.size(); ++j) { if (variantAnims.at(j)->endValue().isValid()) { @@ -690,18 +809,28 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr } if (hasValidEndValue) { - QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); - QObject::connect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); anim->start(); - playingAnimations.append(anim); } } #endif // !QT_NO_ANIMATION // Immediately set the properties that are not animated. - for (int i = 0; i < propertyAssignments.size(); ++i) { - const QPropertyAssignment &assn = propertyAssignments.at(i); - assn.object->setProperty(assn.propertyName, assn.value); + { + QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it; + for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) { + const QList<QPropertyAssignment> &assignments = it.value(); + for (int i = 0; i < assignments.size(); ++i) { + const QPropertyAssignment &assn = assignments.at(i); + assn.object->setProperty(assn.propertyName, assn.value); + } + } + } + + // Emit polished signal for entered states that have no animated properties. + for (int i = 0; i < enteredStates.size(); ++i) { + QState *s = qobject_cast<QState*>(enteredStates.at(i)); + if (s && !animationsForState.contains(s)) + QStatePrivate::get(s)->emitPolished(); } } @@ -713,7 +842,7 @@ bool QStateMachinePrivate::isFinal(const QAbstractState *s) bool QStateMachinePrivate::isParallel(const QAbstractState *s) { const QState *ss = qobject_cast<const QState*>(s); - return ss && QStatePrivate::get(ss)->isParallelGroup; + return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); } bool QStateMachinePrivate::isCompound(const QAbstractState *s) @@ -728,9 +857,8 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) bool QStateMachinePrivate::isAtomic(const QAbstractState *s) { const QState *ss = qobject_cast<const QState*>(s); - return (ss && !QStatePrivate::get(ss)->isParallelGroup - && QStatePrivate::get(ss)->childStates().isEmpty()) - || isFinal(s); + return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) + || isFinal(s); } @@ -831,15 +959,15 @@ QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) // Find error state recursively in parent hierarchy if not set explicitly for context state QAbstractState *errorState = 0; + QState *s = qobject_cast<QState*>(context); - if (s) { + if (s) errorState = s->errorState(); - if (!errorState) - errorState = findErrorState(s->parentState()); - return errorState; - } - return errorState; + if (!errorState) + errorState = findErrorState(context->parentState()); + + return errorState; } void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext) @@ -854,12 +982,19 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta .arg(currentContext->objectName()); break; - case QStateMachine::NoDefaultStateInHistoryState: + case QStateMachine::NoDefaultStateInHistoryStateError: Q_ASSERT(currentContext != 0); errorString = QStateMachine::tr("Missing default state in history state '%1'") .arg(currentContext->objectName()); break; + + case QStateMachine::NoCommonAncestorForTransitionError: + Q_ASSERT(currentContext != 0); + + errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'") + .arg(currentContext->objectName()); + break; default: errorString = QStateMachine::tr("Unknown error"); }; @@ -875,10 +1010,11 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta currentErrorState = initialErrorStateForRoot; } - if (currentErrorState) { - QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); - addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); - } + Q_ASSERT(currentErrorState != 0); + Q_ASSERT(currentErrorState != rootState); + + QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); + addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } #ifndef QT_NO_ANIMATION @@ -904,13 +1040,6 @@ QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, && prop.object == animation->targetObject() && prop.propertyName == animation->propertyName()) { - if (!animation->startValue().isValid()) { - QByteArray propertyName = animation->propertyName(); - QVariant currentValue = animation->targetObject()->property(propertyName); - - QVariantAnimationPrivate::get(animation)->setDefaultStartValue(currentValue); - } - // Only change end value if it is undefined if (!animation->endValue().isValid()) { animation->setEndValue(prop.value); @@ -922,37 +1051,35 @@ QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, return qMakePair(handledAnimations, localResetEndValues); } -static bool isAncestorOf(QObject *anc, QObject *o) -{ - for (o = o->parent() ; o != 0; o = o->parent()) { - if (o == anc) - return true; - } - return false; -} - void QStateMachinePrivate::_q_animationFinished() { Q_Q(QStateMachine); - QAbstractAnimation *animation = qobject_cast<QAbstractAnimation*>(q->sender()); - Q_ASSERT(animation != 0); - QList<QPair<QAbstractAnimation*, QPropertyAssignment> >::iterator it; - for (it = propertiesForAnimations.begin(); it != propertiesForAnimations.end(); ) { - QAbstractAnimation *a = (*it).first; - if (a == animation || isAncestorOf(animation, a)) { - QPropertyAssignment assn = (*it).second; - assn.object->setProperty(assn.propertyName, assn.value); - if (!assn.explicitlySet) - unregisterRestorable(assn.object, assn.propertyName); - it = propertiesForAnimations.erase(it); - } else { - ++it; - } + QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender()); + Q_ASSERT(anim != 0); + QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + if (resetAnimationEndValues.contains(anim)) { + qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize + resetAnimationEndValues.remove(anim); } - playingAnimations.removeOne(animation); - if (playingAnimations.isEmpty()) - emit q->animationsFinished(); + // Set the final property value. + QPropertyAssignment assn = propertyForAnimation.take(anim); + Q_ASSERT(assn.object != 0); + assn.object->setProperty(assn.propertyName, assn.value); + if (!assn.explicitlySet) + unregisterRestorable(assn.object, assn.propertyName); + + QAbstractState *state = stateForAnimation.take(anim); + Q_ASSERT(state != 0); + QHash<QAbstractState*, QList<QAbstractAnimation*> >::iterator it; + it = animationsForState.find(state); + Q_ASSERT(it != animationsForState.end()); + QList<QAbstractAnimation*> &animations = it.value(); + animations.removeOne(anim); + if (animations.isEmpty()) { + animationsForState.erase(it); + QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished(); + } } #endif // !QT_NO_ANIMATION @@ -965,8 +1092,8 @@ public: StartState(QState *parent) : QState(parent) {} protected: - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; class InitialTransition : public QAbstractTransition @@ -976,7 +1103,7 @@ public: : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: virtual bool eventTest(QEvent *) const { return true; } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} }; } // namespace @@ -1011,9 +1138,11 @@ void QStateMachinePrivate::_q_start() start->addTransition(initialTransition); QList<QAbstractTransition*> transitions; transitions.append(initialTransition); - executeTransitionContent(transitions); - enterStates(transitions); - applyProperties(transitions, QList<QAbstractState*>() << initial); + QEvent nullEvent(QEvent::None); + executeTransitionContent(&nullEvent, transitions); + enterStates(&nullEvent, transitions); + applyProperties(transitions, QList<QAbstractState*>() << start, + QList<QAbstractState*>() << initial); delete start; #ifdef QSTATEMACHINE_DEBUG @@ -1077,7 +1206,7 @@ void QStateMachinePrivate::_q_process() } if (!enabledTransitions.isEmpty()) { q->beginMicrostep(e); - microstep(enabledTransitions.toList()); + microstep(e, enabledTransitions.toList()); q->endMicrostep(e); } #ifdef QSTATEMACHINE_DEBUG @@ -1095,10 +1224,12 @@ void QStateMachinePrivate::_q_process() break; case Finished: state = NotRunning; + unregisterAllTransitions(); emit q->finished(); break; case Stopped: state = NotRunning; + unregisterAllTransitions(); emit q->stopped(); break; } @@ -1229,6 +1360,20 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit #endif } +void QStateMachinePrivate::unregisterAllTransitions() +{ + { + QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState); + for (int i = 0; i < transitions.size(); ++i) + unregisterSignalTransition(transitions.at(i)); + } + { + QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState); + for (int i = 0; i < transitions.size(); ++i) + unregisterEventTransition(transitions.at(i)); + } +} + #ifndef QT_NO_STATEMACHINE_EVENTFILTER void QStateMachinePrivate::registerEventTransition(QEventTransition *transition) { @@ -1352,7 +1497,7 @@ public: setObjectName(QString::fromLatin1("DefaultErrorState")); } - void onEntry() + void onEntry(QEvent *) { QAbstractStatePrivate *d = QAbstractStatePrivate::get(this); QStateMachine *machine = d->machine(); @@ -1361,7 +1506,7 @@ public: qPrintable(machine->errorString())); } - void onExit() {} + void onExit(QEvent *) {} }; class RootState : public QState @@ -1372,8 +1517,8 @@ public: { } - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; } // namespace @@ -1442,14 +1587,45 @@ void QStateMachine::setErrorState(QAbstractState *state) \value NoInitialStateError The machine has entered a QState with children which does not have an initial state set. The context of this error is the state which is missing an initial state. - \value NoDefaultStateInHistoryState The machine has entered a QHistoryState which does not have + \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have a default state set. The context of this error is the QHistoryState which is missing a - default state. + default state. + \value NoCommonAncestorForTransitionError The machine has selected a transition whose source + and targets are not part of the same tree of states, and thus are not part of the same + state machine. Commonly, this could mean that one of the states has not been given + any parent or added to any machine. The context of this error is the source state of + the transition. \sa setErrorState() */ /*! + \enum QStateMachine::RestorePolicy + + This enum specifies the restore policy type. The restore policy + takes effect when the machine enters a state which sets one or more + properties. If the restore policy is set to RestoreProperties, + the state machine will save the original value of the property before the + new value is set. + + Later, when the machine either enters a state which does not set + a value for the given property, the property will automatically be restored + to its initial value. + + Only one initial value will be saved for any given property. If a value for a property has + already been saved by the state machine, it will not be overwritten until the property has been + successfully restored. + + \value DoNotRestoreProperties The state machine should not save the initial values of properties + and restore them later. + \value RestoreProperties The state machine should save the initial values of properties + and restore them later. + + \sa QStateMachine::globalRestorePolicy QState::assignProperty() +*/ + + +/*! Returns the error code of the last error that occurred in the state machine. */ QStateMachine::Error QStateMachine::error() const @@ -1478,33 +1654,25 @@ void QStateMachine::clearError() } /*! - Returns the global restore policy of the state machine. + Returns the restore policy of the state machine. - \sa QActionState::restorePolicy() + \sa setGlobalRestorePolicy() */ -QActionState::RestorePolicy QStateMachine::globalRestorePolicy() const +QStateMachine::RestorePolicy QStateMachine::globalRestorePolicy() const { Q_D(const QStateMachine); return d->globalRestorePolicy; } /*! - Sets the global restore policy of the state machine to \a restorePolicy. The default global + Sets the restore policy of the state machine to \a restorePolicy. The default restore policy is QAbstractState::DoNotRestoreProperties. - The global restore policy cannot be set to QAbstractState::GlobalRestorePolicy. - - \sa QAbstractState::setRestorePolicy() + \sa globalRestorePolicy() */ -void QStateMachine::setGlobalRestorePolicy(QAbstractState::RestorePolicy restorePolicy) +void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy) { Q_D(QStateMachine); - if (restorePolicy == QState::GlobalRestorePolicy) { - qWarning("QStateMachine::setGlobalRestorePolicy: Cannot set global restore policy to " - "GlobalRestorePolicy"); - return; - } - d->globalRestorePolicy = restorePolicy; } @@ -1541,7 +1709,7 @@ void QStateMachine::setInitialState(QAbstractState *state) If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine. - \sa removeState(), rootState() + \sa removeState(), rootState(), setInitialState() */ void QStateMachine::addState(QAbstractState *state) { @@ -1578,10 +1746,20 @@ void QStateMachine::removeState(QAbstractState *state) } /*! - Starts this state machine. - The machine will reset its configuration and transition to the initial - state. When a final top-level state is entered, the machine will emit the - finished() signal. + Returns whether this state machine is running. + + start(), stop() +*/ +bool QStateMachine::isRunning() const +{ + Q_D(const QStateMachine); + return (d->state == QStateMachinePrivate::Running); +} + +/*! + Starts this state machine. The machine will reset its configuration and + transition to the initial state. When a final top-level state (QFinalState) + is entered, the machine will emit the finished() signal. \sa started(), finished(), stop(), initialState() */ @@ -1608,9 +1786,10 @@ void QStateMachine::start() } /*! - Stops this state machine. + Stops this state machine. The state machine will stop processing events and + then emit the stopped() signal. - \sa stopped() + \sa stopped(), start() */ void QStateMachine::stop() { @@ -1674,15 +1853,6 @@ void QStateMachine::postInternalEvent(QEvent *event) } /*! - Returns the list of this state machine's states, or an empty list if the - state machine has no states. -*/ -QList<QAbstractState*> QStateMachine::states() const -{ - return QStatePrivate::get(rootState())->childStates(); -} - -/*! \internal Returns the maximal consistent set of states (including parallel and final @@ -1700,7 +1870,8 @@ QSet<QAbstractState*> QStateMachine::configuration() const /*! \fn QStateMachine::started() - This signal is emitted when the state machine has entered its initial state. + This signal is emitted when the state machine has entered its initial state + (QStateMachine::initialState). \sa QStateMachine::finished(), QStateMachine::start() */ @@ -1709,7 +1880,7 @@ QSet<QAbstractState*> QStateMachine::configuration() const \fn QStateMachine::finished() This signal is emitted when the state machine has reached a top-level final - state. + state (QFinalState). \sa QStateMachine::started() */ @@ -1719,21 +1890,9 @@ QSet<QAbstractState*> QStateMachine::configuration() const This signal is emitted when the state machine has stopped. - \sa QStateMachine::stop() + \sa QStateMachine::stop(), QStateMachine::finished() */ -#ifndef QT_NO_ANIMATION - -/*! - \fn QStateMachine::animationsFinished() - - This signal is emitted when the state machine has finished playing all - animations associated with the latest transition (i.e., all properties have - reached their target values). -*/ - -#endif - /*! \reimp */ @@ -1771,7 +1930,7 @@ bool QStateMachine::eventFilter(QObject *watched, QEvent *event) Q_D(QStateMachine); Q_ASSERT(d->qobjectEvents.contains(watched)); if (d->qobjectEvents[watched].contains(event->type())) - postEvent(new QBoundEvent(watched, d->handler->cloneEvent(event))); + postEvent(new QWrappedEvent(watched, d->handler->cloneEvent(event))); return false; } #endif @@ -1827,6 +1986,56 @@ void QStateMachine::endMicrostep(QEvent *event) Q_UNUSED(event); } +#ifndef QT_NO_ANIMATION + +/*! + Returns whether animations are enabled for this state machine. +*/ +bool QStateMachine::animationsEnabled() const +{ + Q_D(const QStateMachine); + return d->animationsEnabled; +} + +/*! + Sets whether animations are \a enabled for this state machine. +*/ +void QStateMachine::setAnimationsEnabled(bool enabled) +{ + Q_D(QStateMachine); + d->animationsEnabled = enabled; +} + +/*! + Adds a default \a animation to be considered for any transition. +*/ +void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimations.append(animation); +} + +/*! + Returns the list of default animations that will be considered for any transition. +*/ +QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const +{ + Q_D(const QStateMachine); + return d->defaultAnimations; +} + +/*! + Removes \a animation from the list of default animations. +*/ +void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimations.removeAll(animation); +} + +#endif // QT_NO_ANIMATION + + static const uint qt_meta_data_QSignalEventGenerator[] = { // content: @@ -1907,6 +2116,7 @@ QSignalEventGenerator::QSignalEventGenerator( \brief The QSignalEvent class represents a Qt signal event. + \since 4.6 \ingroup statemachine A signal event is generated by a QStateMachine in response to a Qt @@ -1921,6 +2131,8 @@ QSignalEventGenerator::QSignalEventGenerator( */ /*! + \internal + Constructs a new QSignalEvent object with the given \a sender, \a signalIndex and \a arguments. */ @@ -1956,7 +2168,7 @@ QSignalEvent::~QSignalEvent() Returns the index of the signal. - \sa QMetaObject::indexOfSignal() + \sa QMetaObject::indexOfSignal(), QMetaObject::method() */ /*! @@ -1965,52 +2177,59 @@ QSignalEvent::~QSignalEvent() Returns the arguments of the signal. */ + /*! - \class QStateFinishedEvent + \class QWrappedEvent - \brief The QStateFinishedEvent class contains parameters that describe a state that has finished. + \brief The QWrappedEvent class holds a clone of an event associated with a QObject. + \since 4.6 \ingroup statemachine - A state is finished when one of its final child states (a QFinalState) is - entered; this will cause a QStateFinishedEvent to be generated by the state - machine. QStateFinishedEvent is part of \l{The State Machine Framework}. + A wrapped event is generated by a QStateMachine in response to a Qt + event. The QEventTransition class provides a transition associated with a + such an event. QWrappedEvent is part of \l{The State Machine Framework}. - Typically you do not create QStateFinishedEvent objects yourself, but rather - use QStateFinishedTransition to create a transition that's triggered by a - state's finished event. + The object() function returns the object that generated the event. The + event() function returns a clone of the original event. - \sa QStateFinishedTransition + \sa QEventTransition */ /*! - Constructs a new QStateFinishedEvent object associated with the given \a state. + \internal + + Constructs a new QWrappedEvent object with the given \a object + and \a event. */ -QStateFinishedEvent::QStateFinishedEvent(QState *state) - : -#ifndef QT_STATEMACHINE_SOLUTION - QEvent(StateFinished) +QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) +#ifdef QT_STATEMACHINE_SOLUTION + : QEvent(QEvent::Type(QEvent::User-3)) #else - QEvent(QEvent::Type(QEvent::User-2)) + : QEvent(QEvent::Wrapped) #endif - , m_state(state) + , m_object(object), m_event(event) { } /*! - Destroys this QStateFinishedEvent. + Destroys this QWrappedEvent. */ -QStateFinishedEvent::~QStateFinishedEvent() +QWrappedEvent::~QWrappedEvent() { } /*! - Returns the state associated with this QStateFinishedEvent. + \fn QWrappedEvent::object() const + + Returns the object that the event is associated with. +*/ + +/*! + \fn QWrappedEvent::event() const + + Returns a clone of the original event. */ -QState *QStateFinishedEvent::state() const -{ - return m_state; -} QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index c7de171..5dc6c0b 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -43,9 +43,9 @@ #define QSTATEMACHINE_H #ifndef QT_STATEMACHINE_SOLUTION -# include <QtCore/qactionstate.h> +# include <QtCore/qabstractstate.h> #else -# include "qactionstate.h" +# include "qabstractstate.h" #endif #include <QtCore/qlist.h> @@ -63,6 +63,8 @@ class QAbstractState; class QState; class QStateMachinePrivate; +class QAbstractAnimation; +class QAbstractState; class Q_CORE_EXPORT QStateMachine : public QObject { Q_OBJECT @@ -70,12 +72,22 @@ class Q_CORE_EXPORT QStateMachine : public QObject Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) Q_PROPERTY(QString errorString READ errorString) + Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) + Q_ENUMS(RestorePolicy) +#ifndef QT_NO_ANIMATION + Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled) +#endif public: + enum RestorePolicy { + DoNotRestoreProperties, + RestoreProperties + }; enum Error { NoError, NoInitialStateError, - NoDefaultStateInHistoryState, + NoDefaultStateInHistoryStateError, + NoCommonAncestorForTransitionError }; QStateMachine(QObject *parent = 0); @@ -96,12 +108,22 @@ public: QString errorString() const; void clearError(); - QAbstractState::RestorePolicy globalRestorePolicy() const; - void setGlobalRestorePolicy(QAbstractState::RestorePolicy restorePolicy); + bool isRunning() const; + +#ifndef QT_NO_ANIMATION + bool animationsEnabled() const; + void setAnimationsEnabled(bool enabled); + + void addDefaultAnimation(QAbstractAnimation *animation); + QList<QAbstractAnimation *> defaultAnimations() const; + void removeDefaultAnimation(QAbstractAnimation *animation); +#endif // QT_NO_ANIMATION + + QStateMachine::RestorePolicy globalRestorePolicy() const; + void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy); void postEvent(QEvent *event, int delay = 0); - QList<QAbstractState*> states() const; QSet<QAbstractState*> configuration() const; #ifndef QT_NO_STATEMACHINE_EVENTFILTER @@ -117,10 +139,6 @@ Q_SIGNALS: void stopped(); void finished(); -#ifndef QT_NO_ANIMATION - void animationsFinished(); -#endif - protected: void postInternalEvent(QEvent *event); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 04dc71e..47b139c 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -62,7 +62,8 @@ #include <QtCore/qpair.h> #include <QtCore/qset.h> -#include "qabstractstate_p.h" +#include "qstate.h" +#include "qstate_p.h" QT_BEGIN_NAMESPACE @@ -119,17 +120,18 @@ public: void _q_animationFinished(); #endif - void microstep(const QList<QAbstractTransition*> &transitionList); + void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; - QList<QAbstractState*> exitStates(const QList<QAbstractTransition*> &transitionList); - void executeTransitionContent(const QList<QAbstractTransition*> &transitionList); - QList<QAbstractState*> enterStates(const QList<QAbstractTransition*> &enabledTransitions); + QList<QAbstractState*> exitStates(QEvent *event, const QList<QAbstractTransition*> &transitionList); + void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList); + QList<QAbstractState*> enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions); void addStatesToEnter(QAbstractState *s, QState *root, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry); void applyProperties(const QList<QAbstractTransition*> &transitionList, + const QList<QAbstractState*> &exitedStates, const QList<QAbstractState*> &enteredStates); bool isInFinalState(QAbstractState *s) const; @@ -148,6 +150,7 @@ public: void unregisterEventTransition(QEventTransition *transition); #endif void unregisterTransition(QAbstractTransition *transition); + void unregisterAllTransitions(); void handleTransitionSignal(const QObject *sender, int signalIndex, void **args); void scheduleProcess(); @@ -169,9 +172,9 @@ public: QSet<QAbstractState*> configuration; QList<QEvent*> internalEventQueue; QList<QEvent*> externalEventQueue; - + QStateMachine::Error error; - QActionState::RestorePolicy globalRestorePolicy; + QStateMachine::RestorePolicy globalRestorePolicy; QString errorString; QSet<QAbstractState *> pendingErrorStates; @@ -179,14 +182,22 @@ public: QAbstractState *initialErrorStateForRoot; #ifndef QT_NO_ANIMATION + bool animationsEnabled; + QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > initializeAnimation(QAbstractAnimation *abstractAnimation, const QPropertyAssignment &prop); - QList<QPair<QAbstractAnimation*, QPropertyAssignment> > propertiesForAnimations; - QList<QAbstractAnimation*> playingAnimations; - QList<QAbstractAnimation*> resetEndValues; -#endif + QHash<QAbstractState*, QList<QAbstractAnimation*> > animationsForState; + QHash<QAbstractAnimation*, QPropertyAssignment> propertyForAnimation; + QHash<QAbstractAnimation*, QAbstractState*> stateForAnimation; + QSet<QAbstractAnimation*> resetAnimationEndValues; + + QList<QAbstractAnimation *> defaultAnimations; + QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForSource; + QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForTarget; + +#endif // QT_NO_ANIMATION #ifndef QT_STATEMACHINE_SOLUTION QSignalEventGenerator *signalEventGenerator; diff --git a/src/corelib/statemachine/qtransition.cpp b/src/corelib/statemachine/qtransition.cpp deleted file mode 100644 index 3becc3a..0000000 --- a/src/corelib/statemachine/qtransition.cpp +++ /dev/null @@ -1,231 +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 "qtransition.h" -#include "qtransition_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QTransition - - \brief The QTransition class provides an action-based transition. - - \ingroup statemachine - - QTransition provides an action-based transition; you add actions with the - addAction() function. The transition executes the actions when the - transition is triggered. QTransition is part of \l{The State Machine - Framework}. - - The invokeMethodOnTransition() function is used for defining method - invocations that should be performed when a transition is taken. - - \code - QStateMachine machine; - QState *s1 = new QState(); - machine.addState(s1); - QTransition *t1 = new QTransition(); - QLabel label; - t1->invokeMethodOnTransition(&label, "clear"); - QState *s2 = new QState(); - machine.addState(s2); - t1->setTargetState(s2); - s1->addTransition(t1); - \endcode - - Actions are executed in the order in which they were added. - - \sa QState::addTransition(), QStateAction -*/ - -QTransitionPrivate::QTransitionPrivate() -{ -} - -QTransitionPrivate::~QTransitionPrivate() -{ -} - -QTransitionPrivate *QTransitionPrivate::get(QTransition *q) -{ - return q->d_func(); -} - -const QTransitionPrivate *QTransitionPrivate::get(const QTransition *q) -{ - return q->d_func(); -} - -QList<QStateAction*> QTransitionPrivate::actions() const -{ - QList<QStateAction*> result; - QList<QObject*>::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *s = qobject_cast<QStateAction*>(*it); - if (s) - result.append(s); - } - return result; -} - -/*! - Constructs a new QTransition object with the given \a sourceState. -*/ -QTransition::QTransition(QState *sourceState) - : QAbstractTransition(*new QTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QTransition object with the given \a targets and \a - sourceState. -*/ -QTransition::QTransition(const QList<QAbstractState*> &targets, QState *sourceState) - : QAbstractTransition(*new QTransitionPrivate, targets, sourceState) -{ -} - -/*! - \internal -*/ -QTransition::QTransition(QTransitionPrivate &dd, QState *parent) - : QAbstractTransition(dd, parent) -{ -} - -/*! - \internal -*/ -QTransition::QTransition(QTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent) - : QAbstractTransition(dd, targets, parent) -{ -} - -/*! - Destroys this transition. -*/ -QTransition::~QTransition() -{ -} - -/*! - Instructs this QTransition to invoke the given \a method of the given \a - object with the given \a arguments when the transition is taken. This - function will create a QStateInvokeMethodAction object and add it to the - actions of the transition. - - \sa setPropertyOnTransition() -*/ -void QTransition::invokeMethodOnTransition(QObject *object, const char *method, - const QList<QVariant> &arguments) -{ - addAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Adds the given \a action to this transition. - The action will be executed when the transition is triggered. - The transition takes ownership of the action. - - \sa removeAction() -*/ -void QTransition::addAction(QStateAction *action) -{ - if (!action) { - qWarning("QTransition::addAction: cannot add null action"); - return; - } - action->setParent(this); -} - -/*! - Removes the given \a action from this transition. - The transition releases ownership of the action. - - \sa addAction() -*/ -void QTransition::removeAction(QStateAction *action) -{ - if (!action) { - qWarning("QTransition::removeAction: cannot remove null action"); - return; - } - action->setParent(0); -} - -/*! - Returns this transitions's actions, or an empty list if the transition has - no actions. - - \sa addAction() -*/ -QList<QStateAction*> QTransition::actions() const -{ - Q_D(const QTransition); - return d->actions(); -} - -/*! - \reimp -*/ -void QTransition::onTransition() -{ - Q_D(QTransition); - QList<QStateAction*> actions = d->actions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -bool QTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qtransition.h b/src/corelib/statemachine/qtransition.h deleted file mode 100644 index 7eec136..0000000 --- a/src/corelib/statemachine/qtransition.h +++ /dev/null @@ -1,96 +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$ -** -****************************************************************************/ - -#ifndef QTRANSITION_H -#define QTRANSITION_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qabstracttransition.h> -#else -#include "qabstracttransition.h" -#endif - -#include <QtCore/qvariant.h> -#include <QtCore/qlist.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateAction; - -class QTransitionPrivate; -class Q_CORE_EXPORT QTransition : public QAbstractTransition -{ - Q_OBJECT -public: - QTransition(QState *sourceState = 0); - QTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0); - ~QTransition(); - - void invokeMethodOnTransition(QObject *object, const char *method, - const QList<QVariant> &args = QList<QVariant>()); - - void addAction(QStateAction *action); - void removeAction(QStateAction *action); - QList<QStateAction*> actions() const; - -protected: - virtual void onTransition(); - - bool event(QEvent *e); - -protected: - QTransition(QTransitionPrivate &dd, QState *parent); - QTransition(QTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent); - -private: - Q_DISABLE_COPY(QTransition) - Q_DECLARE_PRIVATE(QTransition) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qboundevent_p.h b/src/corelib/statemachine/qwrappedevent.h index b641ff3..b01c608 100644 --- a/src/corelib/statemachine/qboundevent_p.h +++ b/src/corelib/statemachine/qwrappedevent.h @@ -39,35 +39,24 @@ ** ****************************************************************************/ -#ifndef QBOUNDEVENT_P_H -#define QBOUNDEVENT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +#ifndef QWRAPPEDEVENT_H +#define QWRAPPEDEVENT_H #include <QtCore/qcoreevent.h> +QT_BEGIN_HEADER + QT_BEGIN_NAMESPACE -class QBoundEvent : public QEvent +QT_MODULE(Core) + +class QObject; + +class Q_CORE_EXPORT QWrappedEvent : public QEvent { public: - QBoundEvent(QObject *object, QEvent *event) -#ifdef QT_STATEMACHINE_SOLUTION - : QEvent(QEvent::Type(QEvent::User-3)), -#else - : QEvent(QEvent::Bound), -#endif - m_object(object), m_event(event) {} - ~QBoundEvent() {} + QWrappedEvent(QObject *object, QEvent *event); + ~QWrappedEvent(); inline QObject *object() const { return m_object; } inline QEvent *event() const { return m_event; } @@ -75,8 +64,13 @@ public: private: QObject *m_object; QEvent *m_event; + +private: + Q_DISABLE_COPY(QWrappedEvent) }; QT_END_NAMESPACE +QT_END_HEADER + #endif diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri index 9c797e2..5b19bc1 100644 --- a/src/corelib/statemachine/statemachine.pri +++ b/src/corelib/statemachine/statemachine.pri @@ -1,12 +1,8 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qstatemachine_p.h \ - $$PWD/qstateaction.h \ - $$PWD/qstateaction_p.h \ $$PWD/qsignaleventgenerator_p.h \ $$PWD/qabstractstate.h \ $$PWD/qabstractstate_p.h \ - $$PWD/qactionstate.h \ - $$PWD/qactionstate_p.h \ $$PWD/qstate.h \ $$PWD/qstate_p.h \ $$PWD/qfinalstate.h \ @@ -14,28 +10,20 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qhistorystate_p.h \ $$PWD/qabstracttransition.h \ $$PWD/qabstracttransition_p.h \ - $$PWD/qtransition.h \ - $$PWD/qtransition_p.h \ - $$PWD/qstatefinishedevent.h \ - $$PWD/qstatefinishedtransition.h \ $$PWD/qsignalevent.h \ $$PWD/qsignaltransition.h \ $$PWD/qsignaltransition_p.h SOURCES += $$PWD/qstatemachine.cpp \ - $$PWD/qstateaction.cpp \ $$PWD/qabstractstate.cpp \ - $$PWD/qactionstate.cpp \ $$PWD/qstate.cpp \ $$PWD/qfinalstate.cpp \ $$PWD/qhistorystate.cpp \ $$PWD/qabstracttransition.cpp \ - $$PWD/qtransition.cpp \ - $$PWD/qstatefinishedtransition.cpp \ $$PWD/qsignaltransition.cpp !contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) { -HEADERS += $$PWD/qboundevent_p.h \ +HEADERS += $$PWD/qwrappedevent.h \ $$PWD/qeventtransition.h \ $$PWD/qeventtransition_p.h SOURCES += $$PWD/qeventtransition.cpp diff --git a/src/gui/animation/animation.pri b/src/gui/animation/animation.pri index 3092117..27763ca 100644 --- a/src/gui/animation/animation.pri +++ b/src/gui/animation/animation.pri @@ -1,8 +1,3 @@ # Qt gui animation module -HEADERS += \ - animation/qitemanimation.h \ - animation/qitemanimation_p.h - -SOURCES += \ - animation/qitemanimation.cpp +SOURCES += animation/qguivariantanimation.cpp diff --git a/src/gui/animation/qitemanimation_p.h b/src/gui/animation/qguivariantanimation.cpp index 027c199..ed18caa 100644 --- a/src/gui/animation/qitemanimation_p.h +++ b/src/gui/animation/qguivariantanimation.cpp @@ -39,45 +39,42 @@ ** ****************************************************************************/ -#ifndef QITEMANIMATION_P_H -#define QITEMANIMATION_P_H +#ifndef QT_NO_ANIMATION -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of QIODevice. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qitemanimation.h" - -#if defined(QT_EXPERIMENTAL_SOLUTION) -#include "qvariantanimation_p.h" +#ifdef QT_EXPERIMENTAL_SOLUTION +# include "qvariantanimation.h" +# include "qvariantanimation_p.h" #else -#include "private/qvariantanimation_p.h" +#include <QtCore/qvariantanimation.h> +#include <private/qvariantanimation_p.h> #endif +#include <QtGui/qcolor.h> + QT_BEGIN_NAMESPACE -class QItemAnimationPrivate : public QVariantAnimationPrivate +template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress) { - Q_DECLARE_PUBLIC(QItemAnimation) -public: - QItemAnimationPrivate() : propertyName(QItemAnimation::None), - target(0) - { - } + return QColor(_q_interpolate(f.red(), t.red(), progress), + _q_interpolate(f.green(), t.green(), progress), + _q_interpolate(f.blue(), t.blue(), progress), + _q_interpolate(f.alpha(), t.alpha(), progress)); +} - void initDefaultStartValue(); +static int qRegisterGuiGetInterpolator() +{ + qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>); + return 1; +} +Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator) - QItemAnimation::PropertyName propertyName; - QGraphicsItem *target; -}; +static int qUnregisterGuiGetInterpolator() +{ + qRegisterAnimationInterpolator<QColor>(0); + return 1; +} +Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator) QT_END_NAMESPACE -#endif //QITEMANIMATION_P_H +#endif //QT_NO_ANIMATION diff --git a/src/gui/animation/qitemanimation.cpp b/src/gui/animation/qitemanimation.cpp deleted file mode 100644 index 484b386..0000000 --- a/src/gui/animation/qitemanimation.cpp +++ /dev/null @@ -1,361 +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 QtGui 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$ -** -****************************************************************************/ - -/*! - \class QItemAnimation - \brief The QItemAnimation class animates properties for QGraphicsItem - \since 4.5 - \ingroup animation - \preliminary - - This class is part of {The Animation Framework}. You can use QItemAnimation - by itself as a simple animation class, or as part of more complex - animations through QAnimationGroup. - - The most common way to use QItemAnimation is to construct an instance - of it by passing a pointer to a QGraphicsItem and the property you - would like to animate to QItemAnimation's constructor. - - The start value of the animation is optional. If you do not set any start - value, the animation will operate on the target's current property value - at the point when the animation was started. You can call setStartValue() - to set the start value, and setEndValue() to set the target value for - the animated property. - - You can choose to assign a target item by either calling setTargetItem() - or by passing a QGraphicsItem pointer to QVariantAnimation's constructor. - - \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} -*/ - - -#ifndef QT_NO_ANIMATION - -#include "qitemanimation.h" -#include "qitemanimation_p.h" - -#include <QtCore/QMutex> -#ifdef QT_EXPERIMENTAL_SOLUTION -#include "qanimationgroup.h" -#else -#include <QtCore/QAnimationGroup> -#endif -#include <QtGui/QGraphicsItem> - - -QT_BEGIN_NAMESPACE - -typedef QPair<QGraphicsItem *, QItemAnimation::PropertyName> QItemAnimationPair; -typedef QHash<QItemAnimationPair, QItemAnimation*> QItemAnimationHash; -Q_GLOBAL_STATIC(QItemAnimationHash, _q_runningAnimations) -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, guardHashLock, (QMutex::Recursive) ) - -void QItemAnimationPrivate::initDefaultStartValue() -{ - if (target && !defaultStartValue.isValid() && (atBeginning() || atEnd())) { - switch (propertyName) - { - case QItemAnimation::Position: - setDefaultStartValue(target->pos()); - break; - case QItemAnimation::Opacity: - setDefaultStartValue(target->opacity()); - break; - case QItemAnimation::RotationX: - setDefaultStartValue(target->xRotation()); - break; - case QItemAnimation::RotationY: - setDefaultStartValue(target->yRotation()); - break; - case QItemAnimation::RotationZ: - setDefaultStartValue(target->zRotation()); - break; - case QItemAnimation::ScaleFactorX: - setDefaultStartValue(target->xScale()); - break; - case QItemAnimation::ScaleFactorY: - setDefaultStartValue(target->yScale()); - break; - default: - break; - } - } -} - - -/*! - Construct a QItemAnimation object. \a parent is passed to QObject's - constructor. -*/ - -QItemAnimation::QItemAnimation(QObject *parent) : QVariantAnimation(*new QItemAnimationPrivate, parent) -{ -} - -/*! - Construct a QItemAnimation object. \a parent is passed to QObject's - constructor. The animation changes the property \a propertyName on \a - target. The default duration is 250ms. - - \sa targetItem, propertyName -*/ - -QItemAnimation::QItemAnimation(QGraphicsItem *target, PropertyName p, QObject *parent) : QVariantAnimation(*new QItemAnimationPrivate, parent) -{ - Q_D(QItemAnimation); - d->target = target; - d->propertyName = p; -} - -/*! - Destroys the QPropertyAnimation instance. - */ -QItemAnimation::~QItemAnimation() -{ - stop(); -} - -/*! - \property QItemAnimation::targetItem - \brief the target Graphics Item for this animation. - - This property defines the target item for this animation. - - \sa targetItem - */ - -QGraphicsItem *QItemAnimation::targetItem() const -{ - Q_D(const QItemAnimation); - return d->target; -} - -void QItemAnimation::setTargetItem(QGraphicsItem *item) -{ - Q_D(QItemAnimation); - d->target = item; -} - -/*! - \property QItemAnimation::propertyName - \brief the target property for this animation - - This property defines the target property for this animation. The - property is required for the animation to operate. - */ -QItemAnimation::PropertyName QItemAnimation::propertyName() const -{ - Q_D(const QItemAnimation); - return d->propertyName; -} - -void QItemAnimation::setPropertyName(PropertyName p) -{ - Q_D(QItemAnimation); - d->propertyName = p; -} - -/*! - This static function returns the list of running animations on \a item. - If item is 0, then it returns all QItemAnimations running on all QGraphicsItem. - */ -QList<QItemAnimation*> QItemAnimation::runningAnimations(QGraphicsItem *item) -{ - QMutexLocker locker(guardHashLock()); - QList<QItemAnimation*> animList = _q_runningAnimations()->values(); - if (item == 0) - return animList; - - QList<QItemAnimation*> ret; - - for (QList<QItemAnimation*>::const_iterator it = animList.constBegin(); it != animList.constEnd(); ++it) { - if ((*it)->targetItem() == item) - ret += *it; - } - - return ret; -} - -/*! - This static function returns the running animations on \a item and on \a property. - \a prop. - */ -QItemAnimation* QItemAnimation::runningAnimation(QGraphicsItem *item, PropertyName prop) -{ - QMutexLocker locker(guardHashLock()); - return _q_runningAnimations()->value(qMakePair(item, prop), 0 /*default value*/); -} - -/*! - \reimp - */ -bool QItemAnimation::event(QEvent *event) -{ - return QVariantAnimation::event(event); -} - -/*! - \reimp - */ -void QItemAnimation::updateCurrentValue(const QVariant &value) -{ - Q_D(QItemAnimation); - if (!d->target || d->state == Stopped) - return; - - switch (d->propertyName) - { - case Position: - d->target->setPos(qVariantValue<QPointF>(value)); - break; - case Opacity: - d->target->setOpacity(qVariantValue<qreal>(value)); - break; - case RotationX: - d->target->setXRotation(qVariantValue<qreal>(value)); - break; - case RotationY: - d->target->setYRotation(qVariantValue<qreal>(value)); - break; - case RotationZ: - d->target->setZRotation(qVariantValue<qreal>(value)); - break; - case ScaleFactorX: - d->target->setXScale(qVariantValue<qreal>(value)); - break; - case ScaleFactorY: - d->target->setYScale(qVariantValue<qreal>(value)); - break; - default: - qWarning("The property you're trying to animate is not managed by the item"); - break; - } -} - - -/*! - \reimp -*/ -void QItemAnimation::updateState(QAbstractAnimation::State oldState, - QAbstractAnimation::State newState) -{ - Q_D(QItemAnimation); - QVariantAnimation::updateState(oldState, newState); - QMutexLocker locker(guardHashLock()); - QItemAnimationHash *hash = _q_runningAnimations(); - QItemAnimationPair key(d->target, d->propertyName); - - //let's try to convert start and target values according to the type of the proerty - //we're animating - if (newState != Stopped) { - int type = QVariant::Invalid; - switch (d->propertyName) - { - case Position: - type = QVariant::PointF; - break; - case Opacity: - case RotationX: - case RotationY: - case RotationZ: - case ScaleFactorX: - case ScaleFactorY: - type = qMetaTypeId<qreal>(); - break; - case None: - default: - break; - - } - if (type != QVariant::Invalid) { - d->convertValues(type); - } - } - - if (newState == Running) { - if (hash->contains(key)) { - QItemAnimation *oldAnim = hash->value(key); - if (oldAnim != this) { - //we try to stop the top level group - QAbstractAnimation *current = oldAnim; - while(current->group() && current->state() != Stopped) current = current->group(); - current->stop(); - } - } - hash->insert(key, this); - // Initialize start value - d->initDefaultStartValue(); - - } else if (hash->value(key) == this) { - hash->remove(key); - } -} - -///TODO: should be placed somewhere else (in its own file) -template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress) -{ - return QColor(_q_interpolate(f.red(), t.red(), progress), - _q_interpolate(f.green(), t.green(), progress), - _q_interpolate(f.blue(), t.blue(), progress), - _q_interpolate(f.alpha(), t.alpha(), progress)); -} - - - -static int qRegisterGuiGetInterpolator() -{ - qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>); - return 1; -} -Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator) - -static int qUnregisterGuiGetInterpolator() -{ - qRegisterAnimationInterpolator<QColor>(0); - return 1; -} -Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator) - -QT_END_NAMESPACE - -#include "moc_qitemanimation.cpp" - -#endif //QT_NO_ANIMATION diff --git a/src/gui/animation/qitemanimation.h b/src/gui/animation/qitemanimation.h deleted file mode 100644 index d630fe7..0000000 --- a/src/gui/animation/qitemanimation.h +++ /dev/null @@ -1,111 +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 QtGui 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$ -** -****************************************************************************/ - -#ifndef QITEMANIMATION_H -#define QITEMANIMATION_H - -#if defined(QT_EXPERIMENTAL_SOLUTION) -# include "qvariantanimation.h" -#else -# include <QtCore/qvariantanimation.h> -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#ifndef QT_NO_ANIMATION - -class QGraphicsItem; - -class QItemAnimationPrivate; -class Q_GUI_EXPORT QItemAnimation : public QVariantAnimation -{ -public: - enum PropertyName - { - None, //default - Position, - Opacity, - RotationX, - RotationY, - RotationZ, - ScaleFactorX, - ScaleFactorY - }; - - Q_OBJECT - Q_PROPERTY(PropertyName propertyName READ propertyName WRITE setPropertyName) - Q_PROPERTY(QGraphicsItem* targetItem READ targetItem WRITE setTargetItem) /*NOTIFY targetItemChanged*/ - -public: - QItemAnimation(QObject *parent = 0); - QItemAnimation(QGraphicsItem *target, PropertyName p = None, QObject *parent = 0); - ~QItemAnimation(); - - QGraphicsItem *targetItem() const; - void setTargetItem(QGraphicsItem *item); - - PropertyName propertyName() const; - void setPropertyName(PropertyName); - - static QList<QItemAnimation*> runningAnimations(QGraphicsItem *item = 0); - static QItemAnimation* runningAnimation(QGraphicsItem *item, PropertyName prop); - -protected: - bool event(QEvent *event); - void updateCurrentValue(const QVariant &value); - void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState); - -private: - Q_DISABLE_COPY(QItemAnimation) - Q_DECLARE_PRIVATE(QItemAnimation) -}; - -#endif //QT_NO_ANIMATION - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif //QITEMANIMATION_H diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 201dfb8..5ff2acf 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2790,7 +2790,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) if (oldTransform == newTransform) return; - // Notify the item that the matrix is changing. + // Notify the item that the transformation matrix is changing. QVariant newTransformVariant(itemChange(ItemMatrixChange, qVariantFromValue<QMatrix>(newTransform.toAffine()))); newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant)); diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp index 2ce428c..7821feb 100644 --- a/src/gui/statemachine/qbasickeyeventtransition.cpp +++ b/src/gui/statemachine/qbasickeyeventtransition.cpp @@ -39,14 +39,14 @@ public: QEvent::Type eventType; int key; - Qt::KeyboardModifiers modifiers; + Qt::KeyboardModifiers modifiersMask; }; QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate() { eventType = QEvent::None; key = 0; - modifiers = Qt::NoModifier; + modifiersMask = Qt::NoModifier; } QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q) @@ -77,17 +77,17 @@ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, /*! Constructs a new event transition for events of the given \a type for the - given \a key, with the given \a modifiers and \a sourceState. + given \a key, with the given \a modifiersMask and \a sourceState. */ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiers, + Qt::KeyboardModifiers modifiersMask, QState *sourceState) : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState) { Q_D(QBasicKeyEventTransition); d->eventType = type; d->key = key; - d->modifiers = modifiers; + d->modifiersMask = modifiersMask; } /*! @@ -134,21 +134,23 @@ void QBasicKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers that this key event transition checks for. + Returns the keyboard modifiers mask that this key event transition checks + for. */ -Qt::KeyboardModifiers QBasicKeyEventTransition::modifiers() const +Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const { Q_D(const QBasicKeyEventTransition); - return d->modifiers; + return d->modifiersMask; } /*! - Sets the keyboard modifiers that this key event transition will check for. + Sets the keyboard modifiers mask that this key event transition will check + for. */ -void QBasicKeyEventTransition::setModifiers(Qt::KeyboardModifiers modifiers) +void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) { Q_D(QBasicKeyEventTransition); - d->modifiers = modifiers; + d->modifiersMask = modifiersMask; } /*! @@ -159,7 +161,8 @@ bool QBasicKeyEventTransition::eventTest(QEvent *event) const Q_D(const QBasicKeyEventTransition); if (event->type() == d->eventType) { QKeyEvent *ke = static_cast<QKeyEvent*>(event); - return (ke->key() == d->key) && (ke->modifiers() == d->modifiers); + return (ke->key() == d->key) + && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask); } return false; } @@ -167,7 +170,7 @@ bool QBasicKeyEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QBasicKeyEventTransition::onTransition() +void QBasicKeyEventTransition::onTransition(QEvent *) { } diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h index ff52f4d..0d08da0 100644 --- a/src/gui/statemachine/qbasickeyeventtransition_p.h +++ b/src/gui/statemachine/qbasickeyeventtransition_p.h @@ -41,7 +41,8 @@ public: QBasicKeyEventTransition(QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiers, QState *sourceState = 0); + Qt::KeyboardModifiers modifiersMask, + QState *sourceState = 0); ~QBasicKeyEventTransition(); QEvent::Type eventType() const; @@ -50,12 +51,12 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *); private: Q_DISABLE_COPY(QBasicKeyEventTransition) diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp index b7583f8..0cb727e 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition.cpp +++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp @@ -39,6 +39,7 @@ public: QEvent::Type eventType; Qt::MouseButton button; + Qt::KeyboardModifiers modifiersMask; QPainterPath path; }; @@ -118,6 +119,26 @@ void QBasicMouseEventTransition::setButton(Qt::MouseButton button) } /*! + Returns the keyboard modifiers mask that this mouse event transition checks + for. +*/ +Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const +{ + Q_D(const QBasicMouseEventTransition); + return d->modifiersMask; +} + +/*! + Sets the keyboard modifiers mask that this mouse event transition will check + for. +*/ +void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +{ + Q_D(QBasicMouseEventTransition); + d->modifiersMask = modifiersMask; +} + +/*! Returns the path for this mouse event transition. */ QPainterPath QBasicMouseEventTransition::path() const @@ -144,6 +165,7 @@ bool QBasicMouseEventTransition::eventTest(QEvent *event) const if (event->type() == d->eventType) { QMouseEvent *me = static_cast<QMouseEvent*>(event); return (me->button() == d->button) + && ((me->modifiers() & d->modifiersMask) == d->modifiersMask) && (d->path.isEmpty() || d->path.contains(me->pos())); } return false; @@ -152,7 +174,7 @@ bool QBasicMouseEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QBasicMouseEventTransition::onTransition() +void QBasicMouseEventTransition::onTransition(QEvent *) { } diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h index ee04fc7..20c7f8f 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition_p.h +++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h @@ -51,12 +51,15 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); + QPainterPath path() const; void setPath(const QPainterPath &path); protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *); private: Q_DISABLE_COPY(QBasicMouseEventTransition) diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index a4e882d..e6ab11b 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -11,6 +11,7 @@ #include "qkeyeventtransition.h" #include "qbasickeyeventtransition_p.h" +#include <QtCore/qwrappedevent.h> #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qeventtransition_p.h" @@ -25,6 +26,7 @@ QT_BEGIN_NAMESPACE \brief The QKeyEventTransition class provides a transition for key events. + \since 4.6 \ingroup statemachine QKeyEventTransition is part of \l{The State Machine Framework}. @@ -38,6 +40,12 @@ QT_BEGIN_NAMESPACE \brief the key that this key event transition is associated with */ +/*! + \property QKeyEventTransition::modifiersMask + + \brief the keyboard modifiers mask that this key event transition checks for +*/ + class QKeyEventTransitionPrivate : public QEventTransitionPrivate { Q_DECLARE_PUBLIC(QKeyEventTransition) @@ -110,32 +118,23 @@ void QKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers that this key event transition checks for. + Returns the keyboard modifiers mask that this key event transition checks + for. */ -Qt::KeyboardModifiers QKeyEventTransition::modifiers() const +Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const { Q_D(const QKeyEventTransition); - return d->transition->modifiers(); + return d->transition->modifiersMask(); } /*! - Sets the keyboard \a modifiers that this key event transition will check - for. + Sets the keyboard \a modifiers mask that this key event transition will + check for. */ -void QKeyEventTransition::setModifiers(Qt::KeyboardModifiers modifiers) +void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) { Q_D(QKeyEventTransition); - d->transition->setModifiers(modifiers); -} - -/*! - \reimp -*/ -bool QKeyEventTransition::testEventCondition(QEvent *event) const -{ - Q_D(const QKeyEventTransition); - d->transition->setEventType(event->type()); - return QAbstractTransitionPrivate::get(d->transition)->callEventTest(event); + d->transition->setModifiersMask(modifiersMask); } /*! @@ -143,15 +142,20 @@ bool QKeyEventTransition::testEventCondition(QEvent *event) const */ bool QKeyEventTransition::eventTest(QEvent *event) const { - return QEventTransition::eventTest(event); + Q_D(const QKeyEventTransition); + if (!QEventTransition::eventTest(event)) + return false; + QWrappedEvent *we = static_cast<QWrappedEvent*>(event); + d->transition->setEventType(we->event()->type()); + return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } /*! \reimp */ -void QKeyEventTransition::onTransition() +void QKeyEventTransition::onTransition(QEvent *event) { - QEventTransition::onTransition(); + QEventTransition::onTransition(event); } QT_END_NAMESPACE diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index 5bae8d7..3f797f1 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -28,6 +28,7 @@ class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition { Q_OBJECT Q_PROPERTY(int key READ key WRITE setKey) + Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) public: QKeyEventTransition(QState *sourceState = 0); QKeyEventTransition(QObject *object, QEvent::Type type, int key, @@ -40,13 +41,12 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: - void onTransition(); + void onTransition(QEvent *event); bool eventTest(QEvent *event) const; - bool testEventCondition(QEvent *event) const; private: Q_DISABLE_COPY(QKeyEventTransition) diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 1621c78..3191a2f 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -11,6 +11,7 @@ #include "qmouseeventtransition.h" #include "qbasicmouseeventtransition_p.h" +#include <QtCore/qwrappedevent.h> #include <QtGui/qpainterpath.h> #if defined(QT_EXPERIMENTAL_SOLUTION) @@ -26,6 +27,7 @@ QT_BEGIN_NAMESPACE \brief The QMouseEventTransition class provides a transition for mouse events. + \since 4.6 \ingroup statemachine QMouseEventTransition is part of \l{The State Machine Framework}. @@ -33,6 +35,18 @@ QT_BEGIN_NAMESPACE \sa QState::addTransition() */ +/*! + \property QMouseEventTransition::button + + \brief the button that this mouse event transition is associated with +*/ + +/*! + \property QMouseEventTransition::modifiersMask + + \brief the keyboard modifiers mask that this mouse event transition checks for +*/ + class QMouseEventTransitionPrivate : public QEventTransitionPrivate { Q_DECLARE_PUBLIC(QMouseEventTransition) @@ -103,7 +117,7 @@ Qt::MouseButton QMouseEventTransition::button() const } /*! - Sets the button that this mouse event transition will check for. + Sets the \a button that this mouse event transition will check for. */ void QMouseEventTransition::setButton(Qt::MouseButton button) { @@ -112,6 +126,26 @@ void QMouseEventTransition::setButton(Qt::MouseButton button) } /*! + Returns the keyboard modifiers mask that this mouse event transition checks + for. +*/ +Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const +{ + Q_D(const QMouseEventTransition); + return d->transition->modifiersMask(); +} + +/*! + Sets the keyboard \a modifiers mask that this mouse event transition will + check for. +*/ +void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +{ + Q_D(QMouseEventTransition); + d->transition->setModifiersMask(modifiersMask); +} + +/*! Returns the path for this mouse event transition. */ QPainterPath QMouseEventTransition::path() const @@ -136,27 +170,22 @@ void QMouseEventTransition::setPath(const QPainterPath &path) /*! \reimp */ -bool QMouseEventTransition::testEventCondition(QEvent *event) const -{ - Q_D(const QMouseEventTransition); - d->transition->setEventType(event->type()); - return QAbstractTransitionPrivate::get(d->transition)->callEventTest(event); -} - -/*! - \reimp -*/ bool QMouseEventTransition::eventTest(QEvent *event) const { - return QEventTransition::eventTest(event); + Q_D(const QMouseEventTransition); + if (!QEventTransition::eventTest(event)) + return false; + QWrappedEvent *we = static_cast<QWrappedEvent*>(event); + d->transition->setEventType(we->event()->type()); + return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } /*! \reimp */ -void QMouseEventTransition::onTransition() +void QMouseEventTransition::onTransition(QEvent *event) { - QEventTransition::onTransition(); + QEventTransition::onTransition(event); } QT_END_NAMESPACE diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index 162b1b5..eee971e 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -29,6 +29,8 @@ class QPainterPath; class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition { Q_OBJECT + Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton) + Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) public: QMouseEventTransition(QState *sourceState = 0); QMouseEventTransition(QObject *object, QEvent::Type type, @@ -42,13 +44,15 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); + QPainterPath path() const; void setPath(const QPainterPath &path); protected: - void onTransition(); + void onTransition(QEvent *event); bool eventTest(QEvent *event) const; - bool testEventCondition(QEvent *event) const; private: Q_DISABLE_COPY(QMouseEventTransition) diff --git a/src/gui/statemachine/statemachine.pri b/src/gui/statemachine/statemachine.pri index 24de458..2eb1e05 100644 --- a/src/gui/statemachine/statemachine.pri +++ b/src/gui/statemachine/statemachine.pri @@ -1,6 +1,3 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - SOURCES += $$PWD/qguistatemachine.cpp !contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) { HEADERS += \ diff --git a/tests/auto/qanimationgroup/tst_qanimationgroup.cpp b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp index ff5c3b4..2952a39 100644 --- a/tests/auto/qanimationgroup/tst_qanimationgroup.cpp +++ b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp @@ -68,6 +68,8 @@ private slots: void statesAndSignals(); void setParentAutoAdd(); void beginNestedGroup(); + void addChildTwice(); + void loopWithoutStartValue(); }; tst_QAnimationGroup::tst_QAnimationGroup() @@ -207,7 +209,7 @@ void tst_QAnimationGroup::setCurrentTime() QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); - a2_s_o1->setIterationCount(3); + a2_s_o1->setLoopCount(3); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); @@ -224,7 +226,7 @@ void tst_QAnimationGroup::setCurrentTime() QVariantAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value"); QVariantAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value"); QVariantAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value"); - a1_p_o2->setIterationCount(3); + a1_p_o2->setLoopCount(3); parallel->addAnimation(a1_p_o1); parallel->addAnimation(a1_p_o2); parallel->addAnimation(a1_p_o3); @@ -233,7 +235,7 @@ void tst_QAnimationGroup::setCurrentTime() QCOMPARE(notTimeDriven->totalDuration(), -1); QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); - loopsForever->setIterationCount(-1); + loopsForever->setLoopCount(-1); QCOMPARE(loopsForever->totalDuration(), -1); QParallelAnimationGroup group; @@ -281,11 +283,11 @@ void tst_QAnimationGroup::setCurrentTime() QCOMPARE(a1_s_o3->currentTime(), 0); QCOMPARE(a1_p_o1->currentTime(), 250); QCOMPARE(a1_p_o2->currentTime(), 0); - QCOMPARE(a1_p_o2->currentIteration(), 1); + QCOMPARE(a1_p_o2->currentLoop(), 1); QCOMPARE(a1_p_o3->currentTime(), 250); QCOMPARE(notTimeDriven->currentTime(), 250); QCOMPARE(loopsForever->currentTime(), 0); - QCOMPARE(loopsForever->currentIteration(), 1); + QCOMPARE(loopsForever->currentLoop(), 1); QCOMPARE(sequence->currentAnimation(), a2_s_o1); // Current time = 251 @@ -294,14 +296,14 @@ void tst_QAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 251); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 1); - QCOMPARE(a2_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 0); QCOMPARE(a3_s_o1->currentTime(), 0); QCOMPARE(sequence2->currentTime(), 251); QCOMPARE(a1_s_o2->currentTime(), 250); QCOMPARE(a1_s_o3->currentTime(), 1); QCOMPARE(a1_p_o1->currentTime(), 250); QCOMPARE(a1_p_o2->currentTime(), 1); - QCOMPARE(a1_p_o2->currentIteration(), 1); + QCOMPARE(a1_p_o2->currentLoop(), 1); QCOMPARE(a1_p_o3->currentTime(), 250); QCOMPARE(notTimeDriven->currentTime(), 251); QCOMPARE(loopsForever->currentTime(), 1); @@ -343,5 +345,69 @@ void tst_QAnimationGroup::beginNestedGroup() } } +void tst_QAnimationGroup::addChildTwice() +{ + QPropertyAnimation *subGroup; + QPropertyAnimation *subGroup2; + QAnimationGroup *parent = new QSequentialAnimationGroup(); + + subGroup = new QPropertyAnimation(); + subGroup->setParent(parent); + parent->addAnimation(subGroup); + QCOMPARE(parent->animationCount(), 1); + + parent->clearAnimations(); + + QCOMPARE(parent->animationCount(), 0); + + // adding the same item twice to a group will remove the item from its current position + // and append it to the end + subGroup = new QPropertyAnimation(parent); + subGroup2 = new QPropertyAnimation(parent); + + QCOMPARE(parent->animationCount(), 2); + QCOMPARE(parent->animationAt(0), subGroup); + QCOMPARE(parent->animationAt(1), subGroup2); + + parent->addAnimation(subGroup); + + QCOMPARE(parent->animationCount(), 2); + QCOMPARE(parent->animationAt(0), subGroup2); + QCOMPARE(parent->animationAt(1), subGroup); + + delete parent; +} + +void tst_QAnimationGroup::loopWithoutStartValue() +{ + QAnimationGroup *parent = new QSequentialAnimationGroup(); + QObject o; + o.setProperty("ole", 0); + QCOMPARE(o.property("ole").toInt(), 0); + + QPropertyAnimation anim1(&o, "ole"); + anim1.setEndValue(-50); + anim1.setDuration(100); + + QPropertyAnimation anim2(&o, "ole"); + anim2.setEndValue(50); + anim2.setDuration(100); + + parent->addAnimation(&anim1); + parent->addAnimation(&anim2); + + parent->setLoopCount(-1); + parent->start(); + + QVERIFY(anim1.startValue().isNull()); + QCOMPARE(anim1.currentValue().toInt(), 0); + QCOMPARE(parent->currentLoop(), 0); + + parent->setCurrentTime(200); + QCOMPARE(parent->currentLoop(), 1); + QCOMPARE(anim1.currentValue().toInt(), 50); + parent->stop(); +} + QTEST_MAIN(tst_QAnimationGroup) #include "tst_qanimationgroup.moc" diff --git a/tests/auto/qanimationstate/qanimationstate.pro b/tests/auto/qanimationstate/qanimationstate.pro deleted file mode 100644 index 8862c27..0000000 --- a/tests/auto/qanimationstate/qanimationstate.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT = core -SOURCES += tst_qanimationstate.cpp - - diff --git a/tests/auto/qanimationstate/tst_qanimationstate.cpp b/tests/auto/qanimationstate/tst_qanimationstate.cpp deleted file mode 100644 index 085db24..0000000 --- a/tests/auto/qanimationstate/tst_qanimationstate.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -****************************************************************************/ - -#include <QtTest/QtTest> -#include <QtCore/qstate.h> -#include <QtCore/qstatemachine.h> -#include <QtCore/qanimationstate.h> - -//TESTED_CLASS=QAnimationState -//TESTED_FILES= - -#define QTRY_COMPARE(__expr, __expected) \ - do { \ - const int __step = 50; \ - const int __timeout = 5000; \ - if ((__expr) != (__expected)) { \ - QTest::qWait(0); \ - } \ - for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ - QTest::qWait(__step); \ - } \ - QCOMPARE(__expr, __expected); \ - } while(0) - - -class tst_QAnimationState : public QObject -{ - Q_OBJECT -public: - tst_QAnimationState(); - virtual ~tst_QAnimationState(); - -private slots: - void init(); - void cleanup(); - void construction(); - void noAnimation(); - void simpleAnimation(); - void twoAnimations(); - void reuseAnimation(); - void nestedTargetState(); - void parallelTargetState(); - void playTwice(); - void twoAnimatedTransitions(); - void globalRestoreProperty(); - void specificRestoreProperty(); - void someAnimationsNotSpecified(); - void someActionsNotAnimated(); - void specificTargetValueOfAnimation(); - void persistentTargetValueOfAnimation(); -}; - -tst_QAnimationState::tst_QAnimationState() -{ -} - -tst_QAnimationState::~tst_QAnimationState() -{ -} - -void tst_QAnimationState::init() -{ -} - -void tst_QAnimationState::cleanup() -{ -} - -void tst_QAnimationState::construction() -{ - QAnimationState as; -} - -class EventTransition : public QTransition -{ -public: - EventTransition(QEvent::Type type, QAbstractState *target) - : QTransition(), m_type(type) { - setTargetState(target); - } -protected: - virtual bool eventTest(QEvent *e) const { - return (e->type() == m_type); - } -private: - QEvent::Type m_type; -}; - -void tst_QAnimationState::noAnimation() -{ - QStateMachine machine; - - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); - s2->setProperty("entered", false); - s2->setPropertyOnEntry(s2, "entered", true); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - s2->addTransition(new EventTransition(QEvent::User, s1)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - QVERIFY(machine.configuration().contains(s1)); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->property("entered").toBool(), true); - QVERIFY(machine.configuration().contains(s2)); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - - QVERIFY(machine.configuration().contains(s1)); - - s2->setProperty("entered", false); - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->property("entered").toBool(), true); - QVERIFY(machine.configuration().contains(s2)); -} - -class ValueCheckerState: public QState -{ -public: - ValueCheckerState(QState *parent) - : QState(parent) - { - } - - void addPropertyToCheck(const QObject *object, const char *propertyName) - { - m_objects.append(object); - m_propertyNames.append(propertyName); - valueOnEntry.append(QVariant()); - } - - QVariantList valueOnEntry; - -protected: - virtual void onEntry() - { - for (int i=0; i<m_objects.size(); ++i) - valueOnEntry[i] = m_objects.at(i)->property(m_propertyNames.at(i)); - - QState::onEntry(); - } - - QList<const QObject *> m_objects; - QList<QByteArray> m_propertyNames; - -}; - -void tst_QAnimationState::simpleAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("fooBar", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "fooBar"); - s2->setPropertyOnEntry(object, "fooBar", 2.0); - - QPropertyAnimation *animation = new QPropertyAnimation(object, "fooBar", s2); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), animation); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::twoAnimations() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - s2->setPropertyOnEntry(object, "bar", 10.0); - - QPropertyAnimation *animationFoo = new QPropertyAnimation(object, "foo", s2); - QPropertyAnimation *animationBar = new QPropertyAnimation(object, "bar", s2); - animationBar->setDuration(900); - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(animationFoo); - as->addAnimation(animationBar); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 10.0); -} - -void tst_QAnimationState::parallelTargetState() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(QState::ParallelGroup, machine.rootState()); - - ValueCheckerState *c1 = new ValueCheckerState(s2); - c1->setPropertyOnEntry(object, "foo", 2.0); - c1->addPropertyToCheck(object, "foo"); - c1->addPropertyToCheck(object, "bar"); - - QState *c2 = new QState(s2); - c2->setPropertyOnEntry(object, "bar", 10.0); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(c1->valueOnEntry.at(0).isValid(), true); - QCOMPARE(c1->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(c1->valueOnEntry.at(1).toDouble(), 10.0); -} - - -void tst_QAnimationState::twoAnimatedTransitions() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - s3->addPropertyToCheck(object, "foo"); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s2)); - s2->addAnimatedTransition(new EventTransition(QEvent::User, s3), - new QPropertyAnimation(object, "foo", s2)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::playTwice() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - QState *s3 = new QState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s2)); - s2->addTransition(new EventTransition(QEvent::User, s3)); - s3->addTransition(s1); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QVERIFY(machine.configuration().contains(s1)); - QCOMPARE(object->property("foo").toDouble(), 2.0); - - s2->valueOnEntry[0] = QVariant(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(object->property("foo").toDouble(), 5.0); -} - -void tst_QAnimationState::nestedTargetState() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QState *s2Child = new QState(s2); - s2Child->setPropertyOnEntry(object, "bar", 10.0); - s2->setInitialState(s2Child); - - QState *s2Child2 = new QState(s2); - s2Child2->setPropertyOnEntry(object, "bar", 11.0); - s2Child->addTransition(s2Child2); // should *not* be considered by QAnimationState as part of target - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 10.0); - QCOMPARE(object->property("bar").toDouble(), 11.0); -} - -void tst_QAnimationState::reuseAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - s3->addPropertyToCheck(object, "foo"); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo", s2); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - s2->addAnimatedTransition(new EventTransition(QEvent::User, s3), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::globalRestoreProperty() -{ - QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->addPropertyToCheck(object, "foo"); - s3->addPropertyToCheck(object, "bar"); - s3->setPropertyOnEntry(object, "bar", 5.0); - - ValueCheckerState *s4 = new ValueCheckerState(machine.rootState()); - s4->addPropertyToCheck(object, "foo"); - s4->addPropertyToCheck(object, "bar"); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s2->addAnimatedTransition(new EventTransition(QEvent::User, s3)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s3->addAnimatedTransition(new EventTransition(QEvent::User, s4)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s3->valueOnEntry.at(1).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s4->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s4->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s4->valueOnEntry.at(1).toDouble(), 3.0); - -} - -void tst_QAnimationState::specificRestoreProperty() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->setRestorePolicy(QState::RestoreProperties); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setRestorePolicy(QState::RestoreProperties); - s3->addPropertyToCheck(object, "foo"); - s3->addPropertyToCheck(object, "bar"); - s3->setPropertyOnEntry(object, "bar", 5.0); - - ValueCheckerState *s4 = new ValueCheckerState(machine.rootState()); - s4->setRestorePolicy(QState::RestoreProperties); - s4->addPropertyToCheck(object, "foo"); - s4->addPropertyToCheck(object, "bar"); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - - as = s2->addAnimatedTransition(new EventTransition(QEvent::User, s3)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s3->addAnimatedTransition(new EventTransition(QEvent::User, s4)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s3->valueOnEntry.at(1).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s4->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s4->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s4->valueOnEntry.at(1).toDouble(), 3.0); -} - -void tst_QAnimationState::someAnimationsNotSpecified() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); -} - -void tst_QAnimationState::someActionsNotAnimated() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - s2->setPropertyOnEntry(object, "bar", 5.0); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s1)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - QCOMPARE(object->property("foo").toDouble(), 2.0); - QCOMPARE(object->property("bar").toDouble(), 5.0); -} - -void tst_QAnimationState::specificTargetValueOfAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); - anim->setEndValue(10.0); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 10.0); - QCOMPARE(object->property("foo").toDouble(), 2.0); -} - -void tst_QAnimationState::persistentTargetValueOfAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(anim->endValue().isValid(), false); -} - - -QTEST_MAIN(tst_QAnimationState) -#include "tst_qanimationstate.moc" diff --git a/tests/auto/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp index 9e3ffcc..8d42e5e 100644 --- a/tests/auto/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/qeasingcurve/tst_qeasingcurve.cpp @@ -96,17 +96,17 @@ void tst_QEasingCurve::type() QEasingCurve curve(QEasingCurve::Linear); QCOMPARE(curve.period(), 0.3); QCOMPARE(curve.amplitude(), 1.0); - + curve.setPeriod(5); curve.setAmplitude(3); QCOMPARE(curve.period(), 5.0); QCOMPARE(curve.amplitude(), 3.0); - + curve.setType(QEasingCurve::InElastic); QCOMPARE(curve.period(), 5.0); QCOMPARE(curve.amplitude(), 3.0); } - + { QEasingCurve curve(QEasingCurve::InElastic); QCOMPARE(curve.period(), 0.3); @@ -132,7 +132,7 @@ void tst_QEasingCurve::type() QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QEasingCurve: Invalid curve type %1") .arg(QEasingCurve::Custom).toLatin1().constData()); curve.setType(QEasingCurve::Custom); - QCOMPARE(curve.type(), QEasingCurve::InCubic); + QCOMPARE(curve.type(), QEasingCurve::InCubic); QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QEasingCurve: Invalid curve type %1") .arg(-1).toLatin1().constData()); curve.setType((QEasingCurve::Type)-1); @@ -191,185 +191,184 @@ void tst_QEasingCurve::valueForProgress_data() // integer values and avoid fp inaccuracies QTest::newRow("Linear") << int(QEasingCurve::Linear) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100); QTest::newRow("InQuad") << int(QEasingCurve::InQuad) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 4 << 16 << 36 << 64 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 1 << 4 << 9 << 16 << 25 << 36 << 48 << 64 << 81 << 100); QTest::newRow("OutQuad") << int(QEasingCurve::OutQuad) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 36 << 64 << 84 << 96 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 19 << 36 << 51 << 64 << 75 << 84 << 90 << 96 << 99 << 100); QTest::newRow("InOutQuad") << int(QEasingCurve::InOutQuad) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 8 << 32 << 68 << 92 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 2 << 8 << 18 << 32 << 50 << 68 << 82 << 92 << 98 << 100); QTest::newRow("OutInQuad") << int(QEasingCurve::OutInQuad) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 32 << 48 << 52 << 68 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 18 << 32 << 42 << 48 << 50 << 52 << 57 << 68 << 82 << 100); QTest::newRow("InCubic") << int(QEasingCurve::InCubic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 6 << 21 << 51 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 2 << 6 << 12 << 21 << 34 << 51 << 72 << 100); QTest::newRow("OutCubic") << int(QEasingCurve::OutCubic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 48 << 78 << 93 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 27 << 48 << 65 << 78 << 87 << 93 << 97 << 99 << 99 << 100); QTest::newRow("InOutCubic") << int(QEasingCurve::InOutCubic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 3 << 25 << 74 << 96 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 3 << 10 << 25 << 50 << 74 << 89 << 96 << 99 << 100); QTest::newRow("OutInCubic") << int(QEasingCurve::OutInCubic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 39 << 49 << 50 << 60 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 24 << 39 << 46 << 49 << 50 << 50 << 53 << 60 << 75 << 100); QTest::newRow("InQuart") << int(QEasingCurve::InQuart) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 2 << 12 << 40 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 0 << 2 << 6 << 12 << 24 << 40 << 65 << 100); QTest::newRow("OutQuart") << int(QEasingCurve::OutQuart) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 59 << 87 << 97 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 34 << 59 << 75 << 87 << 93 << 97 << 99 << 99 << 99 << 100); QTest::newRow("InOutQuart") << int(QEasingCurve::InOutQuart) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 1 << 20 << 79 << 98 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 1 << 6 << 20 << 50 << 79 << 93 << 98 << 99 << 100); QTest::newRow("OutInQuart") << int(QEasingCurve::OutInQuart) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 43 << 49 << 50 << 56 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 29 << 43 << 48 << 49 << 50 << 50 << 51 << 56 << 70 << 100); QTest::newRow("InQuint") << int(QEasingCurve::InQuint) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 1 << 7 << 32 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 0 << 1 << 3 << 7 << 16 << 32 << 59 << 100); QTest::newRow("OutQuint") << int(QEasingCurve::OutQuint) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 67 << 92 << 98 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 40 << 67 << 83 << 92 << 96 << 98 << 99 << 99 << 99 << 100); QTest::newRow("InOutQuint") << int(QEasingCurve::InOutQuint) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 16 << 83 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 3 << 16 << 50 << 83 << 96 << 99 << 99 << 100); QTest::newRow("OutInQuint") << int(QEasingCurve::OutInQuint) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 46 << 49 << 50 << 53 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 33 << 46 << 49 << 49 << 50 << 50 << 50 << 53 << 66 << 100); QTest::newRow("InSine") << int(QEasingCurve::InSine) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 4 << 19 << 41 << 69 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 1 << 4 << 10 << 19 << 29 << 41 << 54 << 69 << 84 << 100); QTest::newRow("OutSine") << int(QEasingCurve::OutSine) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 30 << 58 << 80 << 95 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 15 << 30 << 45 << 58 << 70 << 80 << 89 << 95 << 98 << 100); QTest::newRow("InOutSine") << int(QEasingCurve::InOutSine) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 9 << 34 << 65 << 90 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 2 << 9 << 20 << 34 << 49 << 65 << 79 << 90 << 97 << 100); QTest::newRow("OutInSine") << int(QEasingCurve::OutInSine) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 29 << 47 << 52 << 70 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 15 << 29 << 40 << 47 << 50 << 52 << 59 << 70 << 84 << 100); QTest::newRow("InExpo") << int(QEasingCurve::InExpo) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 1 << 6 << 24 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 0 << 1 << 3 << 6 << 12 << 24 << 49 << 100); QTest::newRow("OutExpo") << int(QEasingCurve::OutExpo) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 75 << 93 << 98 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 50 << 75 << 87 << 93 << 96 << 98 << 99 << 99 << 99 << 100); QTest::newRow("InOutExpo") << int(QEasingCurve::InOutExpo) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 12 << 87 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 3 << 12 << 50 << 87 << 96 << 99 << 99 << 100); QTest::newRow("OutInExpo") << int(QEasingCurve::OutInExpo) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 46 << 49 << 50 << 53 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 37 << 46 << 49 << 49 << 50 << 50 << 50 << 53 << 62 << 100); QTest::newRow("InCirc") << int(QEasingCurve::InCirc) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 2 << 8 << 19 << 40 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 2 << 4 << 8 << 13 << 19 << 28 << 40 << 56 << 100); QTest::newRow("OutCirc") << int(QEasingCurve::OutCirc) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 59 << 80 << 91 << 97 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 43 << 59 << 71 << 80 << 86 << 91 << 95 << 97 << 99 << 100); QTest::newRow("InOutCirc") << int(QEasingCurve::InOutCirc) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 4 << 20 << 80 << 95 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 1 << 4 << 9 << 20 << 50 << 80 << 89 << 95 << 98 << 100); QTest::newRow("OutInCirc") << int(QEasingCurve::OutInCirc) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 40 << 48 << 51 << 60 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 29 << 40 << 45 << 48 << 50 << 51 << 54 << 60 << 70 << 100); QTest::newRow("InElastic") << int(QEasingCurve::InElastic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << 1 << -3 << -12 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << 0 << 1 << -1 << -3 << 12 << -12 << -25 << 100); QTest::newRow("OutElastic") << int(QEasingCurve::OutElastic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 112 << 103 << 98 << 100 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 125 << 112 << 87 << 103 << 101 << 98 << 100 << 100 << 99 << 100); QTest::newRow("InOutElastic") << int(QEasingCurve::InOutElastic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 0 << -6 << 106 << 99 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 0 << 0 << -1 << -6 << 50 << 106 << 101 << 99 << 100 << 100); QTest::newRow("OutInElastic") << int(QEasingCurve::OutInElastic) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 56 << 49 << 49 << 53 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 37 << 56 << 49 << 49 << 50 << 49 << 50 << 53 << 24 << 100); QTest::newRow("InBack") << int(QEasingCurve::InBack) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << -4 << -9 << -2 << 29 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << -1 << -4 << -8 << -9 << -8 << -2 << 9 << 29 << 59 << 100); QTest::newRow("OutBack") << int(QEasingCurve::OutBack) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 70 << 102 << 109 << 104 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 40 << 70 << 90 << 102 << 108 << 109 << 108 << 104 << 101 << 100); QTest::newRow("InOutBack") << int(QEasingCurve::InOutBack) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << -9 << 8 << 91 << 109 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << -3 << -9 << -7 << 8 << 50 << 91 << 107 << 109 << 103 << 100); QTest::newRow("OutInBack") << int(QEasingCurve::OutInBack) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 51 << 52 << 47 << 48 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 35 << 51 << 54 << 52 << 50 << 47 << 45 << 48 << 64 << 100); QTest::newRow("InBounce") << int(QEasingCurve::InBounce) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 6 << 22 << 8 << 69 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 1 << 6 << 6 << 22 << 23 << 9 << 31 << 69 << 92 << 100); QTest::newRow("OutBounce") << int(QEasingCurve::OutBounce) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 30 << 91 << 77 << 93 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 7 << 30 << 68 << 90 << 76 << 77 << 93 << 94 << 98 << 100); QTest::newRow("InOutBounce") << int(QEasingCurve::InOutBounce) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 11 << 34 << 65 << 88 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 3 << 11 << 4 << 34 << 50 << 65 << 95 << 88 << 97 << 100); QTest::newRow("OutInBounce") << int(QEasingCurve::OutInBounce) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 41 << 43 << 56 << 58 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 15 << 40 << 27 << 43 << 50 << 56 << 72 << 58 << 84 << 100); QTest::newRow("InCurve") << int(QEasingCurve::InCurve) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 10 << 37 << 60 << 80 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 2 << 10 << 23 << 37 << 50 << 60 << 70 << 80 << 90 << 100); QTest::newRow("OutCurve") << int(QEasingCurve::OutCurve) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 20 << 39 << 62 << 89 << 100); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 10 << 20 << 30 << 39 << 50 << 62 << 76 << 89 << 97 << 100); QTest::newRow("SineCurve") << int(QEasingCurve::SineCurve) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 0 << 34 << 90 << 90 << 34 << 0); + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 0 << 9 << 34 << 65 << 90 << 100 << 90 << 65 << 34 << 9 << 0); QTest::newRow("CosineCurve") << int(QEasingCurve::CosineCurve) - << (IntList() << 0 << 20 << 40 << 60 << 80 << 100) - << (IntList() << 50 << 97 << 79 << 20 << 2 << 49); - + << (IntList() << 0 << 10 << 20 << 30 << 40 << 50 << 60 << 70 << 80 << 90 << 100) + << (IntList() << 50 << 79 << 97 << 97 << 79 << 50 << 20 << 2 << 2 << 20 << 49); } @@ -386,12 +385,12 @@ void tst_QEasingCurve::valueForProgress() QString strCurve = QLatin1String(mo.enumerator(mo.indexOfEnumerator("Type")).key(c)); QString strInputs; QString strOutputs; - - for (int t = 0; t <= 100; t+= 20) { + + for (int t = 0; t <= 100; t+= 10) { qreal ease = curve.valueForProgress(t/qreal(100)); strInputs += QString::fromAscii(" << %1").arg(t); strOutputs += QString::fromAscii(" << %1").arg(int(100*ease)); - + } QString str = QString::fromAscii(" QTest::newRow(\"%1\") << int(QEasingCurve::%2)\n" "\t\t << (IntList() %3)\n" @@ -460,14 +459,14 @@ void tst_QEasingCurve::operators() QCOMPARE(curve2.valueForProgress(0.25), 0.2); QCOMPARE(curve2.valueForProgress(0.35), 0.3); QCOMPARE(curve2.valueForProgress(0.999999), 0.9); - + // operator== curve.setType(QEasingCurve::InBack); curve2 = curve; curve2.setOvershoot(qreal(1.70158f)); QCOMPARE(curve.overshoot(), curve2.overshoot()); QVERIFY(curve2 == curve); - + curve.setOvershoot(3.0); QVERIFY(curve2 != curve); curve2.setOvershoot(3.0); diff --git a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp index c7f33b7..f2ab57a 100644 --- a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp +++ b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp @@ -71,8 +71,8 @@ private slots: void startGroupWithRunningChild(); void zeroDurationAnimation(); void stopUncontrolledAnimations(); - void iterationCount_data(); - void iterationCount(); + void loopCount_data(); + void loopCount(); void autoAdd(); }; @@ -194,7 +194,7 @@ void tst_QParallelAnimationGroup::setCurrentTime() QVariantAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value"); QVariantAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value"); QVariantAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value"); - a1_p_o2->setIterationCount(3); + a1_p_o2->setLoopCount(3); parallel->addAnimation(a1_p_o1); parallel->addAnimation(a1_p_o2); parallel->addAnimation(a1_p_o3); @@ -203,7 +203,7 @@ void tst_QParallelAnimationGroup::setCurrentTime() QCOMPARE(notTimeDriven->totalDuration(), -1); QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); - loopsForever->setIterationCount(-1); + loopsForever->setLoopCount(-1); QCOMPARE(loopsForever->totalDuration(), -1); QParallelAnimationGroup group; @@ -233,18 +233,18 @@ void tst_QParallelAnimationGroup::setCurrentTime() QCOMPARE(group.currentTime(), 250); QCOMPARE(a1_p_o1->currentTime(), 250); QCOMPARE(a1_p_o2->currentTime(), 0); - QCOMPARE(a1_p_o2->currentIteration(), 1); + QCOMPARE(a1_p_o2->currentLoop(), 1); QCOMPARE(a1_p_o3->currentTime(), 250); QCOMPARE(notTimeDriven->currentTime(), 250); QCOMPARE(loopsForever->currentTime(), 0); - QCOMPARE(loopsForever->currentIteration(), 1); + QCOMPARE(loopsForever->currentLoop(), 1); // Current time = 251 group.setCurrentTime(251); QCOMPARE(group.currentTime(), 251); QCOMPARE(a1_p_o1->currentTime(), 250); QCOMPARE(a1_p_o2->currentTime(), 1); - QCOMPARE(a1_p_o2->currentIteration(), 1); + QCOMPARE(a1_p_o2->currentLoop(), 1); QCOMPARE(a1_p_o3->currentTime(), 250); QCOMPARE(notTimeDriven->currentTime(), 251); QCOMPARE(loopsForever->currentTime(), 1); @@ -589,7 +589,7 @@ void tst_QParallelAnimationGroup::zeroDurationAnimation() group.stop(); - group.setIterationCount(4); + group.setLoopCount(4); stateChangedSpy1.clear(); stateChangedSpy2.clear(); @@ -625,7 +625,7 @@ void tst_QParallelAnimationGroup::stopUncontrolledAnimations() loopsForever.setStartValue(0); loopsForever.setEndValue(100); loopsForever.setDuration(100); - loopsForever.setIterationCount(-1); + loopsForever.setLoopCount(-1); QSignalSpy stateChangedSpy(&anim1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); @@ -670,10 +670,10 @@ struct AnimState { #define Stopped QAbstractAnimation::Stopped Q_DECLARE_METATYPE(AnimState) -void tst_QParallelAnimationGroup::iterationCount_data() +void tst_QParallelAnimationGroup::loopCount_data() { QTest::addColumn<bool>("directionBackward"); - QTest::addColumn<int>("setIterationCount"); + QTest::addColumn<int>("setLoopCount"); QTest::addColumn<int>("initialGroupTime"); QTest::addColumn<int>("currentGroupTime"); QTest::addColumn<AnimState>("expected1"); @@ -742,10 +742,10 @@ void tst_QParallelAnimationGroup::iterationCount_data() } -void tst_QParallelAnimationGroup::iterationCount() +void tst_QParallelAnimationGroup::loopCount() { QFETCH(bool, directionBackward); - QFETCH(int, setIterationCount); + QFETCH(int, setLoopCount); QFETCH(int, initialGroupTime); QFETCH(int, currentGroupTime); QFETCH(AnimState, expected1); @@ -763,7 +763,7 @@ void tst_QParallelAnimationGroup::iterationCount() anim2.setStartValue(0); anim2.setEndValue(100); anim2.setDuration(60); //total 120 - anim2.setIterationCount(2); + anim2.setLoopCount(2); TestAnimation anim3; anim3.setStartValue(0); @@ -774,7 +774,7 @@ void tst_QParallelAnimationGroup::iterationCount() group.addAnimation(&anim2); group.addAnimation(&anim3); - group.setIterationCount(setIterationCount); + group.setLoopCount(setLoopCount); if (initialGroupTime >= 0) group.setCurrentTime(initialGroupTime); if (directionBackward) diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp index f61df49..2e5fd00 100644 --- a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp @@ -42,7 +42,6 @@ #include <QtTest/QtTest> #include <QtCore/qpropertyanimation.h> -#include <QtGui/qitemanimation.h> #include <QtGui/qwidget.h> //TESTED_CLASS=QPropertyAnimation @@ -85,6 +84,7 @@ private slots: void deletion3(); void duration0(); void noStartValue(); + void noStartValueWithLoop(); void startWhenAnotherIsRunning(); void easingcurve_data(); void easingcurve(); @@ -144,7 +144,7 @@ void tst_QPropertyAnimation::construction() void tst_QPropertyAnimation::setCurrentTime_data() { QTest::addColumn<int>("duration"); - QTest::addColumn<int>("iterationCount"); + QTest::addColumn<int>("loopCount"); QTest::addColumn<int>("currentTime"); QTest::addColumn<int>("testCurrentTime"); QTest::addColumn<int>("testCurrentLoop"); @@ -177,7 +177,7 @@ void tst_QPropertyAnimation::setCurrentTime_data() void tst_QPropertyAnimation::setCurrentTime() { QFETCH(int, duration); - QFETCH(int, iterationCount); + QFETCH(int, loopCount); QFETCH(int, currentTime); QFETCH(int, testCurrentTime); QFETCH(int, testCurrentLoop); @@ -186,11 +186,11 @@ void tst_QPropertyAnimation::setCurrentTime() if (duration < 0) QTest::ignoreMessage(QtWarningMsg, "QVariantAnimation::setDuration: cannot set a negative duration"); animation.setDuration(duration); - animation.setIterationCount(iterationCount); + animation.setLoopCount(loopCount); animation.setCurrentTime(currentTime); QCOMPARE(animation.currentTime(), testCurrentTime); - QCOMPARE(animation.currentIteration(), testCurrentLoop); + QCOMPARE(animation.currentLoop(), testCurrentLoop); } void tst_QPropertyAnimation::statesAndSignals_data() @@ -208,7 +208,7 @@ void tst_QPropertyAnimation::statesAndSignals() QSignalSpy finishedSpy(anim, SIGNAL(finished())); QSignalSpy runningSpy(anim, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); - QSignalSpy currentLoopSpy(anim, SIGNAL(currentIterationChanged(int))); + QSignalSpy currentLoopSpy(anim, SIGNAL(currentLoopChanged(int))); anim->setCurrentTime(1); anim->setCurrentTime(100); @@ -217,23 +217,23 @@ void tst_QPropertyAnimation::statesAndSignals() QCOMPARE(currentLoopSpy.count(), 0); QCOMPARE(anim->state(), QAnimationGroup::Stopped); - anim->setIterationCount(3); + anim->setLoopCount(3); anim->setCurrentTime(101); if (uncontrolled) QSKIP("Uncontrolled animations don't handle looping", SkipSingle); QCOMPARE(currentLoopSpy.count(), 1); - QCOMPARE(anim->currentIteration(), 1); + QCOMPARE(anim->currentLoop(), 1); anim->setCurrentTime(0); QCOMPARE(currentLoopSpy.count(), 2); - QCOMPARE(anim->currentIteration(), 0); + QCOMPARE(anim->currentLoop(), 0); anim->start(); QCOMPARE(anim->state(), QAnimationGroup::Running); QCOMPARE(runningSpy.count(), 1); //anim must have started - QCOMPARE(anim->currentIteration(), 0); + QCOMPARE(anim->currentLoop(), 0); runningSpy.clear(); anim->stop(); @@ -241,7 +241,7 @@ void tst_QPropertyAnimation::statesAndSignals() QCOMPARE(runningSpy.count(), 1); //anim must have stopped QCOMPARE(finishedSpy.count(), 0); QCOMPARE(anim->currentTime(), 0); - QCOMPARE(anim->currentIteration(), 0); + QCOMPARE(anim->currentLoop(), 0); QCOMPARE(currentLoopSpy.count(), 2); runningSpy.clear(); @@ -252,24 +252,24 @@ void tst_QPropertyAnimation::statesAndSignals() runningSpy.clear(); QCOMPARE(finishedSpy.count(), 1); QCOMPARE(anim->currentTime(), 100); - QCOMPARE(anim->currentIteration(), 2); + QCOMPARE(anim->currentLoop(), 2); QCOMPARE(currentLoopSpy.count(), 4); anim->start(); // auto-rewinds QCOMPARE(anim->state(), QAnimationGroup::Running); QCOMPARE(anim->currentTime(), 0); - QCOMPARE(anim->currentIteration(), 0); + QCOMPARE(anim->currentLoop(), 0); QCOMPARE(currentLoopSpy.count(), 5); QCOMPARE(runningSpy.count(), 1); // anim has started QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(anim->currentIteration(), 0); + QCOMPARE(anim->currentLoop(), 0); runningSpy.clear(); QTest::qWait(1000); QCOMPARE(currentLoopSpy.count(), 7); QCOMPARE(anim->state(), QAnimationGroup::Stopped); - QCOMPARE(anim->currentIteration(), 2); + QCOMPARE(anim->currentLoop(), 2); QCOMPARE(runningSpy.count(), 1); // anim has stopped QCOMPARE(finishedSpy.count(), 2); QCOMPARE(anim->currentTime(), 100); @@ -340,7 +340,7 @@ void tst_QPropertyAnimation::deletion2() QCOMPARE(runningSpy.count(), 1); QCOMPARE(finishedSpy.count(), 0); - //we can't call deletaLater directly because the delete would only happen in the next iteration of _this_ event loop + //we can't call deletaLater directly because the delete would only happen in the next loop of _this_ event loop QTimer::singleShot(0, object, SLOT(deleteLater())); QTest::qWait(50); @@ -417,6 +417,27 @@ void tst_QPropertyAnimation::noStartValue() QCOMPARE(o.values.last(), 420); } +void tst_QPropertyAnimation::noStartValueWithLoop() +{ + StartValueTester o; + o.setProperty("ole", 42); + o.values.clear(); + + QPropertyAnimation a(&o, "ole"); + a.setEndValue(420); + a.setDuration(250); + a.setLoopCount(2); + a.start(); + + a.setCurrentTime(250); + QCOMPARE(o.values.first(), 42); + QCOMPARE(a.currentValue().toInt(), 42); + QCOMPARE(o.values.last(), 42); + + a.setCurrentTime(500); + QCOMPARE(a.currentValue().toInt(), 420); +} + void tst_QPropertyAnimation::startWhenAnotherIsRunning() { StartValueTester o; @@ -526,13 +547,14 @@ void tst_QPropertyAnimation::startWithoutStartValue() anim.setEndValue(110); anim.start(); current = anim.currentValue().toInt(); - QCOMPARE(current, 42); // the initial default start value - + // the default start value will reevaluate the current property + // and set it to the end value of the last iteration + QCOMPARE(current, 100); QTest::qWait(100); current = anim.currentValue().toInt(); //it is somewhere in the animation - QVERIFY(current > 42); - QVERIFY(current < 110); + QVERIFY(current >= 100); + QVERIFY(current <= 110); } void tst_QPropertyAnimation::playForwardBackward() @@ -602,6 +624,7 @@ QVariant xaxisQPointInterpolator(const QPointF &f, const QPointF &t, qreal progr void tst_QPropertyAnimation::interpolated() { QObject o; + o.setProperty("point", QPointF()); //this will avoid warnings o.setProperty("number", qVariantFromValue<Number>(Number(42))); QCOMPARE(qVariantValue<Number>(o.property("number")), Number(42)); { @@ -627,9 +650,9 @@ void tst_QPropertyAnimation::interpolated() anim.start(); anim.pause(); anim.setCurrentTime(100); - QCOMPARE(o.property("point").toPointF(), QPointF(10, 0)); + QCOMPARE(o.property("point"), QVariant(QPointF(10, 0))); anim.setCurrentTime(500); - QCOMPARE(o.property("point").toPointF(), QPointF(50, 0)); + QCOMPARE(o.property("point"), QVariant(QPointF(50, 0))); } { // unregister it and see if we get back the default behaviour diff --git a/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp index 18b57b2..0631343 100644 --- a/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp +++ b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp @@ -173,7 +173,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); - a2_s_o1->setIterationCount(3); + a2_s_o1->setLoopCount(3); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); @@ -221,7 +221,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 251); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 1); - QCOMPARE(a2_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 0); QCOMPARE(a3_s_o1->currentTime(), 0); QCOMPARE(sequence2->currentTime(), 0); QCOMPARE(a1_s_o2->currentTime(), 0); @@ -233,7 +233,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 750); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 0); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 0); QCOMPARE(sequence2->currentTime(), 0); QCOMPARE(a1_s_o2->currentTime(), 0); @@ -245,7 +245,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1000); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 0); QCOMPARE(sequence2->currentTime(), 0); QCOMPARE(a1_s_o2->currentTime(), 0); @@ -257,7 +257,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1010); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 10); QCOMPARE(sequence2->currentTime(), 0); QCOMPARE(a1_s_o2->currentTime(), 0); @@ -269,7 +269,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 0); QCOMPARE(a1_s_o2->currentTime(), 0); @@ -281,7 +281,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 250); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -293,7 +293,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 500); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -305,7 +305,7 @@ void tst_QSequentialAnimationGroup::setCurrentTime() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 500); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -330,7 +330,7 @@ void tst_QSequentialAnimationGroup::setCurrentTimeWithUncontrolledAnimation() QCOMPARE(notTimeDriven->totalDuration(), -1); QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); - loopsForever->setIterationCount(-1); + loopsForever->setLoopCount(-1); QCOMPARE(loopsForever->totalDuration(), -1); QSequentialAnimationGroup group; @@ -436,7 +436,7 @@ void tst_QSequentialAnimationGroup::seekingForwards() QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); - a2_s_o1->setIterationCount(3); + a2_s_o1->setLoopCount(3); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); @@ -476,7 +476,7 @@ void tst_QSequentialAnimationGroup::seekingForwards() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 250); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -498,7 +498,7 @@ void tst_QSequentialAnimationGroup::seekingForwards() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 500); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -516,7 +516,7 @@ void tst_QSequentialAnimationGroup::seekingBackwards() QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); - a2_s_o1->setIterationCount(3); + a2_s_o1->setLoopCount(3); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); @@ -540,7 +540,7 @@ void tst_QSequentialAnimationGroup::seekingBackwards() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 350); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -564,7 +564,7 @@ void tst_QSequentialAnimationGroup::seekingBackwards() QCOMPARE(a2_s_o1->currentTime(), 0); QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children," "hence they don't reset from their current animation", Continue); - QCOMPARE(a2_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 0); QEXPECT_FAIL("", "rewinding in nested groups is considered as a restart from the children," "hence they don't reset from their current animation", Continue); QCOMPARE(a3_s_o1->currentTime(), 0); @@ -585,7 +585,7 @@ void tst_QSequentialAnimationGroup::seekingBackwards() QCOMPARE(sequence->currentTime(), 1250); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 2); + QCOMPARE(a2_s_o1->currentLoop(), 2); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(sequence2->currentTime(), 500); QCOMPARE(a1_s_o2->currentTime(), 250); @@ -656,11 +656,11 @@ void tst_QSequentialAnimationGroup::pauseAndResume() QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); - a2_s_o1->setIterationCount(2); + a2_s_o1->setLoopCount(2); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); - sequence->setIterationCount(2); + sequence->setLoopCount(2); QSignalSpy a1StateChangedSpy(a1_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); QSignalSpy seqStateChangedSpy(sequence, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); @@ -675,11 +675,11 @@ void tst_QSequentialAnimationGroup::pauseAndResume() group.setCurrentTime(1751); QCOMPARE(group.currentTime(), 1751); QCOMPARE(sequence->currentTime(), 751); - QCOMPARE(sequence->currentIteration(), 1); + QCOMPARE(sequence->currentLoop(), 1); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 1); - QCOMPARE(a3_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 1); + QCOMPARE(a3_s_o1->currentLoop(), 0); QCOMPARE(a3_s_o1->currentTime(), 1); QCOMPARE(group.state(), QAnimationGroup::Paused); @@ -723,11 +723,11 @@ void tst_QSequentialAnimationGroup::pauseAndResume() QVERIFY(group.currentTime() >= 1751); QVERIFY(sequence->currentTime() >= 751); - QCOMPARE(sequence->currentIteration(), 1); + QCOMPARE(sequence->currentLoop(), 1); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 1); - QCOMPARE(a3_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 1); + QCOMPARE(a3_s_o1->currentLoop(), 0); QVERIFY(a3_s_o1->currentTime() >= 1); QCOMPARE(seqStateChangedSpy.count(), 3); // Running,Paused,Running @@ -744,11 +744,11 @@ void tst_QSequentialAnimationGroup::pauseAndResume() QVERIFY(group.currentTime() >= 1751); QVERIFY(sequence->currentTime() >= 751); - QCOMPARE(sequence->currentIteration(), 1); + QCOMPARE(sequence->currentLoop(), 1); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 1); - QCOMPARE(a3_s_o1->currentIteration(), 0); + QCOMPARE(a2_s_o1->currentLoop(), 1); + QCOMPARE(a3_s_o1->currentLoop(), 0); QVERIFY(a3_s_o1->currentTime() >= 1); QCOMPARE(seqStateChangedSpy.count(), 4); // Running,Paused,Running,Paused @@ -780,11 +780,11 @@ void tst_QSequentialAnimationGroup::restart() animsStateChanged[i] = new QSignalSpy(anims[i], SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); } - anims[1]->setIterationCount(2); + anims[1]->setLoopCount(2); sequence->addAnimation(anims[0]); sequence->addAnimation(anims[1]); sequence->addAnimation(anims[2]); - sequence->setIterationCount(2); + sequence->setLoopCount(2); QSequentialAnimationGroup group; group.addAnimation(sequence); @@ -845,17 +845,17 @@ void tst_QSequentialAnimationGroup::looping() QSignalSpy a3Spy(a3_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); QSignalSpy seqSpy(sequence, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); - a2_s_o1->setIterationCount(2); + a2_s_o1->setLoopCount(2); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); sequence->addAnimation(a3_s_o1); - sequence->setIterationCount(2); + sequence->setLoopCount(2); QSequentialAnimationGroup group; QSignalSpy groupSpy(&group, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); group.addAnimation(sequence); - group.setIterationCount(2); + group.setLoopCount(2); group.start(); group.pause(); @@ -864,12 +864,12 @@ void tst_QSequentialAnimationGroup::looping() group.setCurrentTime(1750); QCOMPARE(group.currentTime(), 1750); QCOMPARE(sequence->currentTime(), 750); - QCOMPARE(sequence->currentIteration(), 1); + QCOMPARE(sequence->currentLoop(), 1); QCOMPARE(a1_s_o1->currentTime(), 250); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 1); + QCOMPARE(a2_s_o1->currentLoop(), 1); // this animation is at the beginning because it is the current one inside sequence - QCOMPARE(a3_s_o1->currentIteration(), 0); + QCOMPARE(a3_s_o1->currentLoop(), 0); QCOMPARE(a3_s_o1->currentTime(), 0); QCOMPARE(sequence->currentAnimation(), a3_s_o1); @@ -898,14 +898,14 @@ void tst_QSequentialAnimationGroup::looping() // Looping, current time = duration + 1 group.setCurrentTime(group.duration() + 1); QCOMPARE(group.currentTime(), 1); - QCOMPARE(group.currentIteration(), 1); + QCOMPARE(group.currentLoop(), 1); QCOMPARE(sequence->currentTime(), 1); - QCOMPARE(sequence->currentIteration(), 0); + QCOMPARE(sequence->currentLoop(), 0); QCOMPARE(a1_s_o1->currentTime(), 1); QCOMPARE(a2_s_o1->currentTime(), 250); - QCOMPARE(a2_s_o1->currentIteration(), 1); + QCOMPARE(a2_s_o1->currentLoop(), 1); // this animation is at the end because it was run on the previous loop - QCOMPARE(a3_s_o1->currentIteration(), 0); + QCOMPARE(a3_s_o1->currentLoop(), 0); QCOMPARE(a3_s_o1->currentTime(), 250); QCOMPARE(group.state(), QAnimationGroup::Paused); @@ -1367,7 +1367,7 @@ void tst_QSequentialAnimationGroup::zeroDurationAnimation() group.addAnimation(anim1); group.addAnimation(anim2); group.addAnimation(anim3); - group.setIterationCount(2); + group.setLoopCount(2); group.start(); QCOMPARE(stateChangedSpy.count(), 2); @@ -1401,7 +1401,7 @@ void tst_QSequentialAnimationGroup::stopUncontrolledAnimations() loopsForever.setStartValue(0); loopsForever.setEndValue(100); loopsForever.setDuration(100); - loopsForever.setIterationCount(-1); + loopsForever.setLoopCount(-1); group.addAnimation(¬TimeDriven); group.addAnimation(&loopsForever); @@ -1592,11 +1592,11 @@ void tst_QSequentialAnimationGroup::currentAnimationWithZeroDuration() void tst_QSequentialAnimationGroup::insertAnimation() { QSequentialAnimationGroup group; - group.setIterationCount(2); + group.setLoopCount(2); QPropertyAnimation *anim = new QPropertyAnimation(&group); QCOMPARE(group.duration(), anim->duration()); group.setCurrentTime(300); - QCOMPARE(group.currentIteration(), 1); + QCOMPARE(group.currentLoop(), 1); //this will crash if the sequential group calls duration on the created animation new QPropertyAnimation(&group); diff --git a/tests/auto/qstate/tst_qstate.cpp b/tests/auto/qstate/tst_qstate.cpp index c4a0050..bb7de20 100644 --- a/tests/auto/qstate/tst_qstate.cpp +++ b/tests/auto/qstate/tst_qstate.cpp @@ -9,9 +9,7 @@ #include "qstate.h" #include "qstatemachine.h" -#include "qtransition.h" #include "qsignaltransition.h" -#include "qstateaction.h" // Will try to wait for the condition while allowing event processing #define QTRY_COMPARE(__expr, __expected) \ @@ -42,15 +40,15 @@ private slots: #if 0 void test(); #endif - void setPropertyOnEntry(); - void setPropertyOnEntryTwice(); - void setPropertyOnExit(); - void setPropertyOnExitTwice(); + void assignProperty(); + void assignPropertyTwice(); void historyInitialState(); - void addEntryAction(); + +private: + bool functionCalled; }; -tst_QState::tst_QState() +tst_QState::tst_QState() : functionCalled(false) { } @@ -200,20 +198,20 @@ void tst_QState::test() } #endif -void tst_QState::addEntryAction() +class TestClass: public QObject { - QStateMachine sm; - QState *s0 = new QState(sm.rootState()); - s0->addEntryAction(new QStateSetPropertyAction(this, "objectName", "commandTest")); - sm.setInitialState(s0); + Q_OBJECT +public: + TestClass() : called(false) {} + bool called; + +public slots: + void slot() { called = true; } - sm.start(); - QCoreApplication::processEvents(); - QCOMPARE(this->objectName(), QString::fromLatin1("commandTest")); -} +}; -void tst_QState::setPropertyOnEntry() +void tst_QState::assignProperty() { QStateMachine machine; @@ -221,7 +219,7 @@ void tst_QState::setPropertyOnEntry() object->setProperty("fooBar", 10); QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnEntry(object, "fooBar", 20); + s1->assignProperty(object, "fooBar", 20); machine.setInitialState(s1); machine.start(); @@ -230,7 +228,7 @@ void tst_QState::setPropertyOnEntry() QCOMPARE(object->property("fooBar").toInt(), 20); } -void tst_QState::setPropertyOnEntryTwice() +void tst_QState::assignPropertyTwice() { QStateMachine machine; @@ -238,8 +236,8 @@ void tst_QState::setPropertyOnEntryTwice() object->setProperty("fooBar", 10); QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnEntry(object, "fooBar", 20); - s1->setPropertyOnEntry(object, "fooBar", 30); + s1->assignProperty(object, "fooBar", 20); + s1->assignProperty(object, "fooBar", 30); machine.setInitialState(s1); machine.start(); @@ -248,56 +246,26 @@ void tst_QState::setPropertyOnEntryTwice() QCOMPARE(object->property("fooBar").toInt(), 30); } -void tst_QState::setPropertyOnExit() +class EventTestTransition: public QAbstractTransition { - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("fooBar", 10); - - QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnExit(object, "fooBar", 20); - - QState *s2 = new QState(machine.rootState()); - s1->addTransition(new QTransition(QEvent::User), s2); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - QCOMPARE(object->property("fooBar").toInt(), 10); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - - QCOMPARE(object->property("fooBar").toInt(), 20); -} - -void tst_QState::setPropertyOnExitTwice() -{ - QStateMachine machine; +public: + EventTestTransition(QEvent::Type type, QState *targetState) + : QAbstractTransition(QList<QAbstractState*>() << targetState), m_type(type) + { + } - QObject *object = new QObject(); - object->setProperty("fooBar", 10); +protected: + bool eventTest(QEvent *e) const + { + return e->type() == m_type; + } - QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnExit(object, "fooBar", 20); - s1->setPropertyOnExit(object, "fooBar", 30); + void onTransition(QEvent *) {} - QState *s2 = new QState(machine.rootState()); - s1->addTransition(new QTransition(QEvent::User), s2); +private: + QEvent::Type m_type; - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - QCOMPARE(object->property("fooBar").toInt(), 10); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - - QCOMPARE(object->property("fooBar").toInt(), 30); -} +}; void tst_QState::historyInitialState() { @@ -306,7 +274,7 @@ void tst_QState::historyInitialState() QState *s1 = new QState(machine.rootState()); QState *s2 = new QState(machine.rootState()); - QHistoryState *h1 = s2->addHistoryState(); + QHistoryState *h1 = new QHistoryState(s2); s2->setInitialState(h1); @@ -315,9 +283,9 @@ void tst_QState::historyInitialState() QState *s4 = new QState(s2); - s1->addTransition(new QTransition(QEvent::User), s2); - s2->addTransition(new QTransition(QEvent::User), s1); - s3->addTransition(new QTransition(QEvent::Type(QEvent::User+1)), s4); + s1->addTransition(new EventTestTransition(QEvent::User, s2)); + s2->addTransition(new EventTestTransition(QEvent::User, s1)); + s3->addTransition(new EventTestTransition(QEvent::Type(QEvent::User+1), s4)); machine.setInitialState(s1); machine.start(); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index c906d53..9058cb6 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -45,10 +45,10 @@ #include "qstatemachine.h" #include "qstate.h" -#include "qtransition.h" #include "qhistorystate.h" #include "qkeyeventtransition.h" #include "qmouseeventtransition.h" +#include "private/qstate_p.h" #include "private/qstatemachine_p.h" // Will try to wait for the condition while allowing event processing @@ -70,6 +70,17 @@ static int globalTick; +// Run exec for a maximum of TIMEOUT msecs +#define QCOREAPPLICATION_EXEC(TIMEOUT) \ +{ \ + QTimer timer; \ + timer.setSingleShot(true); \ + timer.setInterval(TIMEOUT); \ + timer.start(); \ + connect(&timer, SIGNAL(timeout()), QCoreApplication::instance(), SLOT(quit())); \ + QCoreApplication::exec(); \ +} + class tst_QStateMachine : public QObject { Q_OBJECT @@ -84,6 +95,8 @@ private slots: void rootState(); void addAndRemoveState(); void stateEntryAndExit(); + void assignProperty(); + void assignPropertyWithAnimation(); void postEvent(); void stateFinished(); void parallelStates(); @@ -91,8 +104,9 @@ private slots: void signalTransitions(); void eventTransitions(); void historyStates(); - void stateActions(); - void transitionActions(); + void startAndStop(); + void targetStateWithNoParent(); + void targetStateDeleted(); void transitionToRootState(); void transitionEntersParent(); @@ -109,19 +123,51 @@ private slots: void customErrorStateIsNull(); void clearError(); void historyStateHasNowhereToGo(); + void historyStateAsInitialState(); void brokenStateIsNeverEntered(); void customErrorStateNotInGraph(); void transitionToStateNotInGraph(); void restoreProperties(); + void defaultGlobalRestorePolicy(); void globalRestorePolicySetToRestore(); void globalRestorePolicySetToDoNotRestore(); - void restorePolicyNotInherited(); - void mixedRestoreProperties(); - void setRestorePolicyToDoNotRestore(); - void setGlobalRestorePolicyToGlobalRestore(); - void restorePolicyOnChildState(); + + //void restorePolicyNotInherited(); + //void mixedRestoreProperties(); + //void setRestorePolicyToDoNotRestore(); + //void setGlobalRestorePolicyToGlobalRestore(); + //void restorePolicyOnChildState(); + void transitionWithParent(); + void transitionsFromParallelStateWithNoChildren(); + void parallelStateTransition(); + void parallelStateAssignmentsDone(); + void nestedRestoreProperties(); + void nestedRestoreProperties2(); + + void simpleAnimation(); + void twoAnimations(); + void twoAnimatedTransitions(); + void playAnimationTwice(); + void nestedTargetStateForAnimation(); + void animatedGlobalRestoreProperty(); + void specificTargetValueOfAnimation(); + + void addDefaultAnimation(); + void addDefaultAnimationWithUnusedAnimation(); + void removeDefaultAnimation(); + void overrideDefaultAnimationWithSpecific(); + +// void addDefaultAnimationForSource(); +// void addDefaultAnimationForTarget(); +// void removeDefaultAnimationForSource(); +// void removeDefaultAnimationForTarget(); +// void overrideDefaultAnimationWithSource(); +// void overrideDefaultAnimationWithTarget(); +// void overrideDefaultSourceAnimationWithSpecific(); +// void overrideDefaultTargetAnimationWithSpecific(); +// void overrideDefaultTargetAnimationWithSource(); }; tst_QStateMachine::tst_QStateMachine() @@ -143,10 +189,10 @@ public: : QState(parent) {} QList<QPair<int, Event> > events; protected: - virtual void onEntry() { + virtual void onEntry(QEvent *) { events.append(qMakePair(globalTick++, Entry)); } - virtual void onExit() { + virtual void onExit(QEvent *) { events.append(qMakePair(globalTick++, Exit)); } }; @@ -161,7 +207,7 @@ protected: virtual bool eventTest(QEvent *) const { return true; } - virtual void onTransition() { + virtual void onTransition(QEvent *) { triggers.append(globalTick++); } }; @@ -194,21 +240,24 @@ void tst_QStateMachine::cleanup() qInstallMsgHandler(s_oldHandler); } -class EventTransition : public QTransition +class EventTransition : public QAbstractTransition { public: EventTransition(QEvent::Type type, QAbstractState *target, QState *parent = 0) - : QTransition(QList<QAbstractState*>() << target, parent), m_type(type) {} + : QAbstractTransition(QList<QAbstractState*>() << target, parent), m_type(type) {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == m_type); } + virtual void onTransition(QEvent *) {} private: QEvent::Type m_type; }; void tst_QStateMachine::transitionToRootState() { + s_countWarnings = false; + QStateMachine machine; QState *initialState = new QState(); @@ -220,16 +269,14 @@ void tst_QStateMachine::transitionToRootState() machine.start(); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 2); + QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(initialState)); - QVERIFY(machine.configuration().contains(machine.rootState())); machine.postEvent(new QEvent(QEvent::User)); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 2); + QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(initialState)); - QVERIFY(machine.configuration().contains(machine.rootState())); } void tst_QStateMachine::transitionEntersParent() @@ -245,21 +292,21 @@ void tst_QStateMachine::transitionEntersParent() QState *greatGrandParent = new QState(); greatGrandParent->setObjectName("grandParent"); - greatGrandParent->setPropertyOnEntry(entryController, "greatGrandParentEntered", true); + greatGrandParent->assignProperty(entryController, "greatGrandParentEntered", true); machine.addState(greatGrandParent); machine.setInitialState(greatGrandParent); QState *grandParent = new QState(greatGrandParent); grandParent->setObjectName("grandParent"); - grandParent->setPropertyOnEntry(entryController, "grandParentEntered", true); + grandParent->assignProperty(entryController, "grandParentEntered", true); QState *parent = new QState(grandParent); parent->setObjectName("parent"); - parent->setPropertyOnEntry(entryController, "parentEntered", true); + parent->assignProperty(entryController, "parentEntered", true); QState *state = new QState(parent); state->setObjectName("state"); - state->setPropertyOnEntry(entryController, "stateEntered", true); + state->assignProperty(entryController, "stateEntered", true); QState *initialStateOfGreatGrandParent = new QState(greatGrandParent); initialStateOfGreatGrandParent->setObjectName("initialStateOfGreatGrandParent"); @@ -336,7 +383,7 @@ public: { } - void onEntry() + void onEntry(QEvent *) { error = m_machine->error(); errorString = m_machine->errorString(); @@ -625,6 +672,8 @@ void tst_QStateMachine::errorStateHasErrors() void tst_QStateMachine::errorStateIsRootState() { + s_countWarnings = false; + QStateMachine machine; machine.setErrorState(machine.rootState()); @@ -648,9 +697,8 @@ void tst_QStateMachine::errorStateIsRootState() machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); - QEXPECT_FAIL("", "Covered by transitionToRootState test. Remove this when that test passes", Continue); QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(initialState)); + QVERIFY(machine.configuration().contains(machine.errorState())); } void tst_QStateMachine::errorStateEntersParentFirst() @@ -666,21 +714,21 @@ void tst_QStateMachine::errorStateEntersParentFirst() QState *greatGrandParent = new QState(); greatGrandParent->setObjectName("greatGrandParent"); - greatGrandParent->setPropertyOnEntry(entryController, "greatGrandParentEntered", true); + greatGrandParent->assignProperty(entryController, "greatGrandParentEntered", true); machine.addState(greatGrandParent); machine.setInitialState(greatGrandParent); QState *grandParent = new QState(greatGrandParent); grandParent->setObjectName("grandParent"); - grandParent->setPropertyOnEntry(entryController, "grandParentEntered", true); + grandParent->assignProperty(entryController, "grandParentEntered", true); QState *parent = new QState(grandParent); parent->setObjectName("parent"); - parent->setPropertyOnEntry(entryController, "parentEntered", true); + parent->assignProperty(entryController, "parentEntered", true); QState *errorState = new QState(parent); errorState->setObjectName("errorState"); - errorState->setPropertyOnEntry(entryController, "errorStateEntered", true); + errorState->assignProperty(entryController, "errorStateEntered", true); machine.setErrorState(errorState); QState *initialStateOfGreatGrandParent = new QState(greatGrandParent); @@ -777,6 +825,40 @@ void tst_QStateMachine::clearError() QVERIFY(machine.errorString().isEmpty()); } +void tst_QStateMachine::historyStateAsInitialState() +{ + QStateMachine machine; + + QHistoryState *hs = new QHistoryState(machine.rootState()); + machine.setInitialState(hs); + + QState *s1 = new QState(machine.rootState()); + hs->setDefaultState(s1); + + QState *s2 = new QState(machine.rootState()); + + QHistoryState *s2h = new QHistoryState(s2); + s2->setInitialState(s2h); + + QState *s21 = new QState(s2); + s2h->setDefaultState(s21); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); +} + void tst_QStateMachine::historyStateHasNowhereToGo() { QStateMachine machine; @@ -789,7 +871,7 @@ void tst_QStateMachine::historyStateHasNowhereToGo() brokenState->setObjectName("brokenState"); brokenState->setInitialState(new QState(brokenState)); - QHistoryState *historyState = brokenState->addHistoryState(); + QHistoryState *historyState = new QHistoryState(brokenState); historyState->setObjectName("historyState"); initialState->addTransition(new EventTransition(QEvent::User, historyState)); @@ -801,8 +883,8 @@ void tst_QStateMachine::historyStateHasNowhereToGo() QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(machine.errorState())); - QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryState); - QCOMPARE(machine.errorString(), QString::fromLatin1("Missing transition from history state 'historyState'")); + QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryStateError); + QCOMPARE(machine.errorString(), QString::fromLatin1("Missing default state in history state 'historyState'")); } void tst_QStateMachine::brokenStateIsNeverEntered() @@ -818,15 +900,15 @@ void tst_QStateMachine::brokenStateIsNeverEntered() machine.setInitialState(initialState); QState *errorState = new QState(machine.rootState()); - errorState->setPropertyOnEntry(entryController, "errorStateEntered", true); + errorState->assignProperty(entryController, "errorStateEntered", true); machine.setErrorState(errorState); QState *brokenState = new QState(machine.rootState()); - brokenState->setPropertyOnEntry(entryController, "brokenStateEntered", true); + brokenState->assignProperty(entryController, "brokenStateEntered", true); brokenState->setObjectName("brokenState"); QState *childState = new QState(brokenState); - childState->setPropertyOnEntry(entryController, "childStateEntered", true); + childState->assignProperty(entryController, "childStateEntered", true); initialState->addTransition(new EventTransition(QEvent::User, brokenState)); @@ -843,8 +925,6 @@ void tst_QStateMachine::brokenStateIsNeverEntered() void tst_QStateMachine::transitionToStateNotInGraph() { - QSKIP("Hangs", SkipAll); - s_countWarnings = false; QStateMachine machine; @@ -854,13 +934,14 @@ void tst_QStateMachine::transitionToStateNotInGraph() machine.setInitialState(initialState); QState *independentState = new QState(); + independentState->setObjectName("independentState"); initialState->addTransition(independentState); machine.start(); QCoreApplication::processEvents(); QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(initialState)); + QVERIFY(machine.configuration().contains(qobject_cast<QState*>(machine.rootState())->errorState())); } void tst_QStateMachine::customErrorStateNotInGraph() @@ -893,22 +974,20 @@ void tst_QStateMachine::restoreProperties() object->setProperty("b", 2); QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QState *S1 = new QState(); S1->setObjectName("S1"); - S1->setPropertyOnEntry(object, "a", 3); - S1->setRestorePolicy(QState::RestoreProperties); + S1->assignProperty(object, "a", 3); machine.addState(S1); QState *S2 = new QState(); S2->setObjectName("S2"); - S2->setPropertyOnEntry(object, "b", 5); - S2->setRestorePolicy(QState::RestoreProperties); + S2->assignProperty(object, "b", 5); machine.addState(S2); QState *S3 = new QState(); S3->setObjectName("S3"); - S3->setRestorePolicy(QState::RestoreProperties); machine.addState(S3); QFinalState *S4 = new QFinalState(); @@ -957,8 +1036,9 @@ void tst_QStateMachine::rootState() void tst_QStateMachine::addAndRemoveState() { QStateMachine machine; - QCOMPARE(machine.states().size(), 1); // the error state - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); + QStatePrivate *root_d = QStatePrivate::get(machine.rootState()); + QCOMPARE(root_d->childStates().size(), 1); // the error state + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: cannot add null state"); machine.addState(0); @@ -967,9 +1047,9 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s1->parentState(), (QState*)0); machine.addState(s1); QCOMPARE(s1->parentState(), machine.rootState()); - QCOMPARE(machine.states().size(), 2); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().size(), 2); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s1); @@ -978,24 +1058,24 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s2->parentState(), (QState*)0); machine.addState(s2); QCOMPARE(s2->parentState(), machine.rootState()); - QCOMPARE(machine.states().size(), 3); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s1); - QCOMPARE(machine.states().at(2), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 3); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().at(2), (QAbstractState*)s2); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s2); machine.removeState(s1); QCOMPARE(s1->parentState(), (QState*)0); - QCOMPARE(machine.states().size(), 2); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 2); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2); machine.removeState(s2); QCOMPARE(s2->parentState(), (QState*)0); - QCOMPARE(machine.states().size(), 1); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().size(), 1); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::removeState: cannot remove null state"); machine.removeState(0); @@ -1013,21 +1093,41 @@ void tst_QStateMachine::stateEntryAndExit() QStateMachine machine; TestState *s1 = new TestState(machine.rootState()); + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); + s1->addTransition((QAbstractState*)0); + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add null transition"); + s1->addTransition((QAbstractTransition*)0); + QTest::ignoreMessage(QtWarningMsg, "QState::removeTransition: cannot remove null transition"); + s1->removeTransition((QAbstractTransition*)0); + TestState *s2 = new TestState(machine.rootState()); QFinalState *s3 = new QFinalState(machine.rootState()); TestTransition *t = new TestTransition(s2); - s1->addTransition(t); - s2->addTransition(s3); + QCOMPARE(s1->addTransition(t), (QAbstractTransition*)t); + { + QAbstractTransition *trans = s2->addTransition(s3); + QVERIFY(trans != 0); + QCOMPARE(trans->sourceState(), (QAbstractState*)s2); + QCOMPARE(trans->targetState(), (QAbstractState*)s3); + s2->removeTransition(trans); + QCOMPARE(trans->sourceState(), (QAbstractState*)0); + QCOMPARE(trans->targetState(), (QAbstractState*)s3); + QCOMPARE(s2->addTransition(trans), trans); + QCOMPARE(trans->sourceState(), (QAbstractState*)s2); + } QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.setInitialState(s1); QVERIFY(machine.configuration().isEmpty()); globalTick = 0; + QVERIFY(!machine.isRunning()); machine.start(); QTRY_COMPARE(startedSpy.count(), 1); QTRY_COMPARE(finishedSpy.count(), 1); + QTRY_COMPARE(stoppedSpy.count(), 0); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(s3)); @@ -1113,6 +1213,170 @@ void tst_QStateMachine::stateEntryAndExit() } } +void tst_QStateMachine::assignProperty() +{ + QStateMachine machine; + QState *s1 = new QState(machine.rootState()); + + QTest::ignoreMessage(QtWarningMsg, "QState::assignProperty: cannot assign property 'foo' of null object"); + s1->assignProperty(0, "foo", QVariant()); + + s1->assignProperty(s1, "objectName", "s1"); + QFinalState *s2 = new QFinalState(machine.rootState()); + s1->addTransition(s2); + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("s1")); + + s1->assignProperty(s1, "objectName", "foo"); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("foo")); + + s1->assignProperty(s1, "noSuchProperty", 123); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("foo")); + QCOMPARE(s1->dynamicPropertyNames().size(), 1); + QCOMPARE(s1->dynamicPropertyNames().at(0), QByteArray("noSuchProperty")); + + QSignalSpy polishedSpy(s1, SIGNAL(polished())); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(polishedSpy.count(), 1); +} + +void tst_QStateMachine::assignPropertyWithAnimation() +{ + // Single animation + { + QStateMachine machine; + QObject obj; + obj.setProperty("foo", 321); + obj.setProperty("bar", 654); + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(250); + trans->addAnimation(&anim); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 789); + } + // Two animations + { + QStateMachine machine; + QObject obj; + obj.setProperty("foo", 321); + obj.setProperty("bar", 654); + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(150); + trans->addAnimation(&anim); + QPropertyAnimation anim2(&obj, "bar"); + anim2.setDuration(150); + trans->addAnimation(&anim2); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 789); + } + // Animation group + { + QStateMachine machine; + QObject obj; + obj.setProperty("foo", 321); + obj.setProperty("bar", 654); + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + s1->assignProperty(&obj, "bar", 321); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 654); + s2->assignProperty(&obj, "baz", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QSequentialAnimationGroup group; + group.addAnimation(new QPropertyAnimation(&obj, "foo")); + group.addAnimation(new QPropertyAnimation(&obj, "bar")); + trans->addAnimation(&group); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 654); + QCOMPARE(obj.property("baz").toInt(), 789); + } + // Nested states + { + QStateMachine machine; + QObject obj; + obj.setProperty("foo", 321); + obj.setProperty("bar", 654); + QState *s1 = new QState(machine.rootState()); + QCOMPARE(s1->childMode(), QState::ExclusiveStates); + QCOMPARE(s1->initialState(), (QAbstractState*)0); + s1->setObjectName("s1"); + s1->assignProperty(&obj, "foo", 123); + s1->assignProperty(&obj, "bar", 456); + QState *s2 = new QState(machine.rootState()); + s2->setObjectName("s2"); + s2->assignProperty(&obj, "foo", 321); + QState *s21 = new QState(s2); + s21->setObjectName("s21"); + s21->assignProperty(&obj, "bar", 654); + QState *s22 = new QState(s2); + s22->setObjectName("s22"); + s22->assignProperty(&obj, "bar", 789); + s2->setInitialState(s21); + QCOMPARE(s2->initialState(), (QAbstractState*)s21); + + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(500); + trans->addAnimation(&anim); + QPropertyAnimation anim2(&obj, "bar"); + anim2.setDuration(250); + trans->addAnimation(&anim2); + + s21->addTransition(s21, SIGNAL(polished()), s22); + + QFinalState *s3 = new QFinalState(machine.rootState()); + s22->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 321); + QCOMPARE(obj.property("bar").toInt(), 789); + } +} + struct StringEvent : public QEvent { public: @@ -1137,7 +1401,7 @@ protected: StringEvent *se = static_cast<StringEvent*>(e); return (m_value == se->value) && (!m_cond.isValid() || (m_cond.indexIn(m_value) != -1)); } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} private: QString m_value; @@ -1154,11 +1418,11 @@ public: { m_value = value; } protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { m_machine->postEvent(new StringEvent(m_value)); } - virtual void onExit() {} + virtual void onExit(QEvent *) {} private: QStateMachine *m_machine; @@ -1200,7 +1464,7 @@ void tst_QStateMachine::stateFinished() s1_1->addTransition(s1_2); s1->setInitialState(s1_1); QFinalState *s2 = new QFinalState(machine.rootState()); - s1->addTransition(new QStateFinishedTransition(s1, QList<QAbstractState*>() << s2)); + s1->addTransition(s1, SIGNAL(finished()), s2); machine.setInitialState(s1); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.start(); @@ -1213,7 +1477,8 @@ void tst_QStateMachine::parallelStates() { QStateMachine machine; - QState *s1 = new QState(QState::ParallelGroup); + QState *s1 = new QState(QState::ParallelStates); + QCOMPARE(s1->childMode(), QState::ParallelStates); QState *s1_1 = new QState(s1); QState *s1_1_1 = new QState(s1_1); QFinalState *s1_1_f = new QFinalState(s1_1); @@ -1229,12 +1494,14 @@ void tst_QStateMachine::parallelStates() QFinalState *s2 = new QFinalState(); machine.addState(s2); - s1->addFinishedTransition(s2); + s1->addTransition(s1, SIGNAL(finished()), s2); machine.setInitialState(s1); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.start(); QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s2)); } void tst_QStateMachine::allSourceToTargetConfigurations() @@ -1345,9 +1612,28 @@ void tst_QStateMachine::signalTransitions() { QStateMachine machine; QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null"); + QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QObject*)0); + SignalEmitter emitter; - s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: signal cannot be null"); + QCOMPARE(s0->addTransition(&emitter, 0, 0), (QObject*)0); + + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QObject*)0); + + QFinalState *s1 = new QFinalState(machine.rootState()); + QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()"); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QObject*)0); + + { + QSignalTransition *trans = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); + QVERIFY(trans != 0); + QCOMPARE(trans->sourceState(), s0); + QCOMPARE(trans->targetState(), (QAbstractState*)s1); + QCOMPARE(trans->senderObject(), (QObject*)&emitter); + QCOMPARE(trans->signal(), QByteArray(SIGNAL(signalWithNoArg()))); + } QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.setInitialState(s0); @@ -1357,6 +1643,8 @@ void tst_QStateMachine::signalTransitions() emitter.emitSignalWithNoArg(); QTRY_COMPARE(finishedSpy.count(), 1); + + emitter.emitSignalWithNoArg(); } { QStateMachine machine; @@ -1448,6 +1736,8 @@ void tst_QStateMachine::eventTransitions() QCoreApplication::processEvents(); QTRY_COMPARE(finishedSpy.count(), 1); + + QTest::mousePress(&button, Qt::LeftButton); } { QStateMachine machine; @@ -1455,10 +1745,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QEventTransition *trans = new QEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); - trans->setEventSource(&button); - QCOMPARE(trans->eventSource(), (QObject*)&button); + trans->setEventObject(&button); + QCOMPARE(trans->eventObject(), (QObject*)&button); trans->setEventType(QEvent::MouseButtonPress); QCOMPARE(trans->eventType(), QEvent::MouseButtonPress); trans->setTargetState(s1); @@ -1480,10 +1770,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QMouseEventTransition *trans = new QMouseEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); QCOMPARE(trans->button(), Qt::NoButton); - trans->setEventSource(&button); + trans->setEventObject(&button); trans->setEventType(QEvent::MouseButtonPress); trans->setButton(Qt::LeftButton); trans->setTargetState(s1); @@ -1527,10 +1817,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QKeyEventTransition *trans = new QKeyEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); QCOMPARE(trans->key(), 0); - trans->setEventSource(&button); + trans->setEventObject(&button); trans->setEventType(QEvent::KeyPress); trans->setKey(Qt::Key_A); trans->setTargetState(s1); @@ -1555,7 +1845,7 @@ void tst_QStateMachine::historyStates() QState *s0 = new QState(root); QState *s00 = new QState(s0); QState *s01 = new QState(s0); - QHistoryState *s0h = s0->addHistoryState(); + QHistoryState *s0h = new QHistoryState(s0); QState *s1 = new QState(root); QFinalState *s2 = new QFinalState(root); @@ -1599,152 +1889,76 @@ void tst_QStateMachine::historyStates() QTRY_COMPARE(finishedSpy.count(), 1); } -class TestStateAction : public QStateAction -{ -public: - TestStateAction() : m_didExecute(false) - {} - bool didExecute() const { - return m_didExecute; - } -protected: - void execute() { - m_didExecute = true; - } -private: - bool m_didExecute; -}; - -void tst_QStateMachine::stateActions() +void tst_QStateMachine::startAndStop() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - - QVERIFY(s1->entryActions().isEmpty()); - QVERIFY(s1->exitActions().isEmpty()); - - QTest::ignoreMessage(QtWarningMsg, "QActionState::addEntryAction: cannot add null action"); - s1->addEntryAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::addExitAction: cannot add null action"); - s1->addExitAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::removeEntryAction: cannot remove null action"); - s1->removeEntryAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::removeExitAction: cannot remove null action"); - s1->removeExitAction(0); - - QFinalState *s2 = new QFinalState(machine.rootState()); - s1->addTransition(s2); - - machine.setInitialState(s1); + QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); - - QObject *obj = new QObject(); - QStateInvokeMethodAction *ima = new QStateInvokeMethodAction(obj, "deleteLater"); - QPointer<QObject> ptr(obj); - QVERIFY(ptr != 0); - s1->addEntryAction(ima); - finishedSpy.clear(); + QVERIFY(!machine.isRunning()); + QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start."); machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); - - s1->removeEntryAction(ima); + QCOMPARE(startedSpy.count(), 0); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + QVERIFY(!machine.isRunning()); + machine.stop(); + QCOMPARE(startedSpy.count(), 0); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); - s1->invokeMethodOnEntry(ima, "deleteLater"); - QCOMPARE(s1->entryActions().size(), 1); - - ptr = ima; - QVERIFY(ptr != 0); - finishedSpy.clear(); - machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); - - while (!s1->entryActions().isEmpty()) { - QStateAction *act = s1->entryActions().first(); - s1->removeEntryAction(act); - delete act; - } - - TestStateAction *act1 = new TestStateAction(); - s1->addEntryAction(act1); - TestStateAction *act2 = new TestStateAction(); - s1->addExitAction(act2); - QVERIFY(!act1->didExecute()); - QVERIFY(!act2->didExecute()); - - finishedSpy.clear(); + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - - QVERIFY(act1->didExecute()); - QVERIFY(act2->didExecute()); + QTRY_COMPARE(machine.isRunning(), true); + QTRY_COMPARE(startedSpy.count(), 1); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(machine.configuration().count(), 1); + QVERIFY(machine.configuration().contains(s1)); - QCOMPARE(s1->entryActions().size(), 1); - QCOMPARE(s2->entryActions().size(), 0); - s2->addEntryAction(act1); // should remove it from s1 - QCOMPARE(s1->entryActions().size(), 0); - QCOMPARE(s2->entryActions().size(), 1); - QCOMPARE(act1->parent(), (QObject*)s2); + machine.stop(); + QTRY_COMPARE(machine.isRunning(), false); + QTRY_COMPARE(stoppedSpy.count(), 1); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); - QCOMPARE(s2->exitActions().size(), 0); - s2->addExitAction(act1); // should remove entry action - QCOMPARE(s2->exitActions().size(), 1); - QCOMPARE(s2->entryActions().size(), 0); - QCOMPARE(act1->parent(), (QObject*)s2); + QCOMPARE(machine.configuration().count(), 1); + QVERIFY(machine.configuration().contains(s1)); } -void tst_QStateMachine::transitionActions() +void tst_QStateMachine::targetStateWithNoParent() { QStateMachine machine; QState *s1 = new QState(machine.rootState()); - - QFinalState *s2 = new QFinalState(machine.rootState()); - QTransition *trans = new EventTransition(QEvent::User, s2); - s1->addTransition(trans); - QVERIFY(trans->actions().isEmpty()); - QTest::ignoreMessage(QtWarningMsg, "QTransition::addAction: cannot add null action"); - trans->addAction(0); - QVERIFY(trans->actions().isEmpty()); - - TestStateAction *act = new TestStateAction(); - trans->addAction(act); - QCOMPARE(trans->actions().size(), 1); - QCOMPARE(trans->actions().at(0), (QStateAction*)act); - QCOMPARE(act->parent(), (QObject*)trans); - QVERIFY(!act->didExecute()); - - trans->removeAction(act); - QVERIFY(trans->actions().isEmpty()); - QCOMPARE(act->parent(), (QObject*)0); - - trans->addAction(act); - - QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + s1->setObjectName("s1"); + QState *s2 = new QState(); + s1->addTransition(s2); machine.setInitialState(s1); + QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QTRY_COMPARE(finishedSpy.count(), 1); - QVERIFY(act->didExecute()); - - trans->invokeMethodOnTransition(act, "deleteLater"); - - QPointer<QStateAction> ptr(act); - QVERIFY(ptr != 0); - finishedSpy.clear(); - machine.start(); - QCoreApplication::processEvents(); + QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 's1'"); + QTRY_COMPARE(machine.isRunning(), true); + QTRY_COMPARE(startedSpy.count(), 1); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(machine.errorState())); + QCOMPARE(machine.error(), QStateMachine::NoCommonAncestorForTransitionError); +} - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); +void tst_QStateMachine::targetStateDeleted() +{ + QStateMachine machine; + QState *s1 = new QState(machine.rootState()); + s1->setObjectName("s1"); + QState *s2 = new QState(machine.rootState()); + QAbstractTransition *trans = s1->addTransition(s2); + delete s2; + QCOMPARE(trans->targetState(), (QAbstractState*)0); + QVERIFY(trans->targetStates().isEmpty()); } void tst_QStateMachine::defaultGlobalRestorePolicy() @@ -1756,10 +1970,10 @@ void tst_QStateMachine::defaultGlobalRestorePolicy() propertyHolder->setProperty("b", 2); QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); QState *s2 = new QState(machine.rootState()); - s2->setPropertyOnEntry(propertyHolder, "b", 4); + s2->assignProperty(propertyHolder, "b", 4); QState *s3 = new QState(machine.rootState()); @@ -1786,6 +2000,7 @@ void tst_QStateMachine::defaultGlobalRestorePolicy() QCOMPARE(propertyHolder->property("b").toInt(), 4); } +/* void tst_QStateMachine::restorePolicyNotInherited() { QStateMachine machine; @@ -1800,12 +2015,12 @@ void tst_QStateMachine::restorePolicyNotInherited() QState *s1 = new QState(parentState); s1->setObjectName("s1"); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); parentState->setInitialState(s1); QState *s2 = new QState(parentState); s2->setObjectName("s2"); - s2->setPropertyOnEntry(propertyHolder, "b", 4); + s2->assignProperty(propertyHolder, "b", 4); QState *s3 = new QState(parentState); s3->setObjectName("s3"); @@ -1832,22 +2047,22 @@ void tst_QStateMachine::restorePolicyNotInherited() QCOMPARE(propertyHolder->property("a").toInt(), 3); QCOMPARE(propertyHolder->property("b").toInt(), 4); -} +}*/ void tst_QStateMachine::globalRestorePolicySetToDoNotRestore() { QStateMachine machine; - machine.setGlobalRestorePolicy(QState::DoNotRestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::DoNotRestoreProperties); QObject *propertyHolder = new QObject(); propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); QState *s2 = new QState(machine.rootState()); - s2->setPropertyOnEntry(propertyHolder, "b", 4); + s2->assignProperty(propertyHolder, "b", 4); QState *s3 = new QState(machine.rootState()); @@ -1874,6 +2089,7 @@ void tst_QStateMachine::globalRestorePolicySetToDoNotRestore() QCOMPARE(propertyHolder->property("b").toInt(), 4); } +/* void tst_QStateMachine::setRestorePolicyToDoNotRestore() { QObject *object = new QObject(); @@ -1884,13 +2100,13 @@ void tst_QStateMachine::setRestorePolicyToDoNotRestore() QState *S1 = new QState(); S1->setObjectName("S1"); - S1->setPropertyOnEntry(object, "a", 3); + S1->assignProperty(object, "a", 3); S1->setRestorePolicy(QState::DoNotRestoreProperties); machine.addState(S1); QState *S2 = new QState(); S2->setObjectName("S2"); - S2->setPropertyOnEntry(object, "b", 5); + S2->assignProperty(object, "b", 5); S2->setRestorePolicy(QState::DoNotRestoreProperties); machine.addState(S2); @@ -1930,19 +2146,20 @@ void tst_QStateMachine::setGlobalRestorePolicyToGlobalRestore() { s_countWarnings = false; QStateMachine machine; - machine.setGlobalRestorePolicy(QState::GlobalRestorePolicy); + machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy); - QCOMPARE(machine.globalRestorePolicy(), QState::DoNotRestoreProperties); + QCOMPARE(machine.globalRestorePolicy(), QStateMachine::DoNotRestoreProperties); QCOMPARE(s_msgType, QtWarningMsg); s_msgType = QtDebugMsg; - machine.setGlobalRestorePolicy(QState::RestoreProperties); - machine.setGlobalRestorePolicy(QState::GlobalRestorePolicy); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy); - QCOMPARE(machine.globalRestorePolicy(), QState::RestoreProperties); + QCOMPARE(machine.globalRestorePolicy(), QStateMachine::RestoreProperties); QCOMPARE(s_msgType, QtWarningMsg); } + void tst_QStateMachine::restorePolicyOnChildState() { QStateMachine machine; @@ -1957,13 +2174,13 @@ void tst_QStateMachine::restorePolicyOnChildState() QState *s1 = new QState(parentState); s1->setRestorePolicy(QState::RestoreProperties); s1->setObjectName("s1"); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); parentState->setInitialState(s1); QState *s2 = new QState(parentState); s2->setRestorePolicy(QState::RestoreProperties); s2->setObjectName("s2"); - s2->setPropertyOnEntry(propertyHolder, "b", 4); + s2->assignProperty(propertyHolder, "b", 4); QState *s3 = new QState(parentState); s3->setRestorePolicy(QState::RestoreProperties); @@ -1991,21 +2208,22 @@ void tst_QStateMachine::restorePolicyOnChildState() QCOMPARE(propertyHolder->property("a").toInt(), 1); QCOMPARE(propertyHolder->property("b").toInt(), 2); } +*/ void tst_QStateMachine::globalRestorePolicySetToRestore() { QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QObject *propertyHolder = new QObject(); propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); QState *s1 = new QState(machine.rootState()); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); QState *s2 = new QState(machine.rootState()); - s2->setPropertyOnEntry(propertyHolder, "b", 4); + s2->assignProperty(propertyHolder, "b", 4); QState *s3 = new QState(machine.rootState()); @@ -2032,6 +2250,7 @@ void tst_QStateMachine::globalRestorePolicySetToRestore() QCOMPARE(propertyHolder->property("b").toInt(), 2); } +/* void tst_QStateMachine::mixedRestoreProperties() { QStateMachine machine; @@ -2041,19 +2260,19 @@ void tst_QStateMachine::mixedRestoreProperties() QState *s1 = new QState(machine.rootState()); s1->setRestorePolicy(QState::RestoreProperties); - s1->setPropertyOnEntry(propertyHolder, "a", 3); + s1->assignProperty(propertyHolder, "a", 3); QState *s2 = new QState(machine.rootState()); - s2->setPropertyOnEntry(propertyHolder, "a", 4); + s2->assignProperty(propertyHolder, "a", 4); QState *s3 = new QState(machine.rootState()); QState *s4 = new QState(machine.rootState()); - s4->setPropertyOnEntry(propertyHolder, "a", 5); + s4->assignProperty(propertyHolder, "a", 5); QState *s5 = new QState(machine.rootState()); s5->setRestorePolicy(QState::RestoreProperties); - s5->setPropertyOnEntry(propertyHolder, "a", 6); + s5->assignProperty(propertyHolder, "a", 6); s1->addTransition(new EventTransition(QEvent::User, s2)); s2->addTransition(new EventTransition(QEvent::User, s3)); @@ -2098,6 +2317,7 @@ void tst_QStateMachine::mixedRestoreProperties() // Enter s3, restore QCOMPARE(propertyHolder->property("a").toInt(), 5); } +*/ void tst_QStateMachine::transitionWithParent() { @@ -2111,5 +2331,1043 @@ void tst_QStateMachine::transitionWithParent() QCOMPARE(trans->targetStates().at(0), (QAbstractState*)s2); } +void tst_QStateMachine::simpleAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("fooBar", 1.0); + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "fooBar", 2.0); + + EventTransition *et = new EventTransition(QEvent::User, s2); + QPropertyAnimation *animation = new QPropertyAnimation(object, "fooBar", s2); + et->addAnimation(animation); + s1->addTransition(et); + + QState *s3 = new QState(machine.rootState()); + s2->addTransition(animation, SIGNAL(finished()), s3); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("fooBar").toDouble(), 2.0); +} + +class SlotCalledCounter: public QObject +{ + Q_OBJECT +public: + SlotCalledCounter() : counter(0) {} + + int counter; + +public slots: + void slot() { counter++; } +}; + +void tst_QStateMachine::twoAnimations() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 3.0); + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + s2->assignProperty(object, "bar", 10.0); + + QPropertyAnimation *animationFoo = new QPropertyAnimation(object, "foo", s2); + QPropertyAnimation *animationBar = new QPropertyAnimation(object, "bar", s2); + animationBar->setDuration(900); + + SlotCalledCounter counter; + connect(animationFoo, SIGNAL(finished()), &counter, SLOT(slot())); + connect(animationBar, SIGNAL(finished()), &counter, SLOT(slot())); + + EventTransition *et = new EventTransition(QEvent::User, s2); + et->addAnimation(animationFoo); + et->addAnimation(animationBar); + s1->addTransition(et); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(object->property("bar").toDouble(), 10.0); + + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::twoAnimatedTransitions() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 5.0); + QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + s2->addTransition(fooAnimation, SIGNAL(finished()), s3); + + QState *s4 = new QState(machine.rootState()); + s4->assignProperty(object, "foo", 2.0); + QPropertyAnimation *fooAnimation2 = new QPropertyAnimation(object, "foo", s4); + s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation2); + + QState *s5 = new QState(machine.rootState()); + QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); + s4->addTransition(fooAnimation2, SIGNAL(finished()), s5); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 5.0); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s5)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::playAnimationTwice() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 5.0); + QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + s2->addTransition(fooAnimation, SIGNAL(finished()), s3); + + QState *s4 = new QState(machine.rootState()); + s4->assignProperty(object, "foo", 2.0); + s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation); + + QState *s5 = new QState(machine.rootState()); + QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); + s4->addTransition(fooAnimation, SIGNAL(finished()), s5); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 5.0); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s5)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::nestedTargetStateForAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 3.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + + s2->assignProperty(object, "foo", 2.0); + + QState *s2Child = new QState(s2); + s2Child->assignProperty(object, "bar", 10.0); + s2->setInitialState(s2Child); + + QState *s2Child2 = new QState(s2); + s2Child2->assignProperty(object, "bar", 11.0); + QAbstractTransition *at = s2Child->addTransition(new EventTransition(QEvent::User, s2Child2)); + + QPropertyAnimation *animation = new QPropertyAnimation(object, "bar", s2); + animation->setDuration(2000); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + animation = new QPropertyAnimation(object, "foo", s2); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + animation = new QPropertyAnimation(object, "bar", s2); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + QState *s3 = new QState(machine.rootState()); + s2->addTransition(s2Child, SIGNAL(polished()), s3); + + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + machine.postEvent(new QEvent(QEvent::User)); + + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(object->property("bar").toDouble(), 10.0); + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::animatedGlobalRestoreProperty() +{ + QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + + QState *s4 = new QState(machine.rootState()); + QObject::connect(s4, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", s2); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + at = s2->addTransition(pa, SIGNAL(finished()), s3); + pa = new QPropertyAnimation(object, "foo", s3); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + at = s3->addTransition(pa, SIGNAL(finished()), s4); + pa = new QPropertyAnimation(object, "foo", s4); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s4)); + QCOMPARE(object->property("foo").toDouble(), 1.0); + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::specificTargetValueOfAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); + anim->setEndValue(10.0); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(anim); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + s2->addTransition(anim, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(anim->endValue().toDouble(), 10.0); +} + +void tst_QStateMachine::addDefaultAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimation(pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 2.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + machine.addDefaultAnimation(pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + pa = new QPropertyAnimation(object, "bar", &machine); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + machine.addDefaultAnimation(pa); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(counter.counter, 1); +} + +void tst_QStateMachine::removeDefaultAnimation() +{ + QStateMachine machine; + + QObject propertyHolder; + propertyHolder.setProperty("foo", 0); + + QCOMPARE(machine.defaultAnimations().size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(&propertyHolder, "foo"); + + machine.addDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + + machine.addDefaultAnimation(anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(&propertyHolder, "foo"); + machine.addDefaultAnimation(anim2); + + QCOMPARE(machine.defaultAnimations().size(), 2); + QVERIFY(machine.defaultAnimations().contains(anim)); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim2); + QCOMPARE(machine.defaultAnimations().size(), 0); +} + +void tst_QStateMachine::overrideDefaultAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +/* +void tst_QStateMachine::addDefaultAnimationForSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimationForSourceState(s1, pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::addDefaultAnimationForTarget() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimationForTargetState(s2, pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::removeDefaultAnimationForSource() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + + machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimationForSourceState(machine.rootState(), anim2); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 2); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim2); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); +} + +void tst_QStateMachine::removeDefaultAnimationForTarget() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + + machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimationForTargetState(machine.rootState(), anim2); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 2); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim2); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); +} + +void tst_QStateMachine::overrideDefaultAnimationWithSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultAnimationWithTarget() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + machine.addDefaultAnimationForTargetState(s2, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped + +} + +void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForSourceState(s1, defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultTargetAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForTargetState(s2, defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForTargetState(s2, defaultAnimation); + machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +*/ + +void tst_QStateMachine::parallelStateAssignmentsDone() +{ + QStateMachine machine; + + QObject *propertyHolder = new QObject(&machine); + propertyHolder->setProperty("foo", 123); + propertyHolder->setProperty("bar", 456); + propertyHolder->setProperty("zoot", 789); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + parallelState->assignProperty(propertyHolder, "foo", 321); + + QState *s2 = new QState(parallelState); + s2->assignProperty(propertyHolder, "bar", 654); + + QState *s3 = new QState(parallelState); + s3->assignProperty(propertyHolder, "zoot", 987); + + s1->addTransition(new EventTransition(QEvent::User, parallelState)); + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(propertyHolder->property("foo").toInt(), 123); + QCOMPARE(propertyHolder->property("bar").toInt(), 456); + QCOMPARE(propertyHolder->property("zoot").toInt(), 789); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(propertyHolder->property("foo").toInt(), 321); + QCOMPARE(propertyHolder->property("bar").toInt(), 654); + QCOMPARE(propertyHolder->property("zoot").toInt(), 987); +} + +void tst_QStateMachine::transitionsFromParallelStateWithNoChildren() +{ + QStateMachine machine; + + QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + machine.setInitialState(parallelState); + + QState *s1 = new QState(machine.rootState()); + parallelState->addTransition(new EventTransition(QEvent::User, s1)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(1, machine.configuration().size()); + QVERIFY(machine.configuration().contains(parallelState)); + + machine.postEvent(new QEvent(QEvent::User)); + + QCoreApplication::processEvents(); + + QCOMPARE(1, machine.configuration().size()); + QVERIFY(machine.configuration().contains(s1)); +} + +void tst_QStateMachine::parallelStateTransition() +{ + QStateMachine machine; + + QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + machine.setInitialState(parallelState); + + QState *s1 = new QState(parallelState); + QState *s2 = new QState(parallelState); + + QState *s1InitialChild = new QState(s1); + s1->setInitialState(s1InitialChild); + + QState *s2InitialChild = new QState(s2); + s2->setInitialState(s2InitialChild); + + QState *s1OtherChild = new QState(s1); + + s1->addTransition(new EventTransition(QEvent::User, s1OtherChild)); + + machine.start(); + QCoreApplication::processEvents(); + + QVERIFY(machine.configuration().contains(parallelState)); + QVERIFY(machine.configuration().contains(s1)); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s1InitialChild)); + QVERIFY(machine.configuration().contains(s2InitialChild)); + QCOMPARE(machine.configuration().size(), 5); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QVERIFY(machine.configuration().contains(parallelState)); + + QVERIFY(machine.configuration().contains(s1)); + + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s1OtherChild)); + QVERIFY(machine.configuration().contains(s2InitialChild)); + QCOMPARE(machine.configuration().size(), 5); + +} + +void tst_QStateMachine::nestedRestoreProperties() +{ + QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QObject *propertyHolder = new QObject(&machine); + propertyHolder->setProperty("foo", 1); + propertyHolder->setProperty("bar", 2); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(propertyHolder, "foo", 3); + + QState *s21 = new QState(s2); + s21->assignProperty(propertyHolder, "bar", 4); + s2->setInitialState(s21); + + QState *s22 = new QState(s2); + s22->assignProperty(propertyHolder, "bar", 5); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + s21->addTransition(new EventTransition(QEvent::User, s22)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + QCOMPARE(propertyHolder->property("foo").toInt(), 1); + QCOMPARE(propertyHolder->property("bar").toInt(), 2); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s22)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 5); +} + +void tst_QStateMachine::nestedRestoreProperties2() +{ + QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QObject *propertyHolder = new QObject(&machine); + propertyHolder->setProperty("foo", 1); + propertyHolder->setProperty("bar", 2); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(propertyHolder, "foo", 3); + + QState *s21 = new QState(s2); + s21->assignProperty(propertyHolder, "bar", 4); + s2->setInitialState(s21); + + QState *s22 = new QState(s2); + s22->assignProperty(propertyHolder, "foo", 6); + s22->assignProperty(propertyHolder, "bar", 5); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + s21->addTransition(new EventTransition(QEvent::User, s22)); + s22->addTransition(new EventTransition(QEvent::User, s21)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + QCOMPARE(propertyHolder->property("foo").toInt(), 1); + QCOMPARE(propertyHolder->property("bar").toInt(), 2); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s22)); + QCOMPARE(propertyHolder->property("foo").toInt(), 6); + QCOMPARE(propertyHolder->property("bar").toInt(), 5); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + +} + + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" diff --git a/tests/benchmarks/qanimation/main.cpp b/tests/benchmarks/qanimation/main.cpp index 7bbcffb..7bb770f 100644 --- a/tests/benchmarks/qanimation/main.cpp +++ b/tests/benchmarks/qanimation/main.cpp @@ -11,8 +11,6 @@ class tst_qanimation : public QObject { Q_OBJECT private slots: - void itemAnimation(); - void itemAnimation_data() { data();} void itemPropertyAnimation(); void itemPropertyAnimation_data() { data();} void dummyAnimation(); @@ -32,35 +30,14 @@ private: void tst_qanimation::data() { - QTest::addColumn<bool>("paused"); + QTest::addColumn<bool>("started"); QTest::newRow("NotRunning") << false; - QTest::newRow("Paused") << true; -} - -void tst_qanimation::itemAnimation() -{ - QFETCH(bool, paused); - QGraphicsWidget item; - - //first the item animation - { - QItemAnimation anim(&item, QItemAnimation::Position); - anim.setDuration(ITERATION_COUNT); - anim.setStartValue(QPointF(0,0)); - anim.setEndValue(QPointF(ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); - QBENCHMARK { - for(int i = 0; i < anim.duration(); ++i) { - anim.setCurrentTime(i); - } - } - } + QTest::newRow("Running") << true; } void tst_qanimation::itemPropertyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); QGraphicsWidget item; //then the property animation @@ -69,8 +46,8 @@ void tst_qanimation::itemPropertyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QPointF(0,0)); anim.setEndValue(QPointF(ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -82,7 +59,7 @@ void tst_qanimation::itemPropertyAnimation() void tst_qanimation::dummyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //first the dummy animation @@ -91,8 +68,8 @@ void tst_qanimation::dummyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < anim.duration(); ++i) { anim.setCurrentTime(i); @@ -103,7 +80,7 @@ void tst_qanimation::dummyAnimation() void tst_qanimation::dummyPropertyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -112,8 +89,8 @@ void tst_qanimation::dummyPropertyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -125,7 +102,7 @@ void tst_qanimation::dummyPropertyAnimation() void tst_qanimation::rectAnimation() { //this is the simplest animation you can do - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -134,8 +111,8 @@ void tst_qanimation::rectAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -147,7 +124,7 @@ void tst_qanimation::rectAnimation() void tst_qanimation::floatAnimation() { //this is the simplest animation you can do - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -156,8 +133,8 @@ void tst_qanimation::floatAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(0.f); anim.setEndValue(1.f); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); diff --git a/tests/benchmarks/qanimation/rectanimation.cpp b/tests/benchmarks/qanimation/rectanimation.cpp index 66c7a33..d60a943 100644 --- a/tests/benchmarks/qanimation/rectanimation.cpp +++ b/tests/benchmarks/qanimation/rectanimation.cpp @@ -7,49 +7,49 @@ static inline int interpolateInteger(int from, int to, qreal progress) } -RectAnimation::RectAnimation(DummyObject *obj) : object(obj), dura(250) +RectAnimation::RectAnimation(DummyObject *obj) : m_object(obj), m_dura(250) { } void RectAnimation::setEndValue(const QRect &rect) { - end = rect; + m_end = rect; } void RectAnimation::setStartValue(const QRect &rect) { - start = rect; + m_start = rect; } void RectAnimation::setDuration(int d) { - dura = d; + m_dura = d; } int RectAnimation::duration() const { - return dura; + return m_dura; } void RectAnimation::updateCurrentTime(int msecs) { - qreal progress = easing.valueForProgress( qreal(msecs) / qreal(dura) ); + qreal progress = m_easing.valueForProgress( qreal(msecs) / qreal(m_dura) ); QRect now; - now.setCoords(interpolateInteger(start.left(), end.left(), progress), - interpolateInteger(start.top(), end.top(), progress), - interpolateInteger(start.right(), end.right(), progress), - interpolateInteger(start.bottom(), end.bottom(), progress)); + now.setCoords(interpolateInteger(m_start.left(), m_end.left(), progress), + interpolateInteger(m_start.top(), m_end.top(), progress), + interpolateInteger(m_start.right(), m_end.right(), progress), + interpolateInteger(m_start.bottom(), m_end.bottom(), progress)); - bool changed = (now != current); + bool changed = (now != m_current); if (changed) - current = now; + m_current = now; if (state() == Stopped) return; - if (object) - object->setRect(current); + if (m_object) + m_object->setRect(m_current); } void RectAnimation::updateState(QAbstractAnimation::State state) diff --git a/tests/benchmarks/qanimation/rectanimation.h b/tests/benchmarks/qanimation/rectanimation.h index c9770c4..99b82b4 100644 --- a/tests/benchmarks/qanimation/rectanimation.h +++ b/tests/benchmarks/qanimation/rectanimation.h @@ -21,10 +21,10 @@ public: virtual void updateState(QAbstractAnimation::State state); private: - DummyObject *object; - QEasingCurve easing; - QRect start, end, current; - int dura; + DummyObject *m_object; + QEasingCurve m_easing; + QRect m_start, m_end, m_current; + int m_dura; }; -#endif
\ No newline at end of file +#endif |