diff options
24 files changed, 349 insertions, 71 deletions
diff --git a/doc/src/declarative/advtutorial1.qdoc b/doc/src/declarative/advtutorial1.qdoc index a96485c..86d14ad 100644 --- a/doc/src/declarative/advtutorial1.qdoc +++ b/doc/src/declarative/advtutorial1.qdoc @@ -41,7 +41,6 @@ /*! \page advtutorial1.html -\example declarative/tutorials/samegame/samegame1 \title Advanced Tutorial 1 - Creating the Game Canvas and Blocks The first step is to create the items in your application. In Same Game we have a main game screen and the blocks that populate it. diff --git a/doc/src/declarative/advtutorial2.qdoc b/doc/src/declarative/advtutorial2.qdoc index 9fab289..40a760d 100644 --- a/doc/src/declarative/advtutorial2.qdoc +++ b/doc/src/declarative/advtutorial2.qdoc @@ -41,7 +41,6 @@ /*! \page advtutorial2.html -\example declarative/tutorials/samegame/samegame2 \title Advanced Tutorial 2 - Populating the Game Canvas Now that we've written some basic elements, let's start writing the game. The diff --git a/doc/src/declarative/advtutorial3.qdoc b/doc/src/declarative/advtutorial3.qdoc index 5ac1be3..e6e4e97 100644 --- a/doc/src/declarative/advtutorial3.qdoc +++ b/doc/src/declarative/advtutorial3.qdoc @@ -41,7 +41,6 @@ /*! \page advtutorial3.html -\example declarative/tutorials/samegame/samegame3 \title Advanced Tutorial 3 - Implementing the Game Logic First we add to the \c initBoard function clearing of the board before filling it up again, so that clicking new game won't leave the previous game diff --git a/doc/src/declarative/advtutorial4.qdoc b/doc/src/declarative/advtutorial4.qdoc index 2599e32..aaa7293 100644 --- a/doc/src/declarative/advtutorial4.qdoc +++ b/doc/src/declarative/advtutorial4.qdoc @@ -41,7 +41,6 @@ /*! \page advtutorial4.html -\example declarative/tutorials/samegame/samegame4 \title Advanced Tutorial 4 - Finishing Touches Now we're going to do two things to liven the game up. Animate the blocks and add a web-based high score system. diff --git a/doc/src/declarative/animation.qdoc b/doc/src/declarative/animation.qdoc index 1314493..d05a444 100644 --- a/doc/src/declarative/animation.qdoc +++ b/doc/src/declarative/animation.qdoc @@ -186,7 +186,7 @@ Transition { } \endcode -To insert an explicit animation into your transition, you can use \target and \property as normal. +To insert an explicit animation into your transition, you can use \c target and \c property as normal. \code Transition { @@ -214,8 +214,8 @@ Transition { \section1 Property Behaviors -A property behavior specifies a default animation to run whenever the property's value changes, regardless -of what caused the change. Unlike Transition, Behavior doesn't provide a way to indicate that a Behavior +A \l{Behavior}{property behavior} specifies a default animation to run whenever the property's value changes, regardless +of what caused the change. Unlike Transition, \l Behavior doesn't provide a way to indicate that a Behavior should only apply under certain circumstances. In the following snippet, we specify that we want the x position of redRect to be animated diff --git a/doc/src/declarative/qmldocument.qdoc b/doc/src/declarative/qmldocument.qdoc index 2775ea6..453c023 100644 --- a/doc/src/declarative/qmldocument.qdoc +++ b/doc/src/declarative/qmldocument.qdoc @@ -44,9 +44,9 @@ \title QML Documents A QML document is a block of QML source code. QML documents generally correspond to files -stored on a disk or network resource, but can be constructed directly from text data. +stored on a disk or network resource, but can also be constructed directly from text data. -A simple QML document looks like this: +Here is a simple QML document: \code import Qt 4.6 diff --git a/doc/src/declarative/qmlintro.qdoc b/doc/src/declarative/qmlintro.qdoc index f84d614..2487a85 100644 --- a/doc/src/declarative/qmlintro.qdoc +++ b/doc/src/declarative/qmlintro.qdoc @@ -48,7 +48,7 @@ \section1 What is QML? QML is a declarative language designed to describe the user interface of a -program: both what it looks like and how it behaves. In QML, a user +program: both what it looks like, and how it behaves. In QML, a user interface is specified as a tree of objects with properties. \section1 What should I know before starting? @@ -56,8 +56,8 @@ interface is specified as a tree of objects with properties. This introduction is meant for those with little or no programming experience. JavaScript is used as a scripting language in QML, so you may want to learn a bit more about it (\l{JavaScript: The Definitive Guide}) before diving -too deep into QML. It's also helpful to have a basic understanding of other web -technologies like HTML and CSS, but not required. +deeper into QML. It's also helpful to have a basic understanding of other web +technologies like HTML and CSS, but it's not required. \section1 Basic QML Syntax @@ -131,18 +131,18 @@ Item { } \endcode -In the example above, the Text2 object will display the same text as Text1. If Text1 is updated, -Text2 will be updated as well. +In the example above, the \c text2 object will display the same text as \c text1. If \c text1 is changed, +\c text2 is automatically changed to the same value. -Note that to refer to other objects, we use their \e id (more information on the id property can be -found in a following section). +Note that to refer to other objects, we use their \e id values. (See below for more +information on the \e id property.) \section1 QML Comments Commenting in QML is similar to JavaScript. \list -\o Single line comments begin with // and end at the end of the line. -\o Multiline comments begin with /* and end with *\/ +\o Single line comments start with // and finish at the end of the line. +\o Multiline comments start with /* and finish with *\/ \endlist \quotefile doc/src/snippets/declarative/comments.qml @@ -173,7 +173,7 @@ Properties begin with a lowercase letter (with the exception of \l{Attached Prop \section2 Property types -QML supports properties of many types (\l{Common QML Types}). The basic types include int, +QML supports properties of many types (see \l{Common QML Types}). The basic types include int, real, bool, string, color, and lists. \code @@ -186,12 +186,12 @@ Item { \endcode QML properties are what is known as \e typesafe. That is, they only allow you to assign a value that -matches the property type. For example, the scale property of item is a real, and if you try to assign +matches the property type. For example, the \c x property of item is a real, and if you try to assign a string to it you will get an error. \badcode Item { - scale: "hello" //illegal! + x: "hello" // illegal! } \endcode @@ -239,8 +239,8 @@ Image { \section2 Default properties -Each object type can specify one of its list properties as its default property. -If a list property has been declared as the default property, the property tag can be omitted. +Each object type can specify one of its list or object properties as its default property. +If a property has been declared as the default property, the property tag can be omitted. For example this code: \code @@ -263,9 +263,27 @@ State { because \c changes is the default property of the \c State type. -\section2 Dot Properties +\section2 Grouped Properties +In some cases properties form a logical group and use a 'dot' or grouped notation +to show this. +Grouped properties can be written like this: +\qml +Text { + font.pixelSize: 12 + font.bold: true +} +\endqml + +or like this: +\qml +Text { + font { pixelSize: 12; bold: true } +} +\endqml + +In the element documentation grouped properties are shown using the 'dot' notation. \section2 Attached Properties \target attached-properties diff --git a/doc/src/declarative/qmlreference.qdoc b/doc/src/declarative/qmlreference.qdoc index f17e9d7..2c79aeb 100644 --- a/doc/src/declarative/qmlreference.qdoc +++ b/doc/src/declarative/qmlreference.qdoc @@ -45,16 +45,22 @@ \target qtdeclarativemainpage - QML is a language for building highly dynamic and fluid applications. It is targetted at the sorts of user - interface (and the sorts of hardware) in embedded devices such as phones, media - players, and set-top boxes. It is also appropriate for highly custom desktop + QML is a language for building the animation rich, + highly fluid user interfaces that are becoming common in portable consumer + electronics devices such as mobile phones, media players, set-top boxes and + netbooks. It is also appropriate for highly custom desktop user interfaces, or special elements in more traditional desktop user interfaces. Building fluid applications is done declaratively, rather than procedurally. That is, you specify \e what the UI should look like and how it should behave rather than specifying step-by-step \e how to build it. Specifying a UI declaratively does not just include the layout of the interface items, but also the way each - individual item looks and behaves and the overall flow of the application. + individual item looks and behaves and the overall flow of the application. + + The QML elements provide a sophisticated set of graphical and behavioral building + blocks. These different elements are combined together in \l {QML Documents}{QML documents} to build components + ranging in complexity from simple buttons and sliders, to complete + internet-enabled applications like a \l {http://www.flickr.com}{Flickr} photo browser. Getting Started: \list @@ -69,6 +75,7 @@ \o \l {QML Documents} \o \l {Property Binding} \o \l {ECMAScript Blocks} + \o \l {QML Scope} \o \l {Network Transparency} \o \l {qmlmodels}{Data Models} \o \l {anchor-layout}{Anchor-based Layout} @@ -82,5 +89,6 @@ QML Reference: \list \o \l {elements}{QML Elements} + \o \l {QML Global Object} \endlist */ diff --git a/doc/src/declarative/qmlstates.qdoc b/doc/src/declarative/qmlstates.qdoc index 261e3f5..ddb0fc8 100644 --- a/doc/src/declarative/qmlstates.qdoc +++ b/doc/src/declarative/qmlstates.qdoc @@ -3,7 +3,7 @@ \target qmlstates \title QML States -QML states describe user interface configurations, including: +QML states typically describe user interface configurations, including: \list \o What UI elements are present \o The properties of those elements (including how they behave) @@ -52,7 +52,7 @@ To animate state changes, you can use \l{state-transitions}{transitions}. Other things you can do in a state change: \list \o override signal handlers with PropertyChanges -\o change an item's parent with ParentChange +\o change an item's visual parent with ParentChange \o change an item's anchors with AnchorChanges \o run some script with StateChangeScript \endlist diff --git a/doc/src/declarative/qmlviewer.qdoc b/doc/src/declarative/qmlviewer.qdoc index f153df2..df96535 100644 --- a/doc/src/declarative/qmlviewer.qdoc +++ b/doc/src/declarative/qmlviewer.qdoc @@ -71,7 +71,7 @@ that is a qreal from 0 to 86400 representing the number of seconds since midnight, dummy data for this could be provided by \c dummydata/clock.qml: \code - Object { property real time: 12345 } + QtObject { property real time: 12345 } \endcode Any QML can be used in the dummy data files. You could even animate the fictional data! diff --git a/doc/src/declarative/scope.qdoc b/doc/src/declarative/scope.qdoc index fc678d1..f7f25f5 100644 --- a/doc/src/declarative/scope.qdoc +++ b/doc/src/declarative/scope.qdoc @@ -44,7 +44,7 @@ \title QML Scope \l {Property Binding}s and \l {ECMAScript Blocks} are executed in a scope chain automatically -established by QML when constructing a component instance. QML is a \e {dynamically scoped} +established by QML when a component instance is constructed. QML is a \e {dynamically scoped} language. Different object instances instantiated from the same component can exist in different scope chains. @@ -91,8 +91,8 @@ Text { \section1 QML Local Scope Most variables references are resolved in the local scope. The local scope is controlled by the -QML component in which the binding or script block was declarated. The following example shows -three different bindings, and the component that dictates their local scope. +QML component in which the binding or script block was defined. The following example shows +three different bindings, and the component that dictates each local scope. \table \row @@ -135,15 +135,15 @@ Rectangle { // Local scope component for binding 3 \endcode \endtable -Inside the local scope, four "sub-scopes" exist. Each "sub-scope" is searched in order when -resolving a name - names in a higher "sub-scopes" shadow those in lower sub-scopes. +Inside the local scope, four "sub-scopes" exist. Each sub-scope is searched in order when +resolving a name; names in higher sub-scopes shadow those in lower sub-scopes. \section2 IDs IDs present in the component take precendence over other names. The QML engine enforces uniqueness of IDs within a component, so their names cannot conflict with one another. -This is an example of using IDs within bindings. +Here is an example of using IDs within bindings: \code Item { @@ -192,7 +192,7 @@ scope object appear in the scope chain, immediately after \l {Script Methods}. In bindings and script blocks established explicitly in \l {QML Documents}, the scope object is always the element containing the binding or script block. The following example shows two bindings, one using grouped properties, and the corresponding scope object. These two bindings -use the scope object to resolve variable references - \c height is a property on \l Rectangle, +use the scope object to resolve variable references: \c height is a property on \l Rectangle, and \c parent is a property on \l Text. \code @@ -269,7 +269,7 @@ Item { \section1 QML Component chain When a QML component is instantiated it is given a parent component instance. The parent -component instance is immutable - it is not effected, for example, by changes in the instance's +component instance is immutable - it is not affected, for example, by changes in the instance's visual parent (in the case of visual elements). Should name resolution fail within the \l {QML Local Scope}, this parent chain is searched. @@ -283,8 +283,8 @@ For each component instance in the chain, the following are examined: This list is a sub-set of that in the \l {QML Local Scope}. -Sub-components used within a component have their parent component instance set to the component -instance that created them. In the following example, the two \c Button instances have the +A sub-component's parent component instance is set to the component that created it. +In the following example, the two \c Button instances have the \c main.qml instance as their parent component instance. If the \c Button type was used from within another QML file, it may have a difference parent component instance, and consequently the \c buttonClicked() method may resolve differently. diff --git a/examples/declarative/tic-tac-toe/content/TicTac.qml b/examples/declarative/tic-tac-toe/content/TicTac.qml new file mode 100644 index 0000000..eb80743 --- /dev/null +++ b/examples/declarative/tic-tac-toe/content/TicTac.qml @@ -0,0 +1,20 @@ +import Qt 4.6 + +Item { + signal clicked + + states: [ + State { name: "X"; PropertyChanges { target: image; source: "pics/x.png" } }, + State { name: "O"; PropertyChanges { target: image; source: "pics/o.png" } } + ] + + Image { + id: image + anchors.centerIn: parent + } + + MouseRegion { + anchors.fill: parent + onClicked: parent.clicked() + } +} diff --git a/examples/declarative/tic-tac-toe/content/pics/board.png b/examples/declarative/tic-tac-toe/content/pics/board.png Binary files differnew file mode 100644 index 0000000..cd85971 --- /dev/null +++ b/examples/declarative/tic-tac-toe/content/pics/board.png diff --git a/examples/declarative/tic-tac-toe/content/pics/o.png b/examples/declarative/tic-tac-toe/content/pics/o.png Binary files differnew file mode 100644 index 0000000..abc7ee0 --- /dev/null +++ b/examples/declarative/tic-tac-toe/content/pics/o.png diff --git a/examples/declarative/tic-tac-toe/content/pics/x.png b/examples/declarative/tic-tac-toe/content/pics/x.png Binary files differnew file mode 100644 index 0000000..ddc65c8 --- /dev/null +++ b/examples/declarative/tic-tac-toe/content/pics/x.png diff --git a/examples/declarative/tic-tac-toe/tic-tac-toe.qml b/examples/declarative/tic-tac-toe/tic-tac-toe.qml new file mode 100644 index 0000000..63ee483 --- /dev/null +++ b/examples/declarative/tic-tac-toe/tic-tac-toe.qml @@ -0,0 +1,115 @@ +import Qt 4.6 +import "content" + +Item { + width: boardimage.width + height: boardimage.height + + Image { + id: boardimage + source: "content/pics/board.png" + } + + Grid { + id: board + anchors.fill: boardimage + + columns: 3 + + Repeater { + model: 9 + TicTac { + width: board.width/3 + height: board.height/3 + onClicked: { + if (!endtimer.running) { + if (!makeMove(index,"X")) + computerTurn() + } + } + } + } + + Script { + function winner() + { + for (var i=0; i<3; ++i) { + if (board.children[i].state!="" + && board.children[i].state==board.children[i+3].state + && board.children[i].state==board.children[i+6].state) + return true + + if (board.children[i*3].state!="" + && board.children[i*3].state==board.children[i*3+1].state + && board.children[i*3].state==board.children[i*3+2].state) + return true + } + + if (board.children[0].state!="" + && board.children[0].state==board.children[4].state!="" + && board.children[0].state==board.children[8].state!="") + return true + + if (board.children[2].state!="" + && board.children[2].state==board.children[4].state!="" + && board.children[2].state==board.children[6].state!="") + return true + + return false + } + + function restart() + { + // No moves left - start again + for (var i=0; i<9; ++i) + board.children[i].state = "" + } + + function makeMove(pos,player) + { + board.children[pos].state = player + if (winner()) { + win(player + " wins") + return true + } else { + return false + } + } + + function computerTurn() + { + // world's dumbest player + for (var i=0; i<9; ++i) + if (board.children[i].state == "") { + makeMove(i,"O") + return + } + restart() + } + + function win(s) + { + msg.text = s + msg.opacity = 1 + endtimer.running = true + } + } + + Timer { + id: endtimer + interval: 1600 + onTriggered: { msg.opacity = 0; restart() } + } + } + + Text { + id: msg + opacity: 0 + anchors.centerIn: parent + color: "blue" + styleColor: "white" + style: Text.Outline + font.pixelSize: 50 + font.bold: true + } +} diff --git a/src/declarative/graphicsitems/qmlgraphicsflipable.cpp b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp index 57d2ee1..9e48bf2 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflipable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflipable.cpp @@ -68,29 +68,39 @@ public: Flipable allows you to specify a front and a back and then flip between those sides. + Here's an example that flips between the front and back sides when clicked: + \qml -Flipable { - width: 40; height: 40 - - transform: Rotation { - id: rotation - origin.x: 20; origin.y: 120 - axis.x: 0; axis.y: 1; axis.z: 0 - angle: 0 - } - front: Image { source: "front.png" } - back: Image { source: "back.png" } + Flipable { + id: flipable + width: 250; height: 250 + property int angle: 0 - states: State { - name: "back" - SetProperties { target: rotation; angle: 180 } - } + transform: Rotation { + id: rotation + origin.x: flipable.width/2; origin.y: flipable.height/2 + axis.x: 0; axis.y: 1; axis.z: 0 // rotate around y-axis + angle: flipable.angle + } + + front: Image { source: "front.png" } + back: Image { source: "back.png" } - transitions: Transition { - NumberAnimation { easing: "easeInOutQuad"; matchProperties: "rotation" } + states: State { + name: "back" + PropertyChanges { target: flipable; angle: 180 } + } + + transitions: Transition { + NumberAnimation { matchProperties: "angle"; duration: 2000 } + } + + MouseRegion { + anchors.fill: parent + onClicked: flipable.state = (flipable.state == 'back' ? 'front' : 'back') + } } -} \endqml \image flipable.gif diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp index 28c8e4f..6a393ee 100644 --- a/src/declarative/util/qmlpropertychanges.cpp +++ b/src/declarative/util/qmlpropertychanges.cpp @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE \brief The PropertyChanges element describes new property values for a state. PropertyChanges changes the properties of an item. It allows you to specify the property - names and values similar to how you normally would specify them for the actual item: + names and values for a state similar to how you normally would specify them for the + actual item: \code PropertyChanges { @@ -67,6 +68,20 @@ QT_BEGIN_NAMESPACE width: 48 } \endcode + + State-specific script for signal handlers can also be specified: + + \qml + PropertyChanges { + target: myMouseRegion + onClicked: doSomethingDifferent() + } + \endqml + + Changes to an Item's parent or anchors should be done using the associated change elements + (ParentChange and AnchorChanges, respectively) rather than PropertyChanges. + + \sa {qmlstate}{States} */ /*! diff --git a/src/declarative/util/qmlstategroup.cpp b/src/declarative/util/qmlstategroup.cpp index d6ce191..4dfa34a 100644 --- a/src/declarative/util/qmlstategroup.cpp +++ b/src/declarative/util/qmlstategroup.cpp @@ -42,6 +42,7 @@ #include "private/qobject_p.h" #include "qmlstategroup_p.h" #include "qmltransition_p.h" +#include "qmlstate_p_p.h" #include <qmlbinding.h> #include <QtCore/qdebug.h> #include <private/qmlglobal_p.h> @@ -57,7 +58,8 @@ class QmlStateGroupPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QmlStateGroup) public: QmlStateGroupPrivate(QmlStateGroup *p) - : nullState(0), states(p), componentComplete(true), ignoreTrans(false) {} + : nullState(0), states(p), componentComplete(true), + ignoreTrans(false), applyingState(false) {} QString currentState; QmlState *nullState; @@ -78,6 +80,7 @@ public: QmlConcreteList<QmlTransition *> transitions; bool componentComplete; bool ignoreTrans; + bool applyingState; QmlTransition *findTransition(const QString &from, const QString &to); void setCurrentStateInternal(const QString &state, bool = false); @@ -212,9 +215,6 @@ void QmlStateGroup::setState(const QString &state) return; d->setCurrentStateInternal(state); - - d->currentState = state; - emit stateChanged(d->currentState); } void QmlStateGroup::classBegin() @@ -334,6 +334,13 @@ void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state, if (!componentComplete) return; + if (applyingState) { + qWarning() << "Can't apply a state change as part of a state definition."; + return; + } + + applyingState = true; + QmlTransition *transition = (ignoreTrans || ignoreTrans) ? 0 : findTransition(currentState, state); if (stateChangeDebug()) { qWarning() << this << "Changing state. From" << currentState << ". To" << state; @@ -353,6 +360,7 @@ void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state, } currentState = state; + emit q->stateChanged(currentState); QmlState *newState = 0; for (int ii = 0; ii < states.count(); ++ii) { @@ -369,6 +377,9 @@ void QmlStateGroupPrivate::setCurrentStateInternal(const QString &state, } newState->apply(q, transition, oldState); + applyingState = false; + if (!transition) + static_cast<QmlStatePrivate*>(QObjectPrivate::get(newState))->complete(); } QmlState *QmlStateGroup::findState(const QString &name) const diff --git a/src/declarative/util/qmlstateoperations.cpp b/src/declarative/util/qmlstateoperations.cpp index e2933b2..9727ca7 100644 --- a/src/declarative/util/qmlstateoperations.cpp +++ b/src/declarative/util/qmlstateoperations.cpp @@ -153,6 +153,9 @@ void QmlParentChangePrivate::doChange(QmlGraphicsItem *targetParent, QmlGraphics More specifically, it will not work if the transform property has been set for any Items involved in the reparenting (defined as any Items in the common ancestor tree for the original and new parent). + + You can specify at which point in a transition you want a ParentChange to occur by + using a ParentAction. */ QML_DEFINE_TYPE(Qt,4,6,ParentChange,QmlParentChange) @@ -166,7 +169,7 @@ QmlParentChange::~QmlParentChange() } /*! - \qmlproperty Object ParentChange::target + \qmlproperty Item ParentChange::target This property holds the item to be reparented */ @@ -310,6 +313,10 @@ public: /*! \qmlclass StateChangeScript QmlStateChangeScript \brief The StateChangeScript element allows you to run a script in a state. + + The script specified will be run immediately when the state is made current. + Alternatively you can use a ScriptAction to specify at which point in the transition + you want the StateChangeScript to be run. */ QML_DEFINE_TYPE(Qt,4,6,StateChangeScript,QmlStateChangeScript) QmlStateChangeScript::QmlStateChangeScript(QObject *parent) @@ -385,8 +392,16 @@ QString QmlStateChangeScript::typeName() const \qmlclass AnchorChanges QmlAnchorChanges \brief The AnchorChanges element allows you to change the anchors of an item in a state. + In the following example we change the top and bottom anchors of an item: \snippet examples/declarative/anchors/anchor-changes.qml 0 + AnchorChanges will 'inject' \c x, \c y, \c width, and \c height changes into the transition, + so you can animate them as you would normally changes to these properties: + \qml + //animate our anchor changes + NumberAnimation { matchTargets: content; matchProperties: "x,y,width,height" } + \endqml + For more information on anchors see \l {anchor-layout}{Anchor Layouts}. */ @@ -432,8 +447,8 @@ public: }; /*! - \qmlproperty Object AnchorChanges::target - This property holds the object that the anchors to change belong to + \qmlproperty Item AnchorChanges::target + This property holds the Item whose anchors will change */ QmlAnchorChanges::QmlAnchorChanges(QObject *parent) diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index ba726db..1a164c7 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -236,11 +236,8 @@ void QmlTransitionManager::transition(const QList<Action> &list, action.property.write(action.toValue); } } - if (!transition) { + if (!transition) d->applyBindings(); - if (d->state) - static_cast<QmlStatePrivate*>(QObjectPrivate::get(d->state))->complete(); - } } void QmlTransitionManager::cancel() diff --git a/tests/auto/declarative/states/data/illegalTempState.qml b/tests/auto/declarative/states/data/illegalTempState.qml new file mode 100644 index 0000000..2702be4 --- /dev/null +++ b/tests/auto/declarative/states/data/illegalTempState.qml @@ -0,0 +1,21 @@ +import Qt 4.6 + +Rectangle { + id: card + width: 100; height: 100 + + states: [ + State { + name: "placed" + PropertyChanges { target: card; state: "idle" } + }, + State { + name: "idle" + } + ] + + MouseRegion { + anchors.fill: parent + onClicked: card.state = "placed" + } +} diff --git a/tests/auto/declarative/states/data/legalTempState.qml b/tests/auto/declarative/states/data/legalTempState.qml new file mode 100644 index 0000000..54c97b9 --- /dev/null +++ b/tests/auto/declarative/states/data/legalTempState.qml @@ -0,0 +1,23 @@ +import Qt 4.6 + +Rectangle { + id: card + width: 100; height: 100 + + states: [ + State { + name: "placed" + onCompleted: card.state = "idle" + StateChangeScript { script: console.log("entering placed") } + }, + State { + name: "idle" + StateChangeScript { script: console.log("entering idle") } + } + ] + + MouseRegion { + anchors.fill: parent + onClicked: card.state = "placed" + } +} diff --git a/tests/auto/declarative/states/tst_states.cpp b/tests/auto/declarative/states/tst_states.cpp index 4847535..17d9263 100644 --- a/tests/auto/declarative/states/tst_states.cpp +++ b/tests/auto/declarative/states/tst_states.cpp @@ -72,6 +72,8 @@ private slots: void incorrectRestoreBug(); void deletingChange(); void deletingState(); + void tempState(); + void illegalTempState(); }; void tst_states::basicChanges() @@ -803,6 +805,33 @@ void tst_states::deletingState() delete rect; } +void tst_states::tempState() +{ + QmlEngine engine; + + QmlComponent rectComponent(&engine, SRCDIR "/data/legalTempState.qml"); + QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create()); + QVERIFY(rect != 0); + + QTest::ignoreMessage(QtDebugMsg, "entering placed"); + QTest::ignoreMessage(QtDebugMsg, "entering idle"); + rect->setState("placed"); + QCOMPARE(rect->state(), QLatin1String("idle")); +} + +void tst_states::illegalTempState() +{ + QmlEngine engine; + + QmlComponent rectComponent(&engine, SRCDIR "/data/illegalTempState.qml"); + QmlGraphicsRectangle *rect = qobject_cast<QmlGraphicsRectangle*>(rectComponent.create()); + QVERIFY(rect != 0); + + QTest::ignoreMessage(QtWarningMsg, "Can't apply a state change as part of a state definition. "); + rect->setState("placed"); + QCOMPARE(rect->state(), QLatin1String("placed")); +} + QTEST_MAIN(tst_states) #include "tst_states.moc" |