diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-05-07 23:41:10 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-05-07 23:41:10 (GMT) |
commit | f3164b608e83a3e2c54643aea984095edc275346 (patch) | |
tree | 14b532e90e2a15b8d2ac5d46738971b0bedc561e /src/corelib | |
parent | b7ac7f5b4d4c8e08b4ded43c9720c712a3663810 (diff) | |
parent | 90057dabcb99759bcb42c1c21db7151c69d98706 (diff) | |
download | Qt-f3164b608e83a3e2c54643aea984095edc275346.zip Qt-f3164b608e83a3e2c54643aea984095edc275346.tar.gz Qt-f3164b608e83a3e2c54643aea984095edc275346.tar.bz2 |
Merge branch 'kinetic-animations' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Conflicts:
src/corelib/animation/qabstractanimation.cpp
src/corelib/animation/qabstractanimation_p.h
src/corelib/animation/qpropertyanimation.cpp
Diffstat (limited to 'src/corelib')
44 files changed, 1207 insertions, 2618 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index f2d8668..f5b9323 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -41,52 +41,59 @@ /*! \class QAbstractAnimation - \ingroup group_animation - \brief The QAbstractAnimation class provides an abstract base class for animations. + \ingroup animation + \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 loop 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 setLoopCount(); a - loop 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} */ /*! @@ -149,13 +156,13 @@ #include <QtCore/qcoreevent.h> #include <QtCore/qpointer.h> -#define TIMER_INTERVAL 5 +#define DEFAULT_TIMER_INTERVAL 16 QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer); -QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), consistentTiming(false) +QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false) { } @@ -182,12 +189,28 @@ void QUnifiedTimer::updateRecentlyStartedAnimations() animationsToStart.clear(); } -void QUnifiedTimer::setConsistentTiming(bool c) +/* + 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 = c; + consistentTiming = b; } -int QUnifiedTimer::elapsedTime() +int QUnifiedTimer::elapsedTime() const { return lastTick; } @@ -195,9 +218,9 @@ int QUnifiedTimer::elapsedTime() 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 = consistentTiming ? oldLastTick + 5 : time.elapsed(); + lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed(); //we transfer the waiting animations into the "really running" state updateRecentlyStartedAnimations(); @@ -208,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(); } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 08eed2b..41983a5 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -58,7 +58,6 @@ #include <QtCore/qtimer.h> #ifndef QT_EXPERIMENTAL_SOLUTION #include <private/qobject_p.h> -#include <qabstractanimation.h> #endif QT_BEGIN_NAMESPACE @@ -119,13 +118,17 @@ private: public: static QUnifiedTimer *instance(); - void timerEvent(QTimerEvent *); - void updateTimer(); void registerAnimation(QAbstractAnimation *animation); void unregisterAnimation(QAbstractAnimation *animation); - void setConsistentTiming(bool c); - int elapsedTime(); + void setTimingInterval(int interval); + void setConsistentTiming(bool consistent); + + int elapsedTime() const; + +protected: + void timerEvent(QTimerEvent *); + void updateTimer(); private: void updateRecentlyStartedAnimations(); @@ -133,6 +136,7 @@ private: QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; + int timingInterval; bool consistentTiming; QList<QAbstractAnimation*> animations, animationsToStart; }; diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 6b03c33..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) - \ingroup group_animation + \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; } } diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 29819e5..5c4339d 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 loopCount, 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 { @@ -382,8 +414,8 @@ QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int in \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 */ diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index efd0938..bbd0695 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -264,9 +264,8 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal - \omitvalue Bound + \omitvalue Wrapped \omitvalue Signal - \omitvalue StateFinished */ /*! 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 89dcff9..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 @@ -59,10 +60,11 @@ QT_BEGIN_NAMESPACE 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 @@ -73,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(), QAbstractState::assignProperty() -*/ - -/*! - \property QAbstractState::restorePolicy - - \brief the restore policy of this state -*/ - -QAbstractStatePrivate::QAbstractStatePrivate() - : restorePolicy(QAbstractState::GlobalRestorePolicy) +QAbstractStatePrivate::QAbstractStatePrivate() { } @@ -137,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(); } /*! @@ -204,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 7c565f0..6c09696 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -57,28 +57,10 @@ #include <private/qobject_p.h> #endif -#include <QtCore/qlist.h> -#include <QtCore/qbytearray.h> -#include <QtCore/qvariant.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 @@ -95,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 dfce310..1897aa6 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -61,7 +61,8 @@ QT_BEGIN_NAMESPACE Framework}. 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. @@ -78,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 @@ -130,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 @@ -286,6 +287,16 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets) d->targetStates = targets; } +/*! + 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 /*! @@ -342,10 +353,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..b4e1c88 100644 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ b/src/corelib/statemachine/qabstracttransition_p.h @@ -79,7 +79,7 @@ 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; diff --git a/src/corelib/statemachine/qactionstate.cpp b/src/corelib/statemachine/qactionstate.cpp deleted file mode 100644 index 1da0350..0000000 --- a/src/corelib/statemachine/qactionstate.cpp +++ /dev/null @@ -1,293 +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. - - \since 4.6 - \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(), 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/qactionstate.h b/src/corelib/statemachine/qactionstate.h deleted file mode 100644 index 517b4b2..0000000 --- a/src/corelib/statemachine/qactionstate.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QACTIONSTATE_H -#define QACTIONSTATE_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qabstractstate.h> -#else -#include "qabstractstate.h" -#endif - -#include <QtCore/qlist.h> -#include <QtCore/qvariant.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateAction; - -class QActionStatePrivate; -class Q_CORE_EXPORT QActionState : public QAbstractState -{ - Q_OBJECT -public: - QActionState(QState *parent = 0); - ~QActionState(); - - 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>()); - - void addEntryAction(QStateAction *action); - void addExitAction(QStateAction *action); - - void removeEntryAction(QStateAction *action); - void removeExitAction(QStateAction *action); - - QList<QStateAction*> entryActions() const; - QList<QStateAction*> exitActions() const; - -protected: - void onEntry(); - void onExit(); - - bool event(QEvent *e); - -protected: - QActionState(QActionStatePrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QActionState) - Q_DECLARE_PRIVATE(QActionState) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qactionstate_p.h b/src/corelib/statemachine/qactionstate_p.h deleted file mode 100644 index a06dde2..0000000 --- a/src/corelib/statemachine/qactionstate_p.h +++ /dev/null @@ -1,83 +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 QACTIONSTATE_P_H -#define QACTIONSTATE_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 "qabstractstate_p.h" -#include "qactionstate.h" - -#include <QtCore/qlist.h> - -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QActionState; -class Q_CORE_EXPORT QActionStatePrivate : public QAbstractStatePrivate -{ - Q_DECLARE_PUBLIC(QActionState) - -public: - QActionStatePrivate(); - ~QActionStatePrivate(); - - static QActionStatePrivate *get(QActionState *q); - static const QActionStatePrivate *get(const QActionState *q); - - QList<QStateAction*> entryActions() const; - QList<QStateAction*> exitActions() const; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qactiontransition.cpp b/src/corelib/statemachine/qactiontransition.cpp deleted file mode 100644 index 7c53e15..0000000 --- a/src/corelib/statemachine/qactiontransition.cpp +++ /dev/null @@ -1,230 +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 "qactiontransition.h" -#include "qactiontransition_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QActionTransition - - \brief The QActionTransition class provides an action-based transition. - - \since 4.6 - \ingroup statemachine - - QActionTransition provides an action-based transition; you add actions with - the addAction() function. The transition executes the actions when the - transition is triggered. QActionTransition 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); - QActionTransition *t1 = new QActionTransition(); - 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 -*/ - -QActionTransitionPrivate::QActionTransitionPrivate() -{ -} - -QActionTransitionPrivate::~QActionTransitionPrivate() -{ -} - -QActionTransitionPrivate *QActionTransitionPrivate::get(QActionTransition *q) -{ - return q->d_func(); -} - -const QActionTransitionPrivate *QActionTransitionPrivate::get(const QActionTransition *q) -{ - return q->d_func(); -} - -QList<QStateAction*> QActionTransitionPrivate::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 QActionTransition object with the given \a sourceState. -*/ -QActionTransition::QActionTransition(QState *sourceState) - : QAbstractTransition(*new QActionTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QActionTransition object with the given \a targets and \a - sourceState. -*/ -QActionTransition::QActionTransition(const QList<QAbstractState*> &targets, QState *sourceState) - : QAbstractTransition(*new QActionTransitionPrivate, targets, sourceState) -{ -} - -/*! - \internal -*/ -QActionTransition::QActionTransition(QActionTransitionPrivate &dd, QState *parent) - : QAbstractTransition(dd, parent) -{ -} - -/*! - \internal -*/ -QActionTransition::QActionTransition(QActionTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent) - : QAbstractTransition(dd, targets, parent) -{ -} - -/*! - Destroys this transition. -*/ -QActionTransition::~QActionTransition() -{ -} - -/*! - Instructs this QActionTransition 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. -*/ -void QActionTransition::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 QActionTransition::addAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionTransition::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 QActionTransition::removeAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionTransition::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*> QActionTransition::actions() const -{ - Q_D(const QActionTransition); - return d->actions(); -} - -/*! - \reimp -*/ -void QActionTransition::onTransition() -{ - Q_D(QActionTransition); - QList<QStateAction*> actions = d->actions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -bool QActionTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qactiontransition.h b/src/corelib/statemachine/qactiontransition.h deleted file mode 100644 index 1a779fa..0000000 --- a/src/corelib/statemachine/qactiontransition.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 QACTIONTRANSITION_H -#define QACTIONTRANSITION_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 QActionTransitionPrivate; -class Q_CORE_EXPORT QActionTransition : public QAbstractTransition -{ - Q_OBJECT -public: - QActionTransition(QState *sourceState = 0); - QActionTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0); - ~QActionTransition(); - - 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: - QActionTransition(QActionTransitionPrivate &dd, QState *parent); - QActionTransition(QActionTransitionPrivate &dd, const QList<QAbstractState*> &targets, QState *parent); - -private: - Q_DISABLE_COPY(QActionTransition) - Q_DECLARE_PRIVATE(QActionTransition) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qactiontransition_p.h b/src/corelib/statemachine/qactiontransition_p.h deleted file mode 100644 index 34f80d1..0000000 --- a/src/corelib/statemachine/qactiontransition_p.h +++ /dev/null @@ -1,80 +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 QACTIONTRANSITION_P_H -#define QACTIONTRANSITION_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 "qabstracttransition_p.h" - -#include <QtCore/qlist.h> - -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QActionTransition; -class Q_CORE_EXPORT QActionTransitionPrivate : public QAbstractTransitionPrivate -{ - Q_DECLARE_PUBLIC(QActionTransition) -public: - QActionTransitionPrivate(); - ~QActionTransitionPrivate(); - - static QActionTransitionPrivate *get(QActionTransition *q); - static const QActionTransitionPrivate *get(const QActionTransition *q); - - QList<QStateAction*> actions() const; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qboundevent_p.h b/src/corelib/statemachine/qboundevent_p.h deleted file mode 100644 index b641ff3..0000000 --- a/src/corelib/statemachine/qboundevent_p.h +++ /dev/null @@ -1,82 +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 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. -// - -#include <QtCore/qcoreevent.h> - -QT_BEGIN_NAMESPACE - -class QBoundEvent : 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() {} - - inline QObject *object() const { return m_object; } - inline QEvent *event() const { return m_event; } - -private: - QObject *m_object; - QEvent *m_event; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 87ed77a..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" @@ -79,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 */ @@ -129,7 +130,7 @@ void QEventTransitionPrivate::invalidate() Constructs a new QEventTransition object with the given \a sourceState. */ QEventTransition::QEventTransition(QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { } @@ -139,7 +140,7 @@ QEventTransition::QEventTransition(QState *sourceState) */ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -155,7 +156,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QEventTransition::QEventTransition(QObject *object, QEvent::Type type, const QList<QAbstractState*> &targets, QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -167,7 +168,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) - : QActionTransition(dd, parent) + : QAbstractTransition(dd, parent) { } @@ -176,7 +177,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent) - : QActionTransition(dd, parent) + : QAbstractTransition(dd, parent) { Q_D(QEventTransition); d->registered = false; @@ -190,7 +191,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, const QList<QAbstractState*> &targets, QState *parent) - : QActionTransition(dd, targets, parent) + : QAbstractTransition(dd, targets, parent) { Q_D(QEventTransition); d->registered = false; @@ -229,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; @@ -239,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) @@ -257,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; } /*! @@ -286,7 +280,7 @@ bool QEventTransition::testEventCondition(QEvent *event) const */ bool QEventTransition::event(QEvent *e) { - return QActionTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index 21a696c..a128cee 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -43,9 +43,9 @@ #define QEVENTTRANSITION_H #ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qactiontransition.h> +#include <QtCore/qabstracttransition.h> #else -#include "qactiontransition.h" +#include "qabstracttransition.h" #endif #include <QtCore/qcoreevent.h> @@ -56,10 +56,10 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QEventTransitionPrivate; -class Q_CORE_EXPORT QEventTransition : public QActionTransition +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 @@ -70,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 2bb5aaa..fca8c0d 100644 --- a/src/corelib/statemachine/qeventtransition_p.h +++ b/src/corelib/statemachine/qeventtransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qactiontransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QEventTransition; -class Q_CORE_EXPORT QEventTransitionPrivate : public QActionTransitionPrivate +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 abf9d2e..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 @@ -55,9 +55,9 @@ QT_BEGIN_NAMESPACE 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: @@ -77,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) @@ -96,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) { } @@ -110,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); } /*! @@ -128,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 8143d41..d1b2391 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -58,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; @@ -69,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); @@ -83,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() @@ -90,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(); @@ -107,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); @@ -152,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 32f2d02..d5833bd 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -96,7 +96,7 @@ QT_BEGIN_NAMESPACE */ /*! - \property QSignalTransition::object + \property QSignalTransition::senderObject \brief the sender object that this signal transition is associated with */ @@ -137,7 +137,7 @@ void QSignalTransitionPrivate::invalidate() Constructs a new signal transition with the given \a sourceState. */ QSignalTransition::QSignalTransition(QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { } @@ -147,7 +147,7 @@ QSignalTransition::QSignalTransition(QState *sourceState) */ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -162,7 +162,7 @@ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QSignalTransition::QSignalTransition(QObject *sender, const char *signal, const QList<QAbstractState*> &targets, QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -245,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 QActionTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index c1a41ae..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/qactiontransition.h> +#include <QtCore/qabstracttransition.h> #else -#include "qactiontransition.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 QActionTransition +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 bd815d9..a23e58c 100644 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ b/src/corelib/statemachine/qsignaltransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qactiontransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QSignalTransition; -class QSignalTransitionPrivate : public QActionTransitionPrivate +class QSignalTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QSignalTransition) public: diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index e3da1c5..4c9e033 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" @@ -66,53 +65,63 @@ QT_BEGIN_NAMESPACE The addTransition() function adds a transition. The removeTransition() function removes a transition. - \section1 States with Child States + 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(). - 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. + \section1 States with Child States - The addHistoryState() function adds a history state. + 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 addFinishedTransition() function creates and adds a transition that's - triggered when a final child state is entered. + 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). + +*/ + +/*! + \property QState::initialState + + \brief the initial state of this state (one of its child states) */ /*! - \enum QState::Type + \property QState::errorState - This enum specifies the type of a state. + \brief the error state of this state +*/ - \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::childMode + + \brief the child mode of this state - \value ParallelGroup The state is a parallel group state. When a parallel - group state is entered, all its child states are entered in parallel. + The default value of this property is QState::ExclusiveStates. */ /*! - \enum QState::HistoryType + \enum QState::ChildMode - This enum specifies the type of history that a QHistoryState records. + This enum specifies how a state's child states are treated. - \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 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) { } @@ -134,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) { } @@ -214,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() @@ -245,30 +291,32 @@ void QState::setErrorState(QAbstractState *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; 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; } /*! @@ -292,20 +340,6 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, 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? @@ -315,7 +349,7 @@ public: UnconditionalTransition(QAbstractState *target) : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: - void onTransition() {} + void onTransition(QEvent *) {} bool eventTest(QEvent *) const { return true; } }; @@ -358,40 +392,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); } /*! @@ -410,7 +423,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; @@ -424,11 +437,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 569d5d5..0000000 --- a/src/corelib/statemachine/qstateaction.cpp +++ /dev/null @@ -1,356 +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. - - \since 4.6 - \ingroup statemachine - - A state action is added to a state by calling QActionState::addEntryAction() - or QActionState::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. - - \since 4.6 - \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 33c3d22..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 "qactiontransition_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 QActionTransitionPrivate -{ - 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) - : QActionTransition(*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) - : QActionTransition(*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 QActionTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatefinishedtransition.h b/src/corelib/statemachine/qstatefinishedtransition.h deleted file mode 100644 index f9320f5..0000000 --- a/src/corelib/statemachine/qstatefinishedtransition.h +++ /dev/null @@ -1,87 +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 QSTATEFINISHEDTRANSITION_H -#define QSTATEFINISHEDTRANSITION_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include <QtCore/qactiontransition.h> -#else -#include "qactiontransition.h" -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QState; - -class QStateFinishedTransitionPrivate; -class Q_CORE_EXPORT QStateFinishedTransition : public QActionTransition -{ - Q_OBJECT - Q_PROPERTY(QState* state READ state WRITE setState) -public: - QStateFinishedTransition(QState *sourceState = 0); - QStateFinishedTransition(QState *state, const QList<QAbstractState*> &targets, - QState *sourceState = 0); - ~QStateFinishedTransition(); - - QState *state() const; // ### name - void setState(QState *state); - -protected: - bool eventTest(QEvent *event) const; - - bool event(QEvent *e); - -private: - Q_DISABLE_COPY(QStateFinishedTransition) - Q_DECLARE_PRIVATE(QStateFinishedTransition) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 0a1d248..21e564c 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 @@ -169,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. */ /*! @@ -183,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() @@ -192,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() @@ -238,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()) { @@ -248,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)); } } @@ -263,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)); } } @@ -344,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; @@ -375,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) { @@ -396,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) { @@ -404,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 } @@ -415,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); @@ -441,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); } } } @@ -503,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()) } @@ -512,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(); @@ -527,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(); } } } @@ -553,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); + } } } - propertyAssignments << restorablesToPropertyList(pendingRestorables); + if (!pendingRestorables.isEmpty()) { + QAbstractState *s; + if (!enteredStates.isEmpty()) + s = enteredStates.last(); // ### handle if parallel + else + s = 0; + propertyAssignmentsForState[s] << 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()) { @@ -691,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(); } } @@ -714,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) @@ -729,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); } @@ -832,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) @@ -855,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"); }; @@ -876,10 +1010,9 @@ 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); + QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); + addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } #ifndef QT_NO_ANIMATION @@ -905,13 +1038,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); @@ -923,37 +1049,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 @@ -966,8 +1090,8 @@ public: StartState(QState *parent) : QState(parent) {} protected: - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; class InitialTransition : public QAbstractTransition @@ -977,7 +1101,7 @@ public: : QAbstractTransition(QList<QAbstractState*>() << target) {} protected: virtual bool eventTest(QEvent *) const { return true; } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} }; } // namespace @@ -1012,9 +1136,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 @@ -1078,7 +1204,7 @@ void QStateMachinePrivate::_q_process() } if (!enabledTransitions.isEmpty()) { q->beginMicrostep(e); - microstep(enabledTransitions.toList()); + microstep(e, enabledTransitions.toList()); q->endMicrostep(e); } #ifdef QSTATEMACHINE_DEBUG @@ -1353,7 +1479,7 @@ public: setObjectName(QString::fromLatin1("DefaultErrorState")); } - void onEntry() + void onEntry(QEvent *) { QAbstractStatePrivate *d = QAbstractStatePrivate::get(this); QStateMachine *machine = d->machine(); @@ -1362,7 +1488,7 @@ public: qPrintable(machine->errorString())); } - void onExit() {} + void onExit(QEvent *) {} }; class RootState : public QState @@ -1373,8 +1499,8 @@ public: { } - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; } // namespace @@ -1443,14 +1569,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 @@ -1479,33 +1636,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; } @@ -1542,7 +1691,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) { @@ -1579,10 +1728,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() */ @@ -1609,9 +1768,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() { @@ -1675,15 +1835,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 @@ -1701,7 +1852,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() */ @@ -1710,7 +1862,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() */ @@ -1720,21 +1872,9 @@ QSet<QAbstractState*> QStateMachine::configuration() const This signal is emitted when the state machine has stopped. - \sa QStateMachine::stop() -*/ - -#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). + \sa QStateMachine::stop(), QStateMachine::finished() */ -#endif - /*! \reimp */ @@ -1772,7 +1912,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 @@ -1828,6 +1968,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: @@ -1960,7 +2150,7 @@ QSignalEvent::~QSignalEvent() Returns the index of the signal. - \sa QMetaObject::indexOfSignal() + \sa QMetaObject::indexOfSignal(), QMetaObject::method() */ /*! @@ -1969,55 +2159,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 */ /*! \internal - Constructs a new QStateFinishedEvent object associated with the given \a state. + 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), d(0) + , 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..bb4a78c 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; @@ -169,9 +171,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 +181,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/qstatefinishedevent.h b/src/corelib/statemachine/qwrappedevent.h index c2f81f7..b01c608 100644 --- a/src/corelib/statemachine/qstatefinishedevent.h +++ b/src/corelib/statemachine/qwrappedevent.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QSTATEFINISHEDEVENT_H -#define QSTATEFINISHEDEVENT_H +#ifndef QWRAPPEDEVENT_H +#define QWRAPPEDEVENT_H #include <QtCore/qcoreevent.h> @@ -50,21 +50,27 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -class QState; +class QObject; -class Q_CORE_EXPORT QStateFinishedEvent : public QEvent +class Q_CORE_EXPORT QWrappedEvent : public QEvent { public: - QStateFinishedEvent(QState *state); - ~QStateFinishedEvent(); + QWrappedEvent(QObject *object, QEvent *event); + ~QWrappedEvent(); - QState *state() const; + inline QObject *object() const { return m_object; } + inline QEvent *event() const { return m_event; } private: - QState *m_state; - void *d; + 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 4179e45..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/qactiontransition.h \ - $$PWD/qactiontransition_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/qactiontransition.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 |