From 4d07bf91ed2d36aee9178ef48508c16277fbb318 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 21 Aug 2014 16:24:54 +0200 Subject: Fix crash with foreach on arguments object We call fullyCreate() on the arguments object when it's initialized on an foreach iterator. That itself however might trigger an allocation, which in turn might collect the ForEachIteratorObject, which is missing a "ProtectThis" in its constructor. Change-Id: Ib8f7e39201e727cde91cbbe8a82cba78aa980f0d Task-number: QTBUG-40844 Reviewed-by: Albert Astals Cid Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4objectiterator.cpp | 40 +++++++++++++++++++++++++-------- src/qml/jsruntime/qv4objectiterator_p.h | 11 ++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index e5f693c323..0efd3045ba 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -54,13 +54,7 @@ ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef , memberIndex(0) , flags(flags) { - object = o.getPointer(); - current = o.getPointer(); - - if (!!object && object->asArgumentsObject()) { - Scope scope(object->engine()); - Scoped (scope, object->asReturnedValue())->fullyCreate(); - } + init(o); } ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags) @@ -71,8 +65,26 @@ ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags) , memberIndex(0) , flags(flags) { - object = o; - current = o; + init(o); +} + +ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, uint flags) + : object(ObjectRef::fromValuePointer(scratch1)) + , current(ObjectRef::fromValuePointer(scratch2)) + , arrayNode(0) + , arrayIndex(0) + , memberIndex(0) + , flags(flags) +{ + object = (Object*)0; + current = (Object*)0; + // Caller needs to call init! +} + +void ObjectIterator::init(const ObjectRef o) +{ + object = o.getPointer(); + current = o.getPointer(); if (!!object && object->asArgumentsObject()) { Scope scope(object->engine()); @@ -194,6 +206,16 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString() DEFINE_OBJECT_VTABLE(ForEachIteratorObject); +ForEachIteratorObject::ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o) + : Object(ctx->engine), it(workArea, workArea + 1, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) +{ + Scope scope(ctx); + ScopedObject protectThis(scope, this); + + setVTable(staticVTable()); + it.init(o); +} + void ForEachIteratorObject::markObjects(Managed *that, ExecutionEngine *e) { ForEachIteratorObject *o = static_cast(that); diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h index c87f284288..5ead1f5a23 100644 --- a/src/qml/jsruntime/qv4objectiterator_p.h +++ b/src/qml/jsruntime/qv4objectiterator_p.h @@ -58,6 +58,7 @@ struct ExecutionContext; struct Property; struct String; struct InternalClass; +struct ForEachIteratorObject; struct Q_QML_EXPORT ObjectIterator { @@ -76,21 +77,21 @@ struct Q_QML_EXPORT ObjectIterator ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags); ObjectIterator(Scope &scope, const ObjectRef o, uint flags); + void init(const ObjectRef o); void next(StringRef name, uint *index, Property *pd, PropertyAttributes *attributes = 0); ReturnedValue nextPropertyName(ValueRef value); ReturnedValue nextPropertyNameAsString(ValueRef value); ReturnedValue nextPropertyNameAsString(); +private: + friend struct ForEachIteratorObject; + ObjectIterator(Value *scratch1, Value *scratch2, uint flags); // Constructor that requires calling init() }; struct ForEachIteratorObject: Object { V4_OBJECT Q_MANAGED_TYPE(ForeachIteratorObject) ObjectIterator it; - ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o) - : Object(ctx->engine), it(workArea, workArea + 1, - o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) { - setVTable(staticVTable()); - } + ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o); ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); } -- cgit v1.2.3 From 5a9f0131f8c0b7424a4d323b0f65237206be45ea Mon Sep 17 00:00:00 2001 From: Josh Arenson Date: Mon, 4 Aug 2014 09:42:27 -0700 Subject: Move syncTimer measurment to the correct place. syncTimer was including the time spent waiting for VSYNC on unchanged frames. This was causing the reported value to be much higher than expected. Task-number: QTBUG-40556 Change-Id: Ife759b4e27faf2124ab330be8d1f42d15c4d2d33 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index c17eb916ae..1cfc689659 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -586,6 +586,10 @@ void QSGRenderThread::syncAndRender() QSG_RT_DEBUG(" - update pending, doing sync"); sync(); } +#ifndef QSG_NO_RENDER_TIMING + if (profileFrames) + syncTime = threadTimer.nsecsElapsed(); +#endif if (!syncResultedInChanges && !(repaintRequested)) { QSG_RT_DEBUG(" - no changes, rendering aborted"); @@ -595,10 +599,6 @@ void QSGRenderThread::syncAndRender() return; } -#ifndef QSG_NO_RENDER_TIMING - if (profileFrames) - syncTime = threadTimer.nsecsElapsed(); -#endif QSG_RT_DEBUG(" - rendering starting"); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); -- cgit v1.2.3 From f5e098e428855925382d25c84f14db4dbf773411 Mon Sep 17 00:00:00 2001 From: Venu Date: Tue, 7 Oct 2014 17:39:30 +0200 Subject: Doc: Updated the \brief and detailed description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just to give a hint to the reader about what the example does. Task-number: QTBUG-37203 Change-Id: Ibb377e4adfb25ed4e4da0a41280e4157fae638ba Reviewed-by: Topi Reiniö Reviewed-by: Leena Miettinen --- examples/quick/shadereffects/doc/src/shadereffects.qdoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/quick/shadereffects/doc/src/shadereffects.qdoc b/examples/quick/shadereffects/doc/src/shadereffects.qdoc index 448ee9f3e3..040bf4978f 100644 --- a/examples/quick/shadereffects/doc/src/shadereffects.qdoc +++ b/examples/quick/shadereffects/doc/src/shadereffects.qdoc @@ -28,11 +28,12 @@ \title Qt Quick Examples - Shader Effects \example shadereffects \image qml-shadereffects-example.png - \brief This is a shader effects example. + \brief A Qt Quick example demonstrating the use of shader effects. \ingroup qtquickexamples This example demonstrates a couple of visual effects that you can perform - with shaders in Qt Quick. For more information, visit + with shaders in Qt Quick. It applies five different effects on a text and + a couple of images. For more information, visit \l{Important Concepts In Qt Quick - Graphical Effects} \include examples-run.qdocinc -- cgit v1.2.3 From 9413d62f6120c8be509bb46adf75ce302550e0b3 Mon Sep 17 00:00:00 2001 From: Venu Date: Wed, 24 Sep 2014 17:11:11 +0200 Subject: Doc: Updated the QML State Machine docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Excluded the src/imports/statemachine directory from qtquick.qdocconf to avoid unnecessary qdoc warnings. - corrected a broken link to an external source - changed the group name to avoid collision - added a \qmlmodule page for QtQml.StateMachine - Reduced the amount of duplication between the C++ and QML state machine overviews. Task-number: QTBUG-41561 Change-Id: I87c815fada7006f0609331e315bb338f062bb4db Reviewed-by: Topi Reiniö --- src/imports/statemachine/finalstate.cpp | 4 +- src/imports/statemachine/signaltransition.cpp | 16 ++- src/imports/statemachine/statebase.cpp | 14 +- src/imports/statemachine/statemachine.cpp | 4 +- src/imports/statemachine/timeouttransition.cpp | 4 +- src/qml/doc/src/statemachine.qdoc | 191 +++++++++++-------------- src/quick/doc/qtquick.qdocconf | 3 +- 7 files changed, 111 insertions(+), 125 deletions(-) diff --git a/src/imports/statemachine/finalstate.cpp b/src/imports/statemachine/finalstate.cpp index b530229389..73e85a1abd 100644 --- a/src/imports/statemachine/finalstate.cpp +++ b/src/imports/statemachine/finalstate.cpp @@ -49,9 +49,9 @@ QQmlListProperty FinalState::children() /*! \qmltype FinalState - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QAbstractState - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief Provides a final state. diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp index 634ec5a43b..eb842914a1 100644 --- a/src/imports/statemachine/signaltransition.cpp +++ b/src/imports/statemachine/signaltransition.cpp @@ -126,8 +126,10 @@ void SignalTransition::invoke() /*! \qmltype QAbstractTransition - \inqmlmodule QtStateMachine 1.0 - \ingroup qmlstatemachine + \inqmlmodule QtQml.StateMachine + \omit + \ingroup statemachine-qmltypes + \endomit \since 5.4 \brief The QAbstractTransition type is the base type of transitions between QAbstractState objects. @@ -184,9 +186,11 @@ void SignalTransition::invoke() /*! \qmltype QSignalTransition - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QAbstractTransition - \ingroup qmlstatemachine + \omit + \ingroup statemachine-qmltypes + \endomit \since 5.4 \brief The QSignalTransition type provides a transition based on a Qt signal. @@ -212,9 +216,9 @@ void SignalTransition::invoke() /*! \qmltype SignalTransition - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QSignalTransition - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief The SignalTransition type provides a transition based on a Qt signal. diff --git a/src/imports/statemachine/statebase.cpp b/src/imports/statemachine/statebase.cpp index ec0fe217b5..d33e294369 100644 --- a/src/imports/statemachine/statebase.cpp +++ b/src/imports/statemachine/statebase.cpp @@ -60,8 +60,10 @@ QQmlListProperty StateBase::children() /*! \qmltype QAbstractState - \inqmlmodule QtStateMachine 1.0 - \ingroup qmlstatemachine + \inqmlmodule QtQml.StateMachine + \omit + \ingroup statemachine-qmltypes + \endomit \since 5.4 \brief The QAbstractState type is the base type of States of a StateMachine. @@ -104,9 +106,9 @@ QQmlListProperty StateBase::children() /*! \qmltype StateBase - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QAbstractState - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief Provides a general-purpose state for StateMachine. @@ -177,9 +179,9 @@ QQmlListProperty StateBase::children() /*! \qmltype HistoryState - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QAbstractState - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief The HistoryState type provides a means of returning to a previously active substate. diff --git a/src/imports/statemachine/statemachine.cpp b/src/imports/statemachine/statemachine.cpp index 6c92edd65f..c65901a175 100644 --- a/src/imports/statemachine/statemachine.cpp +++ b/src/imports/statemachine/statemachine.cpp @@ -79,9 +79,9 @@ QQmlListProperty StateMachine::children() /*! \qmltype StateMachine - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits StateBase - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief Provides a hierarchical finite state machine. diff --git a/src/imports/statemachine/timeouttransition.cpp b/src/imports/statemachine/timeouttransition.cpp index 3709a385a7..fdfb70eaab 100644 --- a/src/imports/statemachine/timeouttransition.cpp +++ b/src/imports/statemachine/timeouttransition.cpp @@ -78,9 +78,9 @@ void TimeoutTransition::componentComplete() /*! \qmltype TimeoutTransition - \inqmlmodule QtStateMachine 1.0 + \inqmlmodule QtQml.StateMachine \inherits QSignalTransition - \ingroup qmlstatemachine + \ingroup statemachine-qmltypes \since 5.4 \brief The TimeoutTransition type provides a transition based on a timer. diff --git a/src/qml/doc/src/statemachine.qdoc b/src/qml/doc/src/statemachine.qdoc index 5a37ef8026..68c57055ca 100644 --- a/src/qml/doc/src/statemachine.qdoc +++ b/src/qml/doc/src/statemachine.qdoc @@ -26,91 +26,77 @@ ****************************************************************************/ /*! - \group qmlstatemachine + \qmlmodule QtQml.StateMachine 1.0 + \title Declarative State Machine QML Types + \brief Provides QML types to create and execute state graphs. + + The following is a list of QML types provided by the module: +*/ + + +/*! \page qmlstatemachine.html \title The Declarative State Machine Framework - \brief An overview of the Declarative State Machine Framework for constructing and executing state graphs. + \brief Overview of the Declarative State Machine Framework for constructing and executing state graphs. \ingroup frameworks-technologies \tableofcontents - The Declarative State Machine Framework provides classes for creating and executing - state graphs in QML. The concepts and notation are based on those from Harel's - \l{http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf} - {Statecharts: A visual formalism for complex systems}, which - is also the basis of UML state diagrams. The semantics of state machine - execution are based on \l{State Chart XML: State Machine Notation for - Control Abstraction}{State Chart XML (SCXML)}. - - Statecharts provide a graphical way of modeling how a system reacts to - stimuli. This is done by defining the possible \e states that the system can - be in, and how the system can move from one state to another (\e transitions - between states). A key characteristic of event-driven systems (such as Qt - applications) is that behavior often depends not only on the last or current - event, but also the events that preceded it. With statecharts, this - information is easy to express. - - The Declarative State Machine Framework provides an API and execution model that can - be used to effectively embed the elements and semantics of statecharts in Qml - applications. The framework integrates tightly with Qt's meta-object system; - for example, transitions between states can be triggered by signals, and - states can be configured to set properties and invoke methods on QObjects. - Qt's event system is used to drive the state machines. - - The state graph in the Declarative State Machine Framework is hierarchical. States - can be nested inside of other states, and the current configuration of the - state machine consists of the set of states which are currently active. - All the states in a valid configuration of the state machine will - have a common ancestor. + The Declarative State Machine Framework provides types for creating and + executing state graphs in QML. It is similar to the C++ State Machine + framework based on Harel's + \l{Statecharts: A visual formalism for complex systems}, which + is also the basis for UML state diagrams. Like its + \l{The State Machine Framework}{C++ counterpart}, the framework provides an + API and execution model based on \l{State Chart XML: State Machine Notation for + Control Abstraction}{State Chart XML (SCXML)} + to embed the elements and semantics of statecharts in QML applications. For user interfaces with multiple visual states, independent of the application's logical state, consider using QML States and Transitions. - \section1 QML types in the Declarative State Machine Framework - - These QML types are provided by QML for creating event-driven state machines. + These following QML types are provided by framework to create event-driven + state machines: - \annotatedlist qmlstatemachine + \annotatedlist statemachine-qmltypes - \section1 A Simple State Machine + \section1 A Simple Example To demonstrate the core functionality of the State Machine API, let's look - at a small example: A state machine with three states, \c s1, \c s2 and \c - s3. The state machine is controlled by a single QPushButton; when the button + at an example: A state machine with three states, \c s1, \c s2 and \c + s3. The state machine is controlled by a single Button; when the button is clicked, the machine transitions to another state. Initially, the state - machine is in state \c s1. The statechart for this machine is as follows: + machine is in state \c s1. The following is a state chart showing the + different states in our example. - \image statemachine-button.png - \omit - \caption This is a caption - \endomit + \image statemachine-button.png The following snippet shows the code needed to create such a state machine. \snippet qml/statemachine/statemachine-button.qml 0 - The state machine executes asynchronously, i.e. it becomes part of your - application's event loop. + The state machine runs asynchronously to become part of your application's + event loop. \section1 State Machines That Finish The state machine defined in the previous section never finishes. In order for a state machine to be able to finish, it needs to have a top-level \e - final state (FinalState object). When the state machine enters a top-level - final state, the machine will emit the \l{StateBase::finished}{finished} - signal and halt. + final state (FinalState object). When the state machine enters the top-level + final state, the machine emits the \l{StateBase::finished}{finished} + signal and halts. All you need to do to introduce a final state in the graph is create a FinalState object and use it as the target of one or more transitions. - \section1 Sharing Transitions By Grouping States + \section1 Sharing Transitions Assume we wanted the user to be able to quit the application at any time by clicking a Quit button. In order to achieve this, we need to create a final state and make it the target of a transition associated with the Quit - button's clicked() signal. We could add a transition from each of \c s1, \c - s2 and \c s3; however, this seems redundant, and one would also have to + button's \e clicked() signal. We could add a transition for each state; + however, this seems redundant and one would also have to remember to add such a transition from every new state that is added in the future. @@ -121,54 +107,50 @@ state. The following diagram shows the new state machine. \image statemachine-button-nested.png - \omit - \caption This is a caption - \endomit The three original states have been renamed \c s11, \c s12 and \c s13 to - reflect that they are now children of the new top-level state, \c s1. Child + reflect that they are now childrens of the new top-level state, \c s1. Child states implicitly inherit the transitions of their parent state. This means it is now sufficient to add a single transition from \c s1 to the final - state \c s2. New states added to \c s1 will also automatically inherit this + state, \c s2. New states added to \c s1 will automatically inherit this transition. All that's needed to group states is to specify the proper parent when the state is created. You also need to specify which of the child states is the - initial one (i.e. which child state the state machine should enter when the + initial one (the child state the state machine should enter when the parent state is the target of a transition). \snippet qml/statemachine/statemachine-button-nested.qml 0 In this case we want the application to quit when the state machine is - finished, so the machine's finished() signal is connected to the - application's quit() slot. + finished, so the machine's \e finished() signal is connected to the + application's \e quit() slot. A child state can override an inherited transition. For example, the following code adds a transition that effectively causes the Quit button to - be ignored when the state machine is in state \c s12. + be ignored when the state machine is in state, \c s12. \snippet qml/statemachine/statemachine-button-nested-ignore-quit.qml 0 - A transition can have any state as its target, i.e. the target state does - not have to be on the same level in the state hierarchy as the source state. + A transition can have any state as its target irrespective of where the + target state is in the state hierarchy. - \section1 Using History States to Save and Restore the Current State + \section1 Using History States Imagine that we wanted to add an "interrupt" mechanism to the example discussed in the previous section; the user should be able to click a button to have the state machine perform some non-related task, after which the state machine should resume whatever it was doing before (i.e. return to the - old state, which is one of \c s11, \c s12 and \c s13 in this case). + old state, which is one of the three states in this case). Such behavior can easily be modeled using \e{history states}. A history state (HistoryState object) is a pseudo-state that represents the child - state that the parent state was in the last time the parent state was - exited. + state that the parent state was in before it exited last. A history state is created as a child of the state for which we wish to record the current child state; when the state machine detects the presence of such a state at runtime, it automatically records the current (real) - child state when the parent state is exited. A transition to the history + child state when the parent state exits. A transition to the history state is in fact a transition to the child state that the state machine had previously saved; the state machine automatically "forwards" the transition to the real child state. @@ -177,9 +159,6 @@ has been added. \image statemachine-button-history.png - \omit - \caption This is a caption - \endomit The following code shows how it can be implemented; in this example we simply display a message box when \c s3 is entered, then immediately return @@ -187,32 +166,27 @@ \snippet qml/statemachine/statemachine-button-history.qml 0 - \section1 Using Parallel States to Avoid a Combinatorial Explosion of States + \section1 Using Parallel States Assume that you wanted to model a set of mutually exclusive properties of a car in a single state machine. Let's say the properties we are interested in are Clean vs Dirty, and Moving vs Not moving. It would take four mutually - exclusive states and eight transitions to be able to represent and freely - move between all possible combinations. + exclusive states and eight transitions to represent the states and freely + move between all possible combinations as shown in the following state chart. \image statemachine-nonparallel.png - \omit - \caption This is a caption - \endomit If we added a third property (say, Red vs Blue), the total number of states would double, to eight; and if we added a fourth property (say, Enclosed vs Convertible), the total number of states would double again, to 16. - Using parallel states, the total number of states and transitions grows - linearly as we add more properties, instead of exponentially. Furthermore, - states can be added to or removed from the parallel state without affecting - any of their sibling states. + This exponential increase can be reduced using parallel states, which enables + linear growth in the number of states and transitions as we add more + properties. Furthermore, states can be added to or removed from the parallel + state without affecting any of their sibling states. The following state + chart shows the different paralles states for the car example. \image statemachine-parallel.png - \omit - \caption This is a caption - \endomit To create a parallel state group, set childMode to QState.ParallelStates. @@ -231,19 +205,20 @@ When a parallel state group is entered, all its child states will be simultaneously entered. Transitions within the individual child states - operate normally. However, any of the child states may take a transition which exits the parent - state. When this happens, the parent state and all of its child states are exited. + operate normally. However, any of the child states may take a transition + which exits the parent state. When this happens, the parent state and all of + its child states are exited. - The parallelism in the State Machine framework follows an interleaved semantics. All parallel - operations will be executed in a single, atomic step of the event processing, so no event can - interrupt the parallel operations. However, events will still be processed sequentially, since - the machine itself is single threaded. As an example: Consider the situation where there are two - transitions that exit the same parallel state group, and their conditions become true - simultaneously. In this case, the event that is processed last of the two will not have any - effect, since the first event will already have caused the machine to exit from the parallel - state. + The parallelism in the State Machine framework follows an interleaved + semantics. All parallel operations will be executed in a single, atomic step + of the event processing, so no event can interrupt the parallel operations. + However, events will still be processed sequentially, as the machine itself + is single threaded. For example, consider the situation where there are two + transitions that exit the same parallel state group, and their conditions + become true simultaneously. In this case, the event that is processed last + of the two will not have any effect. - \section1 Detecting that a Composite State has Finished + \section1 Exiting a Composite State A child state can be final (a FinalState object); when a final child state is entered, the parent state emits the StateBase::finished signal. The @@ -251,9 +226,6 @@ before entering a final state: \image statemachine-finished.png - \omit - \caption This is a caption - \endomit When \c s1 's final state is entered, \c s1 will automatically emit \l{StateBase::finished}{finished}. We use a signal transition to cause this event to @@ -270,11 +242,11 @@ \endqml Using final states in composite states is useful when you want to hide the - internal details of a composite state; i.e. the only thing the outside world - should be able to do is enter the state, and get a notification when the - state has completed its work. This is a very powerful abstraction and - encapsulation mechanism when building complex (deeply nested) state - machines. (In the above example, you could of course create a transition + internal details of a composite state. The outside world should be able to + enter the state and get a notification when the state has completed its work, + without the need to know the internal details. This is a very powerful + abstraction and encapsulation mechanism when building complex (deeply nested) + state machines. (In the above example, you could of course create a transition directly from \c s1 's \c done state rather than relying on \c s1 's finished() signal, but with the consequence that implementation details of \c s1 are exposed and depended on). @@ -286,9 +258,9 @@ A transition need not have a target state. A transition without a target can be triggered the same way as any other transition; the difference is that - when a targetless transition is triggered, it doesn't cause any state - changes. This allows you to react to a signal or event when your machine is - in a certain state, without having to leave that state. Example: + it doesn't cause any state changes. This allows you to react to a signal or + event when your machine is in a certain state, without having to leave that + state. For example: \qml Button { @@ -311,7 +283,14 @@ The "button pressed" message will be displayed each time the button is clicked, but the state machine will remain in its current state (s1). If the target state - were explicitly set to s1, however, s1 would be exited and re-entered each - time (e.g. the QAbstractState::entered and QAbstractState::exited + were explicitly set to s1, s1 would be exited and re-entered each + time (the QAbstractState::entered and QAbstractState::exited signals would be emitted). + + \section1 Related Information + + \list + \li \l{Declarative State Machine QML Types} + \li \l{The State Machine Framework} + \endlist */ diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf index d54e5feecb..41fe42777b 100644 --- a/src/quick/doc/qtquick.qdocconf +++ b/src/quick/doc/qtquick.qdocconf @@ -62,7 +62,8 @@ headerdirs += ../../plugins sourcedirs += ../../plugins #exclude certain directories -excludedirs += ../../imports/models +excludedirs += ../../imports/models \ + ../../imports/statemachine examples.fileextensions += "*.qm" -- cgit v1.2.3 From 18daa3e282cf8c32ce93e26e81504f38161600f3 Mon Sep 17 00:00:00 2001 From: Oleg Shparber Date: Sat, 4 Oct 2014 14:28:22 -0700 Subject: Make QQuickKeyNavigationAttached respect user set values Before this change, when user tried to set KeyNavigation property to the value which was previously automatically assigned, user set flag wasn't raised. Such behavior led to situations, when explicitly set values later were not respected by automatic mutual changes. Change-Id: Id5ba5061c03a61f4d7835a638dc746b1485b9a56 Reviewed-by: Alan Alpert --- src/quick/items/qquickitem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index b8362c9dac..ebe136e556 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -452,7 +452,7 @@ QQuickItem *QQuickKeyNavigationAttached::left() const void QQuickKeyNavigationAttached::setLeft(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->left == i) + if (d->leftSet && d->left == i) return; d->left = i; d->leftSet = true; @@ -474,7 +474,7 @@ QQuickItem *QQuickKeyNavigationAttached::right() const void QQuickKeyNavigationAttached::setRight(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->right == i) + if (d->rightSet && d->right == i) return; d->right = i; d->rightSet = true; @@ -496,7 +496,7 @@ QQuickItem *QQuickKeyNavigationAttached::up() const void QQuickKeyNavigationAttached::setUp(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->up == i) + if (d->upSet && d->up == i) return; d->up = i; d->upSet = true; @@ -518,7 +518,7 @@ QQuickItem *QQuickKeyNavigationAttached::down() const void QQuickKeyNavigationAttached::setDown(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->down == i) + if (d->downSet && d->down == i) return; d->down = i; d->downSet = true; @@ -540,7 +540,7 @@ QQuickItem *QQuickKeyNavigationAttached::tab() const void QQuickKeyNavigationAttached::setTab(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->tab == i) + if (d->tabSet && d->tab == i) return; d->tab = i; d->tabSet = true; @@ -562,7 +562,7 @@ QQuickItem *QQuickKeyNavigationAttached::backtab() const void QQuickKeyNavigationAttached::setBacktab(QQuickItem *i) { Q_D(QQuickKeyNavigationAttached); - if (d->backtab == i) + if (d->backtabSet && d->backtab == i) return; d->backtab = i; d->backtabSet = true; -- cgit v1.2.3 From e157af88554a694ffa550ead5187649a29b5dda8 Mon Sep 17 00:00:00 2001 From: Oleg Shparber Date: Thu, 2 Oct 2014 23:10:53 -0700 Subject: Export QQuickKeyNavigationAttached as a part of the private API This change fixes linking problems when QQuickKeyNavigationAttached is used through private headers. Change-Id: I176a9551718d9ba25c160a3b1caa8872c88d39f3 Reviewed-by: Alan Alpert --- src/quick/items/qquickitem_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 3e1c880db1..4b54dc44af 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -634,7 +634,7 @@ public: bool backtabSet : 1; }; -class QQuickKeyNavigationAttached : public QObject, public QQuickItemKeyFilter +class Q_QUICK_PRIVATE_EXPORT QQuickKeyNavigationAttached : public QObject, public QQuickItemKeyFilter { Q_OBJECT Q_DECLARE_PRIVATE(QQuickKeyNavigationAttached) -- cgit v1.2.3 From 8c3d661163fc7517569f1a70ab70c2b23de25406 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Tue, 9 Sep 2014 15:06:36 +0300 Subject: Return the content position rounded on the right side QQuickFlickable::contentX/Y() returns the negative of the value stored in the QQuickTimeLineValue used by QQuickFlickable. So we must be careful when using things like qRound, and call it with the negative of the value ine the QQuickTimeLineValue, else code like this would fail: QQuickFlickable *f = ... f->setPixelAligned(true) f->setContentY(-10.5) assert(f->contentY() == qRound(-10.5)) // fail The assert expression indeed turns into -11 == -10, which is false but which is not what the user would expect. Change-Id: Ib92ee2fa613b751462237349d9e4e2f2b4652f82 Reviewed-by: Martin Jones --- src/quick/items/qquickflickable.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index c6b7e5a35a..9f1de39186 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -334,7 +334,7 @@ bool QQuickFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExt qreal dist = v2 / (accel * 2.0); if (v > 0) dist = -dist; - qreal target = qRound(data.move.value() - dist); + qreal target = -qRound(-(data.move.value() - dist)); dist = -target + data.move.value(); accel = v2 / (2.0f * qAbs(dist)); @@ -436,18 +436,18 @@ void QQuickFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExt } else if (data.move.value() < maxExtent) { resetTimeline(data); adjustContentPos(data, maxExtent); - } else if (qRound(data.move.value()) != data.move.value()) { + } else if (-qRound(-data.move.value()) != data.move.value()) { // We could animate, but since it is less than 0.5 pixel it's probably not worthwhile. resetTimeline(data); qreal val = data.move.value(); - if (qAbs(qRound(val) - val) < 0.25) // round small differences - val = qRound(val); + if (qAbs(-qRound(-val) - val) < 0.25) // round small differences + val = -qRound(-val); else if (data.smoothVelocity.value() > 0) // continue direction of motion for larger - val = qFloor(val); + val = -qFloor(-val); else if (data.smoothVelocity.value() < 0) - val = qCeil(val); + val = -qCeil(-val); else // otherwise round - val = qRound(val); + val = -qRound(-val); timeline.set(data.move, val); } data.inOvershoot = false; @@ -1374,12 +1374,12 @@ void QQuickFlickablePrivate::replayDelayedPress() //XXX pixelAligned ignores the global position of the Flickable, i.e. assumes Flickable itself is pixel aligned. void QQuickFlickablePrivate::setViewportX(qreal x) { - contentItem->setX(pixelAligned ? qRound(x) : x); + contentItem->setX(pixelAligned ? -qRound(-x) : x); } void QQuickFlickablePrivate::setViewportY(qreal y) { - contentItem->setY(pixelAligned ? qRound(y) : y); + contentItem->setY(pixelAligned ? -qRound(-y) : y); } void QQuickFlickable::timerEvent(QTimerEvent *event) -- cgit v1.2.3 From 9e71faae038de4c41c206f1321da1b37ab6ca8b1 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 4 Oct 2014 17:18:15 +0200 Subject: Fix QQmlExpression/QQmlScriptString/QQmlBinding crashes In the QQmlScriptString we store the binding id and it is an index into the runtimeFunctions array of the compilation unit. However we don't store the compilation unit and instead in QQmlBinding and QQmlExpression try to retrieve it from the cache via the context url (we have the context after all). That turns out to be not a reliable way, as sometimes the URL might slightly differ from the originally compiled cache (qrc:/// turning to qrc:/ maybe). Consequently the type is (unnecessarily) compiled again and unfortunately not _linked_, therefore the runtime functions array is empty. Another option is that when the component was created from a QByteArray, then no entry exists in the cache in the first place. This patch addresses the problem by storing a reference to the compilation unit in the QQmlContextData. That we can safely retrieve and it'll make sure the compilation unit also stays alive. In the process of that the manual reference counting was switched over to QQmlRefCount and QQmlRefPointer for QV4::CompilationUnit. Task-number: QTBUG-41193 Change-Id: I9111f9a3b65618e453954abcd789c039e65a94f7 Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 3 +-- src/qml/compiler/qqmlirbuilder_p.h | 2 +- src/qml/compiler/qqmltypecompiler.cpp | 2 -- src/qml/compiler/qv4compileddata_p.h | 13 ++++------- src/qml/compiler/qv4isel_moth.cpp | 6 +++-- src/qml/compiler/qv4isel_moth_p.h | 2 +- src/qml/compiler/qv4isel_p.cpp | 4 ++-- src/qml/compiler/qv4isel_p.h | 4 ++-- src/qml/jit/qv4isel_masm.cpp | 6 +++-- src/qml/jit/qv4isel_masm_p.h | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 6 ++--- src/qml/jsruntime/qv4profiling_p.h | 10 ++++----- src/qml/jsruntime/qv4script.cpp | 13 ++++------- src/qml/jsruntime/qv4script_p.h | 2 +- src/qml/qml/ftw/qqmlrefcount_p.h | 3 ++- src/qml/qml/qqmlbinding.cpp | 15 ++++--------- src/qml/qml/qqmlcompileddata.cpp | 5 +---- src/qml/qml/qqmlcompiler_p.h | 2 +- src/qml/qml/qqmlcontext_p.h | 3 +++ src/qml/qml/qqmlexpression.cpp | 19 +++++----------- src/qml/qml/qqmlobjectcreator.cpp | 3 ++- src/qml/qml/qqmltypeloader.cpp | 15 ++----------- src/qml/qml/qqmltypeloader_p.h | 2 +- .../data/expressionFromDataComponent.qml | 6 +++++ .../auto/qml/qqmlexpression/tst_qqmlexpression.cpp | 26 ++++++++++++++++++++++ 25 files changed, 87 insertions(+), 87 deletions(-) create mode 100644 tests/auto/qml/qqmlexpression/data/expressionFromDataComponent.qml diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index a96fafac9b..b64e637739 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -538,7 +538,6 @@ Document::Document(bool debugMode) , program(0) , jsGenerator(&jsModule) , unitFlags(0) - , javaScriptCompilationUnit(0) { } @@ -1502,7 +1501,7 @@ bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement) QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) { - QV4::CompiledData::CompilationUnit *compilationUnit = output.javaScriptCompilationUnit; + QQmlRefPointer compilationUnit = output.javaScriptCompilationUnit; QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output); const uint unitSize = jsUnit->unitSize; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index ddd9a22bc2..cc22023f8e 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -317,7 +317,7 @@ struct Q_QML_PRIVATE_EXPORT Document QV4::Compiler::JSUnitGenerator jsGenerator; quint32 unitFlags; - QV4::CompiledData::CompilationUnit *javaScriptCompilationUnit; + QQmlRefPointer javaScriptCompilationUnit; QHash extraSignalParameters; QV4::CompiledData::TypeReferenceMap typeReferences; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 13367efc3d..6a97386767 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -232,8 +232,6 @@ bool QQmlTypeCompiler::compile() document->javaScriptCompilationUnit->data = qmlUnit; compiledData->compilationUnit = document->javaScriptCompilationUnit; - if (compiledData->compilationUnit) - compiledData->compilationUnit->ref(); // Add to type registry of composites if (compiledData->isCompositeType()) diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index e5b7681a7c..6791970461 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -39,6 +39,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -559,18 +560,16 @@ struct TypeReferenceMap : QHash // CompilationUnit * (for functions that need to clean up) // CompiledData::Function *compiledFunction -struct Q_QML_PRIVATE_EXPORT CompilationUnit +struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount { #ifdef V4_BOOTSTRAP CompilationUnit() - : refCount(0) - , data(0) + : data(0) {} virtual ~CompilationUnit() {} #else CompilationUnit() - : refCount(0) - , data(0) + : data(0) , engine(0) , runtimeStrings(0) , runtimeLookups(0) @@ -580,10 +579,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit virtual ~CompilationUnit(); #endif - void ref() { ++refCount; } - void deref() { if (!--refCount) delete this; } - - int refCount; Unit *data; // Called only when building QML, when we build the header for JS first and append QML data diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 40a44844ce..39977375c4 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -446,13 +446,15 @@ void InstructionSelection::run(int functionIndex) delete[] codeStart; } -QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep() +QQmlRefPointer InstructionSelection::backendCompileStep() { compilationUnit->codeRefs.resize(irModule->functions.size()); int i = 0; foreach (IR::Function *irFunction, irModule->functions) compilationUnit->codeRefs[i++] = codeRefs[irFunction]; - return compilationUnit.take(); + QQmlRefPointer result; + result.take(compilationUnit.take()); + return result; } void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 938b60ca05..89f575c633 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -66,7 +66,7 @@ public: virtual void run(int functionIndex); protected: - virtual QV4::CompiledData::CompilationUnit *backendCompileStep(); + virtual QQmlRefPointer backendCompileStep(); virtual void visitJump(IR::Jump *); virtual void visitCJump(IR::CJump *); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index f160954f84..e419084238 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -72,12 +72,12 @@ EvalInstructionSelection::~EvalInstructionSelection() EvalISelFactory::~EvalISelFactory() {} -QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool generateUnitData) +QQmlRefPointer EvalInstructionSelection::compile(bool generateUnitData) { for (int i = 0; i < irModule->functions.size(); ++i) run(i); - QV4::CompiledData::CompilationUnit *unit = backendCompileStep(); + QQmlRefPointer unit = backendCompileStep(); if (generateUnitData) unit->data = jsGenerator->generateUnit(); return unit; diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 984e8ab4bf..504d255eaf 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -57,7 +57,7 @@ public: EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator); virtual ~EvalInstructionSelection() = 0; - QV4::CompiledData::CompilationUnit *compile(bool generateUnitData = true); + QQmlRefPointer compile(bool generateUnitData = true); void setUseFastLookups(bool b) { useFastLookups = b; } void setUseTypeInference(bool onoff) { useTypeInference = onoff; } @@ -74,7 +74,7 @@ public: protected: virtual void run(int functionIndex) = 0; - virtual QV4::CompiledData::CompilationUnit *backendCompileStep() = 0; + virtual QQmlRefPointer backendCompileStep() = 0; bool useFastLookups; bool useTypeInference; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 5cf00f6d60..9ff33feff2 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -293,9 +293,11 @@ const void *InstructionSelection::addConstantTable(QVector *values) return finalValues.constData(); } -QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep() +QQmlRefPointer InstructionSelection::backendCompileStep() { - return compilationUnit.take(); + QQmlRefPointer result; + result.take(compilationUnit.take()); + return result; } void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result) diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 2f64bf1157..8ad97c640b 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -66,7 +66,7 @@ public: const void *addConstantTable(QVector *values); protected: - virtual QV4::CompiledData::CompilationUnit *backendCompileStep(); + virtual QQmlRefPointer backendCompileStep(); virtual void callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result); virtual void callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index cddc45aaf5..84b0eb17af 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -108,7 +108,7 @@ FunctionObject::Data::Data(InternalClass *ic) FunctionObject::Data::~Data() { if (function) - function->compilationUnit->deref(); + function->compilationUnit->release(); } void FunctionObject::init(String *n, bool createProto) @@ -226,7 +226,7 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData) QV4::Compiler::JSUnitGenerator jsGenerator(&module); QScopedPointer isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator)); - QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); + QQmlRefPointer compilationUnit = isel->compile(); QV4::Function *vmf = compilationUnit->linkToEngine(v4); return FunctionObject::createScriptFunction(v4->rootContext, vmf)->asReturnedValue(); @@ -416,7 +416,7 @@ SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bo setVTable(staticVTable()); this->function = function; - function->compilationUnit->ref(); + function->compilationUnit->addref(); Q_ASSERT(function); Q_ASSERT(function->code); diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h index 8224f8a851..7c66ee0049 100644 --- a/src/qml/jsruntime/qv4profiling_p.h +++ b/src/qml/jsruntime/qv4profiling_p.h @@ -80,23 +80,23 @@ public: FunctionCall(Function *function, qint64 start, qint64 end) : m_function(function), m_start(start), m_end(end) - { m_function->compilationUnit->ref(); } + { m_function->compilationUnit->addref(); } FunctionCall(const FunctionCall &other) : m_function(other.m_function), m_start(other.m_start), m_end(other.m_end) - { m_function->compilationUnit->ref(); } + { m_function->compilationUnit->addref(); } ~FunctionCall() - { m_function->compilationUnit->deref(); } + { m_function->compilationUnit->release(); } FunctionCall &operator=(const FunctionCall &other) { if (&other != this) { if (m_function) - m_function->compilationUnit->deref(); + m_function->compilationUnit->release(); m_function = other.m_function; m_start = other.m_start; m_end = other.m_end; - m_function->compilationUnit->ref(); + m_function->compilationUnit->addref(); } return *this; } diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 8e91c0e6a5..fa4b4b1894 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -62,7 +62,7 @@ QmlBindingWrapper::Data::Data(ExecutionContext *scope, Function *f, Object *qml) setVTable(staticVTable()); function = f; if (function) - function->compilationUnit->ref(); + function->compilationUnit->addref(); needsActivation = function ? function->needsActivation() : false; Scope s(scope); @@ -163,14 +163,9 @@ struct CompilationUnitHolder : public Object : Object::Data(engine) , unit(unit) { - unit->ref(); setVTable(staticVTable()); } - ~Data() - { - unit->deref(); - } - QV4::CompiledData::CompilationUnit *unit; + QQmlRefPointer unit; }; V4_OBJECT(Object) @@ -264,7 +259,7 @@ void Script::parse() QScopedPointer isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator)); if (inheritContext) isel->setUseFastLookups(false); - QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); + QQmlRefPointer compilationUnit = isel->compile(); vmFunction = compilationUnit->linkToEngine(v4); ScopedObject holder(valueScope, v4->memoryManager->alloc(v4, compilationUnit)); compilationUnitHolder = holder.asReturnedValue(); @@ -313,7 +308,7 @@ Function *Script::function() return vmFunction; } -QV4::CompiledData::CompilationUnit *Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors) +QQmlRefPointer Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors) { using namespace QQmlJS; using namespace QQmlJS::AST; diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h index 28ac5f3e01..ed93ce49ae 100644 --- a/src/qml/jsruntime/qv4script_p.h +++ b/src/qml/jsruntime/qv4script_p.h @@ -122,7 +122,7 @@ struct Q_QML_EXPORT Script { Function *function(); - static QV4::CompiledData::CompilationUnit *precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors = 0); + static QQmlRefPointer precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList *reportedErrors = 0); static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject); }; diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h index 27f609bf39..3f1d252862 100644 --- a/src/qml/qml/ftw/qqmlrefcount_p.h +++ b/src/qml/qml/ftw/qqmlrefcount_p.h @@ -47,11 +47,12 @@ #include #include +#include QT_BEGIN_NAMESPACE -class QQmlRefCount +class Q_QML_PRIVATE_EXPORT QQmlRefCount { public: inline QQmlRefCount(); diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 8b6bc81935..6033395629 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -93,17 +93,10 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context); QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine()); - if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { - QQmlTypeData *typeData = engine->typeLoader.getType(ctxtdata->url); - Q_ASSERT(typeData); - - if (QQmlCompiledData *cdata = typeData->compiledData()) { - url = cdata->fileName(); - if (scriptPrivate->bindingId != QQmlBinding::Invalid) - runtimeFunction = cdata->compilationUnit->runtimeFunctions.at(scriptPrivate->bindingId); - } - - typeData->release(); + if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) { + url = ctxtdata->url.toString(); + if (scriptPrivate->bindingId != QQmlBinding::Invalid) + runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId); } setNotifyOnValueChanged(true); diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp index eca8070b3f..22838786b6 100644 --- a/src/qml/qml/qqmlcompileddata.cpp +++ b/src/qml/qml/qqmlcompileddata.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine) : engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false), - rootPropertyCache(0), compilationUnit(0), totalBindingsCount(0), totalParserStatusCount(0) + rootPropertyCache(0), totalBindingsCount(0), totalParserStatusCount(0) { Q_ASSERT(engine); } @@ -92,9 +92,6 @@ QQmlCompiledData::~QQmlCompiledData() if (rootPropertyCache) rootPropertyCache->release(); - - if (compilationUnit) - compilationUnit->deref(); } void QQmlCompiledData::clear() diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h index 11646fc6b8..5e76533739 100644 --- a/src/qml/qml/qqmlcompiler_p.h +++ b/src/qml/qml/qqmlcompiler_p.h @@ -123,7 +123,7 @@ public: QVector propertyCaches; QList scripts; - QV4::CompiledData::CompilationUnit *compilationUnit; + QQmlRefPointer compilationUnit; // index in first hash is component index, hash inside maps from object index in that scope to integer id QHash > objectIndexToIdPerComponent; QHash objectIndexToIdForRoot; diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h index d3f283357a..233ea4d34a 100644 --- a/src/qml/qml/qqmlcontext_p.h +++ b/src/qml/qml/qqmlcontext_p.h @@ -141,6 +141,9 @@ public: // VME data that is constructing this context if any void *activeVMEData; + // Compilation unit for contexts that belong to a compiled type. + QQmlRefPointer typeCompilationUnit; + // Property name cache QV4::IdentifierHash propertyNames; diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 22e74135b5..947b55f15d 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -148,20 +148,13 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt if (scriptPrivate->context) { QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context); QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine()); - if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { - QQmlTypeData *typeData = engine->typeLoader.getType(ctxtdata->url); - Q_ASSERT(typeData); + if (engine && ctxtdata && !ctxtdata->url.isEmpty() && ctxtdata->typeCompilationUnit) { + d->url = ctxtdata->url.toString(); + d->line = scriptPrivate->lineNumber; + d->column = scriptPrivate->columnNumber; - if (QQmlCompiledData *cdata = typeData->compiledData()) { - d->url = cdata->fileName(); - d->line = scriptPrivate->lineNumber; - d->column = scriptPrivate->columnNumber; - - if (scriptPrivate->bindingId != QQmlBinding::Invalid) - runtimeFunction = cdata->compilationUnit->runtimeFunctions.at(scriptPrivate->bindingId); - } - - typeData->release(); + if (scriptPrivate->bindingId != QQmlBinding::Invalid) + runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId); } } diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index a827e96ab1..42cac66fbd 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -180,6 +180,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI context->urlString = compiledData->fileName(); context->imports = compiledData->importCache; context->imports->addref(); + context->typeCompilationUnit = compiledData->compilationUnit; context->setParent(parentContext); if (!sharedState->rootContext) { @@ -753,7 +754,7 @@ bool QQmlObjectCreator::setPropertyBinding(QQmlPropertyData *property, const QV4 // ### resolve this at compile time if (property && property->propType == qMetaTypeId()) { QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject); - ss.d.data()->bindingId = binding->value.compiledScriptIndex; + ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : QQmlBinding::Invalid; ss.d.data()->lineNumber = binding->location.line; ss.d.data()->columnNumber = binding->location.column; ss.d.data()->isStringLiteral = binding->type == QV4::CompiledData::Binding::Type_String; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 0e2d4d027a..1b222fe1a3 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2541,7 +2541,6 @@ void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData: QQmlScriptData::QQmlScriptData() : importCache(0) , m_loaded(false) - , m_precompiledScript(0) , m_program(0) { } @@ -2549,10 +2548,6 @@ QQmlScriptData::QQmlScriptData() QQmlScriptData::~QQmlScriptData() { delete m_program; - if (m_precompiledScript) { - m_precompiledScript->deref(); - m_precompiledScript = 0; - } } void QQmlScriptData::initialize(QQmlEngine *engine) @@ -2713,13 +2708,10 @@ void QQmlScriptBlob::dataReceived(const Data &data) } QList errors; - QV4::CompiledData::CompilationUnit *unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors); - if (unit) - unit->ref(); + QQmlRefPointer unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors); + // No need to addref on unit, it's initial refcount is 1 source.clear(); if (!errors.isEmpty()) { - if (unit) - unit->deref(); setError(errors); return; } @@ -2732,7 +2724,6 @@ void QQmlScriptBlob::dataReceived(const Data &data) unit->data = unitData; initializeFromCompilationUnit(unit); - unit->deref(); } void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) @@ -2805,8 +2796,6 @@ void QQmlScriptBlob::initializeFromCompilationUnit(QV4::CompiledData::Compilatio m_scriptData->url = finalUrl(); m_scriptData->urlString = finalUrlString(); m_scriptData->m_precompiledScript = unit; - if (m_scriptData->m_precompiledScript) - m_scriptData->m_precompiledScript->ref(); m_importCache.setBaseUrl(finalUrl(), finalUrlString()); diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 9f98e4fd40..3b5aa1ec7a 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -513,7 +513,7 @@ private: void initialize(QQmlEngine *); bool m_loaded; - QV4::CompiledData::CompilationUnit *m_precompiledScript; + QQmlRefPointer m_precompiledScript; QV4::Script *m_program; QV4::PersistentValue m_value; }; diff --git a/tests/auto/qml/qqmlexpression/data/expressionFromDataComponent.qml b/tests/auto/qml/qqmlexpression/data/expressionFromDataComponent.qml new file mode 100644 index 0000000000..1aefdf0c42 --- /dev/null +++ b/tests/auto/qml/qqmlexpression/data/expressionFromDataComponent.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 +import Test 1.0 +TestObject { + scriptString: { return "success"; } +} + diff --git a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp index 12cb2dce83..f53ef82891 100644 --- a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp +++ b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp @@ -47,6 +47,7 @@ public: private slots: void scriptString(); void syntaxError(); + void expressionFromDataComponent(); }; class TestObject : public QObject @@ -108,6 +109,31 @@ void tst_qqmlexpression::syntaxError() QCOMPARE(v, QVariant()); } +void tst_qqmlexpression::expressionFromDataComponent() +{ + qmlRegisterType("Test", 1, 0, "TestObject"); + + QQmlEngine engine; + QQmlComponent c(&engine); + + QUrl url = testFileUrl("expressionFromDataComponent.qml"); + + { + QFile f(url.toLocalFile()); + QVERIFY(f.open(QIODevice::ReadOnly)); + c.setData(f.readAll(), url); + } + + QScopedPointer object; + object.reset(qobject_cast(c.create())); + Q_ASSERT(!object.isNull()); + + QQmlExpression expression(object->scriptString()); + QVariant result = expression.evaluate(); + QVERIFY(result.type() == QVariant::String); + QCOMPARE(result.toString(), QStringLiteral("success")); +} + QTEST_MAIN(tst_qqmlexpression) #include "tst_qqmlexpression.moc" -- cgit v1.2.3 From 2b5e9534450404fba3bdf89f304d0504ae8587dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Tue, 30 Sep 2014 13:23:56 +0100 Subject: PathView: Fix QML engine thinking currentItem is null when it's not QML didn't re-evaluate any bindings using currentItem because a notification was missing. Change-Id: Icdaa3022e0b01644a060e577d87f011b4ea9fabb Reviewed-by: Alan Alpert --- src/quick/items/qquickpathview.cpp | 5 +++++ tests/auto/quick/qquickpathview/data/pathview4.qml | 20 ++++++++++++++++++++ .../quick/qquickpathview/tst_qquickpathview.cpp | 22 ++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/auto/quick/qquickpathview/data/pathview4.qml diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 00a5400eb2..825845eca9 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1987,12 +1987,14 @@ void QQuickPathView::refill() } } + bool currentChanged = false; if (!currentVisible) { d->currentItemOffset = 1.0; if (d->currentItem) { d->updateItem(d->currentItem, 1.0); } else if (!waiting && d->currentIndex >= 0 && d->currentIndex < d->modelCount) { if ((d->currentItem = d->getItem(d->currentIndex, d->currentIndex))) { + currentChanged = true; d->updateItem(d->currentItem, 1.0); if (QQuickPathViewAttached *att = d->attached(d->currentItem)) att->setIsCurrentItem(true); @@ -2000,6 +2002,7 @@ void QQuickPathView::refill() } } else if (!waiting && !d->currentItem) { if ((d->currentItem = d->getItem(d->currentIndex, d->currentIndex))) { + currentChanged = true; d->currentItem->setFocus(true); if (QQuickPathViewAttached *att = d->attached(d->currentItem)) att->setIsCurrentItem(true); @@ -2019,6 +2022,8 @@ void QQuickPathView::refill() d->releaseItem(d->itemCache.takeLast()); d->inRefill = false; + if (currentChanged) + emit currentItemChanged(); } void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) diff --git a/tests/auto/quick/qquickpathview/data/pathview4.qml b/tests/auto/quick/qquickpathview/data/pathview4.qml new file mode 100644 index 0000000000..c42986d5a3 --- /dev/null +++ b/tests/auto/quick/qquickpathview/data/pathview4.qml @@ -0,0 +1,20 @@ +import QtQuick 2.0 + +Item { + id: root + property bool currentItemIsNull: view.currentItem === null + + PathView { + id: view + objectName: "view" + model: testModel + delegate: Item {} + + path: Path { + PathLine { + y: 0 + x: 0 + } + } + } +} diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index fd6dc4da60..0e9994899f 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -90,6 +90,7 @@ private slots: void pathview2(); void pathview3(); void initialCurrentIndex(); + void initialCurrentItem(); void insertModel_data(); void insertModel(); void removeModel_data(); @@ -237,6 +238,27 @@ void tst_QQuickPathView::items() QCOMPARE(pathview->highlightItem()->position() + offset, start); } +void tst_QQuickPathView::initialCurrentItem() +{ + QScopedPointer window(createView()); + + QaimModel model; + model.addItem("Jules", "12345"); + model.addItem("Vicent", "2345"); + model.addItem("Marvin", "54321"); + + QQmlContext *ctxt = window->rootContext(); + ctxt->setContextProperty("testModel", &model); + + window->setSource(testFileUrl("pathview4.qml")); + qApp->processEvents(); + + QQuickPathView *pathview = findItem(window->rootObject(), "view"); + QVERIFY(pathview != 0); + QVERIFY(pathview->currentIndex() != -1); + QVERIFY(!window->rootObject()->property("currentItemIsNull").toBool()); +} + void tst_QQuickPathView::pathview2() { QQmlEngine engine; -- cgit v1.2.3 From 624844f3db601b48205d7f545732870d45d78300 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 8 Oct 2014 18:14:43 +0200 Subject: Stabilize and fix comparisons in animator tests. compare() will compare properties of objects and neither Qt.rgba nor image.pixel created objects has enumeratable properties so compare is pretty much useless. Use verify + == which will rely on toString() which is ok. A few of the tests relied on execution order of signals emitted on animation.running being changed and would occasionally fail. Change-Id: I531c7f21b58a922a6be9ca2b6de120a68209a6d6 Reviewed-by: Michael Brasser --- tests/auto/qmltest/animators/tst_behavior.qml | 7 ++- tests/auto/qmltest/animators/tst_mixedparallel.qml | 4 +- .../auto/qmltest/animators/tst_mixedsequential.qml | 4 +- tests/auto/qmltest/animators/tst_opacity.qml | 3 +- tests/auto/qmltest/animators/tst_parallel.qml | 4 +- tests/auto/qmltest/animators/tst_rotation.qml | 5 +- tests/auto/qmltest/animators/tst_scale.qml | 5 +- .../auto/qmltest/animators/tst_transformorigin.qml | 72 +++++++++++----------- tests/auto/qmltest/animators/tst_transition.qml | 6 +- tests/auto/qmltest/animators/tst_x.qml | 7 +-- tests/auto/qmltest/animators/tst_y.qml | 7 +-- 11 files changed, 60 insertions(+), 64 deletions(-) diff --git a/tests/auto/qmltest/animators/tst_behavior.qml b/tests/auto/qmltest/animators/tst_behavior.qml index 0b74a74d53..87b0efff17 100644 --- a/tests/auto/qmltest/animators/tst_behavior.qml +++ b/tests/auto/qmltest/animators/tst_behavior.qml @@ -47,8 +47,9 @@ Item { compare(box.scaleChangeCounter, 1); compare(box.scale, 2); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1)); - compare(image.pixel(199, 199), Qt.rgba(0, 0, 1, 1)); + + verify(image.pixel(0, 0) == Qt.rgba(1, 0, 0)); + verify(image.pixel(199, 199) == Qt.rgba(0, 0, 1)); } } @@ -58,7 +59,7 @@ Item { } Timer { - interval: 1000; + interval: 100; repeat: false running: true onTriggered: box.scale = 2 diff --git a/tests/auto/qmltest/animators/tst_mixedparallel.qml b/tests/auto/qmltest/animators/tst_mixedparallel.qml index da5fb9c7ea..2b6ebfc17a 100644 --- a/tests/auto/qmltest/animators/tst_mixedparallel.qml +++ b/tests/auto/qmltest/animators/tst_mixedparallel.qml @@ -48,8 +48,8 @@ Item { compare(box.scale, 2); compare(box.rotation, 180); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1)); - compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1)); + verify(image.pixel(0, 0) == Qt.rgba(0, 0, 1)); + verify(image.pixel(199, 199) == Qt.rgba(1, 0, 0)); } } diff --git a/tests/auto/qmltest/animators/tst_mixedsequential.qml b/tests/auto/qmltest/animators/tst_mixedsequential.qml index 02caa3cae0..6165cf5438 100644 --- a/tests/auto/qmltest/animators/tst_mixedsequential.qml +++ b/tests/auto/qmltest/animators/tst_mixedsequential.qml @@ -48,8 +48,8 @@ Item { compare(box.scale, 2); compare(box.rotation, 180); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1)); - compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1)); + verify(image.pixel(0, 0) == Qt.rgba(0, 0, 1)); + verify(image.pixel(199, 199) == Qt.rgba(1, 0, 0)); } } diff --git a/tests/auto/qmltest/animators/tst_opacity.qml b/tests/auto/qmltest/animators/tst_opacity.qml index e8c3edd46c..37603a9ced 100644 --- a/tests/auto/qmltest/animators/tst_opacity.qml +++ b/tests/auto/qmltest/animators/tst_opacity.qml @@ -42,10 +42,9 @@ Item { TestCase { id: testCase name: "animators-opacity" - when: !animation.running + when: box.opacity == 0.5 function test_endresult() { compare(box.opacityChangeCounter, 1); - compare(box.opacity, 0.5); var image = grabImage(root); compare(image.red(50, 50), 255); verify(image.green(50, 50) > 0); diff --git a/tests/auto/qmltest/animators/tst_parallel.qml b/tests/auto/qmltest/animators/tst_parallel.qml index e9efbda237..7702dd7dd8 100644 --- a/tests/auto/qmltest/animators/tst_parallel.qml +++ b/tests/auto/qmltest/animators/tst_parallel.qml @@ -49,8 +49,8 @@ Item { compare(box.scale, 2); compare(box.rotation, 180); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(0, 0, 1, 1)); - compare(image.pixel(199, 199), Qt.rgba(1, 0, 0, 1)); + verify(image.pixel(0, 0) == Qt.rgba(0, 0, 1)); + verify(image.pixel(199, 199) == Qt.rgba(1, 0, 0)); } } diff --git a/tests/auto/qmltest/animators/tst_rotation.qml b/tests/auto/qmltest/animators/tst_rotation.qml index 8c29df0623..9ff4278527 100644 --- a/tests/auto/qmltest/animators/tst_rotation.qml +++ b/tests/auto/qmltest/animators/tst_rotation.qml @@ -42,12 +42,11 @@ Item { TestCase { id: testCase name: "animators-rotation" - when: !animation.running + when: box.rotation == 180 function test_endresult() { compare(box.rotationChangeCounter, 1); - compare(box.rotation, 180); var image = grabImage(root); - compare(image.pixel(50, 50), Qt.rgba(0, 0, 1)); + verify(image.pixel(50, 50) == Qt.rgba(0, 0, 1)); } } diff --git a/tests/auto/qmltest/animators/tst_scale.qml b/tests/auto/qmltest/animators/tst_scale.qml index 83ab2e5746..10f3430c84 100644 --- a/tests/auto/qmltest/animators/tst_scale.qml +++ b/tests/auto/qmltest/animators/tst_scale.qml @@ -42,12 +42,11 @@ Item { TestCase { id: testCase name: "animators-scale" - when: !animation.running + when: box.scale == 2; function test_endresult() { compare(box.scaleChangeCounter, 1); - compare(box.scale, 2); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(1, 0, 0)); + verify(image.pixel(0, 0) == Qt.rgba(1, 0, 0)); } } diff --git a/tests/auto/qmltest/animators/tst_transformorigin.qml b/tests/auto/qmltest/animators/tst_transformorigin.qml index 5dfe070e80..bd3483dad5 100644 --- a/tests/auto/qmltest/animators/tst_transformorigin.qml +++ b/tests/auto/qmltest/animators/tst_transformorigin.qml @@ -61,60 +61,60 @@ Item { // topleft - compare(image.pixel(40, 40), white); - compare(image.pixel(60, 40), white); - compare(image.pixel(40, 60), white); - compare(image.pixel(60, 60), blue); + verify(image.pixel(40, 40) == white); + verify(image.pixel(60, 40) == white); + verify(image.pixel(40, 60) == white); + verify(image.pixel(60, 60) == blue); // top - compare(image.pixel(140, 40), white); - compare(image.pixel(160, 40), white); - compare(image.pixel(140, 60), blue); - compare(image.pixel(160, 60), blue); + verify(image.pixel(140, 40) == white); + verify(image.pixel(160, 40) == white); + verify(image.pixel(140, 60) == blue); + verify(image.pixel(160, 60) == blue); // topright - compare(image.pixel(240, 40), white); - compare(image.pixel(260, 40), white); - compare(image.pixel(240, 60), blue); - compare(image.pixel(260, 60), white); + verify(image.pixel(240, 40) == white); + verify(image.pixel(260, 40) == white); + verify(image.pixel(240, 60) == blue); + verify(image.pixel(260, 60) == white); // left - compare(image.pixel(40, 140), white); - compare(image.pixel(60, 140), blue); - compare(image.pixel(40, 160), white); - compare(image.pixel(60, 160), blue); + verify(image.pixel(40, 140) == white); + verify(image.pixel(60, 140) == blue); + verify(image.pixel(40, 160) == white); + verify(image.pixel(60, 160) == blue); // center - compare(image.pixel(140, 140), blue); - compare(image.pixel(160, 140), blue); - compare(image.pixel(140, 160), blue); - compare(image.pixel(160, 160), blue); + verify(image.pixel(140, 140) == blue); + verify(image.pixel(160, 140) == blue); + verify(image.pixel(140, 160) == blue); + verify(image.pixel(160, 160) == blue); // right - compare(image.pixel(240, 140), blue); - compare(image.pixel(260, 140), white); - compare(image.pixel(240, 160), blue); - compare(image.pixel(260, 160), white); + verify(image.pixel(240, 140) == blue); + verify(image.pixel(260, 140) == white); + verify(image.pixel(240, 160) == blue); + verify(image.pixel(260, 160) == white); // bottomleft - compare(image.pixel(40, 240), white); - compare(image.pixel(60, 240), blue); - compare(image.pixel(40, 260), white); - compare(image.pixel(60, 260), white); + verify(image.pixel(40, 240) == white); + verify(image.pixel(60, 240) == blue); + verify(image.pixel(40, 260) == white); + verify(image.pixel(60, 260) == white); // bottom - compare(image.pixel(140, 240), blue); - compare(image.pixel(160, 240), blue); - compare(image.pixel(140, 260), white); - compare(image.pixel(160, 260), white); + verify(image.pixel(140, 240) == blue); + verify(image.pixel(160, 240) == blue); + verify(image.pixel(140, 260) == white); + verify(image.pixel(160, 260) == white); // bottomright - compare(image.pixel(240, 240), blue); - compare(image.pixel(260, 240), white); - compare(image.pixel(240, 260), white); - compare(image.pixel(260, 260), white); + verify(image.pixel(240, 240) == blue); + verify(image.pixel(260, 240) == white); + verify(image.pixel(240, 260) == white); + verify(image.pixel(260, 260) == white); } } diff --git a/tests/auto/qmltest/animators/tst_transition.qml b/tests/auto/qmltest/animators/tst_transition.qml index 72dcd343a7..67230d2adf 100644 --- a/tests/auto/qmltest/animators/tst_transition.qml +++ b/tests/auto/qmltest/animators/tst_transition.qml @@ -47,8 +47,8 @@ Item { compare(box.scaleChangeCounter, 1); compare(box.scale, 2); var image = grabImage(root); - compare(image.pixel(0, 0), Qt.rgba(1, 0, 0)); - compare(image.pixel(199, 199), Qt.rgba(0, 0, 1)); + verify(image.pixel(0, 0) == Qt.rgba(1, 0, 0)); + verify(image.pixel(199, 199) == Qt.rgba(0, 0, 1)); } } @@ -75,7 +75,7 @@ Item { } Timer { - interval: 1000; + interval: 100; repeat: false running: true onTriggered: root.state = "two" diff --git a/tests/auto/qmltest/animators/tst_x.qml b/tests/auto/qmltest/animators/tst_x.qml index 8236a82797..35e410e8e2 100644 --- a/tests/auto/qmltest/animators/tst_x.qml +++ b/tests/auto/qmltest/animators/tst_x.qml @@ -42,13 +42,12 @@ Item { TestCase { id: testCase name: "animators-x" - when: !animation.running + when: box.x == 100 function test_endresult() { compare(box.xChangeCounter, 1); - compare(box.x, 100); var image = grabImage(root); - compare(image.pixel(100, 50), Qt.rgba(1, 0, 0)); - compare(image.pixel(99, 50), Qt.rgba(1, 1, 1)); // outside on the left + verify(image.pixel(100, 0) == Qt.rgba(1, 0, 0)); + verify(image.pixel(99, 0) == Qt.rgba(1, 1, 1)); // outside on the left } } diff --git a/tests/auto/qmltest/animators/tst_y.qml b/tests/auto/qmltest/animators/tst_y.qml index 37400ebd85..79fd50e8bf 100644 --- a/tests/auto/qmltest/animators/tst_y.qml +++ b/tests/auto/qmltest/animators/tst_y.qml @@ -42,13 +42,12 @@ Item { TestCase { id: testCase name: "animators-y" - when: !animation.running + when: box.y == 100 function test_endresult() { compare(box.yChangeCounter, 1); - compare(box.y, 100); var image = grabImage(root); - compare(image.pixel(50, 100), Qt.rgba(1, 0, 0)); - compare(image.pixel(50, 99), Qt.rgba(1, 1, 1)); // outside on the left + verify(image.pixel(0, 100) == Qt.rgba(1, 0, 0)); + verify(image.pixel(0, 99) == Qt.rgba(1, 1, 1)); // outside on the top } } -- cgit v1.2.3 From 7f5a59c2025022f99dff9fa030c892adb4473d6a Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 1 Oct 2014 12:40:47 +0200 Subject: Fix issues with Keyboard Focus documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0dcc364456404a761a555da065452a59d1249a2f Reviewed-by: Topi Reiniö --- src/quick/doc/src/concepts/input/focus.qdoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/quick/doc/src/concepts/input/focus.qdoc b/src/quick/doc/src/concepts/input/focus.qdoc index 748c8eb53c..f75f3d2bad 100644 --- a/src/quick/doc/src/concepts/input/focus.qdoc +++ b/src/quick/doc/src/concepts/input/focus.qdoc @@ -47,12 +47,12 @@ is delivered to it. \li The key event is delivered by the scene to the \l Item with \e {active focus}. If no item has active focus, the key event is ignored. \li If the \l QQuickItem with active focus accepts the key event, propagation -stops. Otherwise the event is send to the Item's parent until +stops. Otherwise the event is sent to the Item's parent until the event is accepted, or the root item is reached. If the \c {Rectangle} type in the following example has active focus and the \c A key is pressed, -the event will not be propagated further. Pressing the \c B key the event will propagate to the root -item and thus subsequently be ignored. +the event will not be propagated further. Upon pressing the \c B key, the event will propagate to the root +item and thus be ignored. \snippet qml/focus/rectangle.qml simple key event \snippet qml/focus/rectangle.qml simple key event end -- cgit v1.2.3 From 099ae0597df6f6bbd0b9e05d063a4a58c9cae2ff Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 7 Oct 2014 12:22:26 +0200 Subject: Improve performance of animators. The use of one QCoreApp::postEvent() per completed animation added up to a very large overhead when 1000+ animators were used at the same time. This is very relevant for sprite games and similar and deserves to work at least as good as normal animations. Instead, store the animations to stop and stop then on the gui thread later as a result of frameSwapped. For the benchmark in question this allows for roughly double the amount of animators being started and stopped. Change-Id: Iae3d1ec1502ee1908fdbba708fa9f976aa230064 Reviewed-by: Michael Brasser --- src/quick/items/qquickwindow.cpp | 3 +- src/quick/util/qquickanimatorcontroller.cpp | 44 ++++++++++++++++++++++++++--- src/quick/util/qquickanimatorcontroller_p.h | 21 +++++++++++++- src/quick/util/qquickanimatorjob.cpp | 11 ++------ src/quick/util/qquickanimatorjob_p.h | 2 -- 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 7b300c9ab6..4ec901ceb4 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -458,8 +458,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) q->setSurfaceType(windowManager ? windowManager->windowSurfaceType() : QSurface::OpenGLSurface); q->setFormat(sg->defaultSurfaceFormat()); - animationController = new QQuickAnimatorController(); - animationController->m_window = q; + animationController = new QQuickAnimatorController(q); delayedTouch = 0; diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index e009de205c..cfaa439072 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -44,10 +44,19 @@ QT_BEGIN_NAMESPACE -QQuickAnimatorController::QQuickAnimatorController() - : m_window(0) +QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window) + : m_window(window) , m_nodesAreInvalid(false) { + m_guiEntity = new QQuickAnimatorControllerGuiThreadEntity(); + m_guiEntity->controller = this; + connect(window, SIGNAL(frameSwapped()), m_guiEntity, SLOT(frameSwapped())); +} + +void QQuickAnimatorControllerGuiThreadEntity::frameSwapped() +{ + if (!controller.isNull()) + controller->stopProxyJobs(); } QQuickAnimatorController::~QQuickAnimatorController() @@ -71,6 +80,8 @@ QQuickAnimatorController::~QQuickAnimatorController() if (!m_animatorRoots.contains(job)) delete job; } + + delete m_guiEntity; } static void qquickanimator_invalidate_node(QAbstractAnimationJob *job) @@ -211,6 +222,27 @@ void QQuickAnimatorController::afterNodeSync() } } +void QQuickAnimatorController::proxyWasDestroyed(QQuickAnimatorProxyJob *proxy) +{ + lock(); + m_proxiesToStop.remove(proxy); + unlock(); +} + +void QQuickAnimatorController::stopProxyJobs() +{ + // Need to make a copy under lock and then stop while unlocked. + // Stopping triggers writeBack which in turn may lock, so it needs + // to be outside the lock. It is also safe because deletion of + // proxies happens on the GUI thread, where this code is also executing. + lock(); + QSet jobs = m_proxiesToStop; + m_proxiesToStop.clear(); + unlock(); + foreach (QQuickAnimatorProxyJob *p, jobs) + p->stop(); +} + void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job) { /* We are currently on the render thread and m_deleting is primarily @@ -221,8 +253,10 @@ void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job) */ if (!m_deleting.contains(job)) { QQuickAnimatorProxyJob *proxy = m_animatorRoots[job]; - if (proxy) - QCoreApplication::postEvent(proxy, new QEvent(QEvent::User)); + if (proxy) { + m_window->update(); + m_proxiesToStop << proxy; + } // else already gone... } } @@ -254,12 +288,14 @@ void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstract { proxy->markJobManagedByController(); m_starting[job] = proxy; + m_stopping.remove(job); requestSync(); } void QQuickAnimatorController::stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job) { m_stopping[job] = proxy; + m_starting.remove(job); requestSync(); } diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h index bd44adf928..b13c174606 100644 --- a/src/quick/util/qquickanimatorcontroller_p.h +++ b/src/quick/util/qquickanimatorcontroller_p.h @@ -43,12 +43,14 @@ QT_BEGIN_NAMESPACE +class QQuickAnimatorControllerGuiThreadEntity; + class QQuickAnimatorController : public QObject, public QAnimationJobChangeListener { Q_OBJECT public: - QQuickAnimatorController(); + QQuickAnimatorController(QQuickWindow *window); ~QQuickAnimatorController(); void advance(); @@ -68,6 +70,9 @@ public: void lock() { m_mutex.lock(); } void unlock() { m_mutex.unlock(); } + + void proxyWasDestroyed(QQuickAnimatorProxyJob *proxy); + void stopProxyJobs(); void windowNodesDestroyed(); public Q_SLOTS: @@ -85,11 +90,25 @@ public: QHash m_transforms; QSet m_deletedSinceLastFrame; QQuickWindow *m_window; + QQuickAnimatorControllerGuiThreadEntity *m_guiEntity; + QSet m_proxiesToStop; QMutex m_mutex; bool m_nodesAreInvalid; }; +class QQuickAnimatorControllerGuiThreadEntity : public QObject +{ + Q_OBJECT +public: + QPointer controller; + +public Q_SLOTS: + void frameSwapped(); +}; + + + QT_END_NAMESPACE #endif // QQUICKANIMATORCONTROLLER_P_H diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index fdbffd4709..f29ec49b9f 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -85,6 +85,8 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob() { deleteJob(); + if (m_controller) + m_controller->proxyWasDestroyed(this); } void QQuickAnimatorProxyJob::deleteJob() @@ -179,15 +181,6 @@ void QQuickAnimatorProxyJob::startedByController() m_internalState = State_Running; } -bool QQuickAnimatorProxyJob::event(QEvent *e) -{ - if (e->type() == QEvent::User) { - stop(); - return true; - } - return QObject::event(e); -} - static void qquick_syncback_helper(QAbstractAnimationJob *job) { if (job->isRenderThreadJob()) { diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index 4bdcd6917d..d87c9072a2 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -72,8 +72,6 @@ public: void markJobManagedByController() { m_jobManagedByController = true; } protected: - bool event(QEvent *); - void updateCurrentTime(int); void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState); -- cgit v1.2.3 From f97c03441b8c46ada314f47295ebff4e98bb646e Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Sun, 12 Oct 2014 11:59:13 +0200 Subject: Correct KeyEvent::key documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "text" is a property, not a function. Change-Id: I02158d550ff174076396810dca007df1d734bda5 Reviewed-by: Topi Reiniö --- src/quick/items/qquickevents.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 2ae846a750..e34df86a77 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -61,8 +61,7 @@ Item { See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are independent of the underlying window system. Note that this function does not distinguish between capital and non-capital - letters, use the text() function (returning the Unicode text the - key generated) for this purpose. + letters; use the \l {KeyEvent::}{text} property for this purpose. A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not the result of a known key; for example, it may be the result of -- cgit v1.2.3 From 66a4894e0ef252bb5085b705fbdae96ab3b61369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kari=20Hautam=C3=A4ki?= Date: Wed, 24 Sep 2014 10:05:02 +0300 Subject: examples/quick/positioners: Colors changed and layout obeys screen resolution Change-Id: I61b6358d6d5dff4cc9a14f8774b1c3597e83b550 Reviewed-by: Martin Smith --- .../doc/images/qml-positioners-example.png | Bin 17947 -> 5687 bytes .../positioners/positioners-attachedproperties.qml | 202 ++++++++++++--------- .../quick/positioners/positioners-transitions.qml | 172 ++++++++++-------- 3 files changed, 210 insertions(+), 164 deletions(-) diff --git a/examples/quick/positioners/doc/images/qml-positioners-example.png b/examples/quick/positioners/doc/images/qml-positioners-example.png index 0c02f4a56a..d835aa433f 100644 Binary files a/examples/quick/positioners/doc/images/qml-positioners-example.png and b/examples/quick/positioners/doc/images/qml-positioners-example.png differ diff --git a/examples/quick/positioners/positioners-attachedproperties.qml b/examples/quick/positioners/positioners-attachedproperties.qml index 753e553c7b..b5c6e57b2f 100644 --- a/examples/quick/positioners/positioners-attachedproperties.qml +++ b/examples/quick/positioners/positioners-attachedproperties.qml @@ -39,97 +39,127 @@ ****************************************************************************/ import QtQuick 2.0 +import QtQuick.Controls 1.1 Rectangle { - width: 320 - height: 480 - - // Create column with four rectangles, the fourth one is hidden - Column { - id: column - - //! [0] - Rectangle { - id: red - color: "red" - width: 100 - height: 100 - - Text { - anchors.left: parent.right - anchors.leftMargin: 20 - anchors.verticalCenter: parent.verticalCenter - text: "Index: " + parent.Positioner.index - + (parent.Positioner.isFirstItem ? " (First)" : "") - + (parent.Positioner.isLastItem ? " (Last)" : "") - } - - // When mouse is clicked, display the values of the positioner - MouseArea { - anchors.fill: parent - onClicked: column.showInfo(red.Positioner) - } - } - //! [0] - - Rectangle { - id: green - color: "green" - width: 100 - height: 100 - - Text { - anchors.left: parent.right - anchors.leftMargin: 20 - anchors.verticalCenter: parent.verticalCenter - text: "Index: " + parent.Positioner.index - + (parent.Positioner.isFirstItem ? " (First)" : "") - + (parent.Positioner.isLastItem ? " (Last)" : "") - } - - // When mouse is clicked, display the values of the positioner - MouseArea { - anchors.fill: parent - onClicked: column.showInfo(green.Positioner) - } - } + id: page - Rectangle { - id: blue - color: "blue" - width: 100 - height: 100 - - Text { - anchors.left: parent.right - anchors.leftMargin: 20 - anchors.verticalCenter: parent.verticalCenter - text: "Index: " + parent.Positioner.index - + (parent.Positioner.isFirstItem ? " (First)" : "") - + (parent.Positioner.isLastItem ? " (Last)" : "") - } - - // When mouse is clicked, display the values of the positioner - MouseArea { - anchors.fill: parent - onClicked: column.showInfo(blue.Positioner) - } - } + property real ratio: width / 320 < height / 440 ? width / 320 : height / 440 + property int elementSpacing: 6.3 * ratio - // This rectangle is not visible, so it doesn't have a positioner value - Rectangle { - color: "black" - width: 100 - height: 100 - visible: false + width: 320 + height: 440 + + Button { + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: 10 + text: hidingRect.visible ? "Hide" : "Show" + onClicked: hidingRect.visible = !hidingRect.visible } - // Print the index of the child item in the positioner and convenience - // properties showing if it's the first or last item. - function showInfo(positioner) { - console.log("Item Index = " + positioner.index) - console.log(" isFirstItem = " + positioner.isFirstItem) - console.log(" isLastItem = " + positioner.isLastItem) + // Create column with four rectangles, the fourth one is hidden + Column { + id: column + + anchors.top: parent.top + anchors.left: parent.left + anchors.leftMargin: page.width / 32 + anchors.topMargin: page.height / 48 + spacing: elementSpacing + + //! [0] + Rectangle { + id: green + color: "#80c342" + width: 100 * ratio + height: 100 * ratio + + Text { + anchors.left: parent.right + anchors.leftMargin: 20 + anchors.verticalCenter: parent.verticalCenter + text: "Index: " + parent.Positioner.index + + (parent.Positioner.isFirstItem ? " (First)" : "") + + (parent.Positioner.isLastItem ? " (Last)" : "") + } + + // When mouse is clicked, display the values of the positioner + MouseArea { + anchors.fill: parent + onClicked: column.showInfo(green.Positioner) + } + } + //! [0] + + Rectangle { + id: blue + color: "#14aaff" + width: 100 * ratio + height: 100 * ratio + + Text { + anchors.left: parent.right + anchors.leftMargin: 20 + anchors.verticalCenter: parent.verticalCenter + text: "Index: " + parent.Positioner.index + + (parent.Positioner.isFirstItem ? " (First)" : "") + + (parent.Positioner.isLastItem ? " (Last)" : "") + } + + // When mouse is clicked, display the values of the positioner + MouseArea { + anchors.fill: parent + onClicked: column.showInfo(blue.Positioner) + } + } + + Rectangle { + id: purple + color: "#6400aa" + width: 100 * ratio + height: 100 * ratio + + Text { + anchors.left: parent.right + anchors.leftMargin: 20 + anchors.verticalCenter: parent.verticalCenter + text: "Index: " + parent.Positioner.index + + (parent.Positioner.isFirstItem ? " (First)" : "") + + (parent.Positioner.isLastItem ? " (Last)" : "") + } + + // When mouse is clicked, display the values of the positioner + MouseArea { + anchors.fill: parent + onClicked: column.showInfo(purple.Positioner) + } + } + + // This rectangle is not visible, so it doesn't have a positioner value + Rectangle { + id: hidingRect + color: "#006325" + width: 100 * ratio + height: 100 * ratio + visible: false + + Text { + anchors.left: parent.right + anchors.leftMargin: 20 + anchors.verticalCenter: parent.verticalCenter + text: "Index: " + parent.Positioner.index + + (parent.Positioner.isFirstItem ? " (First)" : "") + + (parent.Positioner.isLastItem ? " (Last)" : "") + } + } + + // Print the index of the child item in the positioner and convenience + // properties showing if it's the first or last item. + function showInfo(positioner) { + console.log("Item Index = " + positioner.index) + console.log(" isFirstItem = " + positioner.isFirstItem) + console.log(" isLastItem = " + positioner.isLastItem) + } } - } } diff --git a/examples/quick/positioners/positioners-transitions.qml b/examples/quick/positioners/positioners-transitions.qml index 8341d6c442..f65db86cca 100644 --- a/examples/quick/positioners/positioners-transitions.qml +++ b/examples/quick/positioners/positioners-transitions.qml @@ -40,10 +40,16 @@ import QtQuick 2.0 -Rectangle { +Item { id: page - width: 320; height: 480 + property real effectiveOpacity: 1.0 + property real ratio: width / 320 < height / 440 ? width / 320 : height / 440 + property int smallSize: 45 * ratio + property int bigSize: 2 * smallSize + property int elementSpacing: 0.14 * smallSize + + anchors.fill: parent Timer { interval: 2000 @@ -53,10 +59,16 @@ Rectangle { } Column { - y: 0 + anchors { + left: parent.left + leftMargin: page.width / 32 + top: parent.top + topMargin: page.height / 48 + } + spacing: elementSpacing populate: Transition { - NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce } + NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } } add: Transition { NumberAnimation { properties: "y"; easing.type: Easing.OutQuad } @@ -65,41 +77,45 @@ Rectangle { NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } } - Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: bigSize; height: smallSize } Rectangle { - id: blueV1 + id: greenV1 visible: opacity != 0 - width: 100; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: bigSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#14aaff"; width: bigSize; height: smallSize } Rectangle { - id: blueV2 + id: greenV2 visible: opacity != 0 - width: 100; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: bigSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "orange"; width: 100; height: 50; border.color: "black"; radius: 15 } - Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#6400aa"; width: bigSize; height: smallSize } + Rectangle { color: "#80c342"; width: bigSize; height: smallSize } } Row { - y: 320 + anchors { + left: page.left + leftMargin: page.width / 32 + bottom: page.bottom + bottomMargin: page.height / 48 + } + spacing: elementSpacing populate: Transition { - NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce } + NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } } add: Transition { NumberAnimation { properties: "x"; easing.type: Easing.OutQuad } @@ -108,42 +124,43 @@ Rectangle { NumberAnimation { properties: "x"; easing.type: Easing.OutBounce } } - Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: smallSize; height: bigSize } Rectangle { id: blueH1 visible: opacity != 0 - width: 50; height: 100 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: smallSize; height: bigSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 } + Rectangle { color: "#14aaff"; width: smallSize; height: bigSize } Rectangle { - id: blueH2 + id: greenH2 visible: opacity != 0 - width: 50; height: 100 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: smallSize; height: bigSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "orange"; width: 50; height: 100; border.color: "black"; radius: 15 } - Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } + Rectangle { color: "#6400aa"; width: smallSize; height: bigSize } + Rectangle { color: "#80c342"; width: smallSize; height: bigSize } } Grid { - x: 120; y: 0 + anchors.top: parent.top + anchors.topMargin: page.height / 48 + anchors.left: flow.left columns: 3 + spacing: elementSpacing populate: Transition { - NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce } + NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } } add: Transition { NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } @@ -152,53 +169,55 @@ Rectangle { NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } } - - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: smallSize; height: smallSize } Rectangle { - id: blueG1 + id: greenG1 visible: opacity != 0 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: smallSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#14aaff"; width: smallSize; height: smallSize } Rectangle { - id: blueG2 + id: greenG2 visible: opacity != 0 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: smallSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } Rectangle { - id: blueG3 + id: greenG3 visible: opacity != 0 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: smallSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } - Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: smallSize; height: smallSize } + Rectangle { color: "#14aaff"; width: smallSize; height: smallSize } + Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } } Flow { - x: 120; y: 160; width: 150 + id: flow + + anchors.right: page.right + anchors.rightMargin: page.width / 32 + y: 2 * bigSize + width: 1.8 * bigSize + spacing: elementSpacing //! [move] move: Transition { @@ -214,49 +233,46 @@ Rectangle { //! [populate] populate: Transition { - NumberAnimation { properties: "x,y"; from: 200; duration: 1500; easing.type: Easing.OutBounce } + NumberAnimation { properties: "x,y"; from: 200; duration: 100; easing.type: Easing.OutBounce } } //! [populate] - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: smallSize; height: smallSize } Rectangle { - id: blueF1 + id: greenF1 visible: opacity != 0 - width: 60; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: 0.6 * bigSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "green"; width: 30; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#14aaff"; width: 0.3 * bigSize; height: smallSize } Rectangle { - id: blueF2 + id: greenF2 visible: opacity != 0 - width: 60; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: 0.6 * bigSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#6400aa"; width: smallSize; height: smallSize } Rectangle { - id: blueF3 + id: greenF3 visible: opacity != 0 - width: 40; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 + width: 0.4 * bigSize; height: smallSize + color: "#006325" + border.color: "transparent" Behavior on opacity { NumberAnimation {} } opacity: effectiveOpacity } - Rectangle { color: "red"; width: 80; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "#80c342"; width: 0.8 * bigSize; height: smallSize } } } -- cgit v1.2.3 From 7f692693d98522187029e82c746627e3bd51be67 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 20 Oct 2014 15:00:39 +0200 Subject: Fix tst_qquickpositioners on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Done-with: Jan Arve Sæther Change-Id: Iff66f62167a5977354319aac311d2cb81d9f3842 Reviewed-by: Jan Arve Sæther --- tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp index 6e5314f4f2..c2ea9cc0d6 100644 --- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp +++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp @@ -1934,6 +1934,9 @@ void tst_qquickpositioners::test_mirroring() QScopedPointer windowB(createView(testFile(qmlFile))); QQuickItem *rootB = qobject_cast(windowB->rootObject()); + // On OS X the windows might get positioned exactly on top of each other + // that means no repaint for the bottom window will ever occur + windowB->setPosition(windowB->position() + QPoint(10, 10)); rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft -- cgit v1.2.3 From 09a67ad96508dad0e85137c68d9e45fc3544a138 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Tue, 23 Sep 2014 11:24:58 +0200 Subject: Make test more robust against ignored children. With the upcoming change that changes the semantics of Accessible.ignored, some assumptions in the test does not hold anymore. Change-Id: I9b34f1ecc61fc0d4e8abe5a5505a5bcff44501d4 Reviewed-by: Frederik Gladhorn --- .../quick/qquickaccessible/data/checkbuttons.qml | 1 + tests/auto/quick/qquickaccessible/data/hittest.qml | 42 +++++++++++++ .../quick/qquickaccessible/data/statictext.qml | 2 + .../qquickaccessible/tst_qquickaccessible.cpp | 72 ++++++++++++---------- 4 files changed, 84 insertions(+), 33 deletions(-) diff --git a/tests/auto/quick/qquickaccessible/data/checkbuttons.qml b/tests/auto/quick/qquickaccessible/data/checkbuttons.qml index 8769c04095..8424e3b2d5 100644 --- a/tests/auto/quick/qquickaccessible/data/checkbuttons.qml +++ b/tests/auto/quick/qquickaccessible/data/checkbuttons.qml @@ -3,6 +3,7 @@ import QtQuick 2.0 Item { width: 400 height: 400 + Accessible.name: "root" // button, not checkable Rectangle { diff --git a/tests/auto/quick/qquickaccessible/data/hittest.qml b/tests/auto/quick/qquickaccessible/data/hittest.qml index 07e2bbaaf6..97eb6013a1 100644 --- a/tests/auto/quick/qquickaccessible/data/hittest.qml +++ b/tests/auto/quick/qquickaccessible/data/hittest.qml @@ -40,6 +40,7 @@ Rectangle { width: 640 height: 480 color: "white" + Accessible.name: "root" Rectangle { id: header color: "#c0c0c0" @@ -165,4 +166,45 @@ Rectangle { } } + TextRect { + x: 0 + y: 300 + text: "rect3" + width: 200 + height: 100 + color: "#ffa0a0" + TextRect { + x: 10 + y: 10 + text: "rect30" + width: 80 + height: 80 + color: "#ffa0a0" + TextRect { + x: 30 + y: 50 + text: "rect300" + width: 80 + height: 80 + color: "#ffa0a0" + } + } + TextRect { + x: 100 + y: 10 + text: "rect31" + width: 80 + height: 80 + color: "#ffa0a0" + TextRect { + x: -50 + y: 60 + z: -3 + text: "rect310" + width: 80 + height: 80 + color: "#ffa0a0" + } + } + } } diff --git a/tests/auto/quick/qquickaccessible/data/statictext.qml b/tests/auto/quick/qquickaccessible/data/statictext.qml index 7cf1b707a0..1092f33daf 100644 --- a/tests/auto/quick/qquickaccessible/data/statictext.qml +++ b/tests/auto/quick/qquickaccessible/data/statictext.qml @@ -3,6 +3,8 @@ import QtQuick 2.0 Item { width: 400 height: 400 + Accessible.name: "root" + Accessible.role: Accessible.Client Text { x: 100 diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp index 2806c41bef..c514f96d24 100644 --- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp +++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp @@ -332,40 +332,46 @@ void tst_QQuickAccessible::hitTest() // check the root item from app QAccessibleInterface *appIface = QAccessible::queryAccessibleInterface(qApp); QVERIFY(appIface); - QAccessibleInterface *itemHit(appIface->childAt(rootRect.x() + 200, rootRect.y() + 50)); + QAccessibleInterface *itemHit = appIface->childAt(rootRect.x() + 200, rootRect.y() + 50); QVERIFY(itemHit); - QCOMPARE(rootRect, itemHit->rect()); - - // hit rect1 - QAccessibleInterface *rect1(rootItem->child(0)); - QRect rect1Rect = rect1->rect(); - QAccessibleInterface *rootItemIface = rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10); - QVERIFY(rootItemIface); - QCOMPARE(rect1Rect, rootItemIface->rect()); - QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect1")); - - // should also work from top level (app) - QAccessibleInterface *app(QAccessible::queryAccessibleInterface(qApp)); - QAccessibleInterface *itemHit2(topLevelChildAt(app, rect1Rect.x() + 10, rect1Rect.y() + 10)); - QVERIFY(itemHit2); - QCOMPARE(itemHit2->rect(), rect1Rect); - QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1")); - - // hit rect201 - QAccessibleInterface *rect2(rootItem->child(1)); - QVERIFY(rect2); - // FIXME: This is seems broken on mac - // QCOMPARE(rect2->rect().translated(rootItem->rect().x(), rootItem->rect().y()), QRect(0, 50, 100, 100)); - QAccessibleInterface *rect20(rect2->child(0)); - QVERIFY(rect20); - QAccessibleInterface *rect201(rect20->child(1)); - QVERIFY(rect201); - - QRect rect201Rect = rect201->rect(); - rootItemIface = windowIface->childAt(rect201Rect.x() + 20, rect201Rect.y() + 20); - QVERIFY(rootItemIface); - QCOMPARE(rootItemIface->rect(), rect201Rect); - QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201")); + QCOMPARE(itemHit->rect(), rootRect); + + QAccessibleInterface *rootItemIface; + for (int c = 0; c < rootItem->childCount(); ++c) { + QAccessibleInterface *iface = rootItem->child(c); + QString name = iface->text(QAccessible::Name); + if (name == QLatin1String("rect1")) { + // hit rect1 + QAccessibleInterface *rect1 = iface; + QRect rect1Rect = rect1->rect(); + QAccessibleInterface *rootItemIface = rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10); + QVERIFY(rootItemIface); + QCOMPARE(rect1Rect, rootItemIface->rect()); + QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect1")); + + // should also work from top level (app) + QAccessibleInterface *app(QAccessible::queryAccessibleInterface(qApp)); + QAccessibleInterface *itemHit2(topLevelChildAt(app, rect1Rect.x() + 10, rect1Rect.y() + 10)); + QVERIFY(itemHit2); + QCOMPARE(itemHit2->rect(), rect1Rect); + QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1")); + } else if (name == QLatin1String("rect2")) { + QAccessibleInterface *rect2 = iface; + // FIXME: This is seems broken on OS X + // QCOMPARE(rect2->rect().translated(rootItem->rect().x(), rootItem->rect().y()), QRect(0, 50, 100, 100)); + QAccessibleInterface *rect20 = rect2->child(0); + QVERIFY(rect20); + QCOMPARE(rect20->text(QAccessible::Name), QLatin1String("rect20")); + QPoint p = rect20->rect().bottomRight() + QPoint(20, 20); + QAccessibleInterface *rect201 = rect20->childAt(p.x(), p.y()); + QVERIFY(rect201); + QCOMPARE(rect201->text(QAccessible::Name), QLatin1String("rect201")); + rootItemIface = topLevelChildAt(windowIface, p.x(), p.y()); + QVERIFY(rootItemIface); + QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201")); + + } + } delete window; QTestAccessibility::clearEvents(); -- cgit v1.2.3 From 5871f3e829f1f48995b5d6c03f7ad31fcda386e5 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 20 Oct 2014 13:58:33 +0200 Subject: Tweak new animation driver. We're removing the bad/reallyBad concept for the benefit of an accumulated lag. When the lag passes over a certain threshold, we switch to time based. The logic for switching back remains unchanged. We also fixed the switching so that elapsed() does not jump from the predicted time to the animation system's wall time, but rather continues from the predicted time with a walltime offset (this is how it was always intended to be). Task-number: QTBUG-42020 Change-Id: I7ee9181aca46cbc18a74fae5e8d513365906c017 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgcontext.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 83b221a8cc..b5bdbde3ad 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -162,7 +162,6 @@ public: , m_vsync(0) , m_mode(VSyncMode) , m_bad(0) - , m_reallyBad(0) , m_good(0) { QScreen *screen = QGuiApplication::primaryScreen(); @@ -185,6 +184,7 @@ public: { m_time = 0; m_timer.start(); + m_wallTime.restart(); QAnimationDriver::start(); } @@ -192,7 +192,7 @@ public: { return m_mode == VSyncMode ? qint64(m_time) - : QAnimationDriver::elapsed(); + : qint64(m_time) + m_wallTime.elapsed(); } void advance() Q_DECL_OVERRIDE @@ -217,25 +217,22 @@ public: m_time += m_vsync; - if (delta > m_vsync * 5) { - ++m_reallyBad; - ++m_bad; - } else if (delta > m_vsync * 1.25) { - ++m_bad; + if (delta > m_vsync * 1.25) { + m_lag += (delta / m_vsync); + m_bad++; + // We tolerate one bad frame without resorting to timer based. This is + // done to cope with a slow loader frame followed by smooth animation. + // However, on the second frame with massive lag, we switch. + if (m_lag > 10 && m_bad > 2) { + m_mode = TimerMode; + qCDebug(QSG_LOG_INFO, "animation driver switched to timer mode"); + m_wallTime.restart(); + } } else { - // reset counters on a good frame. - m_reallyBad = 0; + m_lag = 0; m_bad = 0; } - // rational for the 3 and 50. If we have several really bad frames - // in a row, that would indicate a huge performance problem and we should - // switch right away. For the case of m_bad, we're a bit more tolerant. - if (m_reallyBad > 3 || m_bad > 50) { - m_mode = TimerMode; - qCDebug(QSG_LOG_INFO, "animation driver switched to timer mode"); - } - } else { if (delta < 1.25 * m_vsync) { ++m_good; @@ -249,6 +246,8 @@ public: if (m_good > 10 && !qsg_useConsistentTiming()) { m_time = elapsed(); m_mode = VSyncMode; + m_bad = 0; + m_lag = 0; qCDebug(QSG_LOG_INFO, "animation driver switched to vsync mode"); } } @@ -260,8 +259,9 @@ public: float m_vsync; Mode m_mode; QElapsedTimer m_timer; + QElapsedTimer m_wallTime; + float m_lag; int m_bad; - int m_reallyBad; int m_good; }; -- cgit v1.2.3 From f830c109d09d835551c1325c4904fc9a490b3754 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Thu, 9 Oct 2014 16:05:33 +0200 Subject: qmlstatemachine: Rename StateBase to State As discussed with Brett Stottlmyer and Alan Alpert. Add a section about the implications when importing both QtQml.StateMachine and QtQuick in one single QML file. Change-Id: I8755f4b578e2a6ff4c2377c7a8a0b996ba9b7129 Reviewed-by: BogDan Vatra Reviewed-by: Simon Hausmann --- src/imports/statemachine/finalstate.cpp | 6 +- src/imports/statemachine/plugin.cpp | 8 +- src/imports/statemachine/plugins.qmltypes | 6 +- src/imports/statemachine/state.cpp | 238 +++++++++++++++++++++ src/imports/statemachine/state.h | 69 ++++++ src/imports/statemachine/statebase.cpp | 238 --------------------- src/imports/statemachine/statebase.h | 69 ------ src/imports/statemachine/statemachine.cpp | 16 +- src/imports/statemachine/statemachine.pro | 4 +- .../doc/snippets/qml/statemachine/basicstate.qml | 6 +- .../doc/snippets/qml/statemachine/finalstate.qml | 10 +- .../snippets/qml/statemachine/guardcondition.qml | 11 +- .../doc/snippets/qml/statemachine/historystate.qml | 14 +- .../snippets/qml/statemachine/signaltransition.qml | 10 +- .../qml/statemachine/signaltransitionsignal.qml | 10 +- .../qml/statemachine/simplestatemachine.qml | 10 +- .../statemachine/statemachine-button-history.qml | 12 +- .../statemachine-button-nested-ignore-quit.qml | 10 +- .../statemachine/statemachine-button-nested.qml | 10 +- .../qml/statemachine/statemachine-button.qml | 8 +- .../qml/statemachine/timeouttransition.qml | 10 +- src/qml/doc/src/statemachine.qdoc | 52 ++++- .../qmltest/statemachine/tst_anonymousstate.qml | 4 +- .../qmltest/statemachine/tst_guardcondition.qml | 4 +- .../auto/qmltest/statemachine/tst_historystate.qml | 8 +- .../auto/qmltest/statemachine/tst_initialstate.qml | 4 +- .../statemachine/tst_nestedinitialstates.qml | 8 +- .../statemachine/tst_nestedstatemachine.qml | 8 +- .../qmltest/statemachine/tst_parallelmachine.qml | 18 +- .../auto/qmltest/statemachine/tst_trafficlight.qml | 14 +- 30 files changed, 463 insertions(+), 432 deletions(-) create mode 100644 src/imports/statemachine/state.cpp create mode 100644 src/imports/statemachine/state.h delete mode 100644 src/imports/statemachine/statebase.cpp delete mode 100644 src/imports/statemachine/statebase.h diff --git a/src/imports/statemachine/finalstate.cpp b/src/imports/statemachine/finalstate.cpp index 73e85a1abd..9b3c05e294 100644 --- a/src/imports/statemachine/finalstate.cpp +++ b/src/imports/statemachine/finalstate.cpp @@ -59,9 +59,9 @@ QQmlListProperty FinalState::children() A final state is used to communicate that (part of) a StateMachine has finished its work. When a final top-level state is entered, the state - machine's \l{StateBase::finished}{finished}() signal is emitted. In + machine's \l{State::finished}{finished}() signal is emitted. In general, when a final substate (a child of a State) is entered, the parent - state's \l{StateBase::finished}{finished}() signal is emitted. FinalState + state's \l{State::finished}{finished}() signal is emitted. FinalState is part of \l{The Declarative State Machine Framework}. To use a final state, you create a FinalState object and add a transition @@ -73,5 +73,5 @@ QQmlListProperty FinalState::children() \clearfloat - \sa StateMachine, StateBase + \sa StateMachine, State */ diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index 678a4de199..a1ebe06a80 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -33,7 +33,7 @@ #include "finalstate.h" #include "signaltransition.h" -#include "statebase.h" +#include "state.h" #include "statemachine.h" #include "timeouttransition.h" @@ -51,12 +51,12 @@ class QtQmlStateMachinePlugin : public QQmlExtensionPlugin public: void registerTypes(const char *uri) { - qmlRegisterType(uri, 1, 0, "StateBase"); + qmlRegisterType(uri, 1, 0, "State"); qmlRegisterType(uri, 1, 0, "StateMachine"); qmlRegisterType(uri, 1, 0, "HistoryState"); qmlRegisterType(uri, 1, 0, "FinalState"); - qmlRegisterUncreatableType(uri, 1, 0, "QState", "Don't use this, use StateBase instead"); - qmlRegisterUncreatableType(uri, 1, 0, "QAbstractState", "Don't use this, use StateBase instead"); + qmlRegisterUncreatableType(uri, 1, 0, "QState", "Don't use this, use State instead"); + qmlRegisterUncreatableType(uri, 1, 0, "QAbstractState", "Don't use this, use State instead"); qmlRegisterUncreatableType(uri, 1, 0, "QSignalTransition", "Don't use this, use SignalTransition instead"); qmlRegisterType(uri, 1, 0, "SignalTransition"); qmlRegisterType(uri, 1, 0, "TimeoutTransition"); diff --git a/src/imports/statemachine/plugins.qmltypes b/src/imports/statemachine/plugins.qmltypes index a53d68f8e8..db5897bb0f 100644 --- a/src/imports/statemachine/plugins.qmltypes +++ b/src/imports/statemachine/plugins.qmltypes @@ -130,16 +130,16 @@ Module { exports: ["QtQml.StateMachine/SignalTransition 1.0"] exportMetaObjectRevisions: [0] Property { name: "signal"; type: "QJSValue" } - Property { name: "guard"; type: "bool" } + Property { name: "guard"; type: "QQmlScriptString" } Signal { name: "invokeYourself" } Signal { name: "qmlSignalChanged" } Method { name: "invoke" } } Component { - name: "StateBase" + name: "State" defaultProperty: "children" prototype: "QState" - exports: ["QtQml.StateMachine/StateBase 1.0"] + exports: ["QtQml.StateMachine/State 1.0"] exportMetaObjectRevisions: [0] Property { name: "children"; type: "QObject"; isList: true; isReadonly: true } } diff --git a/src/imports/statemachine/state.cpp b/src/imports/statemachine/state.cpp new file mode 100644 index 0000000000..56ecd015f5 --- /dev/null +++ b/src/imports/statemachine/state.cpp @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Ford Motor Company +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "state.h" + +#include +#include +#include + +State::State(QState *parent) + : QState(parent) +{ +} + +void State::componentComplete() +{ + if (this->machine() == NULL) { + static bool once = false; + if (!once) { + once = true; + qmlInfo(this) << "No top level StateMachine found. Nothing will run without a StateMachine."; + } + } +} + +QQmlListProperty State::children() +{ + return QQmlListProperty(this, &m_children, m_children.append, m_children.count, m_children.at, m_children.clear); +} + +/*! + \qmltype QAbstractState + \inqmlmodule QtQml.StateMachine + \omit + \ingroup statemachine-qmltypes + \endomit + \since 5.4 + + \brief The QAbstractState type is the base type of States of a StateMachine. + + Do not use QAbstractState directly; use State, FinalState or + StateMachine instead. + + \sa StateMachine, State +*/ + +/*! + \qmlproperty bool QAbstractState::active + \readonly active + + The active property of this state. A state is active between + entered() and exited() signals. This property is readonly. + + \sa entered, exited +*/ + +/*! + \qmlsignal QAbstractState::entered() + + This signal is emitted when the State becomes active. + + The corresponding handler is \c onEntered. + + \sa active, exited +*/ + +/*! + \qmlsignal QAbstractState::exited() + + This signal is emitted when the State becomes inactive. + + The corresponding handler is \c onExited. + + \sa active, entered +*/ + +/*! + \qmltype State + \inqmlmodule QtQml.StateMachine + \inherits QAbstractState + \ingroup statemachine-qmltypes + \since 5.4 + + \brief Provides a general-purpose state for StateMachine. + + + State objects can have child states as well as transitions to other + states. State is part of \l{The Declarative State Machine Framework}. + + \section1 States with Child States + + The childMode property determines how child states are treated. For + non-parallel state groups, the initialState property must be used 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 state emits the State::finished() signal when a final child state + (FinalState) is entered. + + The errorState 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). + + \section1 Example Usage + + \snippet qml/statemachine/basicstate.qml document + + \clearfloat + + \sa StateMachine, FinalState +*/ + +/*! + \qmlproperty enumeration State::childMode + + \brief The child mode of this state + + The default value of this property is QState.ExclusiveStates. + + This enum specifies how a state's child states are treated: + \list + \li QState.ExclusiveStates The child states are mutually exclusive and an initial state must be set by setting initialState property. + \li QState.ParallelStates The child states are parallel. When the parent state is entered, all its child states are entered in parallel. + \endlist +*/ + +/*! + \qmlproperty QAbstractState State::errorState + + \brief The error state of this state. +*/ + +/*! + \qmlproperty QAbstractState State::initialState + + \brief The initial state of this state (one of its child states). +*/ + +/*! + \qmlsignal State::finished() + + This signal is emitted when a final child state of this state is entered. + + The corresponding handler is \c onFinished. + + \sa QAbstractState::active, QAbstractState::entered, QAbstractState::exited +*/ + +/*! + \qmltype HistoryState + \inqmlmodule QtQml.StateMachine + \inherits QAbstractState + \ingroup statemachine-qmltypes + \since 5.4 + + \brief The HistoryState type provides a means of returning to a previously active substate. + + A history state is a pseudo-state that represents the child state that the + parent state was in the last time the parent state was exited. A transition + with a history state as its target is in fact a transition to one of the + other child states of the parent state. + HistoryState is part of \l{The Declarative State Machine Framework}. + + Use the defaultState property to set the state that should be entered + if the parent state has never been entered. + + \section1 Example Usage + + \snippet qml/statemachine/historystate.qml document + + \clearfloat + + By default, a history state is shallow, meaning that it will not remember + nested states. This can be configured through the historyType property. + + \sa StateMachine, State +*/ + +/*! + \qmlproperty QAbstractState HistoryState::defaultState + + \brief The default state of this history state. + + The default state indicates the state to transition to if the parent + state has never been entered before. +*/ + +/*! + \qmlproperty enumeration HistoryState::historyType + + \brief The type of history that this history state records. + + The default value of this property is QHistoryState.ShallowHistory. + + This enum specifies the type of history that a QHistoryState records. + \list + \li QHistoryState.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. + \li QHistoryState.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. + \endlist +*/ + diff --git a/src/imports/statemachine/state.h b/src/imports/statemachine/state.h new file mode 100644 index 0000000000..af8783e90d --- /dev/null +++ b/src/imports/statemachine/state.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Ford Motor Company +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STATE_H +#define STATE_H + +#include "childrenprivate.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class State : public QState, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QQmlListProperty children READ children NOTIFY childrenChanged) + Q_CLASSINFO("DefaultProperty", "children") + +public: + explicit State(QState *parent = 0); + + void classBegin() {} + void componentComplete(); + + QQmlListProperty children(); + +Q_SIGNALS: + void childrenChanged(); + +private: + ChildrenPrivate m_children; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/imports/statemachine/statebase.cpp b/src/imports/statemachine/statebase.cpp deleted file mode 100644 index d33e294369..0000000000 --- a/src/imports/statemachine/statebase.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Ford Motor Company -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "statebase.h" - -#include -#include -#include - -StateBase::StateBase(QState *parent) - : QState(parent) -{ -} - -void StateBase::componentComplete() -{ - if (this->machine() == NULL) { - static bool once = false; - if (!once) { - once = true; - qmlInfo(this) << "No top level StateMachine found. Nothing will run without a StateMachine."; - } - } -} - -QQmlListProperty StateBase::children() -{ - return QQmlListProperty(this, &m_children, m_children.append, m_children.count, m_children.at, m_children.clear); -} - -/*! - \qmltype QAbstractState - \inqmlmodule QtQml.StateMachine - \omit - \ingroup statemachine-qmltypes - \endomit - \since 5.4 - - \brief The QAbstractState type is the base type of States of a StateMachine. - - Do not use QAbstractState directly; use StateBase, FinalState or - StateMachine instead. - - \sa StateMachine, StateBase -*/ - -/*! - \qmlproperty bool QAbstractState::active - \readonly active - - The active property of this state. A state is active between - entered() and exited() signals. This property is readonly. - - \sa entered, exited -*/ - -/*! - \qmlsignal QAbstractState::entered() - - This signal is emitted when the State becomes active. - - The corresponding handler is \c onEntered. - - \sa active, exited -*/ - -/*! - \qmlsignal QAbstractState::exited() - - This signal is emitted when the State becomes inactive. - - The corresponding handler is \c onExited. - - \sa active, entered -*/ - -/*! - \qmltype StateBase - \inqmlmodule QtQml.StateMachine - \inherits QAbstractState - \ingroup statemachine-qmltypes - \since 5.4 - - \brief Provides a general-purpose state for StateMachine. - - - StateBase objects can have child states as well as transitions to other - states. StateBase is part of \l{The Declarative State Machine Framework}. - - \section1 States with Child States - - The childMode property determines how child states are treated. For - non-parallel state groups, the initialState property must be used 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 state emits the StateBase::finished() signal when a final child state - (FinalState) is entered. - - The errorState 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). - - \section1 Example Usage - - \snippet qml/statemachine/basicstate.qml document - - \clearfloat - - \sa StateMachine, FinalState -*/ - -/*! - \qmlproperty enumeration StateBase::childMode - - \brief The child mode of this state - - The default value of this property is QState.ExclusiveStates. - - This enum specifies how a state's child states are treated: - \list - \li QState.ExclusiveStates The child states are mutually exclusive and an initial state must be set by setting initialState property. - \li QState.ParallelStates The child states are parallel. When the parent state is entered, all its child states are entered in parallel. - \endlist -*/ - -/*! - \qmlproperty QAbstractState StateBase::errorState - - \brief The error state of this state. -*/ - -/*! - \qmlproperty QAbstractState StateBase::initialState - - \brief The initial state of this state (one of its child states). -*/ - -/*! - \qmlsignal StateBase::finished() - - This signal is emitted when a final child state of this state is entered. - - The corresponding handler is \c onFinished. - - \sa QAbstractState::active, QAbstractState::entered, QAbstractState::exited -*/ - -/*! - \qmltype HistoryState - \inqmlmodule QtQml.StateMachine - \inherits QAbstractState - \ingroup statemachine-qmltypes - \since 5.4 - - \brief The HistoryState type provides a means of returning to a previously active substate. - - A history state is a pseudo-state that represents the child state that the - parent state was in the last time the parent state was exited. A transition - with a history state as its target is in fact a transition to one of the - other child states of the parent state. - HistoryState is part of \l{The Declarative State Machine Framework}. - - Use the defaultState property to set the state that should be entered - if the parent state has never been entered. - - \section1 Example Usage - - \snippet qml/statemachine/historystate.qml document - - \clearfloat - - By default, a history state is shallow, meaning that it will not remember - nested states. This can be configured through the historyType property. - - \sa StateMachine, StateBase -*/ - -/*! - \qmlproperty QAbstractState HistoryState::defaultState - - \brief The default state of this history state. - - The default state indicates the state to transition to if the parent - state has never been entered before. -*/ - -/*! - \qmlproperty enumeration HistoryState::historyType - - \brief The type of history that this history state records. - - The default value of this property is QHistoryState.ShallowHistory. - - This enum specifies the type of history that a QHistoryState records. - \list - \li QHistoryState.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. - \li QHistoryState.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. - \endlist -*/ - diff --git a/src/imports/statemachine/statebase.h b/src/imports/statemachine/statebase.h deleted file mode 100644 index 38fb8f6d57..0000000000 --- a/src/imports/statemachine/statebase.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Ford Motor Company -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef STATE_H -#define STATE_H - -#include "childrenprivate.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class StateBase : public QState, public QQmlParserStatus -{ - Q_OBJECT - Q_INTERFACES(QQmlParserStatus) - Q_PROPERTY(QQmlListProperty children READ children NOTIFY childrenChanged) - Q_CLASSINFO("DefaultProperty", "children") - -public: - explicit StateBase(QState *parent = 0); - - void classBegin() {} - void componentComplete(); - - QQmlListProperty children(); - -Q_SIGNALS: - void childrenChanged(); - -private: - ChildrenPrivate m_children; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/imports/statemachine/statemachine.cpp b/src/imports/statemachine/statemachine.cpp index c65901a175..7b9ebdb88b 100644 --- a/src/imports/statemachine/statemachine.cpp +++ b/src/imports/statemachine/statemachine.cpp @@ -80,7 +80,7 @@ QQmlListProperty StateMachine::children() /*! \qmltype StateMachine \inqmlmodule QtQml.StateMachine - \inherits StateBase + \inherits State \ingroup statemachine-qmltypes \since 5.4 @@ -97,7 +97,7 @@ QQmlListProperty StateMachine::children() algorithm. The framework's \l{The Declarative State Machine Framework}{overview} gives several state graphs and the code to build them. - Before the machine can be started, the \l{StateBase::initialState}{initialState} + Before the machine can be started, the \l{State::initialState}{initialState} must be set. The initial state is the state that the machine enters when started. You can then set running property to true or start() the state machine. The started signal is emitted when the @@ -116,7 +116,7 @@ QQmlListProperty StateMachine::children() \snippet qml/statemachine/simplestatemachine.qml document If an error is encountered, the machine will look for an - \l{StateBase::errorState}{errorState}, and if one is available, it will + \l{State::errorState}{errorState}, and if one is available, it will enter this state. After the error state is entered, the type of the error can be retrieved with error(). The execution of the state graph will not stop when the error state is entered. If no error state applies to the @@ -125,7 +125,7 @@ QQmlListProperty StateMachine::children() \clearfloat - \sa QAbstractState, StateBase, SignalTransition, TimeoutTransition, HistoryState {The Declarative State Machine Framework} + \sa QAbstractState, State, SignalTransition, TimeoutTransition, HistoryState {The Declarative State Machine Framework} */ /*! @@ -181,18 +181,18 @@ QQmlListProperty StateMachine::children() the main application event loop started with QCoreApplication::exec() or QApplication::exec(). - \sa started, StateBase::finished, stop(), StateBase::initialState, running + \sa started, State::finished, stop(), State::initialState, running */ /*! \qmlsignal StateMachine::started() This signal is emitted when the state machine has entered its initial state - (StateBase::initialState). + (State::initialState). The corresponding handler is \c onStarted. - \sa running, start(), StateBase::finished + \sa running, start(), State::finished */ /*! @@ -211,5 +211,5 @@ QQmlListProperty StateMachine::children() The corresponding handler is \c onStopped. - \sa running, stop(), StateBase::finished + \sa running, stop(), State::finished */ diff --git a/src/imports/statemachine/statemachine.pro b/src/imports/statemachine/statemachine.pro index 4cc7089a32..9bb88074e9 100644 --- a/src/imports/statemachine/statemachine.pro +++ b/src/imports/statemachine/statemachine.pro @@ -8,7 +8,7 @@ QT = core-private qml-private SOURCES = \ $$PWD/finalstate.cpp \ $$PWD/signaltransition.cpp \ - $$PWD/statebase.cpp \ + $$PWD/state.cpp \ $$PWD/statemachine.cpp \ $$PWD/timeouttransition.cpp \ $$PWD/plugin.cpp @@ -17,7 +17,7 @@ HEADERS = \ $$PWD/childrenprivate.h \ $$PWD/finalstate.h \ $$PWD/signaltransition.h \ - $$PWD/statebase.h \ + $$PWD/state.h \ $$PWD/statemachine.h \ $$PWD/timeouttransition.h diff --git a/src/qml/doc/snippets/qml/statemachine/basicstate.qml b/src/qml/doc/snippets/qml/statemachine/basicstate.qml index dd9d100e9d..ccdd2b2ec1 100644 --- a/src/qml/doc/snippets/qml/statemachine/basicstate.qml +++ b/src/qml/doc/snippets/qml/statemachine/basicstate.qml @@ -39,15 +39,15 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { - StateMachine { + DSM.StateMachine { id: stateMachine initialState: state running: true - StateBase { + DSM.State { id: state } } diff --git a/src/qml/doc/snippets/qml/statemachine/finalstate.qml b/src/qml/doc/snippets/qml/statemachine/finalstate.qml index d03a4bce40..5865436a52 100644 --- a/src/qml/doc/snippets/qml/statemachine/finalstate.qml +++ b/src/qml/doc/snippets/qml/statemachine/finalstate.qml @@ -39,22 +39,22 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { - StateMachine { + DSM.StateMachine { id: stateMachine initialState: state running: true - StateBase { + DSM.State { id: state - TimeoutTransition { + DSM.TimeoutTransition { targetState: finalState timeout: 200 } } - FinalState { + DSM.FinalState { id: finalState } onFinished: console.log("state finished") diff --git a/src/qml/doc/snippets/qml/statemachine/guardcondition.qml b/src/qml/doc/snippets/qml/statemachine/guardcondition.qml index f9ecf450bd..3d4badb350 100644 --- a/src/qml/doc/snippets/qml/statemachine/guardcondition.qml +++ b/src/qml/doc/snippets/qml/statemachine/guardcondition.qml @@ -39,23 +39,23 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { Button { anchors.fill: parent id: button - StateMachine { - StateBase { - SignalTransition { + DSM.StateMachine { + DSM.State { + DSM.SignalTransition { targetState: finalState signal: button.mysignal // the guard condition uses the mystr string argument from mysignal guard: mystr == "test" } } - FinalState { + DSM.FinalState { id: finalState } } @@ -66,4 +66,3 @@ Rectangle { } } //! [document] - diff --git a/src/qml/doc/snippets/qml/statemachine/historystate.qml b/src/qml/doc/snippets/qml/statemachine/historystate.qml index 237cf57175..7559bfe06c 100644 --- a/src/qml/doc/snippets/qml/statemachine/historystate.qml +++ b/src/qml/doc/snippets/qml/statemachine/historystate.qml @@ -39,38 +39,38 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { Button { anchors.fill: parent id: button text: "Press me" - StateMachine { + DSM.StateMachine { id: stateMachine initialState: parentState running: true - StateBase { + DSM.State { id: parentState initialState: child2 onEntered: console.log("parentState entered") onExited: console.log("parentState exited") - StateBase { + DSM.State { id: child1 onEntered: console.log("child1 entered") onExited: console.log("child1 exited") } - StateBase { + DSM.State { id: child2 onEntered: console.log("child2 entered") onExited: console.log("child2 exited") } - HistoryState { + DSM.HistoryState { id: historyState defaultState: child1 } - SignalTransition { + DSM.SignalTransition { targetState: historyState // Clicking the button will cause the state machine to enter the child state diff --git a/src/qml/doc/snippets/qml/statemachine/signaltransition.qml b/src/qml/doc/snippets/qml/statemachine/signaltransition.qml index 7402ac089f..d00a103d7c 100644 --- a/src/qml/doc/snippets/qml/statemachine/signaltransition.qml +++ b/src/qml/doc/snippets/qml/statemachine/signaltransition.qml @@ -39,23 +39,23 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { - StateMachine { + DSM.StateMachine { id: stateMachine initialState: state running: true - StateBase { + DSM.State { id: state - SignalTransition { + DSM.SignalTransition { targetState: finalState signal: button.clicked guard: guardButton.checked } } - FinalState { + DSM.FinalState { id: finalState } onFinished: Qt.quit() diff --git a/src/qml/doc/snippets/qml/statemachine/signaltransitionsignal.qml b/src/qml/doc/snippets/qml/statemachine/signaltransitionsignal.qml index 44608fed36..90ebd70eb5 100644 --- a/src/qml/doc/snippets/qml/statemachine/signaltransitionsignal.qml +++ b/src/qml/doc/snippets/qml/statemachine/signaltransitionsignal.qml @@ -39,21 +39,21 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { Button { anchors.fill: parent id: button - StateMachine { - StateBase { - SignalTransition { + DSM.StateMachine { + DSM.State { + DSM.SignalTransition { targetState: finalState signal: button.clicked } } - FinalState { + DSM.FinalState { id: finalState } } diff --git a/src/qml/doc/snippets/qml/statemachine/simplestatemachine.qml b/src/qml/doc/snippets/qml/statemachine/simplestatemachine.qml index f5c6923cd1..4e5ea9b65c 100644 --- a/src/qml/doc/snippets/qml/statemachine/simplestatemachine.qml +++ b/src/qml/doc/snippets/qml/statemachine/simplestatemachine.qml @@ -39,26 +39,26 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { Button { anchors.fill: parent id: button text: "Finish state" - StateMachine { + DSM.StateMachine { id: stateMachine initialState: state running: true - StateBase { + DSM.State { id: state - SignalTransition { + DSM.SignalTransition { targetState: finalState signal: button.clicked } } - FinalState { + DSM.FinalState { id: finalState } onFinished: Qt.quit() diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml index 10595a9398..8f628232c1 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-history.qml @@ -39,8 +39,8 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 Rectangle { //![0] @@ -71,7 +71,7 @@ Rectangle { // start the state machine running: true - StateBase { + State { id: s1 // set the initial state initialState: s11 @@ -84,7 +84,7 @@ Rectangle { // do something when the state enters/exits onEntered: console.log("s1 entered") onExited: console.log("s1 exited") - StateBase { + State { id: s11 // create a transition from s1 to s2 when the button is clicked SignalTransition { @@ -96,7 +96,7 @@ Rectangle { onExited: console.log("s11 exited") } - StateBase { + State { id: s12 // create a transition from s2 to s3 when the button is clicked SignalTransition { @@ -107,7 +107,7 @@ Rectangle { onEntered: console.log("s12 entered") onExited: console.log("s12 exited") } - StateBase { + State { id: s13 // create a transition from s3 to s1 when the button is clicked SignalTransition { @@ -133,7 +133,7 @@ Rectangle { onEntered: console.log("s2 entered") onExited: console.log("s2 exited") } - StateBase { + State { id: s3 SignalTransition { targetState: s1h diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml index 00f9cd3871..bf84b4cc90 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested-ignore-quit.qml @@ -39,8 +39,8 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 Rectangle { Row { @@ -66,7 +66,7 @@ Rectangle { // start the state machine running: true - StateBase { + State { id: s1 // set the initial state initialState: s11 @@ -79,7 +79,7 @@ Rectangle { // do something when the state enters/exits onEntered: console.log("s1 entered") onExited: console.log("s1 exited") - StateBase { + State { id: s11 // create a transition from s11 to s12 when the button is clicked SignalTransition { @@ -92,7 +92,7 @@ Rectangle { } //![0] - StateBase { + State { id: s12 // create a transition from s12 to s13 when the button is clicked SignalTransition { @@ -112,7 +112,7 @@ Rectangle { } //![0] - StateBase { + State { id: s13 // create a transition from s13 to s11 when the button is clicked SignalTransition { diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml index 68bd57d85f..dfa093716f 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button-nested.qml @@ -39,8 +39,8 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 Rectangle { //![0] @@ -67,7 +67,7 @@ Rectangle { // start the state machine running: true - StateBase { + State { id: s1 // set the initial state initialState: s11 @@ -80,7 +80,7 @@ Rectangle { // do something when the state enters/exits onEntered: console.log("s1 entered") onExited: console.log("s1 exited") - StateBase { + State { id: s11 // create a transition from s11 to s12 when the button is clicked SignalTransition { @@ -92,7 +92,7 @@ Rectangle { onExited: console.log("s11 exited") } - StateBase { + State { id: s12 // create a transition from s12 to s13 when the button is clicked SignalTransition { @@ -103,7 +103,7 @@ Rectangle { onEntered: console.log("s12 entered") onExited: console.log("s12 exited") } - StateBase { + State { id: s13 // create a transition from s13 to s11 when the button is clicked SignalTransition { diff --git a/src/qml/doc/snippets/qml/statemachine/statemachine-button.qml b/src/qml/doc/snippets/qml/statemachine/statemachine-button.qml index f2817ead8b..6c4ed846e5 100644 --- a/src/qml/doc/snippets/qml/statemachine/statemachine-button.qml +++ b/src/qml/doc/snippets/qml/statemachine/statemachine-button.qml @@ -39,8 +39,8 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 Rectangle { //![0] @@ -60,7 +60,7 @@ Rectangle { // start the state machine running: true - StateBase { + State { id: s1 // create a transition from s1 to s2 when the button is clicked SignalTransition { @@ -72,7 +72,7 @@ Rectangle { onExited: console.log("s1 exited") } - StateBase { + State { id: s2 // create a transition from s2 to s3 when the button is clicked SignalTransition { @@ -83,7 +83,7 @@ Rectangle { onEntered: console.log("s2 entered") onExited: console.log("s2 exited") } - StateBase { + State { id: s3 // create a transition from s3 to s1 when the button is clicked SignalTransition { diff --git a/src/qml/doc/snippets/qml/statemachine/timeouttransition.qml b/src/qml/doc/snippets/qml/statemachine/timeouttransition.qml index b15c99cd22..7b8fa77b13 100644 --- a/src/qml/doc/snippets/qml/statemachine/timeouttransition.qml +++ b/src/qml/doc/snippets/qml/statemachine/timeouttransition.qml @@ -39,8 +39,8 @@ ****************************************************************************/ //! [document] -import QtQml.StateMachine 1.0 import QtQuick 2.0 +import QtQml.StateMachine 1.0 as DSM Rectangle { Button { @@ -49,18 +49,18 @@ Rectangle { text: "Finish state" enabled: !stateMachine.running onClicked: stateMachine.running = true - StateMachine { + DSM.StateMachine { id: stateMachine initialState: state running: true - StateBase { + DSM.State { id: state - TimeoutTransition { + DSM.TimeoutTransition { targetState: finalState timeout: 1000 } } - FinalState { + DSM.FinalState { id: finalState } } diff --git a/src/qml/doc/src/statemachine.qdoc b/src/qml/doc/src/statemachine.qdoc index 68c57055ca..f200f6f3c0 100644 --- a/src/qml/doc/src/statemachine.qdoc +++ b/src/qml/doc/src/statemachine.qdoc @@ -61,7 +61,39 @@ \annotatedlist statemachine-qmltypes - \section1 A Simple Example + \section1 Using both QtQuick and QtQml.StateMachine imports + + \warning If you're attempting to import both \l{QtQuick} and + \e{QtQml.StateMachine} in one single QML file, make sure to import + \e{QtQml.StateMachine} \e{last}. This way, the \e{State} type is provided + by the Declarative State Machine Framework and not by \l{QtQuick}: + + \qml + import QtQuick 2.0 + import QtQml.StateMachine 1.0 + + StateMachine { + State { + // okay, is of type QtQml.StateMachine.State + } + } + \endqml + + Alternatively, you can import \e{QtQml.StateMachine} into a separate + namespace to avoid any ambiguity with QtQuick's \e{State} item: + + \qml + import QtQuick 2.0 + import QtQml.StateMachine 1.0 as DSM + + DSM.StateMachine { + DSM.State { + // ... + } + } + \endqml + + \section1 A Simple State Machine To demonstrate the core functionality of the State Machine API, let's look at an example: A state machine with three states, \c s1, \c s2 and \c @@ -84,7 +116,7 @@ The state machine defined in the previous section never finishes. In order for a state machine to be able to finish, it needs to have a top-level \e final state (FinalState object). When the state machine enters the top-level - final state, the machine emits the \l{StateBase::finished}{finished} + final state, the machine emits the \l{State::finished}{finished} signal and halts. All you need to do to introduce a final state in the graph is create a @@ -191,13 +223,13 @@ To create a parallel state group, set childMode to QState.ParallelStates. \qml - StateBase { + State { id: s1 childMode: QState.ParallelStates - StateBase { + State { id: s11 } - StateBase { + State { id: s12 } } @@ -221,18 +253,18 @@ \section1 Exiting a Composite State A child state can be final (a FinalState object); when a final child state - is entered, the parent state emits the StateBase::finished signal. The + is entered, the parent state emits the State::finished signal. The following diagram shows a composite state \c s1 which does some processing before entering a final state: \image statemachine-finished.png When \c s1 's final state is entered, \c s1 will automatically emit - \l{StateBase::finished}{finished}. We use a signal transition to cause this event to + \l{State::finished}{finished}. We use a signal transition to cause this event to trigger a state change: \qml - StateBase { + State { id: s1 SignalTransition { targetState: s2 @@ -251,7 +283,7 @@ finished() signal, but with the consequence that implementation details of \c s1 are exposed and depended on). - For parallel state groups, the StateBase::finished signal is emitted when \e + For parallel state groups, the State::finished signal is emitted when \e all the child states have entered final states. \section1 Targetless Transitions @@ -270,7 +302,7 @@ id: stateMachine initialState: s1 running: true - StateBase { + State { id: s1 SignalTransition { signal: button.clicked diff --git a/tests/auto/qmltest/statemachine/tst_anonymousstate.qml b/tests/auto/qmltest/statemachine/tst_anonymousstate.qml index cce5f8dcb7..b05d5c67a9 100644 --- a/tests/auto/qmltest/statemachine/tst_anonymousstate.qml +++ b/tests/auto/qmltest/statemachine/tst_anonymousstate.qml @@ -31,12 +31,12 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { - StateBase { + State { } } name: "anonymousState" diff --git a/tests/auto/qmltest/statemachine/tst_guardcondition.qml b/tests/auto/qmltest/statemachine/tst_guardcondition.qml index 71171b2079..0390b5f8fa 100644 --- a/tests/auto/qmltest/statemachine/tst_guardcondition.qml +++ b/tests/auto/qmltest/statemachine/tst_guardcondition.qml @@ -39,15 +39,15 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { id: testCase StateMachine { id: machine initialState: startState - StateBase { + State { id: startState SignalTransition { id: signalTrans diff --git a/tests/auto/qmltest/statemachine/tst_historystate.qml b/tests/auto/qmltest/statemachine/tst_historystate.qml index f2fc110c24..6e2aa70417 100644 --- a/tests/auto/qmltest/statemachine/tst_historystate.qml +++ b/tests/auto/qmltest/statemachine/tst_historystate.qml @@ -31,8 +31,8 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { @@ -40,7 +40,7 @@ TestCase { id: stateMachine initialState: historyState1 - StateBase { + State { id: state1 SignalTransition { id: st1 @@ -48,14 +48,14 @@ TestCase { } } - StateBase { + State { id: state2 initialState: historyState2 HistoryState { id: historyState2 defaultState: state21 } - StateBase { + State { id: state21 } } diff --git a/tests/auto/qmltest/statemachine/tst_initialstate.qml b/tests/auto/qmltest/statemachine/tst_initialstate.qml index 6d5fbadf26..c08b3f7001 100644 --- a/tests/auto/qmltest/statemachine/tst_initialstate.qml +++ b/tests/auto/qmltest/statemachine/tst_initialstate.qml @@ -31,15 +31,15 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { id: myStateMachine initialState: myState; running: true - StateBase { + State { id: myState } } diff --git a/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml index 2906de2986..443771f8f4 100644 --- a/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml +++ b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml @@ -31,20 +31,20 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { id: myStateMachine initialState: parentState - StateBase { + State { id: parentState initialState: childState1 - StateBase { + State { id: childState1 } - StateBase { + State { id: childState2 } } diff --git a/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml b/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml index 41a2c2a852..f584b7cd01 100644 --- a/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml +++ b/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml @@ -31,23 +31,23 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { id: myStateMachine initialState: parentState - StateBase { + State { id: parentState initialState: childStateMachine StateMachine { id: childStateMachine initialState: childState2 - StateBase { + State { id: childState1 } - StateBase { + State { id: childState2 } } diff --git a/tests/auto/qmltest/statemachine/tst_parallelmachine.qml b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml index 0f35af0d99..2e3a5efdfd 100644 --- a/tests/auto/qmltest/statemachine/tst_parallelmachine.qml +++ b/tests/auto/qmltest/statemachine/tst_parallelmachine.qml @@ -31,30 +31,30 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { id: myStateMachine - childMode: StateBase.ParallelStates - StateBase { + childMode: State.ParallelStates + State { id: childState1 - childMode: StateBase.ParallelStates - StateBase { + childMode: State.ParallelStates + State { id: childState11 } - StateBase { + State { id: childState12 } } - StateBase { + State { id: childState2 initialState: childState21 - StateBase { + State { id: childState21 } - StateBase { + State { id: childState22 } } diff --git a/tests/auto/qmltest/statemachine/tst_trafficlight.qml b/tests/auto/qmltest/statemachine/tst_trafficlight.qml index 8a7cad8268..3f731a4014 100644 --- a/tests/auto/qmltest/statemachine/tst_trafficlight.qml +++ b/tests/auto/qmltest/statemachine/tst_trafficlight.qml @@ -31,8 +31,8 @@ ** ****************************************************************************/ -import QtQml.StateMachine 1.0 import QtTest 1.0 +import QtQml.StateMachine 1.0 TestCase { StateMachine { @@ -42,10 +42,10 @@ TestCase { id: finalState } - StateBase { + State { id: red initialState: justRed - StateBase { + State { id: justRed SignalTransition { id: e1 @@ -56,7 +56,7 @@ TestCase { targetState: finalState } } - StateBase { + State { id: waitingForGreen TimeoutTransition { id: e2 @@ -65,7 +65,7 @@ TestCase { } } } - StateBase { + State { id: yellowred TimeoutTransition { id: e3 @@ -73,7 +73,7 @@ TestCase { timeout: 10 } } - StateBase { + State { id: green TimeoutTransition { id: e4 @@ -81,7 +81,7 @@ TestCase { timeout: 50 } } - StateBase { + State { id: yellow TimeoutTransition { id: e5 -- cgit v1.2.3 From d6661ca409ebf1e4a2fa21fa4f084f63f70052e3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 20 Oct 2014 13:46:13 +0200 Subject: Fix failing makeCurrent in basic renderloop when closing windows The makeCurrent() call can fail if there is no underlying platform window present anymore (due to close()). Just continuing with the cleanup is wrong: There may be another context current (from the application or from some other component of Qt) and there are GL calls issued which would mess up the state in that context. Therefore we ensure there's a context/surface by using a temporary QOffscreenSurface. Task-number: QTBUG-41942 Change-Id: I79f35a1f5bbe7a8a14943e8603764575ed119f93 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgrenderloop.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index cd92d12d43..f2586b1e40 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -274,15 +275,30 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) m_windows.remove(window); hide(window); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); - if (gl) - gl->makeCurrent(window); + + bool current = false; + QScopedPointer offscreenSurface; + if (gl) { + QSurface *surface = window; + // There may be no platform window if the window got closed. + if (!window->handle()) { + offscreenSurface.reset(new QOffscreenSurface); + offscreenSurface->setFormat(gl->format()); + offscreenSurface->create(); + surface = offscreenSurface.data(); + } + current = gl->makeCurrent(surface); + } + if (Q_UNLIKELY(!current)) + qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context"; + d->cleanupNodesOnShutdown(); if (m_windows.size() == 0) { rc->invalidate(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); delete gl; gl = 0; - } else if (gl && window == gl->surface()) { + } else if (gl && window == gl->surface() && current) { gl->doneCurrent(); } } -- cgit v1.2.3 From db16f3e56e73846bc70eab08869dfb57706db2bf Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Wed, 10 Sep 2014 13:10:19 +0200 Subject: Improve hit testing so that it works better with ignored items The hit testing won't work very well with the upcoming patch that changes which items that can be ignored. (basically it doesn't consider the isAccessible flag, so childAt_helper might return a node that was supposed to be ignored) Earlier this was a sensible optimization in order to avoid too many heap allocations and deallocations of interfaces, but these are cheap now, so we can do it the do it the 'proper way' (i.e. before this patch we didn't respect the a11y hierarchy as given by QAccessibleInterface child() and parent(). This also uses the QAccessibleInterface::rect() directly now instead of using the itemScreenRect() function, which was shared between QAccessibleQuickWindow and QAccessibleQuickItem. Since this changes the order of child interfaces to paint order (i.e. second child interface is on top of first child interface), we need to ensure that we hit test child interfaces in the correct order. They should now always be processed with the last interface first, and then return as soon as something is hit. Change-Id: Ie951fc3b48b7affd9f7e98687a1cbbe008857d2a Reviewed-by: Frederik Gladhorn --- src/quick/accessible/qaccessiblequickitem.cpp | 60 ++++++++++++++++++++------- src/quick/accessible/qaccessiblequickitem_p.h | 2 + src/quick/accessible/qaccessiblequickview.cpp | 57 ++++--------------------- src/quick/accessible/qqmlaccessible.cpp | 21 ---------- src/quick/accessible/qqmlaccessible_p.h | 2 - 5 files changed, 57 insertions(+), 85 deletions(-) diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index c201076199..fe01326bbc 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -82,17 +82,42 @@ bool QAccessibleQuickItem::clipsChildren() const return static_cast(item())->clip(); } +QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const +{ + if (item()->clip()) { + if (!rect().contains(x, y)) + return 0; + } + + const QList kids = accessibleUnignoredChildren(item(), true); + for (int i = kids.count() - 1; i >= 0; --i) { + QAccessibleInterface *childIface = QAccessible::queryAccessibleInterface(kids.at(i)); + if (QAccessibleInterface *childChild = childIface->childAt(x, y)) + return childChild; + if (childIface && !childIface->state().invisible) { + if (childIface->rect().contains(x, y)) + return childIface; + } + } + + return 0; +} + QAccessibleInterface *QAccessibleQuickItem::parent() const { QQuickItem *parent = item()->parentItem(); + QQuickWindow *window = item()->window(); + QQuickItem *ci = window ? window->contentItem() : 0; + while (parent && parent != ci) + parent = parent->parentItem(); + if (parent) { - QQuickWindow *window = item()->window(); - // Jump out to the scene widget if the parent is the root item. - // There are two root items, QQuickWindow::rootItem and - // QQuickView::declarativeRoot. The former is the true root item, - // but is not a part of the accessibility tree. Check if we hit - // it here and return an interface for the scene instead. - if (window && (parent == window->contentItem())) { + if (parent == ci) { + // Jump out to the scene widget if the parent is the root item. + // There are two root items, QQuickWindow::rootItem and + // QQuickView::declarativeRoot. The former is the true root item, + // but is not a part of the accessibility tree. Check if we hit + // it here and return an interface for the scene instead. return QAccessible::queryAccessibleInterface(window); } else { return QAccessible::queryAccessibleInterface(parent); @@ -121,6 +146,19 @@ int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const return kids.indexOf(static_cast(iface->object())); } +QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +{ + QList items; + QList childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems() + : item->childItems(); + Q_FOREACH (QQuickItem *child, childItems) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); + if (itemPrivate->isAccessible) + items.append(child); + } + return items; +} + QList QAccessibleQuickItem::childItems() const { if ( role() == QAccessible::Button || @@ -133,13 +171,7 @@ QList QAccessibleQuickItem::childItems() const role() == QAccessible::ProgressBar) return QList(); - QList items; - Q_FOREACH (QQuickItem *child, item()->childItems()) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); - if (itemPrivate->isAccessible) - items.append(child); - } - return items; + return accessibleUnignoredChildren(item()); } QAccessible::State QAccessibleQuickItem::state() const diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h index 5cf120a802..84e82fff86 100644 --- a/src/quick/accessible/qaccessiblequickitem_p.h +++ b/src/quick/accessible/qaccessiblequickitem_p.h @@ -53,6 +53,7 @@ public: QRect viewRect() const; bool clipsChildren() const; + QAccessibleInterface *childAt(int x, int y) const; QAccessibleInterface *parent() const; QAccessibleInterface *child(int index) const; @@ -118,6 +119,7 @@ private: }; QRect itemScreenRect(QQuickItem *item); +QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder = false); #endif // QT_NO_ACCESSIBILITY diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp index cfd62b877d..db0b042d3b 100644 --- a/src/quick/accessible/qaccessiblequickview.cpp +++ b/src/quick/accessible/qaccessiblequickview.cpp @@ -53,7 +53,7 @@ QAccessibleQuickWindow::QAccessibleQuickWindow(QQuickWindow *object) QQuickItem *QAccessibleQuickWindow::rootItem() const { if (QQuickItem *ci = window()->contentItem()) { - const QList &childItems = ci->childItems(); + const QList &childItems = accessibleUnignoredChildren(ci); if (!childItems.isEmpty()) return childItems.first(); } @@ -110,56 +110,17 @@ QString QAccessibleQuickWindow::text(QAccessible::Text text) const return window()->title(); } - -/*! - \internal - - Can also return \a item itself - */ -static QQuickItem *childAt_helper(QQuickItem *item, int x, int y) -{ - if (!item->isVisible() || !item->isEnabled()) - return 0; - - if (item->flags() & QQuickItem::ItemClipsChildrenToShape) { - if (!itemScreenRect(item).contains(x, y)) - return 0; - } - - QAccessibleInterface *accessibleInterface = QAccessible::queryAccessibleInterface(item); - // this item has no Accessible attached property - if (!accessibleInterface) - return 0; - - if (accessibleInterface->childCount() == 0) { - return (itemScreenRect(item).contains(x, y)) ? item : 0; - } - - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - - QList children = itemPrivate->paintOrderChildItems(); - for (int i = children.count() - 1; i >= 0; --i) { - QQuickItem *child = children.at(i); - if (QQuickItem *childChild = childAt_helper(child, x, y)) - return childChild; - } - - QRect screenRect = itemScreenRect(item); - - if (screenRect.contains(x, y)) - return item; - - return 0; -} - QAccessibleInterface *QAccessibleQuickWindow::childAt(int x, int y) const { Q_ASSERT(window()); - QQuickItem *root = rootItem(); - if (root) { - if (QQuickItem *item = childAt_helper(root, x, y)) - return QAccessible::queryAccessibleInterface(item); - return QAccessible::queryAccessibleInterface(root); + for (int i = childCount() - 1; i >= 0; --i) { + QAccessibleInterface *childIface = child(i); + if (childIface && !childIface->state().invisible) { + if (QAccessibleInterface *iface = childIface->childAt(x, y)) + return iface; + if (childIface->rect().contains(x, y)) + return childIface; + } } return 0; } diff --git a/src/quick/accessible/qqmlaccessible.cpp b/src/quick/accessible/qqmlaccessible.cpp index 65d321d0a1..53eb6a7a0d 100644 --- a/src/quick/accessible/qqmlaccessible.cpp +++ b/src/quick/accessible/qqmlaccessible.cpp @@ -54,27 +54,6 @@ QQmlAccessible::~QQmlAccessible() { } -QAccessibleInterface *QQmlAccessible::childAt(int x, int y) const -{ - // Note that this function will disregard stacking order. - // (QAccessibleQuickView::childAt() does this correctly and more efficient) - - // If the item clips its children, we can return early if the coordinate is outside its rect - if (clipsChildren()) { - if (!rect().contains(x, y)) - return 0; - } - - for (int i = childCount() - 1; i >= 0; --i) { - QAccessibleInterface *childIface = child(i); - if (childIface && !childIface->state().invisible) { - if (childIface->rect().contains(x, y)) - return childIface; - } - } - return 0; -} - QAccessible::State QQmlAccessible::state() const { QAccessible::State state; diff --git a/src/quick/accessible/qqmlaccessible_p.h b/src/quick/accessible/qqmlaccessible_p.h index 38e3dcff59..5948f06cb5 100644 --- a/src/quick/accessible/qqmlaccessible_p.h +++ b/src/quick/accessible/qqmlaccessible_p.h @@ -64,7 +64,6 @@ public: void *interface_cast(QAccessible::InterfaceType t); virtual QRect viewRect() const = 0; - QAccessibleInterface *childAt(int, int) const; QAccessible::State state() const; QStringList actionNames() const; @@ -72,7 +71,6 @@ public: QStringList keyBindingsForAction(const QString &actionName) const; protected: - virtual bool clipsChildren() const = 0; // For subclasses, use instantiateObject factory method outside the class. QQmlAccessible(QObject *object); }; -- cgit v1.2.3 From f08338614578db9d98d7496b2a338d0e2dddc1bb Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 25 Sep 2014 11:40:21 +0200 Subject: Don't assume there is only one toplevel item. With the upcoming introduction of unignoredChildren, there can exist many top level items (if the root item is ignored). Change-Id: If7aaea08fdd4d1f5a0a5109e1239c53e0af9b61e Reviewed-by: Frederik Gladhorn --- src/quick/accessible/qaccessiblequickview.cpp | 31 +++++++++++++++------------ src/quick/accessible/qaccessiblequickview_p.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp index db0b042d3b..e3ee1d2722 100644 --- a/src/quick/accessible/qaccessiblequickview.cpp +++ b/src/quick/accessible/qaccessiblequickview.cpp @@ -50,19 +50,16 @@ QAccessibleQuickWindow::QAccessibleQuickWindow(QQuickWindow *object) { } -QQuickItem *QAccessibleQuickWindow::rootItem() const +QList QAccessibleQuickWindow::rootItems() const { - if (QQuickItem *ci = window()->contentItem()) { - const QList &childItems = accessibleUnignoredChildren(ci); - if (!childItems.isEmpty()) - return childItems.first(); - } - return 0; + if (QQuickItem *ci = window()->contentItem()) + return accessibleUnignoredChildren(ci); + return QList(); } int QAccessibleQuickWindow::childCount() const { - return rootItem() ? 1 : 0; + return rootItems().count(); } QAccessibleInterface *QAccessibleQuickWindow::parent() const @@ -73,8 +70,9 @@ QAccessibleInterface *QAccessibleQuickWindow::parent() const QAccessibleInterface *QAccessibleQuickWindow::child(int index) const { - if (index == 0) - return QAccessible::queryAccessibleInterface(rootItem()); + const QList &kids = rootItems(); + if (index >= 0 && index < kids.count()) + return QAccessible::queryAccessibleInterface(kids.at(index)); return 0; } @@ -127,12 +125,17 @@ QAccessibleInterface *QAccessibleQuickWindow::childAt(int x, int y) const int QAccessibleQuickWindow::indexOfChild(const QAccessibleInterface *iface) const { + int i = -1; if (iface) { - QQuickItem *declarativeRoot = rootItem(); - if (declarativeRoot == iface->object()) - return 0; + const QList &roots = rootItems(); + i = roots.count() - 1; + while (i >= 0) { + if (iface->object() == roots.at(i)) + break; + --i; + } } - return -1; + return i; } QT_END_NAMESPACE diff --git a/src/quick/accessible/qaccessiblequickview_p.h b/src/quick/accessible/qaccessiblequickview_p.h index 44a3bc047b..f6da6ba25d 100644 --- a/src/quick/accessible/qaccessiblequickview_p.h +++ b/src/quick/accessible/qaccessiblequickview_p.h @@ -60,7 +60,7 @@ public: private: QQuickWindow *window() const { return static_cast(object()); } - QQuickItem *rootItem() const; + QList rootItems() const; }; #endif // QT_NO_ACCESSIBILITY -- cgit v1.2.3 From 9ab2cd2d888705dcc4d103f7782b6df64d9b6d03 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 14 Oct 2014 15:14:13 +0200 Subject: QQuickSpriteEngine do not use OpenGL without checking for GLContext In the case that QQuickSpriteEngine::assembledImage() is called when there is no current OpenGL context, return a null QImage instead of crashing. This is needed for the Qt Quick 2d Renderer case. Change-Id: I75b9b1f31f05cc0800293435d660e498fecc4d20 Reviewed-by: aavit Reviewed-by: Gunnar Sletta --- src/quick/items/qquickspriteengine.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 645830c014..c5e70c9a8b 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -381,6 +381,10 @@ QImage QQuickSpriteEngine::assembledImage() m_imageStateCount = 0; int maxSize = 0; + //If there is no current OpenGL Context + if (!QOpenGLContext::currentContext()) + return QImage(); + QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize); #ifdef SPRITE_IMAGE_DEBUG qDebug() << "MAX TEXTURE SIZE" << maxSize; -- cgit v1.2.3 From 8c257264c1873dcf11115d738f9510c1b65da844 Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Tue, 14 Oct 2014 15:31:05 +0200 Subject: QQuickCustomParticle: Check for current OpenGL Context before use QQuickCustomParticle::buildCustomNodes() assumes there is a valid OpenGL context, but when there is not it will simply crash. Instead we check for a valid current OpenGL context first, and return 0 if it is not availalbe. This needed for the Qt Quick 2d Renderer. Change-Id: I6bfcfc8fa9581bfd27015f719fc527c36492eade Reviewed-by: aavit Reviewed-by: Gunnar Sletta --- src/particles/qquickcustomparticle.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index e03acd693a..2ab24175a3 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -303,6 +303,9 @@ QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffec QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes() { + if (!QOpenGLContext::currentContext()) + return 0; + if (QOpenGLContext::currentContext()->isOpenGLES() && m_count * 4 > 0xffff) { printf("CustomParticle: Too many particles... \n"); return 0; -- cgit v1.2.3 From 744ba012df4570ad14a07e9ad81a9002b6ab6ff3 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Fri, 22 Aug 2014 13:12:46 +0200 Subject: Fix a bug in implementation of Accessible.ignored m_ignored is not really used. (cherry-picked from dev branch: 2c42d6af19f57ae013da0a4c45b6e1de8fb99e99) Change-Id: Ic2926fbdf22a6a5bc82fe9f4475b7b8058eacae5 Reviewed-by: Frederik Gladhorn --- src/quick/items/qquickaccessibleattached.cpp | 2 +- src/quick/items/qquickaccessibleattached_p.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 0ec0d5e460..3f0ebab6f3 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -294,7 +294,7 @@ bool QQuickAccessibleAttached::ignored() const void QQuickAccessibleAttached::setIgnored(bool ignored) { - if (m_ignored != ignored) { + if (this->ignored() != ignored) { item()->d_func()->isAccessible = !ignored; emit ignoredChanged(); } diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 00659dc07a..270360895d 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -213,7 +213,6 @@ private: QAccessible::State m_state; QString m_name; QString m_description; - bool m_ignored; public: using QObject::property; -- cgit v1.2.3 From dbbb514a084440c05d17e44c7992726d94b26750 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 21 Oct 2014 13:53:43 +0200 Subject: Check list property before component when validating bindings There are lists that won't accept a component as element. For example QQuickItem's children will only accept QQuickItems. Task-number: QTBUG-41848 Change-Id: I0fc7b0d1a4770d596caf681be92dff216f48d32b Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmltypecompiler.cpp | 4 ++-- tests/auto/qml/qqmllanguage/data/badListItemType.errors.txt | 1 + tests/auto/qml/qqmllanguage/data/badListItemType.qml | 5 +++++ tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 8 ++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/badListItemType.errors.txt create mode 100644 tests/auto/qml/qqmllanguage/data/badListItemType.qml diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 6a97386767..3a27a859fd 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -2334,8 +2334,6 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co return true; } - if (isComponent(binding->value.objectIndex)) - return true; if (QQmlMetaType::isInterface(property->propType)) { // Can only check at instantiation time if the created sub-object successfully casts to the @@ -2354,6 +2352,8 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co } } return true; + } else if (isComponent(binding->value.objectIndex)) { + return true; } else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) { return true; } else if (QQmlValueTypeFactory::isValueType(property->propType)) { diff --git a/tests/auto/qml/qqmllanguage/data/badListItemType.errors.txt b/tests/auto/qml/qqmllanguage/data/badListItemType.errors.txt new file mode 100644 index 0000000000..76809dc9a1 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/badListItemType.errors.txt @@ -0,0 +1 @@ +4:15:Cannot assign object to list diff --git a/tests/auto/qml/qqmllanguage/data/badListItemType.qml b/tests/auto/qml/qqmllanguage/data/badListItemType.qml new file mode 100644 index 0000000000..d612bb47b9 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/badListItemType.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + children: Component { Item {} } // QTBUG-41848 +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index d6d2911285..ec3e38dd14 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -118,6 +118,7 @@ private slots: void dynamicProperties(); void dynamicPropertiesNested(); void listProperties(); + void badListItemType(); void dynamicObjectProperties(); void dynamicSignalsAndSlots(); void simpleBindings(); @@ -1332,6 +1333,13 @@ void tst_qqmllanguage::listProperties() QCOMPARE(object->property("test").toInt(), 2); } +void tst_qqmllanguage::badListItemType() +{ + QQmlComponent component(&engine, testFileUrl("badListItemType.qml")); + QVERIFY(component.isError()); + VERIFY_ERRORS("badListItemType.errors.txt"); +} + // Tests the creation and assignment of dynamic object properties // ### Not complete void tst_qqmllanguage::dynamicObjectProperties() -- cgit v1.2.3 From f28755240b9d72eb748c2f9469a58601bffdecf1 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Thu, 25 Sep 2014 11:41:44 +0200 Subject: Support Accessible.ignored on non-leaf items Ignoring items with children will make the children appear as children of the parent of the ignored item. Since setAccessibleFlagAndListener now only sets the flag we also rename the function to just setAccessible Change-Id: I79fc311509a3e454b4698274c63ad0e879fb93e3 Reviewed-by: Frederik Gladhorn --- src/quick/accessible/qaccessiblequickitem.cpp | 21 +++- src/quick/accessible/qaccessiblequickitem_p.h | 1 - src/quick/items/qquickaccessibleattached.cpp | 2 +- src/quick/items/qquickitem.cpp | 15 +-- src/quick/items/qquickitem_p.h | 2 +- tests/auto/quick/qquickaccessible/data/hittest.qml | 1 + tests/auto/quick/qquickaccessible/data/ignored.qml | 127 +++++++++++++++++++++ .../quick/qquickaccessible/qquickaccessible.pro | 9 +- .../qquickaccessible/tst_qquickaccessible.cpp | 33 ++++++ 9 files changed, 185 insertions(+), 26 deletions(-) create mode 100644 tests/auto/quick/qquickaccessible/data/ignored.qml diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index fe01326bbc..3f023ae621 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -108,7 +108,7 @@ QAccessibleInterface *QAccessibleQuickItem::parent() const QQuickItem *parent = item()->parentItem(); QQuickWindow *window = item()->window(); QQuickItem *ci = window ? window->contentItem() : 0; - while (parent && parent != ci) + while (parent && !QQuickItemPrivate::get(parent)->isAccessible && parent != ci) parent = parent->parentItem(); if (parent) { @@ -120,6 +120,8 @@ QAccessibleInterface *QAccessibleQuickItem::parent() const // it here and return an interface for the scene instead. return QAccessible::queryAccessibleInterface(window); } else { + while (parent && !parent->d_func()->isAccessible) + parent = parent->parentItem(); return QAccessible::queryAccessibleInterface(parent); } } @@ -146,16 +148,23 @@ int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const return kids.indexOf(static_cast(iface->object())); } -QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +static void unignoredChildren(QQuickItem *item, QList *items, bool paintOrder) { - QList items; QList childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems() : item->childItems(); Q_FOREACH (QQuickItem *child, childItems) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); - if (itemPrivate->isAccessible) - items.append(child); + if (QQuickItemPrivate::get(child)->isAccessible) { + items->append(child); + } else { + unignoredChildren(child, items, paintOrder); + } } +} + +QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +{ + QList items; + unignoredChildren(item, &items, paintOrder); return items; } diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h index 84e82fff86..e8486721f3 100644 --- a/src/quick/accessible/qaccessiblequickitem_p.h +++ b/src/quick/accessible/qaccessiblequickitem_p.h @@ -121,7 +121,6 @@ private: QRect itemScreenRect(QQuickItem *item); QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrder = false); - #endif // QT_NO_ACCESSIBILITY QT_END_NAMESPACE diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 3f0ebab6f3..59c0c2e8a0 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -266,7 +266,7 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) // Enable accessibility for items with accessible content. This also // enables accessibility for the ancestors of souch items. - item->d_func()->setAccessibleFlagAndListener(); + item->d_func()->setAccessible(); QAccessibleEvent ev(item, QAccessible::ObjectCreated); QAccessible::updateAccessibility(&ev); diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ebe136e556..a1376682af 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1607,17 +1607,9 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror) } } -void QQuickItemPrivate::setAccessibleFlagAndListener() +void QQuickItemPrivate::setAccessible() { - Q_Q(QQuickItem); - QQuickItem *item = q; - while (item) { - if (item->d_func()->isAccessible) - break; // already set - grandparents should have the flag set as well. - - item->d_func()->isAccessible = true; - item = item->d_func()->parentItem; - } + isAccessible = true; } /*! @@ -2584,9 +2576,6 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) d->itemChange(ItemParentHasChanged, d->parentItem); d->parentNotifier.notify(); - if (d->isAccessible && d->parentItem) { - d->parentItem->d_func()->setAccessibleFlagAndListener(); - } emit parentChanged(d->parentItem); if (isVisible() && d->parentItem) diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 4b54dc44af..7ef0f903b5 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -510,7 +510,7 @@ public: inline qreal rotation() const { return extra.isAllocated()?extra->rotation:0; } inline qreal opacity() const { return extra.isAllocated()?extra->opacity:1; } - void setAccessibleFlagAndListener(); + void setAccessible(); virtual qreal getImplicitWidth() const; virtual qreal getImplicitHeight() const; diff --git a/tests/auto/quick/qquickaccessible/data/hittest.qml b/tests/auto/quick/qquickaccessible/data/hittest.qml index 97eb6013a1..f081f5476e 100644 --- a/tests/auto/quick/qquickaccessible/data/hittest.qml +++ b/tests/auto/quick/qquickaccessible/data/hittest.qml @@ -41,6 +41,7 @@ Rectangle { height: 480 color: "white" Accessible.name: "root" + Accessible.role: Accessible.Client Rectangle { id: header color: "#c0c0c0" diff --git a/tests/auto/quick/qquickaccessible/data/ignored.qml b/tests/auto/quick/qquickaccessible/data/ignored.qml new file mode 100644 index 0000000000..1caf6ccb56 --- /dev/null +++ b/tests/auto/quick/qquickaccessible/data/ignored.qml @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +import QtQuick 2.0 +import "widgets" + + +Rectangle { + id: page + width: 640 + height: 480 + function col(str) { + return Qt.hsla((str.charCodeAt(0)-65)/9, 1.0, 0.5, 1) + } + color: col(Accessible.name) + Accessible.name: "A" + Accessible.role: Accessible.StaticText + + Rectangle { + id: b + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "B" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 20 + width: 80 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.ignored: true + Accessible.name: "C" + Accessible.role: Accessible.StaticText + + Rectangle { + width: 20 + color: col(Accessible.name) + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + Accessible.name: "E" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 20 + width: 20 + color: col(Accessible.name) + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + Accessible.name: "F" + Accessible.role: Accessible.StaticText + } + + Rectangle { + x: 40 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.ignored: true + Accessible.name: "G" + Accessible.role: Accessible.StaticText + Rectangle { + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "I" + Accessible.role: Accessible.StaticText + } + } + Rectangle { + x: 60 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "H" + Accessible.role: Accessible.StaticText + } + } + + Rectangle { + x: 100 + width: 20 + height: parent.height/2 + anchors.verticalCenter: parent.verticalCenter + color: col(Accessible.name) + Accessible.name: "D" + Accessible.role: Accessible.StaticText + } +} diff --git a/tests/auto/quick/qquickaccessible/qquickaccessible.pro b/tests/auto/quick/qquickaccessible/qquickaccessible.pro index 99c3834147..bdbe2e3fb4 100644 --- a/tests/auto/quick/qquickaccessible/qquickaccessible.pro +++ b/tests/auto/quick/qquickaccessible/qquickaccessible.pro @@ -10,10 +10,11 @@ include (../../shared/util.pri) TESTDATA = data/* -OTHER_FILES += data/checkbuttons.qml -OTHER_FILES += data/hittest.qml -OTHER_FILES += data/pushbutton.qml -OTHER_FILES += data/statictext.qml +OTHER_FILES += data/checkbuttons.qml \ + data/hittest.qml \ + data/pushbutton.qml \ + data/statictext.qml \ + data/ignored.qml \ CONFIG += parallel_test diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp index c514f96d24..921c81ae89 100644 --- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp +++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp @@ -106,6 +106,7 @@ private slots: void basicPropertiesTest(); void hitTest(); void checkableTest(); + void ignoredTest(); }; tst_QQuickAccessible::tst_QQuickAccessible() @@ -456,6 +457,38 @@ void tst_QQuickAccessible::checkableTest() QTestAccessibility::clearEvents(); } +void tst_QQuickAccessible::ignoredTest() +{ + QScopedPointer window(new QQuickView()); + window->setSource(testFileUrl("ignored.qml")); + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QQuickItem *contentItem = window->contentItem(); + QVERIFY(contentItem); + QQuickItem *rootItem = contentItem->childItems().first(); + QVERIFY(rootItem); + + // the window becomes active + QAccessible::State activatedChange; + activatedChange.active = true; + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data()); + QVERIFY(iface); + QAccessibleInterface *rectangleA = iface->child(0); + + QCOMPARE(rectangleA->role(), QAccessible::StaticText); + QCOMPARE(rectangleA->text(QAccessible::Name), QLatin1String("A")); + static const char *expected = "BEFIHD"; + // check if node "C" and "G" is skipped and that the order is as expected. + for (int i = 0; i < rectangleA->childCount(); ++i) { + QAccessibleInterface *child = rectangleA->child(i); + QCOMPARE(child->text(QAccessible::Name), QString(QLatin1Char(expected[i]))); + } + QTestAccessibility::clearEvents(); +} + QTEST_MAIN(tst_QQuickAccessible) #include "tst_qquickaccessible.moc" -- cgit v1.2.3 From d8447fd1b95e6a3f85e7aaed74755e95ecc91dc8 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 21 Oct 2014 19:50:54 +0200 Subject: Add \since 5.4 to FontMetrics and TextMetrics. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5fa93d559cdfde5e6b84ab0f3f35fd600e6bec4f Reviewed-by: Topi Reiniö --- src/quick/util/qquickfontmetrics.cpp | 1 + src/quick/util/qquicktextmetrics.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/quick/util/qquickfontmetrics.cpp b/src/quick/util/qquickfontmetrics.cpp index a447d3cda0..b65ad3f1ea 100644 --- a/src/quick/util/qquickfontmetrics.cpp +++ b/src/quick/util/qquickfontmetrics.cpp @@ -41,6 +41,7 @@ QT_BEGIN_NAMESPACE \qmltype FontMetrics \instantiates QQuickFontMetrics \inqmlmodule QtQuick + \since 5.4 \ingroup qtquick-text-utility \brief Provides metrics for a given font diff --git a/src/quick/util/qquicktextmetrics.cpp b/src/quick/util/qquicktextmetrics.cpp index 6d31ef582d..fc5b6f11c4 100644 --- a/src/quick/util/qquicktextmetrics.cpp +++ b/src/quick/util/qquicktextmetrics.cpp @@ -41,6 +41,7 @@ QT_BEGIN_NAMESPACE \qmltype TextMetrics \instantiates QQuickTextMetrics \inqmlmodule QtQuick + \since 5.4 \ingroup qtquick-text-utility \brief Provides metrics for a given font and text -- cgit v1.2.3 From 9b965f3fa0899e27667aba4c437206fdf7a14969 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 22 Oct 2014 10:27:46 +0200 Subject: Fix disfunctional QQuickRenderControl with multiple screens Having a retina and non-retina screen connected resulted in getting no output from QQuickRenderControl and QQuickWidget on the non-retina screen. This is caused by the fact that Quick is blindly calling QWindow::devicePixelRatio(). This approach is wrong when using QQuickRenderControl since the QQuickWindow does not have an actual native window and so devicePixelRatio() merely returns some default value which will definitely be wrong for one of the screens. The patch fixes the problem by introducing QQuickWindow::effectiveDevicePixelRatio(), which, via QQuickRenderControl::renderWindowFor, supports the redirected case too. Task-number: QTBUG-42114 Change-Id: I057e01f0a00758dde438fc9b10af3a435b06bb0b Reviewed-by: Paul Olav Tvete --- src/quick/items/qquickimagebase.cpp | 2 +- src/quick/items/qquickrendercontrol.cpp | 2 +- src/quick/items/qquickshadereffectsource.cpp | 4 ++-- src/quick/items/qquickwindow.cpp | 23 ++++++++++++++++++++--- src/quick/items/qquickwindow.h | 2 ++ src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 13 +++++++++++-- src/quick/scenegraph/qsgrenderloop.cpp | 2 +- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 2 +- src/quick/scenegraph/qsgwindowsrenderloop.cpp | 2 +- src/quickwidgets/qquickwidget.cpp | 2 +- 10 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 5ec3e81727..1a5d115a3c 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -206,7 +206,7 @@ void QQuickImageBase::load() options |= QQuickPixmap::Cache; d->pix.clear(this); - const qreal targetDevicePixelRatio = (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio()); + const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio()); d->devicePixelRatio = 1.0; QUrl loadUrl = d->url; diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 79db80595b..7ccd3a0fb4 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -318,7 +318,7 @@ QImage QQuickRenderControl::grab() return QImage(); render(); - QImage grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->devicePixelRatio(), false, false); + QImage grabContent = qt_gl_read_framebuffer(d->window->size() * d->window->effectiveDevicePixelRatio(), false, false); return grabContent; } diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index 52e5ba2464..ccff98828c 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -628,7 +628,7 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint // Crate large textures on high-dpi displays. if (sourceItem()) - textureSize *= d->window->devicePixelRatio(); + textureSize *= d->window->effectiveDevicePixelRatio(); const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize(); // Keep power-of-two by doubling the size. @@ -637,7 +637,7 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint while (textureSize.height() < minTextureSize.height()) textureSize.rheight() *= 2; - m_texture->setDevicePixelRatio(d->window->devicePixelRatio()); + m_texture->setDevicePixelRatio(d->window->effectiveDevicePixelRatio()); m_texture->setSize(textureSize); m_texture->setRecursive(m_recursive); m_texture->setFormat(GLenum(m_format)); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 4ec901ceb4..f6c1412aff 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -365,7 +365,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) emit q->beforeRendering(); runAndClearJobs(&beforeRenderingJobs); int fboId = 0; - const qreal devicePixelRatio = q->devicePixelRatio(); + const qreal devicePixelRatio = q->effectiveDevicePixelRatio(); renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio)); if (renderTargetId) { fboId = renderTargetId; @@ -374,7 +374,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio)); } renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size)); - renderer->setDevicePixelRatio(q->devicePixelRatio()); + renderer->setDevicePixelRatio(devicePixelRatio); context->renderNextFrame(renderer, fboId); emit q->afterRendering(); @@ -3160,7 +3160,7 @@ QImage QQuickWindow::grabWindow() d->syncSceneGraph(); d->renderSceneGraph(size()); - QImage image = qt_gl_read_framebuffer(size() * devicePixelRatio(), false, false); + QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), false, false); d->cleanupNodesOnShutdown(); d->context->invalidate(); context.doneCurrent(); @@ -3923,6 +3923,23 @@ void QQuickWindow::runJobsAfterSwap() d->runAndClearJobs(&d->afterSwapJobs); } +/*! + * Returns the device pixel ratio for this window. + * + * This is different from QWindow::devicePixelRatio() in that it supports + * redirected rendering via QQuickRenderControl. When using a + * QQuickRenderControl, the QQuickWindow is often not created, meaning it is + * never shown and there is no underlying native window created in the + * windowing system. As a result, querying properties like the device pixel + * ratio cannot give correct results. Use this function instead. + * + * \sa QWindow::devicePixelRatio() + */ +int QQuickWindow::effectiveDevicePixelRatio() const +{ + QWindow *w = QQuickRenderControl::renderWindowFor(const_cast(this)); + return w ? w->devicePixelRatio() : devicePixelRatio(); +} #include "moc_qquickwindow.cpp" diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index b52d6b807e..3cac691963 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -142,6 +142,8 @@ public: void scheduleRenderJob(QRunnable *job, RenderStage schedule); + int effectiveDevicePixelRatio() const; + Q_SIGNALS: void frameSwapped(); Q_REVISION(2) void openglContextCreated(QOpenGLContext *context); diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 802c92be9f..b30a504da9 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -350,8 +351,16 @@ void QSGTextMaskMaterial::init(QFontEngine::GlyphFormat glyphFormat) : QFontEngine::Format_A32; } - qreal devicePixelRatio = ctx->surface()->surfaceClass() == QSurface::Window ? - static_cast(ctx->surface())->devicePixelRatio() : ctx->screen()->devicePixelRatio(); + qreal devicePixelRatio; + if (ctx->surface()->surfaceClass() == QSurface::Window) { + QWindow *w = static_cast(ctx->surface()); + if (QQuickWindow *qw = qobject_cast(w)) + devicePixelRatio = qw->effectiveDevicePixelRatio(); + else + devicePixelRatio = w->devicePixelRatio(); + } else { + devicePixelRatio = ctx->screen()->devicePixelRatio(); + } QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio); if (!fontEngine->supportsTransformation(glyphCacheTransform)) diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index f2586b1e40..c66915d19d 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -372,7 +372,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) renderTime = renderTimer.nsecsElapsed(); if (data.grabOnly) { - grabContent = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); + grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false); data.grabOnly = false; } diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 7ac5f0a921..155b52b31a 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -417,7 +417,7 @@ bool QSGRenderThread::event(QEvent *e) QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result"; - *ce->image = qt_gl_read_framebuffer(windowSize * window->devicePixelRatio(), false, false); + *ce->image = qt_gl_read_framebuffer(windowSize * window->effectiveDevicePixelRatio(), false, false); } qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result"; waitCondition.wakeOne(); diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 10eba74607..070d6b82fd 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -286,7 +286,7 @@ QImage QSGWindowsRenderLoop::grab(QQuickWindow *window) d->syncSceneGraph(); d->renderSceneGraph(window->size()); - QImage image = qt_gl_read_framebuffer(window->size() * window->devicePixelRatio(), false, false); + QImage image = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false); return image; } diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index ef6c174b88..4c40288cd0 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -735,7 +735,7 @@ void QQuickWidget::createFramebufferObject() format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); format.setSamples(samples); - QSize fboSize = size() * window()->devicePixelRatio(); + const QSize fboSize = size() * devicePixelRatio(); // Could be a simple hide - show, in which case the previous fbo is just fine. if (!d->fbo || d->fbo->size() != fboSize) { -- cgit v1.2.3 From dd40295c31cacb2560e5c1ac25e217fd497600a3 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Tue, 21 Oct 2014 17:12:30 +0200 Subject: Fix a PIDLIST_ABSOLUTE leak in QQmlEngine on Windows The documentation of SHParseDisplayName doesn't mention that you need to free the ppidl parameter, but the documentation of the ITEMIDLIST does mention that you need to ILFree any ITEMIDLIST passed as PIDLIST_ABSOLUTE. Reproduced the leak by repeatedly showing and closing the window on the task's example. Task-number: QTBUG-41588 Change-Id: I91d08728fc907c59e56ae344a2d12f0865031120 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlengine.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 2b69661c4b..fd8de555af 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -2305,8 +2305,12 @@ static inline QString shellNormalizeFileName(const QString &name) return name; #endif TCHAR buffer[MAX_PATH]; - if (!SHGetPathFromIDList(file, buffer)) + bool gotPath = SHGetPathFromIDList(file, buffer); + ILFree(file); + + if (!gotPath) return name; + QString canonicalName = QString::fromWCharArray(buffer); // Upper case drive letter if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':')) -- cgit v1.2.3 From ed7a6358e35f5fdaf7468371a8b29aa6a3ef0fe7 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 16 Oct 2014 11:06:32 +0200 Subject: Add note to QQuickItem docs about directly setting properties in C++. It's not obvious that calling setPosition() directly, for example, won't trigger animations defined in behaviors that react to that item's x and y properties changing, because a quick glance at the code shows that they have almost identical code paths and both emit geometryChanged(). Change-Id: Ic7f7019b1bbba24732569c0de777ee02d79c1d3b Reviewed-by: Gunnar Sletta --- src/quick/items/qquickitem.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a1376682af..0fb8d0e2f8 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -1749,6 +1749,19 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus) surface. Using scene graph API directly is always significantly faster. + \section1 Behavior Animations + + If your Item uses the \l Behavior type to define animations for property + changes, you should always use either QObject::setProperty(), + QQmlProperty(), or QMetaProperty::write() when you need to modify those + properties from C++. This ensures that the QML engine knows about the + property change. Otherwise, the engine won't be able to carry out your + requested animation. For example, if you call \l setPosition() directly, + any behavior that reacts to changes in the x or y properties will not take + effect, as you are bypassing Qt's meta-object system. Note that these + functions incur a slight performance penalty. For more details, see + \l {Accessing Members of a QML Object Type from C++}. + \sa QQuickWindow, QQuickPaintedItem */ -- cgit v1.2.3 From 3950a2694e6a327b84f037a2357014343d994a41 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 22 Oct 2014 14:57:51 +0200 Subject: Fix line ending for test file Task-number: QTBUG-40574 Change-Id: If1fcc4cb00c8e477b3afff92eb4a3099424fcfa6 Reviewed-by: Lars Knoll --- tests/auto/qml/qqmlecmascript/data/updateCall.qml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/auto/qml/qqmlecmascript/data/updateCall.qml b/tests/auto/qml/qqmlecmascript/data/updateCall.qml index 341a360d25..d310dcac9e 100644 --- a/tests/auto/qml/qqmlecmascript/data/updateCall.qml +++ b/tests/auto/qml/qqmlecmascript/data/updateCall.qml @@ -1,10 +1,10 @@ -import QtQuick 2.1 - -Rectangle { - MouseArea { - anchors.fill: parent; - Component.onCompleted: { - update(); - } - } -} +import QtQuick 2.1 + +Rectangle { + MouseArea { + anchors.fill: parent; + Component.onCompleted: { + update(); + } + } +} -- cgit v1.2.3 From 9a66bb751bb5f5830e5f30a3c1a22ddb5f34f1bb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 21 Oct 2014 11:05:00 +0200 Subject: Reduce memory pressure on the JS stack during garbage collection As the example in QTBUG-42051 demonstrates, QML may produce a lot of binding objects and each of them produce a QV4::Persistent. During the mark phase we may run out of JS stack space. One fix (for the future) is to reduce the number of QV4::Persistent objects, but in the meantime we can also reduce the pressure on the stack by draining it earlier. Task-number: QTBUG-42051 Change-Id: Iea73f8a869048ea0bf3f4a64dbd24b6fb8c68f6b Reviewed-by: Ulf Hermann --- src/qml/jsruntime/qv4mm.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index 0cb10b1506..442a27661b 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -255,6 +255,15 @@ Managed *MemoryManager::allocData(std::size_t size) return m; } +static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) +{ + while (engine->jsStackTop > markBase) { + Managed *m = engine->popForGC(); + Q_ASSERT (m->internalClass()->vtable->markObjects); + m->internalClass()->vtable->markObjects(m, engine); + } +} + void MemoryManager::mark() { Value *markBase = m_d->engine->jsStackTop; @@ -272,6 +281,9 @@ void MemoryManager::mark() } persistent->value.mark(m_d->engine); persistent = persistent->next; + + if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit) + drainMarkStack(m_d->engine, markBase); } collectFromJSStack(); @@ -304,14 +316,12 @@ void MemoryManager::mark() if (keepAlive) qobjectWrapper->getPointer()->mark(m_d->engine); - } - // now that we marked all roots, start marking recursively and popping from the mark stack - while (m_d->engine->jsStackTop > markBase) { - Managed *m = m_d->engine->popForGC(); - Q_ASSERT (m->internalClass()->vtable->markObjects); - m->internalClass()->vtable->markObjects(m, m_d->engine); + if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit) + drainMarkStack(m_d->engine, markBase); } + + drainMarkStack(m_d->engine, markBase); } void MemoryManager::sweep(bool lastSweep) -- cgit v1.2.3 From 5a5db3681fe5f236cbfbddd45f48ae669c7742c5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 22 Oct 2014 11:59:02 +0200 Subject: Add high dpi support to QQuickFramebufferObject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I58aa163bd17fae7190161641d94f51887d8f88a6 Reviewed-by: Morten Johan Sørvig Reviewed-by: Gunnar Sletta --- src/quick/items/qquickframebufferobject.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index dc4668be3f..09a25f4efa 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -161,6 +161,7 @@ public: , renderer(0) , renderPending(true) , invalidatePending(false) + , devicePixelRatio(1) { qsgnode_set_description(this, QStringLiteral("fbonode")); } @@ -202,14 +203,25 @@ public Q_SLOTS: } } + void handleScreenChange() + { + if (window->effectiveDevicePixelRatio() != devicePixelRatio) { + renderer->invalidateFramebufferObject(); + quickFbo->update(); + } + } + public: QQuickWindow *window; QOpenGLFramebufferObject *fbo; QOpenGLFramebufferObject *msDisplayFbo; QQuickFramebufferObject::Renderer *renderer; + QQuickFramebufferObject *quickFbo; bool renderPending; bool invalidatePending; + + int devicePixelRatio; }; /*! @@ -239,7 +251,9 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode n->window = window(); n->renderer = createRenderer(); n->renderer->data = n; + n->quickFbo = this; connect(window(), SIGNAL(beforeRendering()), n, SLOT(render())); + connect(window(), SIGNAL(screenChanged(QScreen*)), n, SLOT(handleScreenChange())); } n->renderer->synchronize(this); @@ -248,6 +262,9 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode QSize desiredFboSize(qMax(minFboSize.width(), width()), qMax(minFboSize.height(), height())); + n->devicePixelRatio = window()->effectiveDevicePixelRatio(); + desiredFboSize *= n->devicePixelRatio; + if (n->fbo && (d->followsItemSize || n->invalidatePending)) { if (n->fbo->size() != desiredFboSize) { delete n->fbo; @@ -414,6 +431,12 @@ void QQuickFramebufferObject::Renderer::invalidateFramebufferObject() * \note Some hardware has issues with small FBO sizes. \a size takes that into account, so * be cautious when overriding the size with a fixed size. A minimal size of 64x64 should * always work. + * + * \note \a size takes the device pixel ratio into account, meaning that it is + * already multiplied by the correct scale factor. When moving the window + * containing the QQuickFramebufferObject item to a screen with different + * settings, the FBO is automatically recreated and this function is invoked + * with the correct size. */ QOpenGLFramebufferObject *QQuickFramebufferObject::Renderer::createFramebufferObject(const QSize &size) { -- cgit v1.2.3 From a1b43cb272ff05bd8c681d4d6320dcfee7339d84 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Mon, 20 Oct 2014 15:46:58 +0200 Subject: Fix non-compiling QtQml code snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-42006 Change-Id: I3c59b0ba27518750cba667f414f58edaa136d250 Reviewed-by: Topi Reiniö Reviewed-by: Jerome Pasion --- src/qml/doc/snippets/qml/qtbinding/variantlistmap/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/doc/snippets/qml/qtbinding/variantlistmap/main.cpp b/src/qml/doc/snippets/qml/qtbinding/variantlistmap/main.cpp index 60ce955a19..f3879e0785 100644 --- a/src/qml/doc/snippets/qml/qtbinding/variantlistmap/main.cpp +++ b/src/qml/doc/snippets/qml/qtbinding/variantlistmap/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) { QQuickView view(QUrl::fromLocalFile("MyItem.qml")); QVariantList list; -list << 10 << Qt::green << "bottles"; +list << 10 << QColor(Qt::green) << "bottles"; QVariantMap map; map.insert("language", "QML"); -- cgit v1.2.3 From e2764c722571025835e41632637d1421ba44fb02 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 17 Oct 2014 14:24:07 +0200 Subject: Screen attached property: expose devicePixelRatio property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I08b22766b3e389b7d27ca4c56729f550b0647a08 Reviewed-by: Jens Bache-Wiig Reviewed-by: Richard Moe Gustavsen Reviewed-by: Morten Johan Sørvig --- examples/quick/window/ScreenInfo.qml | 5 ++++- src/quick/items/qquickscreen.cpp | 18 ++++++++++++++++++ src/quick/items/qquickscreen_p.h | 3 +++ tests/auto/quick/qquickscreen/data/screen.qml | 1 + tests/auto/quick/qquickscreen/tst_qquickscreen.cpp | 2 ++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/examples/quick/window/ScreenInfo.qml b/examples/quick/window/ScreenInfo.qml index 73700720d8..d0a233f759 100644 --- a/examples/quick/window/ScreenInfo.qml +++ b/examples/quick/window/ScreenInfo.qml @@ -38,7 +38,7 @@ ** ****************************************************************************/ -import QtQuick 2.1 +import QtQuick 2.3 import QtQuick.Window 2.1 Item { @@ -85,6 +85,9 @@ Item { Text { text: "logical pixel density" } Text { text: Screen.logicalPixelDensity.toFixed(2) + " dots/mm (" + (Screen.logicalPixelDensity * 25.4).toFixed(2) + " dots/inch)" } + Text { text: "device pixel ratio" } + Text { text: Screen.devicePixelRatio.toFixed(2) } + Text { text: "available virtual desktop" } Text { text: Screen.desktopAvailableWidth + "x" + Screen.desktopAvailableHeight } diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index 926ac7b4ee..8ac5a1e292 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -141,6 +141,15 @@ QT_BEGIN_NAMESPACE The number of physical pixels per millimeter. */ +/*! + \qmlattachedproperty real Screen::devicePixelRatio + \readonly + \since 5.4 + + The ratio between physical pixels and device-independent pixels for the screen. + + Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays. +*/ /*! \qmlattachedproperty Qt::ScreenOrientation Screen::primaryOrientation \readonly @@ -260,6 +269,13 @@ qreal QQuickScreenAttached::pixelDensity() const return m_screen->physicalDotsPerInch() / 25.4; } +qreal QQuickScreenAttached::devicePixelRatio() const +{ + if (!m_screen) + return 1.0; + return m_screen->devicePixelRatio(); +} + Qt::ScreenOrientation QQuickScreenAttached::primaryOrientation() const { if (!m_screen) @@ -340,6 +356,8 @@ void QQuickScreenAttached::screenChanged(QScreen *screen) emit logicalPixelDensityChanged(); if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) emit pixelDensityChanged(); + if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) + emit devicePixelRatioChanged(); connect(screen, SIGNAL(geometryChanged(QRect)), this, SIGNAL(widthChanged())); diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index d661cc6f56..257b18cfe0 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -57,6 +57,7 @@ class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject Q_PROPERTY(int desktopAvailableHeight READ desktopAvailableHeight NOTIFY desktopGeometryChanged) Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged) Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY pixelDensityChanged) + Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged) // TODO Qt 6 Rename primaryOrientation to orientation Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged) // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor @@ -74,6 +75,7 @@ public: int desktopAvailableHeight() const; qreal logicalPixelDensity() const; qreal pixelDensity() const; + qreal devicePixelRatio() const; Qt::ScreenOrientation primaryOrientation() const; Qt::ScreenOrientation orientation() const; Qt::ScreenOrientations orientationUpdateMask() const; @@ -91,6 +93,7 @@ Q_SIGNALS: void desktopGeometryChanged(); void logicalPixelDensityChanged(); void pixelDensityChanged(); + void devicePixelRatioChanged(); void primaryOrientationChanged(); void orientationChanged(); void orientationUpdateMaskChanged(); diff --git a/tests/auto/quick/qquickscreen/data/screen.qml b/tests/auto/quick/qquickscreen/data/screen.qml index dc3803f4e3..c246b3cd83 100644 --- a/tests/auto/quick/qquickscreen/data/screen.qml +++ b/tests/auto/quick/qquickscreen/data/screen.qml @@ -9,6 +9,7 @@ Item { property int curOrientation: Window.Screen.orientation property int priOrientation: Window.Screen.primaryOrientation property int updateMask: Window.Screen.orientationUpdateMask + property real devicePixelRatio: Window.Screen.devicePixelRatio Window.Screen.orientationUpdateMask: Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation } diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp index be543e8022..70ecff51eb 100644 --- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp +++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp @@ -63,6 +63,8 @@ void tst_qquickscreen::basicProperties() QCOMPARE(int(screen->orientation()), root->property("curOrientation").toInt()); QCOMPARE(int(screen->primaryOrientation()), root->property("priOrientation").toInt()); QCOMPARE(int(screen->orientationUpdateMask()), root->property("updateMask").toInt()); + QCOMPARE(screen->devicePixelRatio(), root->property("devicePixelRatio").toReal()); + QVERIFY(screen->devicePixelRatio() >= 1.0); } QTEST_MAIN(tst_qquickscreen) -- cgit v1.2.3 From 40a6845bcce22aca96e1dee26360bdff3e9520fb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 22 Oct 2014 16:47:01 +0200 Subject: Fix assignment to QObject pointer properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit ammends 59ed8c355b99df0b949003a438ab850274261aa0 to always query the Qt meta-type registry to retrieve the QMetaObject for a QObject pointer type. Change-Id: I70d876a5acfa23967fd1a57c96fcd5ac853eaf49 Task-number: QTBUG-39614 Reviewed-by: Jędrzej Nowacki Reviewed-by: Ulf Hermann --- src/qml/qml/qqmlproperty.cpp | 9 ++++---- tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp | 28 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 09b735ae9e..2a888b7a1e 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1611,15 +1611,14 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType) { - if (engine) { + QMetaType metaType(userType); + if ((metaType.flags() & QMetaType::PointerToQObject) && metaType.metaObject()) + return metaType.metaObject(); + if (engine) return engine->rawMetaObjectForType(userType); - } QQmlType *type = QQmlMetaType::qmlType(userType); if (type) return QQmlMetaObject(type->baseMetaObject()); - QMetaType metaType(userType); - if ((metaType.flags() & QMetaType::PointerToQObject) && metaType.metaObject()) - return metaType.metaObject(); return QQmlMetaObject((QObject*)0); } diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp index 6cd1eafafd..62ccec5794 100644 --- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp +++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp @@ -1157,6 +1157,17 @@ void tst_qqmlproperty::read() QVERIFY(v.canConvert(QMetaType::QObjectStar)); QVERIFY(qvariant_cast(v) == o.qObject()); } + { + QQmlEngine engine; + PropertyObject o; + QQmlProperty p(&o, "qObject", &engine); + QCOMPARE(p.propertyTypeCategory(), QQmlProperty::Object); + + QCOMPARE(p.propertyType(), qMetaTypeId()); + QVariant v = p.read(); + QVERIFY(v.canConvert(QMetaType::QObjectStar)); + QVERIFY(qvariant_cast(v) == o.qObject()); + } // Object property { @@ -1432,6 +1443,23 @@ void tst_qqmlproperty::write() QCOMPARE(newData.value(), newObject); QCOMPARE(newData.value(), newObject); } + { + QQmlEngine engine; + PropertyObject o; + QQmlProperty p(&o, QString("qObject"), &engine); + QCOMPARE(o.qObject(), (QObject*)0); + QObject *newObject = new MyQObject(this); + QCOMPARE(p.write(QVariant::fromValue(newObject)), true); + QCOMPARE(o.qObject(), newObject); + QVariant data = p.read(); + QCOMPARE(data.value(), newObject); + QCOMPARE(data.value(), newObject); + // Incompatible types can not be written. + QCOMPARE(p.write(QVariant::fromValue(new MyQmlObject(this))), false); + QVariant newData = p.read(); + QCOMPARE(newData.value(), newObject); + QCOMPARE(newData.value(), newObject); + } } void tst_qqmlproperty::reset() -- cgit v1.2.3 From 0c8bb607e1371b301650029a3e5dfe4641cc2f98 Mon Sep 17 00:00:00 2001 From: Venu Date: Tue, 7 Oct 2014 16:16:13 +0200 Subject: Doc: Fixed an error in the QML snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also updated the C++ snippet to look like a gui app that shows the QML example, instead of a console app that just provides the context data to the QML example. Change-Id: I17aca9f03521cfcadba1a965a4924e87cbf14c62 Task-number: QTBUG-41699 Reviewed-by: Topi Reiniö --- src/qml/doc/src/cppintegration/exposecppattributes.qdoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc index 9527229204..d8e05b4358 100644 --- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc +++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc @@ -398,13 +398,13 @@ methods, as shown below right: \li \code int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); + QGuiApplication app(argc, argv); - QQmlEngine engine; - Message msg; - engine.rootContext()->setContextProperty("msg", &msg); - QQmlComponent component(&engine, QUrl::fromLocalFile("MyItem.qml")); - component.create(); + MessageBoard msgBoard; + QQuickView view; + view.engine()->rootContext()->setContextProperty("msgBoard", &msgBoard); + view.setSource(QUrl::fromLocalFile("MyItem.qml")); + view.show(); return app.exec(); } -- cgit v1.2.3 From 0fc6e4b2c3e187ab60a111b1d1871c1f3e846600 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 20 Oct 2014 13:54:26 +0200 Subject: Remove unnecessary doneCurrent in QQuickWidget Excessive makeCurrent - doneCurrent pairs should be avoided. We already do this in QOpenGLWidget and the QPlatformBackingStore composition code. Remove the doneCurrent from QQuickWidget too. Change-Id: I6f998d381c33880c470f34d7c8462b6ed8cd8ae9 Reviewed-by: Gunnar Sletta --- src/quickwidgets/qquickwidget.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 4c40288cd0..83fe586cb8 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -216,8 +216,6 @@ void QQuickWidgetPrivate::render(bool needsSync) QRect rect(QPoint(0, 0), fbo->size()); QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect); } - - context->doneCurrent(); } void QQuickWidgetPrivate::renderSceneGraph() -- cgit v1.2.3 From e3c6f39734ff54b2d7425f2edaaf6033ef2b1d9e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 22 Oct 2014 16:16:56 +0200 Subject: Relayout rich text when width increases In updateSize() we were trying to force relayouts for RichText when the width changes by always setting widthExceeded to true. But further down in the same function, we overwrote this with textWidth() < idealWidth(), which doesn't work, because both properties are the wrapped width of the document and should only differ if the text cannot be wrapped properly. The result was that when increasing the width of a Text element, we would hit the optimization and skip the relayout. [ChangeLog][Text] Fixed Text with the RichText format to correctly update wrapping when the width of the element grows. Change-Id: I5fd87052a5ba7e8ee2549be0cfac4adc8ddf8290 Task-number: QTBUG-33020 Reviewed-by: Simon Hausmann --- src/quick/items/qquicktext.cpp | 1 - tests/auto/quick/qquicktext/tst_qquicktext.cpp | 29 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index b943b8a4e6..bfa2fccd67 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -490,7 +490,6 @@ void QQuickTextPrivate::updateSize() else extra->doc->setTextWidth(extra->doc->idealWidth()); // ### Text does not align if width is not set (QTextDoc bug) - widthExceeded = extra->doc->textWidth() < extra->doc->idealWidth(); QSizeF dsize = extra->doc->size(); layedOutTextRect = QRectF(QPointF(0,0), dsize); size = QSizeF(extra->doc->idealWidth(),dsize.height()); diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index b7335ccc4a..2e5212d5d8 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -416,6 +416,35 @@ void tst_qquicktext::wrap() delete textObject; } + // Check that increasing width from idealWidth will cause a relayout + for (int i = 0; i < richText.size(); i++) + { + QString componentStr = "import QtQuick 2.0\nText { wrapMode: Text.WordWrap; textFormat: Text.RichText; width: 30; text: \"" + richText.at(i) + "\" }"; + QQmlComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickText *textObject = qobject_cast(textComponent.create()); + + QVERIFY(textObject != 0); + QCOMPARE(textObject->width(), 30.); + QVERIFY(textObject->height() > textHeight); + + QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(textObject); + QVERIFY(textPrivate != 0); + QVERIFY(textPrivate->extra.isAllocated()); + + QTextDocument *doc = textPrivate->extra->doc; + QVERIFY(doc != 0); + textObject->setWidth(doc->idealWidth()); + QCOMPARE(textObject->width(), doc->idealWidth()); + QVERIFY(textObject->height() > textHeight); + + qreal oldHeight = textObject->height(); + textObject->setWidth(100); + QVERIFY(textObject->height() < oldHeight); + + delete textObject; + } + // richtext again with a fixed height for (int i = 0; i < richText.size(); i++) { -- cgit v1.2.3 From 6e883c535b91c55289d54aa639199ca0a4decaec Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 23 Oct 2014 11:28:22 +0200 Subject: Fix pixelgrid snapping of native text on retina displays. Change 63e6c9ada82dc8f16e705cef5f89292784b7ace4 introduced snapping to the pixel grid in the vertex shader for native text, but this code was broken on retina displays because it assumed integer only positions. Fix it by including the retina scale factor into the rounding. Task-number: QTBUG-38702 Change-Id: I84492b02d64f263c9fe030790e04cf79b0dc4e2f Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 28 +++++++++++++++-------- src/quick/scenegraph/shaders/styledtext.vert | 3 ++- src/quick/scenegraph/shaders/styledtext_core.vert | 3 ++- src/quick/scenegraph/shaders/textmask.vert | 3 ++- src/quick/scenegraph/shaders/textmask_core.vert | 3 ++- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index b30a504da9..5cca474ea1 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -59,6 +59,21 @@ static inline QVector4D qsg_premultiply(const QVector4D &c, float globalOpacity) return QVector4D(c.x() * o, c.y() * o, c.z() * o, o); } +static inline int qsg_device_pixel_ratio(QOpenGLContext *ctx) +{ + int devicePixelRatio = 1; + if (ctx->surface()->surfaceClass() == QSurface::Window) { + QWindow *w = static_cast(ctx->surface()); + if (QQuickWindow *qw = qobject_cast(w)) + devicePixelRatio = qw->effectiveDevicePixelRatio(); + else + devicePixelRatio = w->devicePixelRatio(); + } else { + devicePixelRatio = ctx->screen()->devicePixelRatio(); + } + return devicePixelRatio; +} + class QSGTextMaskShader : public QSGMaterialShader { public: @@ -102,6 +117,7 @@ void QSGTextMaskShader::initialize() m_matrix_id = program()->uniformLocation("matrix"); m_color_id = program()->uniformLocation("color"); m_textureScale_id = program()->uniformLocation("textureScale"); + program()->setUniformValue("dpr", (float) qsg_device_pixel_ratio(QOpenGLContext::currentContext())); } void QSGTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) @@ -351,16 +367,8 @@ void QSGTextMaskMaterial::init(QFontEngine::GlyphFormat glyphFormat) : QFontEngine::Format_A32; } - qreal devicePixelRatio; - if (ctx->surface()->surfaceClass() == QSurface::Window) { - QWindow *w = static_cast(ctx->surface()); - if (QQuickWindow *qw = qobject_cast(w)) - devicePixelRatio = qw->effectiveDevicePixelRatio(); - else - devicePixelRatio = w->devicePixelRatio(); - } else { - devicePixelRatio = ctx->screen()->devicePixelRatio(); - } + qreal devicePixelRatio = qsg_device_pixel_ratio(ctx); + QTransform glyphCacheTransform = QTransform::fromScale(devicePixelRatio, devicePixelRatio); if (!fontEngine->supportsTransformation(glyphCacheTransform)) diff --git a/src/quick/scenegraph/shaders/styledtext.vert b/src/quick/scenegraph/shaders/styledtext.vert index 14fefc2564..7001bbc262 100644 --- a/src/quick/scenegraph/shaders/styledtext.vert +++ b/src/quick/scenegraph/shaders/styledtext.vert @@ -1,6 +1,7 @@ uniform highp mat4 matrix; uniform highp vec2 textureScale; uniform highp vec2 shift; +uniform highp float dpr; attribute highp vec4 vCoord; attribute highp vec2 tCoord; @@ -12,5 +13,5 @@ void main() { sampleCoord = tCoord * textureScale; shiftedSampleCoord = (tCoord - shift) * textureScale; - gl_Position = matrix * floor(vCoord + 0.5); + gl_Position = matrix * floor(vCoord * dpr + 0.5) / dpr; } diff --git a/src/quick/scenegraph/shaders/styledtext_core.vert b/src/quick/scenegraph/shaders/styledtext_core.vert index 65bdb66814..c522877bb3 100644 --- a/src/quick/scenegraph/shaders/styledtext_core.vert +++ b/src/quick/scenegraph/shaders/styledtext_core.vert @@ -9,10 +9,11 @@ out vec2 shiftedSampleCoord; uniform mat4 matrix; uniform vec2 textureScale; uniform vec2 shift; +uniform float dpr; void main() { sampleCoord = tCoord * textureScale; shiftedSampleCoord = (tCoord - shift) * textureScale; - gl_Position = matrix * round(vCoord); + gl_Position = matrix * round(vCoord * dpr) / dpr; } diff --git a/src/quick/scenegraph/shaders/textmask.vert b/src/quick/scenegraph/shaders/textmask.vert index dd8918839e..4c678270d0 100644 --- a/src/quick/scenegraph/shaders/textmask.vert +++ b/src/quick/scenegraph/shaders/textmask.vert @@ -1,5 +1,6 @@ uniform highp mat4 matrix; uniform highp vec2 textureScale; +uniform highp float dpr; attribute highp vec4 vCoord; attribute highp vec2 tCoord; @@ -9,5 +10,5 @@ varying highp vec2 sampleCoord; void main() { sampleCoord = tCoord * textureScale; - gl_Position = matrix * floor(vCoord + 0.5); + gl_Position = matrix * floor(vCoord * dpr + 0.5) / dpr; } diff --git a/src/quick/scenegraph/shaders/textmask_core.vert b/src/quick/scenegraph/shaders/textmask_core.vert index d145d33195..f996040f70 100644 --- a/src/quick/scenegraph/shaders/textmask_core.vert +++ b/src/quick/scenegraph/shaders/textmask_core.vert @@ -7,9 +7,10 @@ out vec2 sampleCoord; uniform mat4 matrix; uniform vec2 textureScale; +uniform float dpr; void main() { sampleCoord = tCoord * textureScale; - gl_Position = matrix * round(vCoord); + gl_Position = matrix * round(vCoord * dpr) / dpr; } -- cgit v1.2.3 From 174e998e4ef59f422afc94ea1165802ed5552c3f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 23 Oct 2014 16:51:41 +0200 Subject: QmlEngine: Use separate mutex for network access manager Creating the network access manager can involve blocking calls to DBus, which apparently can take quite long in pathological cases. Using the same mutex in this case like for instance registering objects can therefore result in a freezing UI. Mitigate this by introducing a separate mutex. Task-number: QTBUG-41183 Change-Id: I55bd8453d8e4bbc0bda1591eb3fd48b50ca921c1 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlengine.cpp | 4 ++-- src/qml/qml/qqmlengine_p.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index fd8de555af..a187c76042 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1023,7 +1023,7 @@ QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory) { Q_D(QQmlEngine); - QMutexLocker locker(&d->mutex); + QMutexLocker locker(&d->networkAccessManagerMutex); d->networkAccessManagerFactory = factory; } @@ -1050,7 +1050,7 @@ void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const { - QMutexLocker locker(&mutex); + QMutexLocker locker(&networkAccessManagerMutex); QNetworkAccessManager *nam; if (networkAccessManagerFactory) { nam = networkAccessManagerFactory->create(parent); diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 3a47e059ea..f19bfc84b3 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -260,6 +260,7 @@ public: static bool qml_debugging_enabled; + mutable QMutex networkAccessManagerMutex; mutable QMutex mutex; private: -- cgit v1.2.3 From 0f65f30cf463c98ded6074751b525e34eb2a73e9 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 23 Oct 2014 00:34:09 +0200 Subject: Fix build with QT_NO_DEBUG_OUTPUT defined The use of the qDebug() macro to construct a QDebug object fails when QT_NO_DEBUG_OUTPUT is defined when building Qt. This patch aims to fix this. [ChangeLog][General][Build] Can now build with QT_NO_DEBUG_OUTPUT defined Change-Id: If807ee3439db2a98b4d146f75860a98f40c247ec Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index ce331cc883..838251ed08 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -228,6 +228,7 @@ void qsg_dumpShadowRoots(BatchRootInfo *i, int indent) void qsg_dumpShadowRoots(Node *n) { +#ifndef QT_NO_DEBUG_OUTPUT static int indent = 0; ++indent; @@ -247,6 +248,9 @@ void qsg_dumpShadowRoots(Node *n) qsg_dumpShadowRoots(*child); --indent; +#else + Q_UNUSED(n) +#endif } Updater::Updater(Renderer *r) @@ -1073,6 +1077,7 @@ void Renderer::turnNodeIntoBatchRoot(Node *node) void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) { +#ifndef QT_NO_DEBUG_OUTPUT if (Q_UNLIKELY(debug_change())) { QDebug debug = qDebug(); debug << "dirty:"; @@ -1100,7 +1105,7 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) else debug << node; } - +#endif // As this function calls nodeChanged recursively, we do it at the top // to avoid that any of the others are processed twice. if (state & QSGNode::DirtySubtreeBlocked) { @@ -1847,7 +1852,7 @@ void Renderer::uploadBatch(Batch *b) e = e->nextInBatch; } } - +#ifndef QT_NO_DEBUG_OUTPUT if (Q_UNLIKELY(debug_upload())) { const char *vd = b->vbo.data; qDebug() << " -- Vertex Data, count:" << b->vertexCount << " - " << g->sizeOfVertex() << "bytes/vertex"; @@ -1880,11 +1885,11 @@ void Renderer::uploadBatch(Batch *b) } const quint16 *id = -#ifdef QSG_SEPARATE_INDEX_BUFFER +# ifdef QSG_SEPARATE_INDEX_BUFFER (const quint16 *) (b->ibo.data); -#else +# else (const quint16 *) (b->vbo.data + b->drawSets.at(0).indices); -#endif +# endif { QDebug iDump = qDebug(); iDump << " -- Index Data, count:" << b->indexCount; @@ -1900,6 +1905,7 @@ void Renderer::uploadBatch(Batch *b) qDebug() << " -- DrawSet: indexCount:" << s.indexCount << " vertices:" << s.vertices << " z:" << s.zorders << " indices:" << s.indices; } } +#endif // QT_NO_DEBUG_OUTPUT unmap(&b->vbo); #ifdef QSG_SEPARATE_INDEX_BUFFER @@ -2121,6 +2127,7 @@ void Renderer::renderMergedBatch(const Batch *batch) Element *e = batch->first; Q_ASSERT(e); +#ifndef QT_NO_DEBUG_OUTPUT if (Q_UNLIKELY(debug_render())) { QDebug debug = qDebug(); debug << " -" @@ -2139,6 +2146,7 @@ void Renderer::renderMergedBatch(const Batch *batch) debug << "opacity:" << e->node->inheritedOpacity(); batch->uploadedThisFrame = false; } +#endif QSGGeometryNode *gn = e->node; -- cgit v1.2.3 From 01cdb04ad579f9105694556062d83d61253aa23f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 23 Oct 2014 16:01:06 +0200 Subject: Stop waiting in QTcpServerConnection if waitForBytesWritten fails There is no point in waiting any further for the remaining bytes to be written as it will never succeed. We might get luckier by creating a local event loop and repeatedly calling processEvents(), but as that is considerably worse style and because you shouldn't rely on the connection to send on exit anyway we don't do that. Task-number: QTBUG-42158, see also QTBUG-24451 Change-Id: I79ffd5f5a4a7c41ff8dc0c4f6f1ca7e091844c9d Reviewed-by: Simon Hausmann --- src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp index 55981ffa50..4388fa7eb1 100644 --- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp +++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp @@ -113,8 +113,13 @@ void QTcpServerConnection::disconnect() { Q_D(QTcpServerConnection); - while (d->socket && d->socket->bytesToWrite() > 0) - d->socket->waitForBytesWritten(); + while (d->socket && d->socket->bytesToWrite() > 0) { + if (!d->socket->waitForBytesWritten()) { + qWarning("QML Debugger: Failed to send remaining %lld bytes on disconnect.", + d->socket->bytesToWrite()); + break; + } + } // protocol might still be processing packages at this point d->protocol->deleteLater(); -- cgit v1.2.3 From fe919589699790c93b29794f7d116122dd79fbca Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Wed, 22 Oct 2014 15:03:51 +0300 Subject: Android: Keyboard doesn't hide from done button QLineEdit closes input method on enter key press, TextInput should also do the same. Commit and hide input method on enter key. When Qt::ImhMultiLine input method hint set only commit. Task-number: QTBUG-37850 Change-Id: I5a06e3eb777d7f794dd1493b307f0b05a2caf281 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/items/qquicktextinput.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 27752d53b4..1f03fb21e2 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1292,6 +1292,7 @@ void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo) \li Qt.ImhDate - The text editor functions as a date field. \li Qt.ImhTime - The text editor functions as a time field. + \li Qt.ImhMultiLine - The text editor doesn't close software input keyboard when Return or Enter key is pressed (since QtQuick 2.4). \endlist Flags that restrict input (exclusive flags) are: @@ -4192,6 +4193,12 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (hasAcceptableInput(m_text) == AcceptableInput || fixup()) { + + QInputMethod *inputMethod = QGuiApplication::inputMethod(); + inputMethod->commit(); + if (!(q->inputMethodHints() & Qt::ImhMultiLine)) + inputMethod->hide(); + emit q->accepted(); emit q->editingFinished(); } -- cgit v1.2.3 From 4e7c588f027f6a846fc343975bc8bcce5f69f6ff Mon Sep 17 00:00:00 2001 From: Venu Date: Thu, 23 Oct 2014 16:32:47 +0200 Subject: Doc: Updated the code snippets for the toLocalexxx functions Using Date() as a regular function without the new operator returns a string and not a date object. Change-Id: I083bb62c0cb3041a053d43e3085c3d0d10423db6 Task-number: QTBUG-41712 Reviewed-by: Mitch Curtis Reviewed-by: Leena Miettinen --- src/qml/doc/src/javascript/date.qdoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qml/doc/src/javascript/date.qdoc b/src/qml/doc/src/javascript/date.qdoc index 208e2be3f7..4f897af928 100644 --- a/src/qml/doc/src/javascript/date.qdoc +++ b/src/qml/doc/src/javascript/date.qdoc @@ -153,7 +153,7 @@ import QtQuick 2.0 Text { - text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE")) + text: "The date is: " + new Date().toLocaleString(Qt.locale("de_DE")) } \endcode */ @@ -175,7 +175,7 @@ import QtQuick 2.0 Text { - text: "The date is: " + Date().toLocaleDateString(Qt.locale("de_DE")) + text: "The date is: " + new Date().toLocaleDateString(Qt.locale("de_DE")) } \endcode */ @@ -197,7 +197,7 @@ import QtQuick 2.0 Text { - text: "The date is: " + Date().toLocaleTimeString(Qt.locale("de_DE")) + text: "The date is: " + new Date().toLocaleTimeString(Qt.locale("de_DE")) } \endcode */ -- cgit v1.2.3 From d21c096f358eaf4dd7245680f38b836bebe43da5 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Mon, 20 Oct 2014 13:07:21 +0200 Subject: Fix crash in SpriteSequence When QML declares sprites and goalSprite in wrong order the goalsprite attempts to set it on null spriteEngine. This patch ensures that the order doesn't matter anymore. Task-number: QTBUG-40595 Change-Id: I57f1c8754b2e2af91e0c7f72d1d67fec3ad4ede5 Reviewed-by: Lars Knoll --- src/quick/items/qquickspritesequence.cpp | 10 ++-- .../qquickspritesequence/data/spriteaftergoal.qml | 60 ++++++++++++++++++++++ .../qquickspritesequence/data/spritebeforegoal.qml | 60 ++++++++++++++++++++++ .../tst_qquickspritesequence.cpp | 26 ++++++++++ 4 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml create mode 100644 tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 0be6486bf0..a9a823c2ce 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -243,7 +243,8 @@ void QQuickSpriteSequence::setGoalSprite(const QString &sprite) if (m_goalState != sprite){ m_goalState = sprite; emit goalSpriteChanged(sprite); - m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite)); + if (m_spriteEngine) + m_spriteEngine->setGoal(m_spriteEngine->stateIndex(sprite)); } } @@ -257,10 +258,13 @@ void QQuickSpriteSequence::createEngine() //TODO: delay until component complete if (m_spriteEngine) delete m_spriteEngine; - if (m_sprites.count()) + if (m_sprites.count()) { m_spriteEngine = new QQuickSpriteEngine(m_sprites, this); - else + if (!m_goalState.isEmpty()) + m_spriteEngine->setGoal(m_spriteEngine->stateIndex(m_goalState)); + } else { m_spriteEngine = 0; + } reset(); } diff --git a/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml b/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml new file mode 100644 index 0000000000..189458ad90 --- /dev/null +++ b/tests/auto/quick/qquickspritesequence/data/spriteaftergoal.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// QTBUG-40595 +import QtQuick 2.0 + +Rectangle { + width: 320 + height: 320 + + SpriteSequence + { + anchors.centerIn: parent + + width: 300 + height: 300 + + goalSprite: "foobar" + + sprites: + [ + Sprite + { + name: "foobar" + source: "squarefacesprite.png" + } + ] + } +} + diff --git a/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml b/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml new file mode 100644 index 0000000000..23326fb5cc --- /dev/null +++ b/tests/auto/quick/qquickspritesequence/data/spritebeforegoal.qml @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// QTBUG-40595 +import QtQuick 2.0 + +Rectangle { + width: 320 + height: 320 + + SpriteSequence + { + anchors.centerIn: parent + + width: 300 + height: 300 + + sprites: + [ + Sprite + { + name: "foobar" + source: "squarefacesprite.png" + } + ] + + goalSprite: "foobar" + } +} + diff --git a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp index 6cfdc90364..26ddff1009 100644 --- a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp +++ b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp @@ -46,6 +46,8 @@ private slots: void test_framerateAdvance();//Separate codepath for QQuickSpriteEngine void test_huge();//Separate codepath for QQuickSpriteEngine void test_jumpToCrash(); + void test_spriteBeforeGoal(); + void test_spriteAfterGoal(); }; void tst_qquickspritesequence::test_properties() @@ -119,6 +121,30 @@ void tst_qquickspritesequence::test_jumpToCrash() delete window; } +void tst_qquickspritesequence::test_spriteBeforeGoal() +{ + QQuickView *window = new QQuickView(0); + + window->setSource(testFileUrl("spritebeforegoal.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + //verify: Don't crash + + delete window; +} + +void tst_qquickspritesequence::test_spriteAfterGoal() +{ + QQuickView *window = new QQuickView(0); + + window->setSource(testFileUrl("spriteaftergoal.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + //verify: Don't crash + + delete window; +} + QTEST_MAIN(tst_qquickspritesequence) #include "tst_qquickspritesequence.moc" -- cgit v1.2.3 From cfff375afcfe63d25b3c1904ff58a90bcd1edb43 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 23 Oct 2014 09:50:12 +0200 Subject: Fix license headers in Qml grammar specification The grammar file itself wasn't updated accordignly and the license headers that are embedded in the grammar that will be copied into the generated files were also oudated. Re-generating the parser would produce files with the wrong license headers. Change-Id: I1db83df8a9c4bddfb58901f41a4d40f6b1396507 Reviewed-by: Lars Knoll --- src/qml/parser/qqmljs.g | 90 +++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 48 deletions(-) diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index de4fec4d56..56dfe46b2a 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -1,21 +1,31 @@ ---------------------------------------------------------------------------- -- --- Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +-- Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -- Contact: http://www.qt-project.org/legal -- -- This file is part of the QtQml module of the Qt Toolkit. -- --- $QT_BEGIN_LICENSE:LGPL-ONLY$ +-- $QT_BEGIN_LICENSE:LGPL21$ +-- Commercial License Usage +-- Licensees holding valid commercial Qt licenses may use this file in +-- accordance with the commercial license agreement provided with the +-- Software or, alternatively, in accordance with the terms contained in +-- a written agreement between you and Digia. For licensing terms and +-- conditions see http://qt.digia.com/licensing. For further information +-- use the contact form at http://qt.digia.com/contact-us. +-- -- GNU Lesser General Public License Usage --- 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. +-- Alternatively, this file may be used under the terms of the GNU Lesser +-- General Public License version 2.1 or version 3 as published by the Free +-- Software Foundation and appearing in the file LICENSE.LGPLv21 and +-- LICENSE.LGPLv3 included in the packaging of this file. Please review the +-- following information to ensure the GNU Lesser General Public License +-- requirements will be met: https://www.gnu.org/licenses/lgpl.html and +-- http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -- --- If you have questions regarding the use of this file, please contact --- us via http://www.qt-project.org/. +-- In addition, as a special exception, Digia gives you certain additional +-- rights. These rights are described in the Digia Qt LGPL Exception +-- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -- -- $QT_END_LICENSE$ -- @@ -89,41 +99,33 @@ /./**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, 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. -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -142,41 +144,33 @@ /:/**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, 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. -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ -- cgit v1.2.3 From f876562de8eb978cea39fe72e76c49ae51ff2f97 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 23 Oct 2014 12:05:44 +0200 Subject: Fix syntax error when trying to declare read-only object properties The grammar did not allow for the declaration of readonly property QtObject foo: QtObject { ... } and it required a workaround through an alias: readonly property alias foo: _foo property QtObject _foo: QtObject { ... } This was merely a glitch in the grammar, I see no reason not to support this. The semantics are like a const pointer in C++, the property itself is read-only but the object pointed to has per-property defined read/write semantics. Task-number: QTBUG-41971 Change-Id: I99e2e7ed58731e387a38e46ec39922d280a21ceb Reviewed-by: Michael Brasser Reviewed-by: Lars Knoll --- src/qml/parser/qqmljs.g | 25 + src/qml/parser/qqmljsgrammar.cpp | 1668 ++++++++++---------- src/qml/parser/qqmljsgrammar_p.h | 12 +- src/qml/parser/qqmljsparser.cpp | 384 ++--- src/qml/parser/qqmljsparser_p.h | 4 +- .../qqmllanguage/data/readonlyObjectProperty.qml | 7 + tests/auto/qml/qqmllanguage/qqmllanguage.pro | 3 + tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 19 + 8 files changed, 1092 insertions(+), 1030 deletions(-) create mode 100644 tests/auto/qml/qqmllanguage/data/readonlyObjectProperty.qml diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 56dfe46b2a..616e3b3166 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -1084,6 +1084,31 @@ case $rule_number: { } break; ./ +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; +/. +case $rule_number: { + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); // insert a fake ';' before ':' + + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); + propertyName->identifierToken = loc(4); + propertyName->next = 0; + + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); + binding->colonToken = loc(5); + + node->binding = binding; + + sym(1).Node = node; +} break; +./ + UiObjectMember: FunctionDeclaration ; /. case $rule_number: { diff --git a/src/qml/parser/qqmljsgrammar.cpp b/src/qml/parser/qqmljsgrammar.cpp index d3fb3f8d1f..2600a5e14c 100644 --- a/src/qml/parser/qqmljsgrammar.cpp +++ b/src/qml/parser/qqmljsgrammar.cpp @@ -57,35 +57,35 @@ const short QQmlJSGrammar::lhs [] = { 130, 130, 130, 130, 130, 130, 130, 111, 138, 138, 138, 139, 139, 140, 140, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, - 111, 111, 124, 124, 124, 124, 124, 124, 124, 143, + 111, 111, 111, 124, 124, 124, 124, 124, 124, 124, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 129, 145, 145, - 145, 145, 144, 144, 149, 149, 149, 147, 147, 150, - 150, 150, 150, 153, 153, 153, 153, 153, 153, 153, + 143, 143, 143, 143, 143, 143, 143, 143, 129, 145, + 145, 145, 145, 144, 144, 149, 149, 149, 147, 147, + 150, 150, 150, 150, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, - 153, 153, 153, 153, 154, 154, 120, 120, 120, 120, - 120, 157, 157, 158, 158, 158, 158, 156, 156, 159, - 159, 160, 160, 161, 161, 161, 162, 162, 162, 162, - 162, 162, 162, 162, 162, 162, 163, 163, 163, 163, - 164, 164, 164, 165, 165, 165, 165, 166, 166, 166, - 166, 166, 166, 166, 167, 167, 167, 167, 167, 167, - 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, - 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, - 175, 175, 176, 176, 177, 177, 178, 178, 179, 179, - 180, 180, 181, 181, 148, 148, 182, 182, 183, 183, + 153, 153, 153, 153, 153, 154, 154, 120, 120, 120, + 120, 120, 157, 157, 158, 158, 158, 158, 156, 156, + 159, 159, 160, 160, 161, 161, 161, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 163, 163, 163, + 163, 164, 164, 164, 165, 165, 165, 165, 166, 166, + 166, 166, 166, 166, 166, 167, 167, 167, 167, 167, + 167, 168, 168, 168, 168, 168, 169, 169, 169, 169, + 169, 170, 170, 171, 171, 172, 172, 173, 173, 174, + 174, 175, 175, 176, 176, 177, 177, 178, 178, 179, + 179, 180, 180, 181, 181, 148, 148, 182, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, - 109, 109, 184, 184, 185, 185, 186, 186, 108, 108, + 183, 109, 109, 184, 184, 185, 185, 186, 186, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, - 108, 108, 108, 131, 195, 195, 194, 194, 142, 142, - 196, 196, 197, 197, 199, 199, 198, 200, 203, 201, - 201, 204, 202, 202, 132, 133, 133, 134, 134, 187, - 187, 187, 187, 187, 187, 187, 187, 188, 188, 188, - 188, 189, 189, 189, 189, 190, 190, 135, 136, 205, - 205, 208, 208, 206, 206, 209, 207, 191, 192, 192, - 137, 137, 137, 210, 211, 193, 193, 212, 141, 155, - 155, 213, 213, 152, 152, 151, 151, 214, 112, 112, - 215, 215, 110, 110, 146, 146, 216}; + 108, 108, 108, 108, 131, 195, 195, 194, 194, 142, + 142, 196, 196, 197, 197, 199, 199, 198, 200, 203, + 201, 201, 204, 202, 202, 132, 133, 133, 134, 134, + 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, + 188, 188, 189, 189, 189, 189, 190, 190, 135, 136, + 205, 205, 208, 208, 206, 206, 209, 207, 191, 192, + 192, 137, 137, 137, 210, 211, 193, 193, 212, 141, + 155, 155, 213, 213, 152, 152, 151, 151, 214, 112, + 112, 215, 215, 110, 110, 146, 146, 216}; const short QQmlJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, @@ -95,110 +95,110 @@ const short QQmlJSGrammar::rhs [] = { 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, 5, 5, 5, 6, 6, 10, 6, + 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 3, 3, 4, 5, 3, 4, 3, 1, 1, 2, - 3, 4, 1, 2, 3, 7, 8, 1, 3, 1, + 2, 3, 3, 4, 5, 3, 4, 3, 1, 1, + 2, 3, 4, 1, 2, 3, 7, 8, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, - 5, 1, 2, 4, 4, 4, 3, 0, 1, 1, - 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, - 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, - 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, - 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, + 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, + 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, + 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, + 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, + 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 1, 2, 0, 1, 3, 3, - 1, 1, 1, 3, 1, 3, 2, 2, 2, 0, - 1, 2, 0, 1, 1, 2, 2, 7, 5, 7, - 7, 7, 5, 9, 10, 7, 8, 2, 2, 3, - 3, 2, 2, 3, 3, 3, 3, 5, 5, 3, - 5, 1, 2, 0, 1, 4, 3, 3, 3, 3, - 3, 3, 4, 5, 2, 2, 2, 1, 8, 8, - 7, 1, 3, 0, 1, 0, 1, 1, 1, 1, - 1, 2, 1, 1, 0, 1, 2}; + 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, + 3, 1, 1, 1, 3, 1, 3, 2, 2, 2, + 0, 1, 2, 0, 1, 1, 2, 2, 7, 5, + 7, 7, 7, 5, 9, 10, 7, 8, 2, 2, + 3, 3, 2, 2, 3, 3, 3, 3, 5, 5, + 3, 5, 1, 2, 0, 1, 4, 3, 3, 3, + 3, 3, 3, 4, 5, 2, 2, 2, 1, 8, + 8, 7, 1, 3, 0, 1, 0, 1, 1, 1, + 1, 1, 2, 1, 1, 0, 1, 2}; const short QQmlJSGrammar::action_default [] = { - 0, 0, 28, 0, 0, 0, 28, 0, 184, 251, - 215, 223, 219, 163, 235, 211, 3, 148, 81, 164, - 227, 231, 152, 181, 162, 167, 147, 201, 188, 0, - 88, 89, 84, 0, 78, 73, 355, 0, 0, 0, - 0, 86, 0, 0, 82, 85, 77, 0, 0, 74, - 76, 79, 75, 87, 80, 0, 83, 0, 0, 177, - 0, 0, 164, 183, 166, 165, 0, 0, 0, 179, - 180, 178, 182, 0, 212, 0, 0, 0, 0, 202, - 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, - 186, 187, 185, 190, 194, 193, 191, 189, 204, 203, - 205, 0, 220, 0, 216, 0, 0, 158, 145, 157, - 146, 114, 115, 116, 141, 117, 142, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, - 143, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 144, 0, 0, 156, 252, 159, 0, 160, 0, - 161, 155, 0, 248, 241, 239, 246, 247, 245, 244, - 250, 243, 242, 240, 249, 236, 0, 224, 0, 0, - 228, 0, 0, 232, 0, 0, 158, 150, 0, 149, - 0, 154, 168, 0, 344, 344, 345, 0, 342, 0, - 343, 0, 346, 259, 266, 265, 273, 261, 0, 262, - 0, 347, 0, 354, 263, 264, 81, 269, 267, 351, - 348, 353, 270, 0, 281, 0, 0, 0, 0, 338, - 0, 355, 253, 295, 0, 0, 0, 282, 0, 0, - 271, 272, 0, 260, 268, 296, 297, 0, 344, 0, - 0, 346, 0, 339, 340, 0, 328, 352, 0, 312, - 313, 314, 315, 0, 308, 309, 310, 311, 336, 337, - 0, 0, 0, 0, 0, 300, 301, 302, 257, 255, - 217, 225, 221, 237, 213, 258, 0, 164, 229, 233, - 206, 195, 0, 0, 214, 0, 0, 0, 0, 207, - 0, 0, 0, 0, 0, 199, 197, 200, 198, 196, - 209, 208, 210, 0, 222, 0, 218, 0, 256, 164, - 0, 238, 253, 254, 0, 253, 0, 0, 304, 0, - 0, 0, 306, 0, 226, 0, 0, 230, 0, 0, - 234, 293, 0, 285, 294, 288, 0, 292, 0, 253, - 286, 0, 253, 0, 0, 305, 0, 0, 0, 307, - 0, 0, 0, 299, 0, 298, 81, 108, 356, 0, - 0, 113, 275, 278, 0, 114, 281, 117, 142, 119, - 120, 84, 124, 125, 78, 126, 129, 82, 85, 253, - 79, 87, 132, 80, 134, 83, 136, 137, 282, 139, - 140, 144, 0, 110, 109, 112, 96, 111, 95, 0, - 105, 276, 274, 0, 0, 0, 346, 0, 106, 152, - 153, 158, 0, 151, 0, 316, 317, 0, 344, 0, - 0, 346, 0, 107, 0, 0, 0, 319, 324, 322, - 325, 0, 0, 323, 324, 0, 320, 0, 321, 277, - 327, 0, 277, 326, 0, 329, 330, 0, 277, 331, - 332, 0, 0, 333, 0, 0, 0, 334, 335, 170, - 169, 0, 0, 0, 303, 0, 0, 0, 318, 290, - 283, 0, 291, 287, 0, 289, 279, 0, 280, 284, - 0, 0, 346, 0, 341, 99, 0, 0, 103, 90, - 0, 92, 101, 0, 93, 102, 104, 94, 100, 91, - 0, 97, 174, 172, 176, 173, 171, 175, 349, 6, - 350, 4, 2, 71, 98, 0, 0, 74, 76, 75, - 37, 5, 0, 72, 0, 51, 50, 49, 0, 0, + 0, 0, 28, 0, 0, 0, 28, 0, 185, 252, + 216, 224, 220, 164, 236, 212, 3, 149, 82, 165, + 228, 232, 153, 182, 163, 168, 148, 202, 189, 0, + 89, 90, 85, 0, 79, 74, 356, 0, 0, 0, + 0, 87, 0, 0, 83, 86, 78, 0, 0, 75, + 77, 80, 76, 88, 81, 0, 84, 0, 0, 178, + 0, 0, 165, 184, 167, 166, 0, 0, 0, 180, + 181, 179, 183, 0, 213, 0, 0, 0, 0, 203, + 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, + 187, 188, 186, 191, 195, 194, 192, 190, 205, 204, + 206, 0, 221, 0, 217, 0, 0, 159, 146, 158, + 147, 115, 116, 117, 142, 118, 143, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 144, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 145, 0, 0, 157, 253, 160, 0, 161, 0, + 162, 156, 0, 249, 242, 240, 247, 248, 246, 245, + 251, 244, 243, 241, 250, 237, 0, 225, 0, 0, + 229, 0, 0, 233, 0, 0, 159, 151, 0, 150, + 0, 155, 169, 0, 345, 345, 346, 0, 343, 0, + 344, 0, 347, 260, 267, 266, 274, 262, 0, 263, + 0, 348, 0, 355, 264, 265, 82, 270, 268, 352, + 349, 354, 271, 0, 282, 0, 0, 0, 0, 339, + 0, 356, 254, 296, 0, 0, 0, 283, 0, 0, + 272, 273, 0, 261, 269, 297, 298, 0, 345, 0, + 0, 347, 0, 340, 341, 0, 329, 353, 0, 313, + 314, 315, 316, 0, 309, 310, 311, 312, 337, 338, + 0, 0, 0, 0, 0, 301, 302, 303, 258, 256, + 218, 226, 222, 238, 214, 259, 0, 165, 230, 234, + 207, 196, 0, 0, 215, 0, 0, 0, 0, 208, + 0, 0, 0, 0, 0, 200, 198, 201, 199, 197, + 210, 209, 211, 0, 223, 0, 219, 0, 257, 165, + 0, 239, 254, 255, 0, 254, 0, 0, 305, 0, + 0, 0, 307, 0, 227, 0, 0, 231, 0, 0, + 235, 294, 0, 286, 295, 289, 0, 293, 0, 254, + 287, 0, 254, 0, 0, 306, 0, 0, 0, 308, + 0, 0, 0, 300, 0, 299, 82, 109, 357, 0, + 0, 114, 276, 279, 0, 115, 282, 118, 143, 120, + 121, 85, 125, 126, 79, 127, 130, 83, 86, 254, + 80, 88, 133, 81, 135, 84, 137, 138, 283, 140, + 141, 145, 0, 111, 110, 113, 97, 112, 96, 0, + 106, 277, 275, 0, 0, 0, 347, 0, 107, 153, + 154, 159, 0, 152, 0, 317, 318, 0, 345, 0, + 0, 347, 0, 108, 0, 0, 0, 320, 325, 323, + 326, 0, 0, 324, 325, 0, 321, 0, 322, 278, + 328, 0, 278, 327, 0, 330, 331, 0, 278, 332, + 333, 0, 0, 334, 0, 0, 0, 335, 336, 171, + 170, 0, 0, 0, 304, 0, 0, 0, 319, 291, + 284, 0, 292, 288, 0, 290, 280, 0, 281, 285, + 0, 0, 347, 0, 342, 100, 0, 0, 104, 91, + 0, 93, 102, 0, 94, 103, 105, 95, 101, 92, + 0, 98, 175, 173, 177, 174, 172, 176, 350, 6, + 351, 4, 2, 72, 99, 0, 0, 75, 77, 76, + 37, 5, 0, 73, 0, 51, 50, 49, 0, 0, 64, 0, 65, 41, 42, 43, 44, 46, 47, 68, 45, 0, 51, 0, 0, 0, 0, 0, 60, 0, 61, 0, 0, 32, 0, 0, 69, 33, 0, 36, - 34, 30, 0, 35, 31, 0, 62, 0, 63, 152, - 0, 66, 70, 0, 0, 0, 0, 67, 0, 58, + 34, 30, 0, 35, 31, 0, 62, 0, 63, 153, + 0, 66, 70, 0, 0, 0, 0, 153, 278, 0, + 67, 82, 115, 282, 118, 143, 120, 121, 85, 125, + 126, 127, 130, 83, 86, 254, 88, 133, 81, 135, + 84, 137, 138, 283, 140, 141, 145, 71, 0, 58, 52, 59, 53, 0, 0, 0, 0, 55, 0, 56, - 57, 54, 0, 0, 152, 277, 0, 0, 48, 81, - 114, 281, 117, 142, 119, 120, 84, 124, 125, 126, - 129, 82, 85, 253, 87, 132, 80, 134, 83, 136, - 137, 282, 139, 140, 144, 0, 38, 39, 0, 40, - 8, 0, 0, 9, 0, 11, 0, 10, 0, 1, - 27, 15, 14, 26, 13, 12, 29, 7, 0, 18, - 0, 19, 0, 24, 25, 0, 20, 21, 0, 22, - 23, 16, 17, 357}; + 57, 54, 0, 0, 0, 0, 48, 0, 38, 39, + 0, 40, 8, 0, 0, 9, 0, 11, 0, 10, + 0, 1, 27, 15, 14, 26, 13, 12, 29, 7, + 0, 18, 0, 19, 0, 24, 25, 0, 20, 21, + 0, 22, 23, 16, 17, 358}; const short QQmlJSGrammar::goto_default [] = { - 7, 639, 211, 198, 209, 521, 509, 634, 647, 508, - 633, 637, 635, 643, 22, 640, 638, 636, 18, 520, + 7, 641, 211, 198, 209, 521, 509, 636, 649, 508, + 635, 639, 637, 645, 22, 642, 640, 638, 18, 520, 562, 552, 559, 554, 539, 193, 197, 199, 204, 234, - 212, 231, 543, 583, 582, 203, 233, 26, 487, 486, + 212, 231, 543, 613, 612, 203, 233, 26, 487, 486, 359, 358, 9, 357, 360, 202, 480, 361, 109, 17, 147, 24, 13, 146, 19, 25, 59, 23, 8, 28, 27, 280, 15, 274, 10, 270, 12, 272, 11, 271, @@ -209,295 +209,267 @@ const short QQmlJSGrammar::goto_default [] = { 0}; const short QQmlJSGrammar::action_index [] = { - 239, 1406, 2692, 2692, 2794, 1119, 115, 29, 168, -106, - 26, -23, -60, 225, -106, 306, 33, -106, -106, 732, - -2, 145, 243, 223, -106, -106, -106, 379, 227, 1406, - -106, -106, -106, 539, -106, -106, 2488, 1698, 1406, 1406, - 1406, -106, 1023, 1406, -106, -106, -106, 1406, 1406, -106, - -106, -106, -106, -106, -106, 1406, -106, 1406, 1406, -106, - 1406, 1406, 114, 206, -106, -106, 1406, 1406, 1406, -106, - -106, -106, 211, 1406, 302, 1406, 1406, 1406, 1406, 369, - 1406, 1406, 1406, 1406, 1406, 1406, 226, 1406, 1406, 1406, - 135, 151, 110, 257, 279, 276, 256, 222, 475, 475, - 475, 1406, 7, 1406, 57, 2284, 1406, 1406, -106, -106, + 264, 1225, 2708, 2708, 2606, 938, 94, 104, 119, -106, + 92, 79, 81, 262, -106, 263, 78, -106, -106, 654, + 89, 125, 259, 229, -106, -106, -106, 322, 314, 1225, + -106, -106, -106, 412, -106, -106, 2300, 1713, 1225, 1225, + 1225, -106, 842, 1225, -106, -106, -106, 1225, 1225, -106, + -106, -106, -106, -106, -106, 1225, -106, 1225, 1225, -106, + 1225, 1225, 141, 216, -106, -106, 1225, 1225, 1225, -106, + -106, -106, 209, 1225, 281, 1225, 1225, 1225, 1225, 367, + 1225, 1225, 1225, 1225, 1225, 1225, 219, 1225, 1225, 1225, + 101, 102, 115, 314, 314, 314, 314, 314, 357, 347, + 337, 1225, 71, 1225, 70, 2198, 1225, 1225, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, -106, - -106, -106, 136, 1406, -106, -106, 30, -24, -106, 1406, - -106, -106, 1406, -106, -106, -106, -106, -106, -106, -106, - -106, -106, -106, -106, -106, -106, 1406, 2, 1406, 1406, - 10, 97, 1406, -106, 2284, 1406, 1406, -106, 141, -106, - -45, -106, -106, 4, 457, 386, 89, 79, -106, 448, - -106, 74, 2692, -106, -106, -106, -106, -106, 164, -106, - 460, -106, 85, -106, -106, -106, 96, -106, -106, -106, - 2692, -106, -106, 547, -106, 629, 143, 2794, 62, 54, - 43, 2998, 1406, -106, 51, 1406, 52, -106, 47, 45, - -106, -106, 454, -106, -106, -106, -106, 64, 352, 31, - 61, 2692, 27, -106, -106, 2794, -106, -106, 139, -106, - -106, -106, -106, 126, -106, -106, -106, -106, -106, -106, - -6, 25, 1406, 130, 159, -106, -106, -106, 1600, -106, - 68, 65, 5, -106, 308, 60, 3, 835, 99, 105, - 337, 207, 408, 1406, 317, 1406, 1406, 1406, 1406, 353, - 1406, 1406, 1406, 1406, 1406, 186, 203, 204, 212, 219, - 333, 343, 359, 1406, 20, 1406, 202, 1406, -106, 732, - 1406, -106, 1406, 81, 72, 1406, 77, 2794, -106, 1406, - 149, 2794, -106, 1406, 80, 1406, 1406, 94, 88, 1406, - -106, -8, 128, -25, -106, -106, 1406, -106, 471, 1406, - -106, -53, 1406, -56, 2794, -106, 1406, 134, 2794, -106, - 1406, 138, 2794, -5, 2794, -106, -4, -106, 9, -9, - 37, -106, -106, 2794, -12, 555, 32, 629, 123, 1406, - 2794, 41, 18, 504, 2386, 21, 1023, 49, 46, 1505, - 2386, 42, 16, 44, 1406, 24, -10, 1406, 17, 1406, - -15, -18, 2590, -106, -106, -106, -106, -106, -106, 1406, - -106, -106, -106, -1, -26, -3, 2692, -27, -106, 277, - -106, 1406, -28, -106, 90, -106, -106, 1, 552, -40, - -11, 2692, -29, -106, 1406, 117, 14, -106, 50, -106, - 40, 119, 1406, -106, 11, 35, -106, -54, -106, 2794, - -106, 116, 2794, -106, 267, -106, -106, 121, 2794, -7, - -106, -31, -19, -106, 376, 6, 78, -106, -106, -106, - -106, 1406, 98, 2794, -106, 1406, 106, 2794, -106, 76, - -106, 254, -106, -106, 1406, -106, -106, 552, -106, -106, - 71, 75, 2692, 67, -106, -106, 122, 1992, -106, -106, - 1796, -106, -106, 1894, -106, -106, -106, -106, -106, -106, - 113, -106, -106, -106, -106, -106, -106, -106, -106, -106, - 2692, -106, -106, -106, 111, 22, 929, 152, 39, 48, - -106, -106, 301, -106, 147, -106, -106, -106, 468, 155, - -106, 2182, -106, -106, -106, -106, -106, -106, -106, -106, - -106, 178, -30, 463, 181, -14, 400, 229, -106, -32, - -106, 929, 104, -106, 0, 929, -106, -106, 1311, -106, - -106, -106, 1215, -106, -106, 248, -106, 2182, -106, 392, - 59, -106, -106, 244, 552, 73, 2182, -106, 236, -106, - 237, -106, 70, 15, 368, 214, 355, -106, 103, -106, - -106, -106, 2087, 721, 392, 2896, 1698, 34, -106, 56, - 598, 55, 629, 107, 1406, 2794, 53, 23, 544, 36, - 1023, 58, 66, 1505, 69, 38, 63, 1406, 95, 84, - 1406, 102, 1406, 83, 82, 124, -106, -106, 87, -106, - -106, 929, 813, 91, 929, -106, 271, -106, 86, -106, - -106, 100, 101, -106, -106, -106, -106, -106, 552, -106, - 209, -106, 109, -106, -106, 552, -106, -106, 92, -106, - -106, -106, -106, -106, + -106, -106, 98, 1225, -106, -106, 66, 65, -106, 1225, + -106, -106, 1225, -106, -106, -106, -106, -106, -106, -106, + -106, -106, -106, -106, -106, -106, 1225, 44, 1225, 1225, + 64, 57, 1225, -106, 2198, 1225, 1225, -106, 137, -106, + 49, -106, -106, 93, 344, 474, 95, 86, -106, 390, + -106, 85, 2708, -106, -106, -106, -106, -106, 189, -106, + 474, -106, 80, -106, -106, -106, 83, -106, -106, -106, + 2708, -106, -106, 490, -106, 551, 130, 2606, 46, 51, + 52, 2912, 1225, -106, 63, 1225, 56, -106, 58, 60, + -106, -106, 474, -106, -106, -106, -106, 61, 474, 62, + 67, 2708, 68, -106, -106, 2606, -106, -106, 87, -106, + -106, -106, -106, 110, -106, -106, -106, -106, -106, -106, + -24, 69, 1225, 122, 143, -106, -106, -106, 1419, -106, + 74, 76, 77, -106, 269, 73, 72, 611, 75, 114, + 397, 314, 474, 1225, 287, 1225, 1225, 1225, 1225, 397, + 1225, 1225, 1225, 1225, 1225, 218, 215, 198, 192, 182, + 397, 397, 312, 1225, 55, 1225, 59, 1225, -106, 654, + 1225, -106, 1225, 54, 53, 1225, 50, 2606, -106, 1225, + 124, 2606, -106, 1225, 90, 1225, 1225, 105, 88, 1225, + -106, 84, 157, -27, -106, -106, 1225, -106, 474, 1225, + -106, 82, 1225, 91, 2606, -106, 1225, 120, 2606, -106, + 1225, 103, 2606, -9, 2606, -106, -2, -106, 11, -30, + 17, -106, -106, 2606, -37, 469, 15, 551, 138, 1225, + 2606, 14, -16, 433, 2402, -20, 842, 6, 5, 1324, + 2402, 4, -36, 2, 1225, 7, -18, 1225, 10, 1225, + -26, -13, 2504, -106, -106, -106, -106, -106, -106, 1225, + -106, -106, -106, -33, -59, -25, 2708, 23, -106, 197, + -106, 1225, -12, -106, 140, -106, -106, 22, 474, -4, + 26, 2708, 12, -106, 1225, 113, 30, -106, 142, -106, + 142, 121, 1225, -106, -3, 45, -106, -5, -106, 2606, + -106, 108, 2606, -106, 207, -106, -106, 106, 2606, 37, + -106, 25, 36, -106, 474, 38, 40, -106, -106, -106, + -106, 1225, 136, 2606, -106, 1225, 166, 2606, -106, 13, + -106, 200, -106, -106, 1225, -106, -106, 474, -106, -106, + -17, 16, 2708, -11, -106, -106, 131, 1811, -106, -106, + 1615, -106, -106, 1517, -106, -106, -106, -106, -106, -106, + 109, -106, -106, -106, -106, -106, -106, -106, -106, -106, + 2708, -106, -106, -106, 233, -19, 748, 152, -60, 41, + -106, -106, 191, -106, 177, -106, -106, -106, 387, 203, + -106, 1906, -106, -106, -106, -106, -106, -106, -106, -106, + -106, 180, 43, 376, 174, 48, 474, 240, -106, 8, + -106, 748, 111, -106, -1, 748, -106, -106, 1130, -106, + -106, -106, 1034, -106, -106, 228, -106, 1906, -106, 295, + 21, -106, -106, 184, 379, 39, 2001, 288, 2810, 18, + -106, 34, 482, 33, 551, 138, 1225, 2606, 31, 9, + 399, 3, 643, 19, 29, 1324, 28, 1, 27, 1225, + 24, 0, 1225, 20, 1225, -7, -8, -106, 193, -106, + 205, -106, 47, 42, 329, 208, 319, -106, 128, -106, + -106, -106, 2096, 748, 1713, 35, -106, 132, -106, -106, + 32, -106, -106, 748, 748, 94, 748, -106, 250, -106, + 116, -106, -106, 233, 233, -106, -106, -106, -106, -106, + 393, -106, 214, -106, 100, -106, -106, 474, -106, -106, + 96, -106, -106, -106, -106, -106, - -111, 43, 59, 70, 71, 369, 40, -111, -111, -111, - -111, -111, -111, -111, -111, -111, -111, -111, -111, 21, - -111, -111, -111, -111, -111, -111, -111, -111, -111, 79, - -111, -111, -111, -16, -111, -111, 5, -26, 23, 73, - 91, -111, 83, 61, -111, -111, -111, 88, 87, -111, - -111, -111, -111, -111, -111, 29, -111, 66, 39, -111, - 97, 193, -111, -111, -111, -111, 160, 180, 183, -111, - -111, -111, -111, 176, -111, 167, 151, 155, 152, -111, - 148, 187, 195, 197, 199, 201, -111, 186, 92, 194, + -111, 15, 71, 87, 80, 305, -6, -111, -111, -111, + -111, -111, -111, -111, -111, -111, -111, -111, -111, -42, + -111, -111, -111, -111, -111, -111, -111, -111, -111, 95, + -111, -111, -111, 3, -111, -111, -5, -11, 9, 109, + 91, -111, 62, 45, -111, -111, -111, 50, 63, -111, + -111, -111, -111, -111, -111, 32, -111, 203, 197, -111, + 189, 178, -111, -111, -111, -111, 182, 185, 188, -111, + -111, -111, -111, 193, -111, 198, 168, 113, 114, -111, + 133, 116, 123, 129, 130, 132, -111, 136, 139, 142, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, 103, -111, 108, -111, 181, -2, -42, -111, -111, + -111, 148, -111, 151, -111, 186, 6, -37, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 34, -111, -111, -111, -111, -111, 3, - -111, -111, 10, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, -111, -111, -111, 127, -111, 109, 15, - -111, -111, 16, -111, 225, 44, 128, -111, -111, -111, - -111, -111, -111, -111, 25, 157, -111, -111, -111, 26, - -111, -111, 24, -111, -111, -111, -111, -111, -111, -111, - 22, -111, -111, -111, -111, -111, -111, -111, -111, -111, - 179, -111, -111, 45, -111, 46, -111, 107, -111, 48, - -111, 106, 62, -111, -111, 163, -3, -111, -111, -111, - -111, -111, -14, -111, -111, -111, -111, -111, 57, -111, - -111, 224, -111, -111, -111, 227, -111, -111, -111, -111, + -111, -111, -111, 42, -111, -111, -111, -111, -111, 22, + -111, -111, 2, -111, -111, -111, -111, -111, -111, -111, + -111, -111, -111, -111, -111, -111, 96, -111, 66, 21, + -111, -111, 0, -111, 274, 35, 88, -111, -111, -111, + -111, -111, -111, -111, 41, 75, -111, -111, -111, 49, + -111, -111, 48, -111, -111, -111, -111, -111, -111, -111, + 57, -111, -111, -111, -111, -111, -111, -111, -111, -111, + 77, -111, -111, 54, -111, 27, -111, 243, -111, 25, + -111, 160, 36, -111, -111, 169, 40, -111, -111, -111, + -111, -111, 56, -111, -111, -111, -111, -111, 180, -111, + -111, 163, -111, -111, -111, 246, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, 35, -111, -111, -111, -111, -111, 72, -111, + -111, -111, 8, -111, -111, -111, -111, -111, 69, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, 12, 264, -111, 258, 246, 254, 209, -111, - 60, 51, 52, 27, 53, -111, -111, -111, -111, -111, - -111, -111, -111, 244, -111, 255, -111, 203, -111, -111, - 207, -111, 217, -111, -111, 198, -111, 208, -111, 8, - -111, 215, -111, 232, -111, 233, 234, -111, -111, 223, - -111, -111, -111, -111, -111, -111, 230, -111, 95, 113, - -111, -111, 153, -111, 156, -111, 2, -111, 147, -111, - 58, -111, 137, -111, 100, -111, -111, -111, -111, -111, - -111, -111, -111, 135, -111, 41, -111, 54, -111, 117, - 162, -111, -111, 50, 169, -111, 174, -111, -111, 32, - 178, -111, -111, -111, 31, -111, 7, 144, -111, 130, - -111, -111, 142, -111, -111, -111, -111, -111, -111, 11, - -111, -111, -111, -111, -111, -111, 214, -111, -111, -111, - -111, 140, -111, -111, -111, -111, -111, -111, 158, -111, - -111, 149, -111, -111, 47, -111, -111, -111, -111, -111, - -55, -111, 38, -111, -67, -111, -111, -111, -111, 263, - -111, -111, 262, -111, -111, -111, -111, -111, 190, -76, - -111, -111, 30, -111, 19, -111, 14, -111, -111, -111, - -111, 33, -111, 272, -111, 64, -111, 175, -111, -111, - -111, -111, -111, -111, 18, -111, -111, 69, -111, -111, - -111, -111, 114, -111, -111, -111, -111, 20, -111, -111, - 110, -111, -111, 28, -111, -111, -111, -111, -111, -111, + -111, -111, 61, 211, -111, 272, 257, 256, 236, -111, + 81, 83, 85, 68, 94, -111, -111, -111, -111, -111, + -111, -111, -111, 235, -111, 218, -111, 209, -111, -111, + 244, -111, 227, -111, -111, 228, -111, 238, -111, 33, + -111, 167, -111, 245, -111, 253, 254, -111, -111, 225, + -111, -111, -111, -111, -111, -111, 217, -111, 194, 213, + -111, -111, 208, -111, 207, -111, 52, -111, 205, -111, + 55, -111, 201, -111, 199, -111, -111, -111, -111, -111, + -111, -111, -111, 278, -111, 39, -111, 34, -111, 173, + 219, -111, -111, 53, 231, -111, 73, -111, -111, 44, + 59, -111, -111, -111, 47, -111, 24, 102, -111, 101, + -111, -111, 111, -111, -111, -111, -111, -111, -111, 26, + -111, -111, -111, -111, -111, -111, 65, -111, -111, -111, + -111, 76, -111, -111, -111, -111, -111, -111, 79, -111, + -111, 89, -111, -111, 51, -111, -111, -111, -111, -111, + -62, -111, 37, -111, -63, -111, -111, -111, -111, 387, + -111, -111, 264, -111, -111, -111, -111, -111, 158, -54, + -111, -111, 28, -111, 38, -111, 23, -111, -111, -111, + -111, 43, -111, 78, -111, 58, -111, 67, -111, -111, + -111, -111, -111, -111, 18, -111, -111, 195, -111, -111, + -111, -111, 161, -111, -111, -111, -111, 20, -111, -111, + 157, -111, -111, 31, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, - 86, -111, -111, -111, -111, -111, 55, -111, -111, -111, - -111, -111, -111, -111, -7, -111, -111, -111, 1, -111, - -111, 329, -111, -111, -111, -111, -111, -111, -111, -111, - -111, -111, -111, 0, -11, -111, -10, -111, -111, -111, - -111, 204, -111, -111, -111, 205, -111, -111, 317, -111, - -111, -111, 311, -111, -111, -111, -111, 370, -111, -111, - -9, -111, -111, -4, -12, -111, 337, -111, -111, -111, - -18, -111, -111, -111, -1, -17, -6, -111, -111, -111, - -111, -111, 466, 78, -111, 82, 307, -13, -111, -111, - -8, -111, 6, -111, 74, 76, -111, -111, 9, -111, - 85, -111, -111, 17, -111, -111, -111, 4, -111, -22, - 84, -111, 67, -111, -111, -111, -111, -111, 49, -111, - -111, 37, 42, 68, 77, -111, -111, -111, -111, -111, - -111, -111, -111, -111, -111, -111, -111, -111, 13, -111, - -111, -111, -111, -111, -111, 36, -111, -111, -111, -111, - -111, -111, -111, -111}; + 206, -111, -111, -111, -111, -111, -7, -111, -111, -111, + -111, -111, -111, -111, -24, -111, -111, -111, -12, -111, + -111, 342, -111, -111, -111, -111, -111, -111, -111, -111, + -111, -111, -111, -16, -32, -111, 5, -111, -111, -111, + -111, 152, -111, -111, -111, 248, -111, -111, 330, -111, + -111, -111, 324, -111, -111, -111, -111, 385, -111, -111, + -21, -111, -111, 1, 14, -111, 367, -111, 232, 12, + -111, -111, 11, -111, 10, -111, 164, 141, -111, -111, + 7, -111, 64, -111, -111, 19, -111, -111, -111, 17, + -111, -1, 60, -111, 46, -111, -111, -111, -111, -111, + -15, -111, -111, -111, -2, -17, -4, -111, -111, -111, + -111, -111, 484, 138, 313, -3, -111, -111, -111, -111, + 4, -111, -111, 13, 16, 97, 127, -111, -111, -111, + -111, -111, -111, -111, -111, -111, -111, -111, -111, -111, + -14, -111, -111, -111, -111, -111, -111, -8, -111, -111, + -111, -111, -111, -111, -111, -111}; const short QQmlJSGrammar::action_info [] = { - 166, 438, 551, 245, 344, 454, 346, 544, 342, 336, - 546, 354, 166, 452, 448, 181, 432, 392, 465, 103, - 420, 461, 421, 448, -138, 101, 423, 73, 408, 663, - 406, -135, 413, 558, 405, 404, 151, 418, 149, -141, - 185, 143, 439, 402, 399, 432, 398, 428, -122, -111, - 101, -133, 424, -112, 268, 432, -130, 350, 73, 268, - -122, 262, -141, 245, 312, -130, 456, 558, 307, 283, - -133, 261, 350, -112, 424, 588, -111, 578, 585, 350, - 576, 465, 243, 461, 305, 448, 103, 424, 524, 143, - 184, 240, 558, 474, 241, 329, 323, 189, 268, 305, - 238, 323, -135, 245, 172, 573, 143, 192, 482, -138, - 0, 448, 555, 303, 143, 174, 174, 448, 465, 461, - 558, 143, 484, 442, 143, 143, 174, 451, 303, 435, - 490, 481, 555, 315, 175, 175, 338, 317, 143, 191, - 244, 452, 143, 0, 143, 175, 143, 662, 661, 143, - 60, 416, 415, 660, 659, 325, 64, 143, 463, 326, - 556, 61, 531, 0, 590, 589, 467, 65, 259, 258, - 654, 653, 143, 501, 436, 60, 525, 426, 491, 0, - 626, 542, 631, 632, 259, 258, 61, 257, 256, 339, - 264, 60, 144, 174, 348, 168, 0, 179, 352, 169, - 252, 251, 61, 283, 259, 258, 631, 632, 60, 321, - 525, 87, 175, 88, 411, 0, 532, 530, 66, 61, - 267, 265, 527, 66, 89, 236, 235, 527, 87, 87, - 88, 88, 87, 526, 88, 66, 549, 87, 526, 88, - 105, 89, 89, 525, 87, 89, 88, 87, 266, 88, - 89, 87, 87, 88, 88, 567, 527, 89, 174, 106, - 89, 107, 477, 67, 89, 89, 525, 526, 67, 68, - 657, 656, 580, 525, 68, 143, 0, 175, 0, 176, - 67, 87, 87, 88, 88, 0, 68, 0, 0, 527, - 550, 548, 174, 0, 89, 89, 0, 581, 579, 0, - 526, 87, 655, 88, 87, 0, 88, 0, 592, 568, - 566, 175, 527, 411, 89, 478, 476, 89, 650, 527, - 75, 76, 0, 526, 75, 76, 285, 286, 446, 445, - 526, 0, 651, 649, 558, 285, 286, 6, 5, 4, - 1, 3, 2, 0, 0, 0, 0, 77, 78, 0, - 0, 77, 78, 287, 288, 0, 290, 291, 0, 0, - 290, 291, 287, 288, 648, 292, 290, 291, 293, 292, - 294, 0, 293, 0, 294, 292, 290, 291, 293, 0, - 294, 35, 290, 291, 35, 292, 0, 0, 293, 0, - 294, 292, 80, 81, 293, 593, 294, 35, 0, 0, - 82, 83, 80, 81, 84, 35, 85, 174, 0, 0, - 82, 83, 0, 0, 84, 35, 85, 0, 49, 52, - 50, 49, 52, 50, 0, -98, 175, 0, 176, 35, - 0, 0, 0, 0, 49, 52, 50, 35, 0, 0, - 0, 0, 49, 52, 50, 0, 46, 34, 51, 46, - 34, 51, 49, 52, 50, 0, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 49, 52, 50, 0, - 46, 34, 51, 0, 49, 52, 50, 35, 0, 0, - 46, 34, 51, 35, 0, 0, 35, 0, 0, 35, - 0, 0, 35, 0, 46, 34, 51, 35, 80, 81, - 35, 0, 46, 34, 51, 0, 82, 83, 0, 0, - 84, 0, 85, 0, 49, 52, 50, 0, 0, 0, - 49, 52, 50, 49, 52, 50, 49, 52, 50, 49, - 52, 50, 0, 35, 49, 52, 50, 49, 52, 50, - 184, 0, 46, 34, 51, 0, 0, 0, 46, 34, - 51, 46, 34, 51, 46, 34, 51, 46, 34, 51, - 0, 0, 46, 34, 51, 46, 34, 51, 35, 0, - 49, 52, 50, 35, 0, 184, 35, 0, 0, 0, - 184, 35, 0, 0, 35, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 49, 52, 50, 250, 249, - 49, 52, 50, 49, 52, 50, 250, 249, 49, 52, - 50, 49, 52, 50, 0, 0, 0, 35, 0, 0, + 424, 405, 432, 404, 346, 245, 573, 354, 406, -134, + 461, -112, -113, -131, -136, 448, 350, -139, 402, 392, + 268, -123, -142, 465, 399, 398, -131, -139, 465, 461, + 474, -136, 558, 448, -134, -112, -113, 424, -123, 350, + -142, 245, 551, 481, 484, 268, 576, 524, 413, 482, + 438, 558, 439, 261, 558, 615, 420, 452, 418, 421, + 283, 454, 143, 428, 172, 558, 166, 423, 558, 448, + 608, 73, 546, 448, 149, 283, 0, 323, 408, 0, + 544, 307, 268, 0, 0, 0, 143, 184, 350, 448, + 245, 166, 101, 73, 461, 329, 465, 238, 456, 424, + 241, 336, 618, 189, 665, 262, 143, 323, 0, 181, + 317, 143, 451, 0, 315, 442, 143, 143, 192, 555, + 0, 143, 240, 243, 303, 151, 452, 101, 143, 185, + 143, 435, 143, 312, 305, 244, 0, 0, 303, 490, + 555, 60, 60, 342, 143, 143, 191, 432, 252, 251, + 103, 344, 61, 61, 144, 60, 305, 662, 661, 60, + 103, 656, 655, 352, 325, 338, 61, 556, 326, 501, + 61, 257, 256, 426, 143, 168, 436, 664, 663, 169, + 348, 542, 264, 64, 321, 633, 634, 491, 628, 620, + 619, 259, 258, 179, 65, 174, 463, 143, 622, 259, + 258, 416, 415, 525, 267, 265, 525, 87, 477, 88, + 531, 0, 174, 525, 175, 143, 411, 87, 339, 88, + 89, 66, 0, 87, 558, 88, 467, 527, 66, 610, + 89, 175, 266, 411, 525, 567, 89, 525, 526, 0, + 87, 66, 88, 87, 87, 88, 88, 549, 174, 527, + 236, 235, 527, 89, 611, 609, 89, 89, 0, 527, + 526, 478, 476, 526, 532, 530, 67, 175, 446, 445, + 526, 0, 68, 67, 174, 659, 658, 105, 0, 68, + 527, 75, 76, 527, 0, 623, 67, 285, 286, 568, + 566, 526, 68, 175, 526, 176, 106, 652, 107, 75, + 76, 550, 548, 174, 0, 285, 286, 657, 77, 78, + 174, 653, 651, 0, 287, 288, 0, 0, 0, 0, + 0, -99, 175, 0, 176, 0, 77, 78, -99, 175, + 0, 176, 287, 288, 0, 290, 291, 0, 0, 87, + 0, 88, 0, 650, 292, 80, 81, 293, 35, 294, + 0, 0, 89, 82, 83, 0, 0, 84, 35, 85, + 80, 81, 6, 5, 4, 1, 3, 2, 82, 83, + 80, 81, 84, 35, 85, 0, 0, 0, 82, 83, + 80, 81, 84, 0, 85, 49, 52, 50, 82, 83, + 80, 81, 84, 0, 85, 49, 52, 50, 82, 83, + 0, 0, 84, 0, 85, 35, 0, 0, 35, 0, + 49, 52, 50, 46, 34, 51, 35, 0, 0, 35, + 290, 291, 35, 46, 34, 51, 0, 0, 35, 292, + 0, 0, 293, 0, 294, 184, 0, 0, 46, 34, + 51, 35, 49, 52, 50, 49, 52, 50, 184, 0, + 0, 0, 0, 49, 52, 50, 49, 52, 50, 49, + 52, 50, 35, 0, 0, 49, 52, 50, 0, 184, + 46, 34, 51, 46, 34, 51, 0, 0, 49, 52, + 50, 46, 34, 51, 46, 34, 51, 46, 34, 51, + 0, 0, 0, 46, 34, 51, 0, 0, 35, 49, + 52, 50, 0, 35, 0, 0, 46, 34, 51, 0, + 0, 35, 0, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, + 250, 249, 0, 0, 0, 49, 52, 50, 0, 0, + 49, 52, 50, 250, 249, 0, 0, 0, 49, 52, + 50, 250, 249, 0, 0, 0, 49, 52, 50, 0, 0, 0, 0, 46, 34, 51, 0, 0, 46, 34, - 51, 46, 34, 51, 0, 0, 46, 34, 51, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 35, 250, - 249, 0, 0, 0, 49, 52, 50, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 255, 254, 46, 34, 51, 49, 52, 50, 0, 0, + 51, 0, 0, 0, 0, 0, 46, 34, 51, 0, + 35, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 30, 31, 153, 0, 0, 0, 0, - 0, 0, 0, 33, 0, 154, 0, 0, 0, 155, - 35, 0, 0, 0, 36, 37, 0, 38, 156, 0, - 157, 0, 0, 0, 516, 0, 0, 0, 45, 0, - 0, 158, 0, 159, 64, 0, 0, 0, 0, 0, - 0, 160, 0, 0, 161, 65, 53, 49, 52, 50, - 162, 54, 0, 0, 0, 0, 163, 0, 0, 0, - 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, - 0, 0, 164, 0, 0, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 153, 0, - 0, 0, 35, 0, 0, 0, 36, 37, 154, 38, - 0, 0, 155, 0, 0, 0, 516, 0, 0, 0, - 45, 156, 0, 157, 0, 0, 319, 0, 0, 0, - 0, 0, 0, 0, 158, 0, 159, 64, 53, 49, - 52, 50, 0, 54, 160, 0, 0, 161, 65, 0, - 0, 0, 0, 162, 44, 56, 32, 0, 0, 163, - 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 164, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 255, 254, 153, 0, 0, 49, 52, 50, + 0, 0, 0, 0, 154, 0, 0, 0, 155, 0, + 0, 0, 0, 0, 0, 0, 0, 156, 0, 157, + 0, 0, 319, 0, 0, 46, 34, 51, 0, 0, + 158, 0, 159, 64, 0, 30, 31, 153, 0, 0, + 160, 0, 0, 161, 65, 33, 0, 154, 0, 162, + 0, 155, 35, 0, 0, 163, 36, 37, 0, 38, + 156, 0, 157, 0, 0, 0, 42, 0, 0, 0, + 45, 164, 0, 158, 0, 159, 64, 0, 0, 0, + 0, 0, 0, 160, 0, 0, 161, 65, 53, 49, + 52, 50, 162, 54, 0, 0, 0, 0, 163, 0, + 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, + 41, 0, 0, 0, 164, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 36, 37, 0, 38, 0, 0, 0, 0, - 0, 0, 516, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, + 0, 36, 37, 0, 38, 0, 0, 0, 0, 0, + 0, 516, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 30, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, - 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, - 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, - 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, - 52, 50, 0, 54, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, - 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 515, - 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, - 0, 219, 0, 0, 0, 0, 0, 0, 35, 0, - 0, 0, 36, 37, 0, 38, 0, 0, 0, 0, - 0, 0, 516, 0, 0, 0, 45, 0, 0, 0, + 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, + 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 30, 31, 0, 0, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, + 0, 0, 0, 0, 0, 42, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 53, 517, 519, 518, 0, 54, - 0, 0, 0, 0, 227, 0, 0, 0, 0, 0, - 44, 56, 32, 214, 0, 0, 41, 0, 0, 0, - 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 515, 0, 30, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, - 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, - 0, 38, 0, 0, 0, 0, 0, 0, 516, 0, - 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, - 563, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 53, 517, 519, 518, 0, 54, 0, 0, 0, 0, - 227, 0, 0, 0, 0, 0, 44, 56, 32, 214, - 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, - 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 515, 0, 30, 31, 0, 0, 0, 0, 0, - 0, 0, 0, 219, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, - 0, 0, 0, 0, 516, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 560, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 53, 517, 519, 518, - 0, 54, 0, 0, 0, 0, 227, 0, 0, 0, - 0, 0, 44, 56, 32, 214, 0, 0, 41, 0, - 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, + 50, 0, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, + 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 515, 0, + 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, + 219, 0, 0, 0, 0, 0, 0, 35, 0, 0, + 0, 36, 37, 0, 38, 0, 0, 0, 0, 0, + 0, 516, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, - 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -131, 0, 0, 0, 29, 30, 31, 0, + 0, 0, 0, 53, 517, 519, 518, 0, 54, 0, + 0, 0, 0, 227, 0, 0, 0, 0, 0, 44, + 56, 32, 214, 0, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 515, 0, 30, 31, 0, 0, + 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, + 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, + 38, 0, 0, 0, 0, 0, 0, 516, 0, 0, + 0, 45, 0, 0, 0, 0, 0, 0, 0, 563, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, + 517, 519, 518, 0, 54, 0, 0, 0, 0, 227, + 0, 0, 0, 0, 0, 44, 56, 32, 214, 0, + 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, + 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 515, 0, 30, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 219, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, + 0, 0, 0, 516, 0, 0, 0, 45, 0, 0, + 0, 0, 0, 0, 0, 560, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 53, 517, 519, 518, 0, + 54, 0, 0, 0, 0, 227, 0, 0, 0, 0, + 0, 44, 56, 32, 214, 0, 0, 41, 0, 0, + 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, @@ -507,369 +479,362 @@ const short QQmlJSGrammar::action_info [] = { 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, - 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, - 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, - 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 53, 49, 52, 50, 0, - 54, 0, 55, 0, 57, 282, 58, 0, 0, 0, - 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, - 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 488, 0, 0, 29, - 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, - 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, - 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, - 0, 48, 0, 0, 489, 0, 0, 0, 0, 0, - 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, - 55, 0, 57, 0, 58, 0, 0, 0, 0, 44, - 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, - 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 488, 0, 0, 29, 30, 31, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, - 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, - 0, 0, 494, 0, 0, 0, 0, 0, 0, 0, - 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, - 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, - 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, - 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 496, 0, 0, 29, 30, 31, 0, 0, + 0, -132, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, 0, 0, - 497, 0, 0, 0, 0, 0, 0, 0, 0, 53, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, 0, 55, 0, 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 496, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 35, 0, 0, 0, 36, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 499, 0, - 0, 0, 0, 0, 0, 0, 0, 53, 49, 52, - 50, 0, 54, 0, 55, 0, 57, 0, 58, 0, - 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, - 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, + 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 35, 0, + 0, 0, 36, 37, 0, 38, 0, 0, 0, 39, + 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, + 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 53, 49, 52, 50, 0, 54, + 0, 55, 0, 57, 282, 58, 0, 0, 0, 0, + 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, + 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 496, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, - 0, 0, 0, 0, 0, 0, 35, 220, 0, 0, - 595, 596, 0, 38, 0, 0, 0, 39, 0, 40, + 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, + 36, 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, 0, - 48, 0, 0, 0, 0, 0, 0, 0, 223, 0, - 0, 0, 53, 49, 52, 50, 224, 54, 0, 55, - 226, 57, 0, 58, 0, 229, 0, 0, 44, 56, + 48, 0, 0, 497, 0, 0, 0, 0, 0, 0, + 0, 0, 53, 49, 52, 50, 0, 54, 0, 55, + 0, 57, 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, - 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, - 0, 35, 220, 0, 0, 221, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, - 0, 0, 0, 223, 0, 0, 0, 53, 49, 52, - 50, 224, 54, 0, 55, 226, 57, 0, 58, 0, - 229, 0, 0, 44, 56, 32, 0, 0, 0, 41, - 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, - 113, 0, 0, 115, 117, 118, 0, 0, 119, 0, - 120, 0, 0, 0, 122, 123, 124, 0, 0, 0, - 0, 0, 0, 35, 125, 126, 127, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 131, 0, 0, 0, 0, 0, 0, - 49, 52, 50, 132, 133, 134, 0, 136, 137, 138, - 139, 140, 141, 0, 0, 129, 135, 121, 114, 116, - 130, 0, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 111, 112, 113, 0, 0, 115, 117, 118, 0, 0, - 119, 0, 120, 0, 0, 0, 122, 123, 124, 0, - 0, 0, 0, 0, 0, 35, 125, 126, 127, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, - 0, 0, 0, 395, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, - 0, 397, 49, 52, 50, 132, 133, 134, 0, 136, - 137, 138, 139, 140, 141, 0, 0, 129, 135, 121, - 114, 116, 130, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 488, 0, 0, 29, 30, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 0, 0, 0, 35, 0, 0, 0, 36, 37, + 0, 38, 0, 0, 0, 39, 0, 40, 42, 43, + 0, 0, 45, 0, 0, 0, 47, 0, 48, 0, + 0, 494, 0, 0, 0, 0, 0, 0, 0, 0, + 53, 49, 52, 50, 0, 54, 0, 55, 0, 57, + 0, 58, 0, 0, 0, 0, 44, 56, 32, 0, + 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, + 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 488, 0, 0, 29, 30, 31, 0, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, + 0, 0, 35, 0, 0, 0, 36, 37, 0, 38, + 0, 0, 0, 39, 0, 40, 42, 43, 0, 0, + 45, 0, 0, 0, 47, 0, 48, 0, 0, 489, + 0, 0, 0, 0, 0, 0, 0, 0, 53, 49, + 52, 50, 0, 54, 0, 55, 0, 57, 0, 58, + 0, 0, 0, 0, 44, 56, 32, 0, 0, 0, + 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 496, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 0, 36, 37, 0, 38, 0, 0, + 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, + 0, 0, 47, 0, 48, 0, 0, 499, 0, 0, + 0, 0, 0, 0, 0, 0, 53, 49, 52, 50, + 0, 54, 0, 55, 0, 57, 0, 58, 0, 0, + 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, + 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 221, + 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 0, 55, 226, + 57, 0, 58, 0, 229, 0, 0, 44, 56, 32, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, + 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, + 35, 220, 0, 0, 578, 37, 0, 38, 0, 0, + 0, 39, 0, 40, 42, 43, 0, 0, 45, 0, + 0, 0, 47, 0, 48, 0, 0, 0, 0, 0, + 0, 0, 223, 0, 0, 0, 53, 49, 52, 50, + 224, 54, 0, 55, 226, 57, 0, 58, 0, 229, + 0, 0, 44, 56, 32, 0, 0, 0, 41, 0, + 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 578, + 624, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 0, 55, 226, + 57, 0, 58, 0, 229, 0, 0, 44, 56, 32, + 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, 0, 115, 117, 118, 0, 0, 119, 0, 120, 0, 0, 0, 122, 123, 124, 0, 0, 0, 0, 0, 0, 35, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 0, 0, 0, 395, 0, 0, 0, 0, + 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, - 0, 0, 0, 397, 49, 52, 50, 132, 133, 134, + 0, 0, 0, 0, 49, 52, 50, 132, 133, 134, 0, 136, 137, 138, 139, 140, 141, 0, 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, - 0, 0, 46, 374, 380, 0, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, 0, 115, 117, 118, 0, 0, 119, 0, 120, 0, 0, 0, 122, 123, 124, 0, 0, 0, 0, 0, 0, 35, 125, 126, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 395, 0, 0, - 0, 0, 0, 0, 0, 396, 0, 0, 0, 131, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 0, 0, 0, 0, 0, 397, 49, 52, 50, 132, 133, 134, 0, 136, 137, 138, 139, 140, 141, 0, 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, 0, 0, 46, 374, 380, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 213, 0, 0, 0, - 0, 215, 0, 29, 30, 31, 217, 0, 0, 0, - 0, 0, 0, 218, 219, 0, 0, 0, 0, 0, - 0, 35, 220, 0, 0, 221, 37, 0, 38, 0, - 0, 0, 39, 0, 40, 42, 43, 0, 0, 45, - 0, 0, 0, 47, 0, 48, 0, 0, 0, 0, - 0, 222, 0, 223, 0, 0, 0, 53, 49, 52, - 50, 224, 54, 225, 55, 226, 57, 227, 58, 228, - 229, 0, 0, 44, 56, 32, 214, 216, 0, 41, + 0, 0, 0, 0, 0, 0, 111, 112, 113, 0, + 0, 115, 117, 118, 0, 0, 119, 0, 120, 0, + 0, 0, 122, 123, 124, 0, 0, 0, 0, 0, + 0, 35, 125, 126, 127, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 128, 0, 0, 0, 395, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 131, 0, 0, 0, 0, 0, 397, 49, 52, + 50, 132, 133, 134, 0, 136, 137, 138, 139, 140, + 141, 0, 0, 129, 135, 121, 114, 116, 130, 0, 0, 0, 0, 0, 0, 0, 46, 34, 51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, - 0, 0, 0, 215, 0, 29, 30, 31, 217, 0, - 0, 0, 0, 0, 0, 218, 33, 0, 0, 0, - 0, 0, 0, 35, 220, 0, 0, 221, 37, 0, - 38, 0, 0, 0, 39, 0, 40, 42, 43, 0, - 0, 45, 0, 0, 0, 47, 0, 48, 0, 0, - 0, 0, 0, 222, 0, 223, 0, 0, 0, 53, - 49, 52, 50, 224, 54, 225, 55, 226, 57, 227, - 58, 228, 229, 0, 0, 44, 56, 32, 214, 216, - 0, 41, 0, 0, 0, 0, 0, 0, 46, 34, - 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 600, 112, 113, 0, 0, 602, 117, 604, 30, 31, - 605, 0, 120, 0, 0, 0, 122, 607, 608, 0, - 0, 0, 0, 0, 0, 35, 609, 126, 127, 221, - 37, 0, 38, 0, 0, 0, 39, 0, 40, 610, - 43, 0, 0, 612, 0, 0, 0, 47, 0, 48, - 0, 0, 0, 0, 0, 613, 0, 223, 0, 0, - 0, 614, 49, 52, 50, 615, 616, 617, 55, 619, - 620, 621, 622, 623, 624, 0, 0, 611, 618, 606, - 601, 603, 130, 41, 0, 0, 0, 0, 0, 0, - 46, 374, 380, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 365, 112, 113, 0, 0, 367, 117, 369, - 30, 31, 370, 0, 120, 0, 0, 0, 122, 372, - 373, 0, 0, 0, 0, 0, 0, 35, 375, 126, - 127, 221, 37, 0, 38, 0, 0, 0, 39, 0, - 40, 376, 43, 0, 0, 378, 0, 0, 0, 47, - 0, 48, 0, -277, 0, 0, 0, 379, 0, 223, - 0, 0, 0, 381, 49, 52, 50, 382, 383, 384, - 55, 386, 387, 388, 389, 390, 391, 0, 0, 377, - 385, 371, 366, 368, 130, 41, 0, 0, 0, 0, - 0, 0, 46, 374, 380, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 111, 112, + 113, 0, 0, 115, 117, 118, 0, 0, 119, 0, + 120, 0, 0, 0, 122, 123, 124, 0, 0, 0, + 0, 0, 0, 35, 125, 126, 127, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, + 0, 395, 0, 0, 0, 0, 0, 0, 0, 396, + 0, 0, 0, 131, 0, 0, 0, 0, 0, 397, + 49, 52, 50, 132, 133, 134, 0, 136, 137, 138, + 139, 140, 141, 0, 0, 129, 135, 121, 114, 116, + 130, 0, 0, 0, 0, 0, 0, 0, 46, 374, + 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 0, 0, 0, 215, 0, 29, 30, 31, + 217, 0, 0, 0, 0, 0, 0, 218, 33, 0, + 0, 0, 0, 0, 0, 35, 220, 0, 0, 221, + 37, 0, 38, 0, 0, 0, 39, 0, 40, 42, + 43, 0, 0, 45, 0, 0, 0, 47, 0, 48, + 0, 0, 0, 0, 0, 222, 0, 223, 0, 0, + 0, 53, 49, 52, 50, 224, 54, 225, 55, 226, + 57, 227, 58, 228, 229, 0, 0, 44, 56, 32, + 214, 216, 0, 41, 0, 0, 0, 0, 0, 0, + 46, 34, 51, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 213, 0, 0, 0, 0, 215, 0, 29, + 30, 31, 217, 0, 0, 0, 0, 0, 0, 218, + 219, 0, 0, 0, 0, 0, 0, 35, 220, 0, + 0, 221, 37, 0, 38, 0, 0, 0, 39, 0, + 40, 42, 43, 0, 0, 45, 0, 0, 0, 47, + 0, 48, 0, 0, 0, 0, 0, 222, 0, 223, + 0, 0, 0, 53, 49, 52, 50, 224, 54, 225, + 55, 226, 57, 227, 58, 228, 229, 0, 0, 44, + 56, 32, 214, 216, 0, 41, 0, 0, 0, 0, + 0, 0, 46, 34, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 582, 112, 113, 0, 0, 584, + 117, 586, 30, 31, 587, 0, 120, 0, 0, 0, + 122, 589, 590, 0, 0, 0, 0, 0, 0, 35, + 591, 126, 127, 221, 37, 0, 38, 0, 0, 0, + 39, 0, 40, 592, 43, 0, 0, 594, 0, 0, + 0, 47, 0, 48, 0, 0, 0, 0, 0, 595, + 0, 223, 0, 0, 0, 596, 49, 52, 50, 597, + 598, 599, 55, 601, 602, 603, 604, 605, 606, 0, + 0, 593, 600, 588, 583, 585, 130, 41, 0, 0, + 0, 0, 0, 0, 46, 374, 380, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 365, 112, 113, 0, + 0, 367, 117, 369, 30, 31, 370, 0, 120, 0, + 0, 0, 122, 372, 373, 0, 0, 0, 0, 0, + 0, 35, 375, 126, 127, 221, 37, 0, 38, 0, + 0, 0, 39, 0, 40, 376, 43, 0, 0, 378, + 0, 0, 0, 47, 0, 48, 0, -278, 0, 0, + 0, 379, 0, 223, 0, 0, 0, 381, 49, 52, + 50, 382, 383, 384, 55, 386, 387, 388, 389, 390, + 391, 0, 0, 377, 385, 371, 366, 368, 130, 41, + 0, 0, 0, 0, 0, 0, 46, 374, 380, 0, + 0, 0, 0, 0, 0, 0, 0, 0, - 148, 142, 183, 447, 469, 347, 575, 444, 547, 627, - 248, 320, 587, 572, 584, 586, 485, 591, 565, 529, - 313, 545, 447, 393, 253, 528, 500, 183, 574, 453, - 331, 652, 447, 437, 444, 313, 462, 455, 263, 457, - 237, 441, 206, 188, 190, 150, 16, 178, 433, 630, - 425, 641, 165, 400, 658, 458, 642, 171, 173, 248, - 475, 351, 498, 248, 253, 313, 183, 466, 183, 541, - 495, 629, 253, 512, 511, 188, 145, 206, 260, 645, - 644, 62, 0, 62, 362, 507, 298, 469, 206, 206, - 247, 514, 514, 62, 206, 460, 646, 409, 152, 409, - 599, 628, 355, 239, 206, 62, 62, 62, 362, 260, - 296, 297, 299, 331, 62, 62, 313, 504, 206, 295, - 62, 62, 459, 460, 356, 206, 277, 62, 62, 502, - 182, 281, 206, 62, 410, 182, 410, 401, 62, 353, - 459, 62, 62, 506, 505, 62, 62, 503, 493, 349, - 91, 62, 492, 206, 63, 206, 313, 62, 345, 483, - 393, 479, 62, 62, 260, 206, 444, 206, 510, 102, - 148, 62, 104, 182, 206, 188, 188, 468, 180, 170, - 206, 62, 148, 247, 62, 394, 460, 393, 409, 340, - 412, 341, 362, 206, 422, 167, 393, 206, 62, 108, - 459, 313, 62, 187, 419, 62, 62, 86, 206, 62, - 318, 98, 100, 403, 62, 99, 69, 322, 514, 514, - 313, 62, 417, 553, 557, 410, 206, 79, 110, 246, - 62, 343, 206, 206, 62, 0, 70, 62, 74, 71, - 62, 62, 206, 108, 90, 206, 93, 62, 62, 62, - 72, 62, 92, 62, 94, 62, 95, 309, 96, 407, - 97, 309, 281, 62, 362, 362, 281, 0, 281, 242, - 302, 0, 110, 177, 464, 0, 316, 309, 0, 308, - 206, 206, 281, 311, 309, 0, 62, 62, 309, 281, - 206, 281, 281, 281, 0, 314, 0, 0, 62, 330, - 62, 324, 0, 281, 327, 281, 337, 300, 62, 62, - 328, 304, 62, 281, 281, 301, 564, 281, 62, 289, - 306, 569, 561, 281, 0, 514, 553, 284, 625, 0, - 0, 514, 0, 0, 522, 0, 0, 0, 0, 0, - 522, 0, 0, 0, 0, 0, 513, 523, 0, 485, - 443, 440, 513, 523, 533, 534, 535, 536, 540, 537, - 538, 577, 533, 534, 535, 536, 540, 537, 538, 0, + 545, 572, 565, 632, 654, 148, 529, 541, 528, 142, + 660, 263, 500, 393, 617, 616, 621, 614, 16, 629, + 444, 183, 313, 547, 447, 183, 631, 643, 253, 248, + 644, 485, 575, 574, 607, 152, 320, 437, 178, 313, + 441, 433, 173, 183, 165, 253, 462, 313, 457, 447, + 444, 453, 253, 458, 425, 347, 455, 248, 351, 188, + 475, 466, 498, 171, 150, 447, 206, 190, 400, 468, + 0, 183, 248, 495, 469, 237, 409, 393, 409, 331, + 464, 247, 512, 206, 145, 206, 62, 409, 507, 206, + 0, 511, 0, 188, 0, 206, 206, 188, 206, 62, + 62, 504, 460, 417, 62, 206, 505, 206, 647, 646, + 407, 0, 0, 410, 62, 410, 459, 62, 148, 506, + 62, 187, 62, 277, 410, 419, 412, 298, 281, 393, + 148, 0, 0, 0, 422, 62, 170, 62, 180, 62, + 295, 514, 296, 260, 297, 62, 648, 503, 62, 62, + 62, 182, 514, 299, 394, 62, 62, 460, 459, 206, + 362, 630, 362, 62, 167, 502, 514, 62, 62, 322, + 62, 553, 444, 99, 100, 93, 206, 62, 356, 206, + 510, 206, 94, 62, 62, 206, 62, 62, 95, 96, + 62, 97, 86, 62, 90, 493, 62, 91, 188, 492, + 92, 355, 62, 353, 108, 62, 483, 349, 242, 345, + 247, 313, 331, 469, 102, 104, 313, 206, 62, 206, + 182, 260, 62, 206, 206, 206, 239, 62, 98, 182, + 313, 313, 62, 110, 362, 72, 62, 206, 69, 62, + 318, 70, 62, 62, 71, 260, 63, 62, 246, 393, + 581, 62, 62, 460, 0, 74, 206, 62, 79, 459, + 0, 206, 514, 309, 206, 62, 362, 557, 281, 0, + 281, 309, 62, 0, 284, 403, 281, 281, 0, 309, + 401, 0, 206, 306, 281, 308, 343, 479, 340, 62, + 62, 341, 108, 337, 281, 281, 206, 302, 309, 62, + 0, 330, 304, 281, 281, 314, 316, 62, 309, 0, + 62, 62, 281, 281, 324, 281, 281, 301, 300, 514, + 311, 110, 177, 0, 327, 0, 62, 569, 522, 564, + 328, 281, 553, 289, 627, 561, 0, 0, 514, 0, + 513, 523, 0, 0, 514, 0, 0, 522, 0, 0, + 0, 0, 443, 522, 0, 485, 0, 0, 0, 513, + 523, 0, 0, 0, 0, 513, 523, 533, 534, 535, + 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, + 0, 577, 0, 0, 0, 0, 0, 0, 0, 362, + 579, 580, 533, 534, 535, 536, 540, 537, 538, 569, + 0, 0, 0, 0, 0, 206, 0, 0, 570, 571, + 533, 534, 535, 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 514, 569, 0, 0, 0, 0, 0, - 0, 0, 522, 570, 571, 533, 534, 535, 536, 540, - 537, 538, 0, 0, 513, 523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 0, 0, 0, 0, 625, 626, 533, + 534, 535, 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 594, 0, 0, 0, 0, 0, 0, 0, 0, 597, - 598, 533, 534, 535, 536, 540, 537, 538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0}; + 0, 0, 0, 0, 0}; const short QQmlJSGrammar::action_check [] = { - 2, 55, 34, 7, 60, 36, 31, 37, 61, 17, - 24, 16, 2, 20, 33, 60, 5, 8, 36, 79, - 60, 36, 33, 33, 7, 48, 55, 1, 55, 0, - 33, 7, 60, 33, 60, 36, 60, 36, 8, 7, - 36, 8, 7, 55, 7, 5, 55, 33, 7, 7, - 48, 7, 36, 7, 36, 5, 7, 36, 1, 36, - 7, 36, 7, 7, 61, 7, 60, 33, 8, 1, - 7, 77, 36, 7, 36, 60, 7, 29, 8, 36, - 7, 36, 55, 36, 79, 33, 79, 36, 66, 8, - 36, 60, 33, 17, 33, 7, 2, 8, 36, 79, - 36, 2, 7, 7, 7, 66, 8, 33, 33, 7, - -1, 33, 8, 48, 8, 15, 15, 33, 36, 36, - 33, 8, 55, 7, 8, 8, 15, 6, 48, 10, - 8, 60, 8, 61, 34, 34, 8, 60, 8, 60, - 55, 20, 8, -1, 8, 34, 8, 61, 62, 8, - 40, 61, 62, 61, 62, 50, 42, 8, 60, 54, - 56, 51, 7, -1, 61, 62, 60, 53, 61, 62, - 61, 62, 8, 60, 55, 40, 29, 60, 56, -1, - 56, 29, 91, 92, 61, 62, 51, 61, 62, 61, - 60, 40, 56, 15, 60, 50, -1, 56, 60, 54, - 61, 62, 51, 1, 61, 62, 91, 92, 40, 60, - 29, 25, 34, 27, 36, -1, 61, 62, 12, 51, - 61, 62, 75, 12, 38, 61, 62, 75, 25, 25, - 27, 27, 25, 86, 27, 12, 7, 25, 86, 27, - 15, 38, 38, 29, 25, 38, 27, 25, 89, 27, - 38, 25, 25, 27, 27, 7, 75, 38, 15, 34, - 38, 36, 8, 57, 38, 38, 29, 86, 57, 63, - 61, 62, 36, 29, 63, 8, -1, 34, -1, 36, - 57, 25, 25, 27, 27, -1, 63, -1, -1, 75, - 61, 62, 15, -1, 38, 38, -1, 61, 62, -1, - 86, 25, 93, 27, 25, -1, 27, -1, 7, 61, - 62, 34, 75, 36, 38, 61, 62, 38, 47, 75, - 18, 19, -1, 86, 18, 19, 18, 19, 61, 62, - 86, -1, 61, 62, 33, 18, 19, 98, 99, 100, - 101, 102, 103, -1, -1, -1, -1, 45, 46, -1, - -1, 45, 46, 45, 46, -1, 23, 24, -1, -1, - 23, 24, 45, 46, 93, 32, 23, 24, 35, 32, - 37, -1, 35, -1, 37, 32, 23, 24, 35, -1, - 37, 29, 23, 24, 29, 32, -1, -1, 35, -1, - 37, 32, 23, 24, 35, 94, 37, 29, -1, -1, - 31, 32, 23, 24, 35, 29, 37, 15, -1, -1, - 31, 32, -1, -1, 35, 29, 37, -1, 66, 67, - 68, 66, 67, 68, -1, 33, 34, -1, 36, 29, - -1, -1, -1, -1, 66, 67, 68, 29, -1, -1, - -1, -1, 66, 67, 68, -1, 94, 95, 96, 94, - 95, 96, 66, 67, 68, -1, -1, -1, -1, -1, - -1, -1, 94, 95, 96, -1, 66, 67, 68, -1, - 94, 95, 96, -1, 66, 67, 68, 29, -1, -1, - 94, 95, 96, 29, -1, -1, 29, -1, -1, 29, - -1, -1, 29, -1, 94, 95, 96, 29, 23, 24, - 29, -1, 94, 95, 96, -1, 31, 32, -1, -1, - 35, -1, 37, -1, 66, 67, 68, -1, -1, -1, - 66, 67, 68, 66, 67, 68, 66, 67, 68, 66, - 67, 68, -1, 29, 66, 67, 68, 66, 67, 68, - 36, -1, 94, 95, 96, -1, -1, -1, 94, 95, - 96, 94, 95, 96, 94, 95, 96, 94, 95, 96, - -1, -1, 94, 95, 96, 94, 95, 96, 29, -1, - 66, 67, 68, 29, -1, 36, 29, -1, -1, -1, - 36, 29, -1, -1, 29, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 94, 95, - 96, -1, -1, -1, -1, 66, 67, 68, 61, 62, - 66, 67, 68, 66, 67, 68, 61, 62, 66, 67, - 68, 66, 67, 68, -1, -1, -1, 29, -1, -1, + 36, 60, 5, 36, 31, 7, 66, 16, 33, 7, + 36, 7, 7, 7, 7, 33, 36, 7, 55, 8, + 36, 7, 7, 36, 7, 55, 7, 7, 36, 36, + 17, 7, 33, 33, 7, 7, 7, 36, 7, 36, + 7, 7, 34, 60, 55, 36, 7, 66, 60, 33, + 55, 33, 7, 77, 33, 8, 60, 20, 36, 33, + 1, 36, 8, 33, 7, 33, 2, 55, 33, 33, + 29, 1, 24, 33, 8, 1, -1, 2, 55, -1, + 37, 8, 36, -1, -1, -1, 8, 36, 36, 33, + 7, 2, 48, 1, 36, 7, 36, 36, 60, 36, + 33, 17, 60, 8, 0, 36, 8, 2, -1, 60, + 60, 8, 6, -1, 61, 7, 8, 8, 33, 8, + -1, 8, 60, 55, 48, 60, 20, 48, 8, 36, + 8, 10, 8, 61, 79, 55, -1, -1, 48, 8, + 8, 40, 40, 61, 8, 8, 60, 5, 61, 62, + 79, 60, 51, 51, 56, 40, 79, 61, 62, 40, + 79, 61, 62, 60, 50, 8, 51, 56, 54, 60, + 51, 61, 62, 60, 8, 50, 55, 61, 62, 54, + 60, 29, 60, 42, 60, 91, 92, 56, 56, 61, + 62, 61, 62, 56, 53, 15, 60, 8, 7, 61, + 62, 61, 62, 29, 61, 62, 29, 25, 8, 27, + 7, -1, 15, 29, 34, 8, 36, 25, 61, 27, + 38, 12, -1, 25, 33, 27, 60, 75, 12, 36, + 38, 34, 89, 36, 29, 7, 38, 29, 86, -1, + 25, 12, 27, 25, 25, 27, 27, 7, 15, 75, + 61, 62, 75, 38, 61, 62, 38, 38, -1, 75, + 86, 61, 62, 86, 61, 62, 57, 34, 61, 62, + 86, -1, 63, 57, 15, 61, 62, 15, -1, 63, + 75, 18, 19, 75, -1, 94, 57, 18, 19, 61, + 62, 86, 63, 34, 86, 36, 34, 47, 36, 18, + 19, 61, 62, 15, -1, 18, 19, 93, 45, 46, + 15, 61, 62, -1, 45, 46, -1, -1, -1, -1, + -1, 33, 34, -1, 36, -1, 45, 46, 33, 34, + -1, 36, 45, 46, -1, 23, 24, -1, -1, 25, + -1, 27, -1, 93, 32, 23, 24, 35, 29, 37, + -1, -1, 38, 31, 32, -1, -1, 35, 29, 37, + 23, 24, 98, 99, 100, 101, 102, 103, 31, 32, + 23, 24, 35, 29, 37, -1, -1, -1, 31, 32, + 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, + 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, + -1, -1, 35, -1, 37, 29, -1, -1, 29, -1, + 66, 67, 68, 94, 95, 96, 29, -1, -1, 29, + 23, 24, 29, 94, 95, 96, -1, -1, 29, 32, + -1, -1, 35, -1, 37, 36, -1, -1, 94, 95, + 96, 29, 66, 67, 68, 66, 67, 68, 36, -1, + -1, -1, -1, 66, 67, 68, 66, 67, 68, 66, + 67, 68, 29, -1, -1, 66, 67, 68, -1, 36, + 94, 95, 96, 94, 95, 96, -1, -1, 66, 67, + 68, 94, 95, 96, 94, 95, 96, 94, 95, 96, + -1, -1, -1, 94, 95, 96, -1, -1, 29, 66, + 67, 68, -1, 29, -1, -1, 94, 95, 96, -1, + -1, 29, -1, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, + 61, 62, -1, -1, -1, 66, 67, 68, -1, -1, + 66, 67, 68, 61, 62, -1, -1, -1, 66, 67, + 68, 61, 62, -1, -1, -1, 66, 67, 68, -1, -1, -1, -1, 94, 95, 96, -1, -1, 94, 95, - 96, 94, 95, 96, -1, -1, 94, 95, 96, 94, - 95, 96, -1, -1, -1, -1, -1, -1, 29, 61, - 62, -1, -1, -1, 66, 67, 68, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, -1, -1, -1, -1, -1, 94, 95, 96, -1, + 29, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 61, 62, 94, 95, 96, 66, 67, 68, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, 12, 13, 3, -1, -1, -1, -1, - -1, -1, -1, 22, -1, 13, -1, -1, -1, 17, - 29, -1, -1, -1, 33, 34, -1, 36, 26, -1, - 28, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, - -1, 49, -1, -1, 52, 53, 65, 66, 67, 68, - 58, 70, -1, -1, -1, -1, 64, -1, -1, -1, - -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, - -1, -1, 80, -1, -1, 94, 95, 96, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, 3, -1, - -1, -1, 29, -1, -1, -1, 33, 34, 13, 36, - -1, -1, 17, -1, -1, -1, 43, -1, -1, -1, - 47, 26, -1, 28, -1, -1, 31, -1, -1, -1, - -1, -1, -1, -1, 39, -1, 41, 42, 65, 66, - 67, 68, -1, 70, 49, -1, -1, 52, 53, -1, - -1, -1, -1, 58, 81, 82, 83, -1, -1, 64, - 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, - -1, -1, -1, -1, -1, 80, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 61, 62, 3, -1, -1, 66, 67, 68, + -1, -1, -1, -1, 13, -1, -1, -1, 17, -1, + -1, -1, -1, -1, -1, -1, -1, 26, -1, 28, + -1, -1, 31, -1, -1, 94, 95, 96, -1, -1, + 39, -1, 41, 42, -1, 12, 13, 3, -1, -1, + 49, -1, -1, 52, 53, 22, -1, 13, -1, 58, + -1, 17, 29, -1, -1, 64, 33, 34, -1, 36, + 26, -1, 28, -1, -1, -1, 43, -1, -1, -1, + 47, 80, -1, 39, -1, 41, 42, -1, -1, -1, + -1, -1, -1, 49, -1, -1, 52, 53, 65, 66, + 67, 68, 58, 70, -1, -1, -1, -1, 64, -1, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, -1, 80, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, + -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12, 13, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, - -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, - 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, - 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, - 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, - -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, - -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, - -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, - -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, + 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, + -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, - -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, - 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, - -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, - -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, - -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, - -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, - -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, - 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, - 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, - -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, - 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, - -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, - 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, - -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, - -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, - -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, - -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, - -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, + 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, + 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, + -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, + -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, - 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, + -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, + -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, + 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, + -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, + -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, + -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, + -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, @@ -879,101 +844,100 @@ const short QQmlJSGrammar::action_check [] = { -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, - -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, - -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, - 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, - -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, - 70, -1, 72, -1, 74, 75, 76, -1, -1, -1, - -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, - -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, - 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, - 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, - -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, - 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, - -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, - 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, - 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, - -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, - -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, - -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, - 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, - 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, - -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, - -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, - 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, - -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, - 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, + -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, - -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, - 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, - -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, + 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, + -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, + -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, + -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, + 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, + -1, 72, -1, 74, 75, 76, -1, -1, -1, -1, + 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, + -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, - -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, - 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, - -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, - 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, + 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, + -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, - -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, - 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, - -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, - 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, - 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, - 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, - 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, - 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, - -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, - -1, 65, 66, 67, 68, 69, 70, 71, -1, 73, - 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, + 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, + -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, + 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, + -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, + 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, + -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, + 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, + -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, + -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, + 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, + -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, + 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, + -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, + -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, + -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, + 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, + -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, + -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, + 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, + -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, - -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, + -1, -1, -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, @@ -982,104 +946,126 @@ const short QQmlJSGrammar::action_check [] = { 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, - -1, -1, -1, -1, -1, 55, -1, -1, -1, 59, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, - -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, - -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, - -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, - -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, - -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, - -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, + -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, + -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, + -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, + 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, - -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, - -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, - -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, - 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, - -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, - -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, + 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, - -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, + 86, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, - 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, - -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, + 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, + 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, - 84, 85, 86, 87, -1, -1, -1, -1, -1, -1, + 84, 85, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, - 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, - 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, - 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, + -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, + 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, - -1, 53, -1, 55, -1, -1, -1, 59, -1, 61, + -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, - 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, + 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, -1, -1, - -1, -1, -1, -1, + -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, + 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, + 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, + -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, + -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, + -1, -1, -1, -1, 94, 95, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, + -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, + -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, + -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, + -1, -1, -1, -1, -1, -1, 94, 95, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, - 42, 3, 18, 25, 18, 3, 18, 3, 18, 22, - 18, 3, 18, 22, 32, 32, 42, 18, 18, 18, - 3, 32, 25, 18, 18, 32, 3, 18, 32, 105, - 18, 18, 25, 100, 3, 3, 3, 18, 3, 25, - 18, 3, 18, 18, 18, 42, 3, 3, 103, 9, - 3, 14, 42, 42, 18, 25, 14, 42, 42, 18, - 42, 3, 42, 18, 18, 3, 18, 3, 18, 14, - 42, 22, 18, 2, 4, 18, 42, 18, 2, 11, - 12, 54, -1, 54, 2, 56, 59, 18, 18, 18, - 4, 14, 14, 54, 18, 56, 19, 14, 77, 14, - 18, 23, 2, 46, 18, 54, 54, 54, 2, 2, - 59, 59, 59, 18, 54, 54, 3, 56, 18, 59, - 54, 54, 56, 56, 18, 18, 54, 54, 54, 56, - 56, 59, 18, 54, 51, 56, 51, 2, 54, 2, - 56, 54, 54, 56, 56, 54, 54, 56, 38, 2, - 58, 54, 42, 18, 57, 18, 3, 54, 2, 45, - 18, 92, 54, 54, 2, 18, 3, 18, 109, 66, - 42, 54, 64, 56, 18, 18, 18, 2, 50, 70, - 18, 54, 42, 4, 54, 43, 56, 18, 14, 94, - 50, 78, 2, 18, 45, 68, 18, 18, 54, 18, - 56, 3, 54, 46, 46, 54, 54, 59, 18, 54, - 2, 60, 60, 44, 54, 60, 56, 2, 14, 14, - 3, 54, 44, 19, 19, 51, 18, 60, 47, 2, - 54, 78, 18, 18, 54, -1, 56, 54, 62, 56, - 54, 54, 18, 18, 58, 18, 59, 54, 54, 54, - 57, 54, 58, 54, 59, 54, 59, 54, 59, 45, - 59, 54, 59, 54, 2, 2, 59, -1, 59, 45, - 61, -1, 47, 48, 2, -1, 78, 54, -1, 76, - 18, 18, 59, 76, 54, -1, 54, 54, 54, 59, - 18, 59, 59, 59, -1, 78, -1, -1, 54, 76, - 54, 69, -1, 59, 71, 59, 76, 61, 54, 54, - 76, 67, 54, 59, 59, 61, 5, 59, 54, 61, - 65, 14, 5, 59, -1, 14, 19, 63, 21, -1, - -1, 14, -1, -1, 23, -1, -1, -1, -1, -1, - 23, -1, -1, -1, -1, -1, 35, 36, -1, 42, - 88, 88, 35, 36, 25, 26, 27, 28, 29, 30, - 31, 24, 25, 26, 27, 28, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 14, 14, -1, -1, -1, -1, -1, - -1, -1, 23, 23, 24, 25, 26, 27, 28, 29, - 30, 31, -1, -1, 35, 36, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 32, 22, 18, 9, 18, 42, 18, 14, 32, 3, + 18, 3, 3, 18, 18, 32, 18, 32, 3, 22, + 3, 18, 3, 18, 25, 18, 22, 14, 18, 18, + 14, 42, 18, 32, 22, 77, 3, 100, 3, 3, + 3, 103, 42, 18, 42, 18, 3, 3, 25, 25, + 3, 105, 18, 25, 3, 3, 18, 18, 3, 18, + 42, 3, 42, 42, 42, 25, 18, 18, 42, 2, + -1, 18, 18, 42, 18, 18, 14, 18, 14, 18, + 2, 4, 2, 18, 42, 18, 54, 14, 56, 18, + -1, 4, -1, 18, -1, 18, 18, 18, 18, 54, + 54, 56, 56, 44, 54, 18, 56, 18, 11, 12, + 45, -1, -1, 51, 54, 51, 56, 54, 42, 56, + 54, 46, 54, 54, 51, 46, 50, 59, 59, 18, + 42, -1, -1, -1, 45, 54, 70, 54, 50, 54, + 59, 14, 59, 2, 59, 54, 19, 56, 54, 54, + 54, 56, 14, 59, 43, 54, 54, 56, 56, 18, + 2, 23, 2, 54, 68, 56, 14, 54, 54, 2, + 54, 19, 3, 60, 60, 59, 18, 54, 18, 18, + 109, 18, 59, 54, 54, 18, 54, 54, 59, 59, + 54, 59, 59, 54, 58, 38, 54, 58, 18, 42, + 58, 2, 54, 2, 18, 54, 45, 2, 45, 2, + 4, 3, 18, 18, 66, 64, 3, 18, 54, 18, + 56, 2, 54, 18, 18, 18, 46, 54, 60, 56, + 3, 3, 54, 47, 2, 57, 54, 18, 56, 54, + 2, 56, 54, 54, 56, 2, 57, 54, 2, 18, + 18, 54, 54, 56, -1, 62, 18, 54, 60, 56, + -1, 18, 14, 54, 18, 54, 2, 19, 59, -1, + 59, 54, 54, -1, 63, 44, 59, 59, -1, 54, + 2, -1, 18, 65, 59, 76, 78, 92, 94, 54, + 54, 78, 18, 76, 59, 59, 18, 61, 54, 54, + -1, 76, 67, 59, 59, 78, 78, 54, 54, -1, + 54, 54, 59, 59, 69, 59, 59, 61, 61, 14, + 76, 47, 48, -1, 71, -1, 54, 14, 23, 5, + 76, 59, 19, 61, 21, 5, -1, -1, 14, -1, + 35, 36, -1, -1, 14, -1, -1, 23, -1, -1, + -1, -1, 88, 23, -1, 42, -1, -1, -1, 35, + 36, -1, -1, -1, -1, 35, 36, 25, 26, 27, + 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, + -1, 14, -1, -1, -1, -1, -1, -1, -1, 2, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 14, + -1, -1, -1, -1, -1, 18, -1, -1, 23, 24, + 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 88, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 14, -1, -1, -1, -1, -1, -1, -1, -1, 23, - 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, + -1, -1, -1, -1, -1, -1, -1, 23, 24, 25, + 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -1087,6 +1073,6 @@ const short QQmlJSGrammar::action_check [] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1}; + -1, -1, -1, -1, -1}; QT_END_NAMESPACE diff --git a/src/qml/parser/qqmljsgrammar_p.h b/src/qml/parser/qqmljsgrammar_p.h index 6b3d1c8013..7a369be194 100644 --- a/src/qml/parser/qqmljsgrammar_p.h +++ b/src/qml/parser/qqmljsgrammar_p.h @@ -161,15 +161,15 @@ public: T_XOR = 79, T_XOR_EQ = 80, - ACCEPT_STATE = 663, - RULE_COUNT = 357, - STATE_COUNT = 664, + ACCEPT_STATE = 665, + RULE_COUNT = 358, + STATE_COUNT = 666, TERMINAL_COUNT = 106, NON_TERMINAL_COUNT = 111, - GOTO_INDEX_OFFSET = 664, - GOTO_INFO_OFFSET = 3104, - GOTO_CHECK_OFFSET = 3104 + GOTO_INDEX_OFFSET = 666, + GOTO_INFO_OFFSET = 3018, + GOTO_CHECK_OFFSET = 3018 }; static const char *const spell []; diff --git a/src/qml/parser/qqmljsparser.cpp b/src/qml/parser/qqmljsparser.cpp index 262043b3b8..762e60c827 100644 --- a/src/qml/parser/qqmljsparser.cpp +++ b/src/qml/parser/qqmljsparser.cpp @@ -567,56 +567,78 @@ case 69: { } break; case 70: { - sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); + AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); // insert a fake ';' before ':' + + AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(4)); + propertyName->identifierToken = loc(4); + propertyName->next = 0; + + AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( + propertyName, sym(6).UiQualifiedId, sym(7).UiObjectInitializer); + binding->colonToken = loc(5); + + node->binding = binding; + + sym(1).Node = node; } break; case 71: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; -case 79: { +case 72: { + sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); +} break; + +case 80: { AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; -case 80: { +case 81: { AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 81: { +case 82: { AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; -case 82: { +case 83: { AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; -case 83: { +case 84: { AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; -case 84: { +case 85: { AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; -case 85: -case 86: { +case 86: +case 87: { AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; -case 87: { +case 88: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -632,7 +654,7 @@ case 87: { sym(1).Node = node; } break; -case 88: { +case 89: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); @@ -648,28 +670,28 @@ case 88: { sym(1).Node = node; } break; -case 89: { +case 90: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; -case 90: { +case 91: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 91: { +case 92: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; -case 92: { +case 93: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); @@ -678,7 +700,7 @@ case 92: { sym(1).Node = node; } break; -case 93: { +case 94: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); @@ -687,7 +709,7 @@ case 93: { sym(1).Node = node; } break; -case 94: { +case 95: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( @@ -699,7 +721,7 @@ case 94: { sym(1).Node = node; } break; -case 95: { +case 96: { AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyAssignmentList->finish ()); node->lbraceToken = loc(1); @@ -707,14 +729,14 @@ case 95: { sym(1).Node = node; } break; -case 96: { +case 97: { AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; -case 97: { +case 98: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); @@ -734,48 +756,48 @@ case 97: { } } break; -case 98: { +case 99: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; -case 99: { +case 100: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; -case 100: { +case 101: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 101: { +case 102: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 102: { +case 103: { AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; -case 103: { +case 104: { AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; -case 104: { +case 105: { AST::PropertyNameAndValue *node = new (pool) AST::PropertyNameAndValue( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; -case 105: { +case 106: { AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( sym(2).PropertyName, sym(6).FunctionBody); node->getSetToken = loc(1); @@ -786,7 +808,7 @@ case 105: { sym(1).Node = node; } break; -case 106: { +case 107: { AST::PropertyGetterSetter *node = new (pool) AST::PropertyGetterSetter( sym(2).PropertyName, sym(4).FormalParameterList, sym(7).FunctionBody); node->getSetToken = loc(1); @@ -797,56 +819,56 @@ case 106: { sym(1).Node = node; } break; -case 107: { +case 108: { sym(1).Node = new (pool) AST::PropertyAssignmentList(sym(1).PropertyAssignment); } break; -case 108: { +case 109: { AST::PropertyAssignmentList *node = new (pool) AST::PropertyAssignmentList( sym(1).PropertyAssignmentList, sym(3).PropertyAssignment); node->commaToken = loc(2); sym(1).Node = node; } break; -case 109: { +case 110: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 110: { +case 111: { AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 111: { +case 112: { AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 112: { +case 113: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; -case 148: { +case 149: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 149: { +case 150: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 150: { +case 151: { AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); @@ -854,384 +876,384 @@ case 150: { sym(1).Node = node; } break; -case 152: { +case 153: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; -case 153: { +case 154: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 154: { +case 155: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; -case 155: { +case 156: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; -case 156: { +case 157: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 157: { +case 158: { sym(1).Node = 0; } break; -case 158: { +case 159: { sym(1).Node = sym(1).ArgumentList->finish(); } break; -case 159: { +case 160: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; -case 160: { +case 161: { AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 164: { +case 165: { AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; -case 165: { +case 166: { AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; -case 167: { +case 168: { AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; -case 168: { +case 169: { AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; -case 169: { +case 170: { AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; -case 170: { +case 171: { AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; -case 171: { +case 172: { AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; -case 172: { +case 173: { AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; -case 173: { +case 174: { AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; -case 174: { +case 175: { AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; -case 175: { +case 176: { AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; -case 177: { +case 178: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 178: { +case 179: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 179: { +case 180: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 181: { +case 182: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 182: { +case 183: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 184: { +case 185: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 185: { +case 186: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 186: { +case 187: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 188: { +case 189: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 189: { +case 190: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 190: { +case 191: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 191: { +case 192: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 192: { +case 193: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 193: { +case 194: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 195: { +case 196: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 196: { +case 197: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 197: { +case 198: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 198: { +case 199: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 199: { +case 200: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 201: { +case 202: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 202: { +case 203: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 203: { +case 204: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 204: { +case 205: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 206: { +case 207: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 207: { +case 208: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 208: { +case 209: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 209: { +case 210: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 211: { +case 212: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 213: { +case 214: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 215: { +case 216: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 217: { +case 218: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 219: { +case 220: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 221: { +case 222: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 223: { +case 224: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 225: { +case 226: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 227: { +case 228: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 229: { +case 230: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 231: { +case 232: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1239,7 +1261,7 @@ case 231: { sym(1).Node = node; } break; -case 233: { +case 234: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); @@ -1247,112 +1269,112 @@ case 233: { sym(1).Node = node; } break; -case 235: { +case 236: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 237: { +case 238: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; -case 238: { +case 239: { sym(1).ival = QSOperator::Assign; } break; -case 239: { +case 240: { sym(1).ival = QSOperator::InplaceMul; } break; -case 240: { +case 241: { sym(1).ival = QSOperator::InplaceDiv; } break; -case 241: { +case 242: { sym(1).ival = QSOperator::InplaceMod; } break; -case 242: { +case 243: { sym(1).ival = QSOperator::InplaceAdd; } break; -case 243: { +case 244: { sym(1).ival = QSOperator::InplaceSub; } break; -case 244: { +case 245: { sym(1).ival = QSOperator::InplaceLeftShift; } break; -case 245: { +case 246: { sym(1).ival = QSOperator::InplaceRightShift; } break; -case 246: { +case 247: { sym(1).ival = QSOperator::InplaceURightShift; } break; -case 247: { +case 248: { sym(1).ival = QSOperator::InplaceAnd; } break; -case 248: { +case 249: { sym(1).ival = QSOperator::InplaceXor; } break; -case 249: { +case 250: { sym(1).ival = QSOperator::InplaceOr; } break; -case 251: { +case 252: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 252: { +case 253: { sym(1).Node = 0; } break; -case 255: { +case 256: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; -case 256: { +case 257: { sym(1).Node = 0; } break; -case 273: { +case 274: { AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 274: { +case 275: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; -case 275: { +case 276: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; -case 276: { +case 277: { sym(1).Node = 0; } break; -case 277: { +case 278: { sym(1).Node = sym(1).StatementList->finish (); } break; -case 279: { +case 280: { AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); @@ -1360,76 +1382,76 @@ case 279: { sym(1).Node = node; } break; -case 280: { +case 281: { sym(1).ival = T_CONST; } break; -case 281: { +case 282: { sym(1).ival = T_VAR; } break; -case 282: { +case 283: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; -case 283: { +case 284: { AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; -case 284: { +case 285: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; -case 285: { +case 286: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; -case 286: { +case 287: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 287: { +case 288: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 288: { +case 289: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 289: { +case 290: { sym(1).Node = 0; } break; -case 291: { +case 292: { // ### TODO: AST for initializer sym(1) = sym(2); } break; -case 292: { +case 293: { sym(1).Node = 0; } break; -case 294: { +case 295: { AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; -case 296: { +case 297: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 297: { +case 298: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1438,7 +1460,7 @@ case 297: { sym(1).Node = node; } break; -case 298: { +case 299: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); @@ -1446,7 +1468,7 @@ case 298: { sym(1).Node = node; } break; -case 301: { +case 302: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); @@ -1456,7 +1478,7 @@ case 301: { sym(1).Node = node; } break; -case 302: { +case 303: { AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); @@ -1464,7 +1486,7 @@ case 302: { sym(1).Node = node; } break; -case 303: { +case 304: { AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); @@ -1475,7 +1497,7 @@ case 303: { sym(1).Node = node; } break; -case 304: { +case 305: { AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); @@ -1488,7 +1510,7 @@ case 304: { sym(1).Node = node; } break; -case 305: { +case 306: { AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); @@ -1498,7 +1520,7 @@ case 305: { sym(1).Node = node; } break; -case 306: { +case 307: { AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); @@ -1509,14 +1531,14 @@ case 306: { sym(1).Node = node; } break; -case 308: { +case 309: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 310: { +case 311: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); @@ -1524,14 +1546,14 @@ case 310: { sym(1).Node = node; } break; -case 312: { +case 313: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 314: { +case 315: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); @@ -1539,14 +1561,14 @@ case 314: { sym(1).Node = node; } break; -case 316: { +case 317: { AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 317: { +case 318: { AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); @@ -1554,7 +1576,7 @@ case 317: { sym(1).Node = node; } break; -case 318: { +case 319: { AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); @@ -1562,83 +1584,83 @@ case 318: { sym(1).Node = node; } break; -case 319: { +case 320: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; -case 320: { +case 321: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; -case 321: { +case 322: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; -case 322: { +case 323: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; -case 323: { +case 324: { sym(1).Node = 0; } break; -case 324: { +case 325: { sym(1).Node = sym(1).CaseClauses->finish (); } break; -case 325: { +case 326: { AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; -case 326: { +case 327: { AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 327: { +case 328: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; -case 329: { +case 330: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; -case 330: { +case 331: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; -case 331: { +case 332: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 332: { +case 333: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; -case 333: { +case 334: { AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); @@ -1647,20 +1669,20 @@ case 333: { sym(1).Node = node; } break; -case 334: { +case 335: { AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; -case 336: { +case 337: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; -case 338: { +case 339: { AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); @@ -1671,7 +1693,7 @@ case 338: { sym(1).Node = node; } break; -case 339: { +case 340: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) @@ -1683,7 +1705,7 @@ case 339: { sym(1).Node = node; } break; -case 340: { +case 341: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).FunctionBody); node->functionToken = loc(1); node->lparenToken = loc(2); @@ -1693,56 +1715,56 @@ case 340: { sym(1).Node = node; } break; -case 341: { +case 342: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; -case 342: { +case 343: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; -case 343: { +case 344: { sym(1).Node = 0; } break; -case 344: { +case 345: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; -case 345: { +case 346: { sym(1).Node = 0; } break; -case 347: { +case 348: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; -case 349: { +case 350: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; -case 350: { +case 351: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; -case 351: { +case 352: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; -case 352: { +case 353: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; -case 353: { +case 354: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; -case 354: { +case 355: { sym(1).Node = 0; } break; diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h index b0abf06b25..cf9f641fbc 100644 --- a/src/qml/parser/qqmljsparser_p.h +++ b/src/qml/parser/qqmljsparser_p.h @@ -240,9 +240,9 @@ protected: -#define J_SCRIPT_REGEXPLITERAL_RULE1 87 +#define J_SCRIPT_REGEXPLITERAL_RULE1 88 -#define J_SCRIPT_REGEXPLITERAL_RULE2 88 +#define J_SCRIPT_REGEXPLITERAL_RULE2 89 QT_QML_END_NAMESPACE diff --git a/tests/auto/qml/qqmllanguage/data/readonlyObjectProperty.qml b/tests/auto/qml/qqmllanguage/data/readonlyObjectProperty.qml new file mode 100644 index 0000000000..3fc332f565 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/readonlyObjectProperty.qml @@ -0,0 +1,7 @@ +import QtQml 2.0 + +QtObject { + readonly property QtObject subObject: QtObject { + property int readWrite: 42 + } +} diff --git a/tests/auto/qml/qqmllanguage/qqmllanguage.pro b/tests/auto/qml/qqmllanguage/qqmllanguage.pro index 3b0518cfdf..f0c8bb6c1b 100644 --- a/tests/auto/qml/qqmllanguage/qqmllanguage.pro +++ b/tests/auto/qml/qqmllanguage/qqmllanguage.pro @@ -16,3 +16,6 @@ QT += core-private gui-private qml-private network testlib include (../../shared/util.pri) DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 + +OTHER_FILES += \ + data/readonlyObjectProperty.qml diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index ec3e38dd14..12d2f53596 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -151,6 +151,7 @@ private slots: void nestedComponentRoots(); void registrationOrder(); void readonly(); + void readonlyObjectProperties(); void receivers(); void registeredCompositeType(); void implicitImportsLast(); @@ -3274,6 +3275,24 @@ void tst_qqmllanguage::readonly() delete o; } +void tst_qqmllanguage::readonlyObjectProperties() +{ + QQmlComponent component(&engine, testFileUrl("readonlyObjectProperty.qml")); + + QScopedPointer o(component.create()); + QVERIFY(!o.isNull()); + + QQmlProperty prop(o.data(), QStringLiteral("subObject"), &engine); + QVERIFY(!prop.isWritable()); + QVERIFY(!prop.write(QVariant::fromValue(o.data()))); + + QObject *subObject = qvariant_cast(prop.read()); + QVERIFY(subObject); + QCOMPARE(subObject->property("readWrite").toInt(), int(42)); + subObject->setProperty("readWrite", QVariant::fromValue(int(100))); + QCOMPARE(subObject->property("readWrite").toInt(), int(100)); +} + void tst_qqmllanguage::receivers() { QQmlComponent component(&engine, testFileUrl("receivers.qml")); -- cgit v1.2.3 From f06daaf3d8747c6c0a277bf055c80d8f2e7bcc81 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 24 Oct 2014 15:06:22 +0200 Subject: Properly handle negative years when printing JS Dates to strings. JavaScript knows a year 0. That is correctly translated into QDateTime terms when creating a Date object, but it's not correctly translated back when converting the JavaScript date to a string. Task-number: QTBUG-29491 Change-Id: I46b200a144434187656d08e87f422f97523acd0e Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4dateobject.cpp | 8 +++++++- tests/auto/qml/qqmlecmascript/data/negativeyear.qml | 8 ++++++++ tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qml/qqmlecmascript/data/negativeyear.qml diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 66601b64e5..e00a705700 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -557,7 +557,13 @@ static inline QString ToString(double t) { if (std::isnan(t)) return QStringLiteral("Invalid Date"); - QString str = ToDateTime(t, Qt::LocalTime).toString() + QStringLiteral(" GMT"); + QDateTime dateTime = ToDateTime(t, Qt::LocalTime); + + // JavaScript knows a year 0, while QDateTime doesn't. So, in order to show the right date we + // have to add a year to negative ones here. + if (dateTime.date().year() < 0) + dateTime = dateTime.addYears(1); + QString str = dateTime.toString() + QStringLiteral(" GMT"); double tzoffset = LocalTZA + DaylightSavingTA(t); if (tzoffset) { int hours = static_cast(::fabs(tzoffset) / 1000 / 60 / 60); diff --git a/tests/auto/qml/qqmlecmascript/data/negativeyear.qml b/tests/auto/qml/qqmlecmascript/data/negativeyear.qml new file mode 100644 index 0000000000..11defbe914 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/negativeyear.qml @@ -0,0 +1,8 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Item { + function check_negative() { + return "result: " + new Date(-2000, 0, 1); + } +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 196f6b96f9..019d6790e1 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -200,6 +200,7 @@ private slots: void sequenceSort(); void dateParse(); void utcDate(); + void negativeYear(); void qtbug_22464(); void qtbug_21580(); void singleV8BindingDestroyedDuringEvaluation(); @@ -7378,6 +7379,22 @@ void tst_qqmlecmascript::utcDate() QVERIFY(q.toBool() == true); } +void tst_qqmlecmascript::negativeYear() +{ + QQmlComponent component(&engine, testFileUrl("negativeyear.qml")); + + QObject *object = component.create(); + if (object == 0) + qDebug() << component.errorString(); + QVERIFY(object != 0); + + QVariant q; + QMetaObject::invokeMethod(object, "check_negative", + Q_RETURN_ARG(QVariant, q)); + // Strip the timezone. It should be irrelevant as the date was created with the same one. + QCOMPARE(q.toString().left(32), QStringLiteral("result: Mon Jan 1 00:00:00 -2000")); +} + void tst_qqmlecmascript::concatenatedStringPropertyAccess() { QQmlComponent component(&engine, testFileUrl("concatenatedStringPropertyAccess.qml")); -- cgit v1.2.3 From 58725137882deafa3d43f2d29855cf5e53fc6c76 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 16 Oct 2014 18:01:22 +0200 Subject: Expose searchEdit accessible property to Qt Quick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I9230deaa75d1e9a9614f364d4adf92349c8a1901 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickaccessibleattached.cpp | 6 ++++++ src/quick/items/qquickaccessibleattached_p.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 59c0c2e8a0..a4ab0a96b1 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -179,6 +179,12 @@ QT_BEGIN_NAMESPACE By default this property is \c false. */ +/*! \qmlproperty bool QtQuick::Accessible::searchEdit + \brief This property holds whether this item is input for a search query. + This property will only affect editable text. + + By default this property is \c false. +*/ /*! \qmlproperty bool QtQuick::Accessible::ignored \brief This property holds whether this item should be ignored by the accessibility framework. diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 270360895d..4875b2765a 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -88,6 +88,7 @@ public: STATE_PROPERTY(defaultButton) STATE_PROPERTY(passwordEdit) STATE_PROPERTY(selectableText) + STATE_PROPERTY(searchEdit) QQuickAccessibleAttached(QObject *parent); ~QQuickAccessibleAttached(); -- cgit v1.2.3 From bb1969692efb8e9d5815a11ba34c8c6d349e7330 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 16 Oct 2014 14:18:19 +0200 Subject: Remove logic that some accessible objects cannot have children MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many places where this doesn't make sense (a button in a search field, a line in a list represented as button with a child button to remove the list item...). Change-Id: Iab1d411adda696a01b1dcfdebb0a250066d6a7c2 Reviewed-by: Jan Arve Sæther --- src/quick/accessible/qaccessiblequickitem.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 3f023ae621..3234d3d85f 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -170,16 +170,6 @@ QList accessibleUnignoredChildren(QQuickItem *item, bool paintOrde QList QAccessibleQuickItem::childItems() const { - if ( role() == QAccessible::Button || - role() == QAccessible::CheckBox || - role() == QAccessible::RadioButton || - role() == QAccessible::SpinBox || - role() == QAccessible::EditableText || - role() == QAccessible::Slider || - role() == QAccessible::PageTab || - role() == QAccessible::ProgressBar) - return QList(); - return accessibleUnignoredChildren(item()); } -- cgit v1.2.3 From c7ea1cd9237045e3a8b2b148c57f6d26dd547f7e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 17 Oct 2014 08:46:30 +0200 Subject: QML State Machine plugin: correct URL in Q_PLUGIN_METADATA org.qt-project.org is redundant Change-Id: Id6a6794e1fc1e4403b3bfcdebbe06a487f904041 Reviewed-by: Sebastian Sauer Reviewed-by: Brett Stottlemyer Reviewed-by: J-P Nurmi --- src/imports/statemachine/plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index a1ebe06a80..5af90c99ff 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE class QtQmlStateMachinePlugin : public QQmlExtensionPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.org.Qt.QtQml.StateMachine/1.0") + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtQml.StateMachine/1.0") public: void registerTypes(const char *uri) -- cgit v1.2.3 From 32af8055985c1f978574eec62512638f472e8290 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Thu, 23 Oct 2014 16:01:57 +0200 Subject: Fix leaks in QQuickImageParticle Make sure that ImageData instances, m_shadowData as well as the QSGGeometry of particle nodes are destroyed together with their QQuickImageParticle. Also implement the assignment operator for QQuickParticleData to avoid its v8Datum pointer to be copied over to the shadow datum in getShadowDatum. This would cause a double delete of the QQuickV4ParticleData when trying to call clearShadows() in the destructor. Task-number: QTBUG-36782 Change-Id: Ie03f2be0415daeb7f4f6e5f92295a3ab26a62155 Reviewed-by: Joerg Bornemann --- src/particles/qquickimageparticle.cpp | 23 ++++++++++------------- src/particles/qquickimageparticle_p.h | 9 ++++----- src/particles/qquickparticlesystem.cpp | 20 ++++++++++++++++++++ src/particles/qquickparticlesystem_p.h | 3 +++ 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 60a67d55a6..50fa9dbc64 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -706,10 +706,6 @@ void fillUniformArrayFromImage(float* array, const QImage& img, int size) QQuickImageParticle::QQuickImageParticle(QQuickItem* parent) : QQuickParticlePainter(parent) - , m_image(0) - , m_colorTable(0) - , m_sizeTable(0) - , m_opacityTable(0) , m_color_variation(0.0) , m_material(0) , m_alphaVariation(0.0) @@ -742,6 +738,7 @@ QQuickImageParticle::QQuickImageParticle(QQuickItem* parent) QQuickImageParticle::~QQuickImageParticle() { + clearShadows(); } QQmlListProperty QQuickImageParticle::sprites() @@ -759,15 +756,14 @@ void QQuickImageParticle::setImage(const QUrl &image) { if (image.isEmpty()){ if (m_image) { - delete m_image; - m_image = 0; + m_image.reset(); emit imageChanged(); } return; } if (!m_image) - m_image = new ImageData; + m_image.reset(new ImageData); if (image == m_image->source) return; m_image->source = image; @@ -780,14 +776,14 @@ void QQuickImageParticle::setColortable(const QUrl &table) { if (table.isEmpty()){ if (m_colorTable) { - delete m_colorTable; + m_colorTable.reset(); emit colortableChanged(); } return; } if (!m_colorTable) - m_colorTable = new ImageData; + m_colorTable.reset(new ImageData); if (table == m_colorTable->source) return; m_colorTable->source = table; @@ -799,14 +795,14 @@ void QQuickImageParticle::setSizetable(const QUrl &table) { if (table.isEmpty()){ if (m_sizeTable) { - delete m_sizeTable; + m_sizeTable.reset(); emit sizetableChanged(); } return; } if (!m_sizeTable) - m_sizeTable = new ImageData; + m_sizeTable.reset(new ImageData); if (table == m_sizeTable->source) return; m_sizeTable->source = table; @@ -818,14 +814,14 @@ void QQuickImageParticle::setOpacitytable(const QUrl &table) { if (table.isEmpty()){ if (m_opacityTable) { - delete m_opacityTable; + m_opacityTable.reset(); emit opacitytableChanged(); } return; } if (!m_opacityTable) - m_opacityTable = new ImageData; + m_opacityTable.reset(new ImageData); if (table == m_opacityTable->source) return; m_opacityTable->source = table; @@ -1406,6 +1402,7 @@ void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node) else //Simple g = new QSGGeometry(SimpleParticle_AttributeSet, count, 0); + node->setFlag(QSGNode::OwnsGeometry); node->setGeometry(g); if (perfLevel <= Colored){ g->setDrawingMode(GL_POINTS); diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h index ac61ceeb10..657d945bca 100644 --- a/src/particles/qquickimageparticle_p.h +++ b/src/particles/qquickimageparticle_p.h @@ -352,17 +352,16 @@ private: QUrl source; QQuickPixmap pix; }; - ImageData *m_image; - ImageData *m_colorTable; - ImageData *m_sizeTable; - ImageData *m_opacityTable; + QScopedPointer m_image; + QScopedPointer m_colorTable; + QScopedPointer m_sizeTable; + QScopedPointer m_opacityTable; bool loadingSomething(); QColor m_color; qreal m_color_variation; - QSGGeometryNode *m_rootNode; QHash m_nodes; QHash m_idxStarts;//TODO: Proper resizing will lead to needing a spriteEngine per particle - do this after sprite engine gains transparent sharing? QList > m_startsIdx;//Same data, optimized for alternate retrieval diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp index 79d88ee601..db5d607922 100644 --- a/src/particles/qquickparticlesystem.cpp +++ b/src/particles/qquickparticlesystem.cpp @@ -478,6 +478,26 @@ QQuickParticleData::~QQuickParticleData() delete v8Datum; } +QQuickParticleData::QQuickParticleData(const QQuickParticleData &other) +{ + *this = other; +} + +QQuickParticleData &QQuickParticleData::operator=(const QQuickParticleData &other) +{ + clone(other); + + group = other.group; + e = other.e; + system = other.system; + index = other.index; + systemIndex = other.systemIndex; + // Lazily initialized + v8Datum = 0; + + return *this; +} + void QQuickParticleData::clone(const QQuickParticleData& other) { x = other.x; diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h index 81d78de8ac..4d6c153282 100644 --- a/src/particles/qquickparticlesystem_p.h +++ b/src/particles/qquickparticlesystem_p.h @@ -137,6 +137,9 @@ public: QQuickParticleData(QQuickParticleSystem* sys); ~QQuickParticleData(); + QQuickParticleData(const QQuickParticleData &other); + QQuickParticleData &operator=(const QQuickParticleData &other); + //Convenience functions for working backwards, because parameters are from the start of particle life //If setting multiple parameters at once, doing the conversion yourself will be faster. -- cgit v1.2.3 From 8f6436f125faae91eb472ddddbbae06dba5da671 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Wed, 15 Oct 2014 13:58:34 +0200 Subject: Move action handlers to the Accessible attached object With this change, instead of writing: function accessiblePressAction() { submit() } You should write: Accessible.onPressAction: { submit() } For the moment, only 4 actions are added: press, toggle, increase and decrease. The old style action handlers are deprecated, and removed from the documentation. New style action handlers will be preferred in case an item declares both styles. Change-Id: I11919e631d8476d55540f94252757b911c44ade4 Reviewed-by: Frederik Gladhorn --- .../quick/quick-accessibility/content/Button.qml | 2 +- src/quick/accessible/qaccessiblequickitem.cpp | 13 +++- src/quick/items/qquickaccessibleattached.cpp | 82 +++++++++++++++++++--- src/quick/items/qquickaccessibleattached_p.h | 11 +++ tests/manual/accessibility/textandbuttons.qml | 5 +- 5 files changed, 97 insertions(+), 16 deletions(-) diff --git a/examples/quick/quick-accessibility/content/Button.qml b/examples/quick/quick-accessibility/content/Button.qml index 96704de4fe..2baa66f91a 100644 --- a/examples/quick/quick-accessibility/content/Button.qml +++ b/examples/quick/quick-accessibility/content/Button.qml @@ -42,7 +42,7 @@ Rectangle { Accessible.name: text Accessible.description: "This button does " + text Accessible.role: Accessible.Button - function accessiblePressAction() { + Accessible.onPressAction: { button.clicked() } //! [button] diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index 3234d3d85f..e13224f6fb 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -39,7 +39,6 @@ #include "QtQuick/private/qquicktext_p.h" #include "QtQuick/private/qquickaccessibleattached_p.h" #include "QtQuick/qquicktextdocument.h" - QT_BEGIN_NAMESPACE #ifndef QT_NO_ACCESSIBILITY @@ -217,16 +216,24 @@ QStringList QAccessibleQuickItem::actionNames() const QStringList actions = QQmlAccessible::actionNames(); if (state().focusable) actions.append(QAccessibleActionInterface::setFocusAction()); + + // ### The following can lead to duplicate action names. We'll fix that when we kill QQmlAccessible + if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item())) + attached->availableActions(&actions); return actions; } void QAccessibleQuickItem::doAction(const QString &actionName) { + bool accepted = false; if (actionName == QAccessibleActionInterface::setFocusAction()) { item()->forceActiveFocus(); - } else { - QQmlAccessible::doAction(actionName); + accepted = true; } + if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item())) + accepted = attached->doAction(actionName); + if (!accepted) + QQmlAccessible::doAction(actionName); } QStringList QAccessibleQuickItem::keyBindingsForAction(const QString &actionName) const diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index a4ab0a96b1..38b26a53d0 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE Accessible.role: Accessible.Button Accessible.name: label.text Accessible.description: "shows the next page" - function accessiblePressAction() { + Accessible.onPressAction: { // do a button click } } @@ -79,8 +79,8 @@ QT_BEGIN_NAMESPACE The name is a short and consise description of the control and should reflect the visual label. In this case it is not clear what the button does with the name only, so \l description contains an explanation. - There is also a function \c accessiblePressAction() which can be invoked by assistive tools to trigger - the button. This function needs to have the same effect as tapping or clicking the button would have. + There is also a signal handler \l {Accessible::pressAction}{Accessible.pressAction} which can be invoked by assistive tools to trigger + the button. This signal handler needs to have the same effect as tapping or clicking the button would have. \sa Accessibility */ @@ -117,7 +117,7 @@ QT_BEGIN_NAMESPACE \table \header \li \b {Role} - \li \b {Properties and functions} + \li \b {Properties and signals} \li \b {Explanation} \row \li All interactive elements @@ -128,13 +128,14 @@ QT_BEGIN_NAMESPACE can be moved from item to item. \row \li Button, CheckBox, RadioButton - \li \c accessiblePressAction() - \li A button should have a function with the name \c accessiblePressAction. - This function may be called by an assistive tool such as a screen-reader. + \li \l {Accessible::pressAction}{Accessible.pressAction} + \li A button should have a signal handler with the name \c onPressAction. + This signal may be emitted by an assistive tool such as a screen-reader. The implementation needs to behave the same as a mouse click or tap on the button. \row \li CheckBox, RadioButton - \li \l checkable, \l checked + \li \l checkable, \l checked, \l {Accessible::toggleAction}{Accessible.toggleAction} + \li The check state of the check box. Updated on Press, Check and Uncheck actions. \row \li Slider, SpinBox, Dial, ScrollBar @@ -142,7 +143,7 @@ QT_BEGIN_NAMESPACE \li These properties reflect the state and possible values for the elements. \row \li Slider, SpinBox, Dial, ScrollBar - \li \c accessibleIncreaseAction(), \c accessibleDecreaseAction() + \li \l {Accessible::increaseAction}{Accessible.increaseAction}, \l {Accessible::decreaseAction}{Accessible.decreaseAction} \li Actions to increase and decrease the value of the element. \endtable */ @@ -262,6 +263,40 @@ QT_BEGIN_NAMESPACE By default this property is \c false. */ +/*! + \qmlsignal QtQuick::Accessible::pressAction() + + This signal is emitted when a press action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onPressAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::toggleAction() + + This signal is emitted when a toggle action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onToggleAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::increaseAction() + + This signal is emitted when a increase action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onIncreaseAction. +*/ +/*! + \qmlsignal QtQuick::Accessible::decreaseAction() + + This signal is emitted when a decrease action is received from an assistive tool such as a screen-reader. + + The corresponding handler is \c onDecreaseAction. +*/ + +const QMetaMethod QQuickAccessibleAttached::sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction); +const QMetaMethod QQuickAccessibleAttached::sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction); +const QMetaMethod QQuickAccessibleAttached::sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction); +const QMetaMethod QQuickAccessibleAttached::sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction); + QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) : QObject(parent), m_role(QAccessible::NoRole) { @@ -306,6 +341,35 @@ void QQuickAccessibleAttached::setIgnored(bool ignored) } } +bool QQuickAccessibleAttached::doAction(const QString &actionName) +{ + const QMetaMethod *sig = 0; + if (actionName == QAccessibleActionInterface::pressAction()) + sig = &sigPress; + else if (actionName == QAccessibleActionInterface::toggleAction()) + sig = &sigToggle; + else if (actionName == QAccessibleActionInterface::increaseAction()) + sig = &sigIncrease; + else if (actionName == QAccessibleActionInterface::decreaseAction()) + sig = &sigDecrease; + + if (sig && isSignalConnected(*sig)) + return sig->invoke(this); + return false; +} + +void QQuickAccessibleAttached::availableActions(QStringList *actions) const +{ + if (isSignalConnected(sigPress)) + actions->append(QAccessibleActionInterface::pressAction()); + if (isSignalConnected(sigToggle)) + actions->append(QAccessibleActionInterface::toggleAction()); + if (isSignalConnected(sigIncrease)) + actions->append(QAccessibleActionInterface::increaseAction()); + if (isSignalConnected(sigDecrease)) + actions->append(QAccessibleActionInterface::decreaseAction()); +} + QT_END_NAMESPACE #endif diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 4875b2765a..53b1d2954d 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -188,6 +188,8 @@ public: QAccessible::State state() { return m_state; } bool ignored() const; + bool doAction(const QString &actionName); + void availableActions(QStringList *actions) const; public Q_SLOTS: void valueChanged() { @@ -206,6 +208,10 @@ Q_SIGNALS: void nameChanged(); void descriptionChanged(); void ignoredChanged(); + void pressAction(); + void toggleAction(); + void increaseAction(); + void decreaseAction(); private: QQuickItem *item() const { return static_cast(parent()); } @@ -215,6 +221,11 @@ private: QString m_name; QString m_description; + static const QMetaMethod sigPress; + static const QMetaMethod sigToggle; + static const QMetaMethod sigIncrease; + static const QMetaMethod sigDecrease; + public: using QObject::property; }; diff --git a/tests/manual/accessibility/textandbuttons.qml b/tests/manual/accessibility/textandbuttons.qml index 48ce6e26e9..74c3bf3897 100644 --- a/tests/manual/accessibility/textandbuttons.qml +++ b/tests/manual/accessibility/textandbuttons.qml @@ -50,9 +50,8 @@ Rectangle { Accessible.role : Accessible.Button - function accessibleAction(action) { - if (action == Qt.Press) - buttonAction() + Accessible.onPressAction: { + buttonAction() } function buttonAction() { -- cgit v1.2.3 From 125befb309f5eccd80cbffd815396d35c49c08f2 Mon Sep 17 00:00:00 2001 From: Jian Liang Date: Sat, 25 Oct 2014 17:15:49 +0800 Subject: Fix QQmlTypeData object leak Drop the refcount added in QQmlTypeLoader::getType() to prevent object leakage in resolveQmlType. Change-Id: I8bd9c486294912cc00ce5feb350c3ff79c6aac09 Reviewed-by: Simon Hausmann --- src/qml/compiler/qqmlirbuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index b64e637739..339278fbe8 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1810,6 +1810,7 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe if (type->isCompositeSingleton()) { QQmlRefPointer tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url); Q_ASSERT(tdata); + tdata->release(); // Decrease the reference count added from QQmlTypeLoader::getType() // When a singleton tries to reference itself, it may not be complete yet. if (tdata->isComplete()) { initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId)); -- cgit v1.2.3 From 51d8f62dacc9b37a50e522162d5438a624ee9168 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 21 Oct 2014 14:54:45 +0200 Subject: Rework our simple array implementation Implement the simple array as a circular buffer instead of an array with head room. This fixes a couple of severe issues with performance and memory management if the array is being used as a queue. Task-number: QTBUG-41421 Change-Id: I146ad8a874407c108aa8fe1eae68e9957e154847 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4argumentsobject.cpp | 2 +- src/qml/jsruntime/qv4arraydata.cpp | 261 ++++++++++++++++--------------- src/qml/jsruntime/qv4arraydata_p.h | 41 +++-- src/qml/jsruntime/qv4arrayobject.cpp | 25 ++- src/qml/jsruntime/qv4functionobject.cpp | 6 +- src/qml/jsruntime/qv4lookup.cpp | 15 +- src/qml/jsruntime/qv4object.cpp | 25 +-- src/qml/jsruntime/qv4object_p.h | 4 +- src/qml/jsruntime/qv4runtime.cpp | 4 +- 9 files changed, 199 insertions(+), 184 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 9ac279bf87..d79521ca2f 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -78,7 +78,7 @@ void ArgumentsObject::fullyCreate() uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount); uint argCount = qMin(context()->d()->realArgumentCount, context()->d()->callData->argc); - ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true); + ArrayData::realloc(this, ArrayData::Sparse, argCount, true); context()->d()->engine->requireArgumentsAccessors(numAccessors); mappedArguments().ensureIndex(engine(), numAccessors); for (uint i = 0; i < (uint)numAccessors; ++i) { diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index d58dbb91d4..469081e683 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -87,65 +87,61 @@ const ArrayVTable SparseArrayData::static_vtbl = SparseArrayData::length }; +Q_STATIC_ASSERT(sizeof(ArrayData::Data) == sizeof(SimpleArrayData::Data)); +Q_STATIC_ASSERT(sizeof(ArrayData::Data) == sizeof(SparseArrayData::Data)); -void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes) +void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes) { ArrayData *d = o->arrayData(); - uint oldAlloc = 0; + uint alloc = 8; uint toCopy = 0; - if (alloc < 8) - alloc = 8; + uint offset = 0; if (d) { bool hasAttrs = d->attrs(); enforceAttributes |= hasAttrs; - if (!offset && alloc <= d->alloc() && newType == d->type() && hasAttrs == enforceAttributes) + if (requested <= d->alloc() && newType == d->type() && hasAttrs == enforceAttributes) return; - oldAlloc = d->alloc(); if (d->type() < Sparse) { - offset = qMax(offset, static_cast(d)->offset()); + offset = static_cast(d)->d()->offset; toCopy = static_cast(d)->len(); } else { - Q_ASSERT(!offset); toCopy = d->alloc(); - newType = Sparse; } + if (d->type() > newType) + newType = d->type(); } if (enforceAttributes && newType == Simple) newType = Complex; - alloc = qMax(alloc, 2*oldAlloc) + offset; - size_t size = alloc*sizeof(Value); + while (alloc < requested) + alloc *= 2; + size_t size = sizeof(ArrayData::Data) + alloc*sizeof(Value); if (enforceAttributes) size += alloc*sizeof(PropertyAttributes); + ArrayData *newData; if (newType < Sparse) { - size += sizeof(SimpleArrayData::Data); - SimpleArrayData *newData = static_cast(o->engine()->memoryManager->allocManaged(size)); - new (newData->d()) SimpleArrayData::Data(o->engine()); - newData->setAlloc(alloc - offset); - newData->setType(newType); - newData->setArrayData(reinterpret_cast(newData->d() + 1) + offset); - newData->setAttrs(enforceAttributes ? reinterpret_cast(newData->arrayData() + alloc) + offset : 0); - newData->offset() = offset; - newData->len() = d ? static_cast(d)->len() : 0; - o->setArrayData(newData); + SimpleArrayData *n = static_cast(o->engine()->memoryManager->allocManaged(size)); + new (n->d()) SimpleArrayData::Data(o->engine()); + n->d()->offset = 0; + n->len() = d ? static_cast(d)->len() : 0; + newData = n; } else { - size += sizeof(SparseArrayData::Data); - SparseArrayData *newData = static_cast(o->engine()->memoryManager->allocManaged(size)); - new (newData->d()) SparseArrayData::Data(o->engine()); - newData->setAlloc(alloc); - newData->setType(newType); - newData->setArrayData(reinterpret_cast(newData->d() + 1)); - newData->setAttrs(enforceAttributes ? reinterpret_cast(newData->arrayData() + alloc) : 0); - o->setArrayData(newData); + SparseArrayData *n = static_cast(o->engine()->memoryManager->allocManaged(size)); + new (n->d()) SparseArrayData::Data(o->engine()); + newData = n; } + newData->setAlloc(alloc); + newData->setType(newType); + newData->d()->arrayData = reinterpret_cast(newData->d() + 1); + newData->setAttrs(enforceAttributes ? reinterpret_cast(newData->d()->arrayData + alloc) : 0); + o->setArrayData(newData); if (d) { - memcpy(o->arrayData()->arrayData(), d->arrayData(), sizeof(Value)*toCopy); if (enforceAttributes) { if (d->attrs()) memcpy(o->arrayData()->attrs(), d->attrs(), sizeof(PropertyAttributes)*toCopy); @@ -153,56 +149,56 @@ void ArrayData::realloc(Object *o, Type newType, uint offset, uint alloc, bool e for (uint i = 0; i < toCopy; ++i) o->arrayData()->attrs()[i] = Attr_Data; } + + if (toCopy > d->d()->alloc - offset) { + uint copyFromStart = toCopy - (d->d()->alloc - offset); + memcpy(o->arrayData()->d()->arrayData + toCopy - copyFromStart, d->d()->arrayData, sizeof(Value)*copyFromStart); + toCopy -= copyFromStart; + } + memcpy(o->arrayData()->d()->arrayData, d->d()->arrayData + offset, sizeof(Value)*toCopy); } if (newType != Sparse) return; - SparseArrayData *newData = static_cast(o->arrayData()); + SparseArrayData *sparse = static_cast(o->arrayData()); + + uint *lastFree; if (d && d->type() == Sparse) { SparseArrayData *old = static_cast(d); - newData->setSparse(old->sparse()); + sparse->setSparse(old->sparse()); old->setSparse(0); - newData->freeList() = old->freeList(); + sparse->freeList() = old->freeList(); + lastFree = &sparse->freeList(); } else { - newData->setSparse(new SparseArray); - uint *lastFree = &newData->freeList(); + sparse->setSparse(new SparseArray); + lastFree = &sparse->freeList(); for (uint i = 0; i < toCopy; ++i) { - if (!newData->arrayData()[i].isEmpty()) { - SparseArrayNode *n = newData->sparse()->insert(i); + if (!sparse->arrayData()[i].isEmpty()) { + SparseArrayNode *n = sparse->sparse()->insert(i); n->value = i; } else { *lastFree = i; - newData->arrayData()[i].tag = Value::Empty_Type; - lastFree = &newData->arrayData()[i].uint_32; + sparse->arrayData()[i].tag = Value::Empty_Type; + lastFree = &sparse->arrayData()[i].uint_32; } } } - uint *lastFree = &newData->freeList(); - for (uint i = toCopy; i < newData->alloc(); ++i) { - *lastFree = i; - newData->arrayData()[i].tag = Value::Empty_Type; - lastFree = &newData->arrayData()[i].uint_32; + if (toCopy < sparse->alloc()) { + for (uint i = toCopy; i < sparse->alloc(); ++i) { + *lastFree = i; + sparse->arrayData()[i].tag = Value::Empty_Type; + lastFree = &sparse->arrayData()[i].uint_32; + } + *lastFree = UINT_MAX; } - *lastFree = newData->alloc(); - // ### Could explicitly free the old data } - -void SimpleArrayData::getHeadRoom(Object *o) -{ - SimpleArrayData *dd = static_cast(o->arrayData()); - Q_ASSERT(dd); - Q_ASSERT(!dd->offset()); - uint offset = qMax(dd->len() >> 2, (uint)16); - realloc(o, Simple, offset, 0, false); -} - ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes) { - realloc(o, Simple, 0, n, enforceAttributes); + realloc(o, Simple, n, enforceAttributes); return o->arrayData(); } @@ -211,7 +207,7 @@ void ArrayData::ensureAttributes(Object *o) if (o->arrayData() && o->arrayData()->attrs()) return; - ArrayData::realloc(o, Simple, 0, 0, true); + ArrayData::realloc(o, Simple, 0, true); } @@ -220,7 +216,7 @@ void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e) SimpleArrayData *dd = static_cast(d); uint l = dd->len(); for (uint i = 0; i < l; ++i) - dd->arrayData()[i].mark(e); + dd->data(i).mark(e); } ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index) @@ -228,7 +224,7 @@ ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index) const SimpleArrayData *dd = static_cast(d); if (index >= dd->len()) return Primitive::emptyValue().asReturnedValue(); - return dd->arrayData()[index].asReturnedValue(); + return dd->data(index).asReturnedValue(); } bool SimpleArrayData::put(Object *o, uint index, ValueRef value) @@ -236,7 +232,7 @@ bool SimpleArrayData::put(Object *o, uint index, ValueRef value) SimpleArrayData *dd = static_cast(o->arrayData()); Q_ASSERT(index >= dd->len() || !dd->attrs() || !dd->attrs()[index].isAccessor()); // ### honour attributes - dd->arrayData()[index] = value; + dd->data(index) = value; if (index >= dd->len()) { if (dd->attrs()) dd->attrs()[index] = Attr_Data; @@ -252,12 +248,12 @@ bool SimpleArrayData::del(Object *o, uint index) return true; if (!dd->attrs() || dd->attrs()[index].isConfigurable()) { - dd->arrayData()[index] = Primitive::emptyValue(); + dd->data(index) = Primitive::emptyValue(); if (dd->attrs()) dd->attrs()[index] = Attr_Data; return true; } - if (dd->arrayData()[index].isEmpty()) + if (dd->data(index).isEmpty()) return true; return false; } @@ -276,20 +272,14 @@ void SimpleArrayData::push_front(Object *o, Value *values, uint n) { SimpleArrayData *dd = static_cast(o->arrayData()); Q_ASSERT(!dd->attrs()); - for (int i = n - 1; i >= 0; --i) { - if (!dd->offset()) { - getHeadRoom(o); - dd = static_cast(o->arrayData()); - } - - - --dd->offset(); - --dd->arrayData(); - ++dd->len(); - ++dd->alloc(); - *dd->arrayData() = values[i].asReturnedValue(); + if (dd->len() + n > dd->alloc()) { + realloc(o, Simple, dd->len() + n, false); + dd = static_cast(o->arrayData()); } - + dd->d()->offset = (dd->d()->offset - n) % dd->d()->alloc; + dd->len() += n; + for (uint i = 0; i < n; ++i) + dd->data(i) = values[i].asReturnedValue(); } ReturnedValue SimpleArrayData::pop_front(Object *o) @@ -299,11 +289,9 @@ ReturnedValue SimpleArrayData::pop_front(Object *o) if (!dd->len()) return Encode::undefined(); - ReturnedValue v = dd->arrayData()[0].isEmpty() ? Encode::undefined() : dd->arrayData()[0].asReturnedValue(); - ++dd->offset(); - ++dd->arrayData(); + ReturnedValue v = dd->data(0).isEmpty() ? Encode::undefined() : dd->data(0).asReturnedValue(); + dd->d()->offset = (dd->d()->offset + 1) % dd->d()->alloc; --dd->len(); - --dd->alloc(); return v; } @@ -313,19 +301,17 @@ uint SimpleArrayData::truncate(Object *o, uint newLen) if (dd->len() < newLen) return newLen; - if (dd->attrs()) { - Value *it = dd->arrayData() + dd->len(); - const Value *begin = dd->arrayData() + newLen; - while (--it >= begin) { - if (!it->isEmpty() && !dd->attrs()[it - dd->arrayData()].isConfigurable()) { - newLen = it - dd->arrayData() + 1; - break; - } - *it = Primitive::emptyValue(); - } + if (!dd->attrs()) { + dd->len() = newLen; + return newLen; } - dd->len() = newLen; - return newLen; + + while (dd->len() > newLen) { + if (!dd->data(dd->len() - 1).isEmpty() && !dd->attrs()[dd->len() - 1].isConfigurable()) + return dd->len(); + --dd->len(); + } + return dd->len(); } uint SimpleArrayData::length(const ArrayData *d) @@ -341,9 +327,9 @@ bool SimpleArrayData::putArray(Object *o, uint index, Value *values, uint n) dd = static_cast(o->arrayData()); } for (uint i = dd->len(); i < index; ++i) - dd->arrayData()[i] = Primitive::emptyValue(); + dd->data(i) = Primitive::emptyValue(); for (uint i = 0; i < n; ++i) - dd->arrayData()[index + i] = values[i]; + dd->data(index + i) = values[i]; dd->len() = qMax(dd->len(), index + n); return true; } @@ -385,7 +371,7 @@ void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e) ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes) { - realloc(o, Sparse, 0, n, enforceAttributes); + realloc(o, Sparse, n, enforceAttributes); return o->arrayData(); } @@ -397,12 +383,14 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) if (doubleSlot) { uint *last = &dd->freeList(); while (1) { - if (*last + 1 >= dd->alloc()) { + if (*last == UINT_MAX) { reallocate(o, o->arrayData()->alloc() + 2, true); dd = static_cast(o->arrayData()); last = &dd->freeList(); + Q_ASSERT(*last != UINT_MAX); } + Q_ASSERT(dd->arrayData()[*last].uint_32 != *last); if (dd->arrayData()[*last].uint_32 == (*last + 1)) { // found two slots in a row uint idx = *last; @@ -413,11 +401,12 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) last = &dd->arrayData()[*last].uint_32; } } else { - if (dd->alloc() == dd->freeList()) { - reallocate(o, o->arrayData()->alloc() + 2, false); + if (dd->freeList() == UINT_MAX) { + reallocate(o, o->arrayData()->alloc() + 1, false); dd = static_cast(o->arrayData()); } uint idx = dd->freeList(); + Q_ASSERT(idx != UINT_MAX); dd->freeList() = dd->arrayData()[idx].uint_32; if (dd->attrs()) dd->attrs()[idx] = Attr_Data; @@ -427,10 +416,11 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) ReturnedValue SparseArrayData::get(const ArrayData *d, uint index) { - SparseArrayNode *n = static_cast(d)->sparse()->findNode(index); + const SparseArrayData *s = static_cast(d); + SparseArrayNode *n = s->sparse()->findNode(index); if (!n) return Primitive::emptyValue().asReturnedValue(); - return d->arrayData()[n->value].asReturnedValue(); + return s->arrayData()[n->value].asReturnedValue(); } bool SparseArrayData::put(Object *o, uint index, ValueRef value) @@ -438,13 +428,14 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) if (value->isEmpty()) return true; - SparseArrayNode *n = static_cast(o->arrayData())->sparse()->insert(index); + const SparseArrayData *s = static_cast(o->arrayData()); + SparseArrayNode *n = s->sparse()->insert(index); Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor()); if (n->value == UINT_MAX) n->value = allocate(o); - o->arrayData()->arrayData()[n->value] = value; - if (o->arrayData()->attrs()) - o->arrayData()->attrs()[n->value] = Attr_Data; + s->arrayData()[n->value] = value; + if (s->attrs()) + s->attrs()[n->value] = Attr_Data; return true; } @@ -469,12 +460,12 @@ bool SparseArrayData::del(Object *o, uint index) if (isAccessor) { // free up both indices - dd->arrayData()[pidx + 1].tag = Value::Undefined_Type; + dd->arrayData()[pidx + 1].tag = Value::Empty_Type; dd->arrayData()[pidx + 1].uint_32 = static_cast(dd)->freeList(); dd->arrayData()[pidx].tag = Value::Undefined_Type; dd->arrayData()[pidx].uint_32 = pidx + 1; } else { - dd->arrayData()[pidx].tag = Value::Undefined_Type; + dd->arrayData()[pidx].tag = Value::Empty_Type; dd->arrayData()[pidx].uint_32 = static_cast(dd)->freeList(); } @@ -509,21 +500,23 @@ PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index) void SparseArrayData::push_front(Object *o, Value *values, uint n) { + SparseArrayData *d = static_cast(o->arrayData()); Q_ASSERT(!o->arrayData()->attrs()); for (int i = n - 1; i >= 0; --i) { uint idx = allocate(o); - o->arrayData()->arrayData()[idx] = values[i]; - static_cast(o->arrayData())->sparse()->push_front(idx); + d->arrayData()[idx] = values[i]; + d->sparse()->push_front(idx); } } ReturnedValue SparseArrayData::pop_front(Object *o) { + SparseArrayData *d = static_cast(o->arrayData()); Q_ASSERT(!o->arrayData()->attrs()); - uint idx = static_cast(o->arrayData())->sparse()->pop_front(); + uint idx = d->sparse()->pop_front(); ReturnedValue v; if (idx != UINT_MAX) { - v = o->arrayData()->arrayData()[idx].asReturnedValue(); + v = d->arrayData()[idx].asReturnedValue(); free(o->arrayData(), idx); } else { v = Encode::undefined(); @@ -591,21 +584,30 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) uint oldSize = obj->getLength(); if (other->isSparse()) { + const SparseArrayData *os = static_cast(other); if (otherObj->hasAccessorProperty() && other->hasAttributes()) { Scope scope(obj->engine()); ScopedValue v(scope); - for (const SparseArrayNode *it = static_cast(other)->sparse()->begin(); - it != static_cast(other)->sparse()->end(); it = it->nextNode()) { - v = otherObj->getValue(reinterpret_cast(other->arrayData() + it->value), other->attrs()[it->value]); + for (const SparseArrayNode *it = os->sparse()->begin(); + it != os->sparse()->end(); it = it->nextNode()) { + v = otherObj->getValue(reinterpret_cast(os->arrayData() + it->value), other->attrs()[it->value]); obj->arraySet(oldSize + it->key(), v); } } else { for (const SparseArrayNode *it = static_cast(other)->sparse()->begin(); - it != static_cast(other)->sparse()->end(); it = it->nextNode()) - obj->arraySet(oldSize + it->key(), ValueRef(other->arrayData()[it->value])); + it != os->sparse()->end(); it = it->nextNode()) + obj->arraySet(oldSize + it->key(), ValueRef(os->arrayData()[it->value])); } } else { - obj->arrayPut(oldSize, other->arrayData(), n); + const SimpleArrayData *os = static_cast(other); + uint toCopy = n; + uint chunk = toCopy; + if (chunk > os->alloc() - os->d()->offset) + chunk -= os->alloc() - os->d()->offset; + obj->arrayPut(oldSize, os->arrayData() + os->d()->offset, chunk); + toCopy -= chunk; + if (toCopy) + obj->arrayPut(oldSize + chunk, os->arrayData(), toCopy); } return oldSize + n; @@ -623,18 +625,19 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor) if (index >= d->len()) { // mark possible hole in the array for (uint i = d->len(); i < index; ++i) - d->arrayData()[i] = Primitive::emptyValue(); + d->data(i) = Primitive::emptyValue(); d->len() = index + 1; } - return reinterpret_cast(o->arrayData()->arrayData() + index); + return reinterpret_cast(d->d()->arrayData + d->realIndex(index)); } } o->initSparseArray(); - SparseArrayNode *n = static_cast(o->arrayData())->sparse()->insert(index); + SparseArrayData *s = static_cast(o->arrayData()); + SparseArrayNode *n = s->sparse()->insert(index); if (n->value == UINT_MAX) n->value = SparseArrayData::allocate(o, isAccessor); - return reinterpret_cast(o->arrayData()->arrayData() + n->value); + return reinterpret_cast(s->arrayData() + n->value); } @@ -757,7 +760,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR return; thisObject->setArrayData(0); - ArrayData::realloc(thisObject, ArrayData::Simple, 0, sparse->sparse()->nEntries(), sparse->attrs() ? true : false); + ArrayData::realloc(thisObject, ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false); SimpleArrayData *d = static_cast(thisObject->arrayData()); SparseArrayNode *n = sparse->sparse()->begin(); @@ -768,7 +771,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR break; PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data; - d->arrayData()[i] = thisObject->getValue(reinterpret_cast(sparse->arrayData() + n->value), a); + d->data(i) = thisObject->getValue(reinterpret_cast(sparse->arrayData() + n->value), a); d->attrs()[i] = a.isAccessor() ? Attr_Data : a; n = n->nextNode(); @@ -778,7 +781,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR while (n != sparse->sparse()->end()) { if (n->value >= len) break; - d->arrayData()[i] = sparse->arrayData()[n->value]; + d->data(i) = sparse->arrayData()[n->value]; n = n->nextNode(); ++i; } @@ -805,13 +808,13 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR // sort empty values to the end for (uint i = 0; i < len; i++) { - if (thisObject->arrayData()->arrayData()[i].isEmpty()) { + if (d->data(i).isEmpty()) { while (--len > i) - if (!thisObject->arrayData()->arrayData()[len].isEmpty()) + if (!d->data(len).isEmpty()) break; - Q_ASSERT(!thisObject->arrayData()->attrs() || !thisObject->arrayData()->attrs()[len].isAccessor()); - thisObject->arrayData()->arrayData()[i] = thisObject->arrayData()->arrayData()[len]; - thisObject->arrayData()->arrayData()[len] = Primitive::emptyValue(); + Q_ASSERT(!d->attrs() || !d->attrs()[len].isAccessor()); + d->data(i) = d->data(len); + d->data(len) = Primitive::emptyValue(); } } @@ -822,7 +825,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR ArrayElementLessThan lessThan(context, thisObject, comparefn); - Value *begin = thisObject->arrayData()->arrayData(); + Value *begin = thisObject->arrayData()->d()->arrayData; sortHelper(begin, begin + len, *begin, lessThan); #ifdef CHECK_SPARSE_ARRAYS diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 3b04fe973a..cd080baa4a 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -90,6 +90,14 @@ struct Q_QML_EXPORT ArrayData : public Managed uint alloc; Type type; PropertyAttributes *attrs; + union { + uint len; + uint freeList; + }; + union { + uint offset; + SparseArray *sparse; + }; Value *arrayData; }; V4_MANAGED(Managed) @@ -103,7 +111,6 @@ struct Q_QML_EXPORT ArrayData : public Managed void setAttrs(PropertyAttributes *a) { d()->attrs = a; } Value *arrayData() const { return d()->arrayData; } Value *&arrayData() { return d()->arrayData; } - void setArrayData(Value *v) { d()->arrayData = v; } const ArrayVTable *vtable() const { return reinterpret_cast(internalClass()->vtable); } bool isSparse() const { return this && type() == Sparse; } @@ -136,7 +143,7 @@ struct Q_QML_EXPORT ArrayData : public Managed inline Property *getProperty(uint index) const; static void ensureAttributes(Object *o); - static void realloc(Object *o, Type newType, uint offset, uint alloc, bool enforceAttributes); + static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes); static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen); static uint append(Object *obj, const ArrayObject *otherObj, uint n); @@ -150,17 +157,25 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData Data(ExecutionEngine *engine) : ArrayData::Data(engine->simpleArrayDataClass) {} - uint len; - uint offset; }; V4_ARRAYDATA + uint realIndex(uint index) const { return (index + d()->offset) % d()->alloc; } + Value data(uint index) const { return d()->arrayData[realIndex(index)]; } + Value &data(uint index) { return d()->arrayData[realIndex(index)]; } + + Property *getProperty(uint index) const { + if (index >= len()) + return 0; + index = realIndex(index); + if (d()->arrayData[index].isEmpty()) + return 0; + return reinterpret_cast(d()->arrayData + index); + } + uint &len() { return d()->len; } uint len() const { return d()->len; } - uint &offset() { return d()->offset; } - uint offset() const { return d()->offset; } - static void getHeadRoom(Object *o); static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes); static void markObjects(Managed *d, ExecutionEngine *e); @@ -183,9 +198,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData Data(ExecutionEngine *engine) : ArrayData::Data(engine->emptyClass) { setVTable(staticVTable()); } - - uint freeList; - SparseArray *sparse; }; V4_ARRAYDATA @@ -220,14 +232,13 @@ inline Property *ArrayData::getProperty(uint index) const return 0; if (type() != Sparse) { const SimpleArrayData *that = static_cast(this); - if (index >= that->len() || arrayData()[index].isEmpty()) - return 0; - return reinterpret_cast(arrayData() + index); + return that->getProperty(index); } else { - SparseArrayNode *n = static_cast(this)->sparse()->findNode(index); + const SparseArrayData *that = static_cast(this); + SparseArrayNode *n = that->sparse()->findNode(index); if (!n) return 0; - return reinterpret_cast(arrayData() + n->value); + return reinterpret_cast(that->arrayData() + n->value); } } diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 7515a839ce..eaf474287b 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -614,20 +614,17 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx) return Encode(-1); } else { Q_ASSERT(instance->arrayType() == ArrayData::Simple || instance->arrayType() == ArrayData::Complex); - if (len > instance->arrayData()->length()) - len = instance->arrayData()->length(); - Value *val = instance->arrayData()->arrayData(); - Value *end = val + len; - val += fromIndex; - while (val < end) { - if (!val->isEmpty()) { - value = *val; - if (scope.hasException()) - return Encode::undefined(); - if (RuntimeHelpers::strictEqual(value, searchValue)) - return Encode((uint)(val - instance->arrayData()->arrayData())); - } - ++val; + SimpleArrayData *sa = static_cast(instance->arrayData()); + if (len > sa->len()) + len = sa->len(); + uint idx = fromIndex; + while (idx < len) { + value = sa->data(idx); + if (scope.hasException()) + return Encode::undefined(); + if (RuntimeHelpers::strictEqual(value, searchValue)) + return Encode(idx); + ++idx; } } return Encode(-1); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 84b0eb17af..67f2a0c75c 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -298,9 +298,9 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) for (quint32 i = 0; i < len; ++i) callData->args[i] = arr->getIndexed(i); } else { - int alen = qMin(len, arr->arrayData()->length()); - if (alen) - memcpy(callData->args, arr->arrayData()->arrayData(), alen*sizeof(Value)); + uint alen = qMin(len, arr->arrayData()->length()); + for (uint i = 0; i < alen; ++i) + callData->args[i] = static_cast(arr->arrayData())->data(i); for (quint32 i = alen; i < len; ++i) callData->args[i] = Primitive::undefinedValue(); } diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 6d4f05d8d4..4f2ec8315e 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -164,9 +164,10 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, c Object *o = object->objectValue(); if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { - if (idx < static_cast(o->arrayData())->len()) - if (!o->arrayData()->arrayData()[idx].isEmpty()) - return o->arrayData()->arrayData()[idx].asReturnedValue(); + SimpleArrayData *s = static_cast(o->arrayData()); + if (idx < s->len()) + if (!s->data(idx).isEmpty()) + return s->data(idx).asReturnedValue(); } return indexedGetterFallback(l, object, index); @@ -197,8 +198,8 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value if (idx < UINT_MAX) { if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { SimpleArrayData *s = static_cast(o->arrayData()); - if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) { - s->arrayData()[idx] = value; + if (idx < s->len() && !s->data(idx).isEmpty()) { + s->data(idx) = value; return; } } @@ -221,8 +222,8 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const Valu Object *o = object->objectValue(); if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) { SimpleArrayData *s = static_cast(o->arrayData()); - if (idx < s->len() && !s->arrayData()[idx].isEmpty()) { - s->arrayData()[idx] = v; + if (idx < s->len() && !s->data(idx).isEmpty()) { + s->data(idx) = v; return; } } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 6d78c89d89..1b2532018e 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -533,7 +533,8 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint while (it->arrayNode != o->sparseEnd()) { int k = it->arrayNode->key(); uint pidx = it->arrayNode->value; - Property *p = reinterpret_cast(o->arrayData()->arrayData() + pidx); + SparseArrayData *sa = static_cast(o->arrayData()); + Property *p = reinterpret_cast(sa->arrayData() + pidx); it->arrayNode = it->arrayNode->nextNode(); PropertyAttributes a = o->arrayData()->attributes(k); if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) { @@ -549,14 +550,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint } // dense arrays while (it->arrayIndex < o->arrayData()->length()) { - Value *val = o->arrayData()->arrayData() + it->arrayIndex; + SimpleArrayData *sa = static_cast(o->arrayData()); + Value &val = sa->data(it->arrayIndex); PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex); ++it->arrayIndex; - if (!val->isEmpty() + if (!val.isEmpty() && (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable())) { *index = it->arrayIndex - 1; *attrs = a; - pd->value = *val; + pd->value = val; return; } } @@ -1073,14 +1075,15 @@ void Object::copyArrayData(Object *other) } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){ // do it the slow way ScopedValue v(scope); - for (const SparseArrayNode *it = static_cast(other->arrayData())->sparse()->begin(); - it != static_cast(other->arrayData())->sparse()->end(); it = it->nextNode()) { - v = other->getValue(reinterpret_cast(other->arrayData()->arrayData() + it->value), other->arrayData()->attrs()[it->value]); + const SparseArrayData *osa = static_cast(other->arrayData()); + for (const SparseArrayNode *it = osa->sparse()->begin(); + it != osa->sparse()->end(); it = it->nextNode()) { + v = other->getValue(reinterpret_cast(osa->arrayData() + it->value), other->arrayData()->attrs()[it->value]); arraySet(it->key(), v); } } else { Q_ASSERT(!arrayData() && other->arrayData()); - ArrayData::realloc(this, other->arrayData()->type(), 0, other->arrayData()->alloc(), other->arrayData()->attrs()); + ArrayData::realloc(this, other->arrayData()->type(), other->arrayData()->alloc(), false); if (other->arrayType() == ArrayData::Sparse) { SparseArrayData *od = static_cast(other->arrayData()); SparseArrayData *dd = static_cast(arrayData()); @@ -1089,9 +1092,9 @@ void Object::copyArrayData(Object *other) } else { SimpleArrayData *d = static_cast(arrayData()); d->len() = static_cast(other->arrayData())->len(); - d->offset() = 0; + d->d()->offset = static_cast(other->arrayData())->d()->offset; } - memcpy(arrayData()->arrayData(), other->arrayData()->arrayData(), arrayData()->alloc()*sizeof(Value)); + memcpy(arrayData()->d()->arrayData, other->arrayData()->d()->arrayData, arrayData()->alloc()*sizeof(Value)); } setArrayLengthUnchecked(other->getLength()); } @@ -1132,7 +1135,7 @@ void Object::initSparseArray() if (arrayType() == ArrayData::Sparse) return; - ArrayData::realloc(this, ArrayData::Sparse, 0, 0, false); + ArrayData::realloc(this, ArrayData::Sparse, 0, false); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 77debf121c..86e4e78d28 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -222,12 +222,12 @@ public: } inline void arrayReserve(uint n) { - ArrayData::realloc(this, ArrayData::Simple, 0, n, false); + ArrayData::realloc(this, ArrayData::Simple, n, false); } void arrayCreate() { if (!arrayData()) - ArrayData::realloc(this, ArrayData::Simple, 0, 0, false); + ArrayData::realloc(this, ArrayData::Simple, 0, false); #ifdef CHECK_SPARSE_ARRAYS initSparseArray(); #endif diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 55047e1cf9..5086113964 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -606,8 +606,8 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val if (idx < UINT_MAX) { if (o->arrayType() == ArrayData::Simple) { SimpleArrayData *s = static_cast(o->arrayData()); - if (s && idx < s->len() && !s->arrayData()[idx].isEmpty()) { - s->arrayData()[idx] = value; + if (s && idx < s->len() && !s->data(idx).isEmpty()) { + s->data(idx) = value; return; } } -- cgit v1.2.3 From 8539aa87345fc9a972d9b400fa42fd742b01d4ed Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 22 Oct 2014 16:00:35 +0200 Subject: Reduce size of ArrayData by one pointer The pointer to the real data is not required anymore, as it always follows the class itself. Like this we save one pointer of overhead, and one indirection when doing reads and writes of array data. Change-Id: If6afdac8e97b57420b50e7b7eb8979f77e8dbbcf Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4arraydata.cpp | 22 +++++++++---------- src/qml/jsruntime/qv4arraydata_p.h | 45 ++++++++++++++++++++++++-------------- src/qml/jsruntime/qv4object.cpp | 5 ++--- src/qml/jsruntime/qv4object_p.h | 3 +-- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 469081e683..c40f50153d 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -119,7 +119,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt while (alloc < requested) alloc *= 2; - size_t size = sizeof(ArrayData::Data) + alloc*sizeof(Value); + size_t size = sizeof(ArrayData::Data) + (alloc - 1)*sizeof(Value); if (enforceAttributes) size += alloc*sizeof(PropertyAttributes); @@ -137,7 +137,6 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt } newData->setAlloc(alloc); newData->setType(newType); - newData->d()->arrayData = reinterpret_cast(newData->d() + 1); newData->setAttrs(enforceAttributes ? reinterpret_cast(newData->d()->arrayData + alloc) : 0); o->setArrayData(newData); @@ -417,10 +416,10 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot) ReturnedValue SparseArrayData::get(const ArrayData *d, uint index) { const SparseArrayData *s = static_cast(d); - SparseArrayNode *n = s->sparse()->findNode(index); - if (!n) + index = s->mappedIndex(index); + if (index == UINT_MAX) return Primitive::emptyValue().asReturnedValue(); - return s->arrayData()[n->value].asReturnedValue(); + return s->arrayData()[index].asReturnedValue(); } bool SparseArrayData::put(Object *o, uint index, ValueRef value) @@ -428,7 +427,7 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) if (value->isEmpty()) return true; - const SparseArrayData *s = static_cast(o->arrayData()); + SparseArrayData *s = static_cast(o->arrayData()); SparseArrayNode *n = s->sparse()->insert(index); Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor()); if (n->value == UINT_MAX) @@ -442,6 +441,7 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value) bool SparseArrayData::del(Object *o, uint index) { SparseArrayData *dd = static_cast(o->arrayData()); + SparseArrayNode *n = dd->sparse()->findNode(index); if (!n) return true; @@ -567,14 +567,14 @@ bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n) } -uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) +uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n) { Q_ASSERT(!obj->arrayData()->hasAttributes()); if (!n) return obj->getLength(); - const ArrayData *other = otherObj->arrayData(); + ArrayData *other = otherObj->arrayData(); if (other->isSparse()) obj->initSparseArray(); @@ -584,7 +584,7 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) uint oldSize = obj->getLength(); if (other->isSparse()) { - const SparseArrayData *os = static_cast(other); + SparseArrayData *os = static_cast(other); if (otherObj->hasAccessorProperty() && other->hasAttributes()) { Scope scope(obj->engine()); ScopedValue v(scope); @@ -599,7 +599,7 @@ uint ArrayData::append(Object *obj, const ArrayObject *otherObj, uint n) obj->arraySet(oldSize + it->key(), ValueRef(os->arrayData()[it->value])); } } else { - const SimpleArrayData *os = static_cast(other); + SimpleArrayData *os = static_cast(other); uint toCopy = n; uint chunk = toCopy; if (chunk > os->alloc() - os->d()->offset) @@ -628,7 +628,7 @@ Property *ArrayData::insert(Object *o, uint index, bool isAccessor) d->data(i) = Primitive::emptyValue(); d->len() = index + 1; } - return reinterpret_cast(d->d()->arrayData + d->realIndex(index)); + return reinterpret_cast(d->d()->arrayData + d->mappedIndex(index)); } } diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index cd080baa4a..70c581d75d 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -98,7 +98,7 @@ struct Q_QML_EXPORT ArrayData : public Managed uint offset; SparseArray *sparse; }; - Value *arrayData; + Value arrayData[1]; }; V4_MANAGED(Managed) @@ -109,8 +109,8 @@ struct Q_QML_EXPORT ArrayData : public Managed void setType(Type t) { d()->type = t; } PropertyAttributes *attrs() const { return d()->attrs; } void setAttrs(PropertyAttributes *a) { d()->attrs = a; } - Value *arrayData() const { return d()->arrayData; } - Value *&arrayData() { return d()->arrayData; } + const Value *arrayData() const { return &d()->arrayData[0]; } + Value *arrayData() { return &d()->arrayData[0]; } const ArrayVTable *vtable() const { return reinterpret_cast(internalClass()->vtable); } bool isSparse() const { return this && type() == Sparse; } @@ -140,13 +140,13 @@ struct Q_QML_EXPORT ArrayData : public Managed return Primitive::emptyValue().asReturnedValue(); return vtable()->get(this, i); } - inline Property *getProperty(uint index) const; + inline Property *getProperty(uint index); static void ensureAttributes(Object *o); static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes); static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen); - static uint append(Object *obj, const ArrayObject *otherObj, uint n); + static uint append(Object *obj, ArrayObject *otherObj, uint n); static Property *insert(Object *o, uint index, bool isAccessor = false); }; @@ -160,14 +160,14 @@ struct Q_QML_EXPORT SimpleArrayData : public ArrayData }; V4_ARRAYDATA - uint realIndex(uint index) const { return (index + d()->offset) % d()->alloc; } - Value data(uint index) const { return d()->arrayData[realIndex(index)]; } - Value &data(uint index) { return d()->arrayData[realIndex(index)]; } + uint mappedIndex(uint index) const { return (index + d()->offset) % d()->alloc; } + Value data(uint index) const { return d()->arrayData[mappedIndex(index)]; } + Value &data(uint index) { return d()->arrayData[mappedIndex(index)]; } - Property *getProperty(uint index) const { + Property *getProperty(uint index) { if (index >= len()) return 0; - index = realIndex(index); + index = mappedIndex(index); if (d()->arrayData[index].isEmpty()) return 0; return reinterpret_cast(d()->arrayData + index); @@ -209,6 +209,20 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData static uint allocate(Object *o, bool doubleSlot = false); static void free(ArrayData *d, uint idx); + Property *getProperty(uint index) { + SparseArrayNode *n = sparse()->findNode(index); + if (!n) + return 0; + return reinterpret_cast(arrayData() + n->value); + } + + uint mappedIndex(uint index) const { + SparseArrayNode *n = sparse()->findNode(index); + if (!n) + return UINT_MAX; + return n->value; + } + static void destroy(Managed *d); static void markObjects(Managed *d, ExecutionEngine *e); @@ -226,19 +240,16 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData }; -inline Property *ArrayData::getProperty(uint index) const +inline Property *ArrayData::getProperty(uint index) { if (!this) return 0; if (type() != Sparse) { - const SimpleArrayData *that = static_cast(this); + SimpleArrayData *that = static_cast(this); return that->getProperty(index); } else { - const SparseArrayData *that = static_cast(this); - SparseArrayNode *n = that->sparse()->findNode(index); - if (!n) - return 0; - return reinterpret_cast(that->arrayData() + n->value); + SparseArrayData *that = static_cast(this); + return that->getProperty(index); } } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 1b2532018e..d53ca013b4 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1075,9 +1075,8 @@ void Object::copyArrayData(Object *other) } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){ // do it the slow way ScopedValue v(scope); - const SparseArrayData *osa = static_cast(other->arrayData()); - for (const SparseArrayNode *it = osa->sparse()->begin(); - it != osa->sparse()->end(); it = it->nextNode()) { + SparseArrayData *osa = static_cast(other->arrayData()); + for (const SparseArrayNode *it = osa->sparse()->begin(); it != osa->sparse()->end(); it = it->nextNode()) { v = other->getValue(reinterpret_cast(osa->arrayData() + it->value), other->arrayData()->attrs()[it->value]); arraySet(it->key(), v); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 86e4e78d28..4e9d1527c2 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -114,8 +114,7 @@ struct Q_QML_EXPORT Object: Managed { Members &memberData() { return d()->memberData; } const Members &memberData() const { return d()->memberData; } - const ArrayData *arrayData() const { return d()->arrayData; } - ArrayData *arrayData() { return d()->arrayData; } + ArrayData *arrayData() const { return d()->arrayData; } void setArrayData(ArrayData *a) { d()->arrayData = a; } Property *propertyAt(uint index) const { return reinterpret_cast(memberData().data() + index); } -- cgit v1.2.3 From 57e5407178ce05f577bd032a7bab2508434a4b02 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 27 Oct 2014 08:54:26 +0100 Subject: Don't check the this pointer for 0 in member functions This actually violates the C++ standard that defines that you aren't allowed to call member functions on an invalid object. Instead insert the 0 pointer checks on the caller side where required. Change-Id: I8be3c3831594bb6482e9ef6de6e590ec437ac0f8 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4argumentsobject.cpp | 4 +++- src/qml/jsruntime/qv4arraydata.cpp | 2 +- src/qml/jsruntime/qv4arraydata_p.h | 8 -------- src/qml/jsruntime/qv4arrayobject.cpp | 3 +++ src/qml/jsruntime/qv4functionobject.cpp | 4 +++- src/qml/jsruntime/qv4lookup.cpp | 2 +- src/qml/jsruntime/qv4object.cpp | 19 ++++++++++--------- src/qml/jsruntime/qv4objectproto.cpp | 10 +++++----- src/qml/jsruntime/qv4runtime.cpp | 2 +- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index d79521ca2f..4af8927a2e 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -97,7 +97,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const fullyCreate(); Scope scope(ctx); - Property *pd = arrayData()->getProperty(index); + Property *pd = arrayData() ? arrayData()->getProperty(index) : 0; Property map; PropertyAttributes mapAttrs; bool isMapped = false; @@ -106,6 +106,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const isMapped = arrayData()->attributes(index).isAccessor() && pd->getter() == context()->d()->engine->argumentsAccessors[index].getter(); if (isMapped) { + Q_ASSERT(arrayData()); mapAttrs = arrayData()->attributes(index); map.copy(*pd, mapAttrs); setArrayAttributes(index, Attr_Data); @@ -119,6 +120,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const ctx->d()->strictMode = strict; if (isMapped && attrs.isData()) { + Q_ASSERT(arrayData()); ScopedCallData callData(scope, 1); callData->thisObject = this->asReturnedValue(); callData->args[0] = desc.value; diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index c40f50153d..3235a116ee 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -740,7 +740,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR if (!len) return; - if (!thisObject->arrayData()->length()) + if (!thisObject->arrayData() || !thisObject->arrayData()->length()) return; if (!(comparefn->isUndefined() || comparefn->asObject())) { diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 70c581d75d..c2deb3e385 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -116,8 +116,6 @@ struct Q_QML_EXPORT ArrayData : public Managed bool isSparse() const { return this && type() == Sparse; } uint length() const { - if (!this) - return 0; return vtable()->length(this); } @@ -130,14 +128,10 @@ struct Q_QML_EXPORT ArrayData : public Managed } bool isEmpty(uint i) const { - if (!this) - return true; return (vtable()->get(this, i) == Primitive::emptyValue().asReturnedValue()); } ReturnedValue get(uint i) const { - if (!this) - return Primitive::emptyValue().asReturnedValue(); return vtable()->get(this, i); } inline Property *getProperty(uint index); @@ -242,8 +236,6 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData inline Property *ArrayData::getProperty(uint index) { - if (!this) - return 0; if (type() != Sparse) { SimpleArrayData *that = static_cast(this); return that->getProperty(index); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index eaf474287b..011279ae07 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -268,6 +268,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); @@ -347,6 +348,7 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); @@ -534,6 +536,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx) return Encode::undefined(); instance->arrayCreate(); + Q_ASSERT(instance->arrayData()); uint len = instance->getLength(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 67f2a0c75c..f3ad8ef892 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -298,7 +298,9 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx) for (quint32 i = 0; i < len; ++i) callData->args[i] = arr->getIndexed(i); } else { - uint alen = qMin(len, arr->arrayData()->length()); + uint alen = arr->arrayData() ? arr->arrayData()->length() : 0; + if (alen > len) + alen = len; for (uint i = 0; i < alen; ++i) callData->args[i] = static_cast(arr->arrayData())->data(i); for (quint32 i = alen; i < len; ++i) diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 4f2ec8315e..254666eca2 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -139,7 +139,7 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co } if (idx < UINT_MAX) { - if (!o->arrayData()->hasAttributes()) { + if (o->arrayData() && !o->arrayData()->hasAttributes()) { ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index d53ca013b4..0c61d666ab 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -244,7 +244,7 @@ Property *Object::__getOwnProperty__(String *name, PropertyAttributes *attrs) Property *Object::__getOwnProperty__(uint index, PropertyAttributes *attrs) { - Property *p = arrayData()->getProperty(index); + Property *p = arrayData() ? arrayData()->getProperty(index) : 0; if (p) { if (attrs) *attrs = arrayData()->attributes(index); @@ -289,7 +289,7 @@ Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attr { const Object *o = this; while (o) { - Property *p = o->arrayData()->getProperty(index); + Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0; if (p) { if (attrs) *attrs = o->arrayData()->attributes(index); @@ -355,7 +355,7 @@ bool Object::hasOwnProperty(String *name) const bool Object::hasOwnProperty(uint index) const { - if (!arrayData()->isEmpty(index)) + if (arrayData() && !arrayData()->isEmpty(index)) return true; if (isStringObject()) { String *s = static_cast(this)->d()->value.asString(); @@ -414,7 +414,7 @@ PropertyAttributes Object::query(const Managed *m, String *name) PropertyAttributes Object::queryIndexed(const Managed *m, uint index) { const Object *o = static_cast(m); - if (o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue()) + if (o->arrayData() && o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue()) return o->arrayData()->attributes(index); if (o->isStringObject()) { @@ -618,7 +618,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty) PropertyAttributes attrs; Object *o = this; while (o) { - Property *p = o->arrayData()->getProperty(index); + Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0; if (p) { pd = p; attrs = o->arrayData()->attributes(index); @@ -738,7 +738,7 @@ void Object::internalPutIndexed(uint index, const ValueRef value) PropertyAttributes attrs; - Property *pd = arrayData()->getProperty(index); + Property *pd = arrayData() ? arrayData()->getProperty(index) : 0; if (pd) attrs = arrayData()->attributes(index); @@ -925,7 +925,7 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert Property *current = 0; // Clause 1 - { + if (arrayData()) { current = arrayData()->getProperty(index); if (!current && isStringObject()) current = static_cast(this)->getIndex(index); @@ -962,12 +962,12 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me if (attrs.isEmpty()) return true; - Property *current; + Property *current = 0; PropertyAttributes cattrs; if (member) { current = propertyAt(index); cattrs = internalClass()->propertyData[index]; - } else { + } else if (arrayData()) { current = arrayData()->getProperty(index); cattrs = arrayData()->attributes(index); } @@ -1000,6 +1000,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me if (!member) { // need to convert the array and the slot initSparseArray(); + Q_ASSERT(arrayData()); setArrayAttributes(index, cattrs); current = arrayData()->getProperty(index); } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index a1c61307d1..9cbf4b204e 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -329,11 +329,11 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx) if (!o->arrayData() || !o->arrayData()->length()) return Encode(true); - if (o->arrayData()->length() && !o->arrayData()->attrs()) + Q_ASSERT(o->arrayData() && o->arrayData()->length()); + if (!o->arrayData()->attrs()) return Encode(false); for (uint i = 0; i < o->arrayData()->alloc(); ++i) { - // ### Fix for sparse arrays if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable()) return Encode(false); @@ -355,14 +355,14 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx) if (o->internalClass() != o->internalClass()->frozen()) return Encode(false); - if (!o->arrayData()->length()) + if (!o->arrayData() || !o->arrayData()->length()) return Encode(true); - if (o->arrayData()->length() && !o->arrayData()->attrs()) + Q_ASSERT(o->arrayData() && o->arrayData()->length()); + if (!o->arrayData()->attrs()) return Encode(false); for (uint i = 0; i < o->arrayData()->alloc(); ++i) { - // ### Fix for sparse arrays if (!o->arrayData()->isEmpty(i)) if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable()) return Encode(false); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 5086113964..048ff935bf 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -580,7 +580,7 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object, } if (idx < UINT_MAX) { - if (!o->arrayData()->hasAttributes()) { + if (o->arrayData() && !o->arrayData()->hasAttributes()) { ScopedValue v(scope, o->arrayData()->get(idx)); if (!v->isEmpty()) return v->asReturnedValue(); -- cgit v1.2.3 From 327d0886c3d9e9854849f5bebda4d6825e94a62e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 27 Oct 2014 13:51:27 +0100 Subject: Reduce memory pressure on system malloc when allocating large items on the GC heap Try to free our large items for every 8 megabytes of additional large item memory we allocate. This helps in particular on 32-bit builds and was noticable in tst_qqmlecmascript::push_and_shift(). Change-Id: I4cc0b188e58ccaf32026e38c7aaf1cfadc83148b Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4mm.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index 442a27661b..b9a4a55b4a 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -104,6 +104,7 @@ struct MemoryManager::Data }; LargeItem *largeItems; + std::size_t totalLargeItemsAllocated; GCDeletable *deletable; @@ -120,6 +121,7 @@ struct MemoryManager::Data , maxShift(6) , maxChunkSize(32*1024) , largeItems(0) + , totalLargeItemsAllocated(0) , deletable(0) { memset(smallItems, 0, sizeof(smallItems)); @@ -185,6 +187,9 @@ Managed *MemoryManager::allocData(std::size_t size) // doesn't fit into a small bucket if (size >= MemoryManager::Data::MaxItemSize) { + if (m_d->totalLargeItemsAllocated > 8 * 1024 * 1024) + runGC(); + // we use malloc for this MemoryManager::Data::LargeItem *item = static_cast( malloc(Q_V4_PROFILE_ALLOC(m_d->engine, size + sizeof(MemoryManager::Data::LargeItem), @@ -193,6 +198,7 @@ Managed *MemoryManager::allocData(std::size_t size) item->next = m_d->largeItems; item->size = size; m_d->largeItems = item; + m_d->totalLargeItemsAllocated += size; return item->managed(); } @@ -476,6 +482,7 @@ void MemoryManager::runGC() memset(m_d->allocCount, 0, sizeof(m_d->allocCount)); m_d->totalAlloc = 0; + m_d->totalLargeItemsAllocated = 0; } size_t MemoryManager::getUsedMem() const -- cgit v1.2.3 From df7f3141bddfd84590091612b271521a5d721a37 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 22 Oct 2014 12:43:42 +0200 Subject: Don't document Context2D's TextMetrics as its own QML type. It can't be instantiated like a QML type, so it's actually better to just document measureText() (which is the only way to construct objects of this type) as returning an object containing some metrics for the current font. This should have no effect on user code. This solves the issue of the new TextMetrics type's documentation not showing up. TextMetrics is a type that *can* be instantiated and is more feature complete. It provides a declarative API for the functions that take arguments in QFontMetrics. Change-Id: I46251e6f3aa7179ab569f5131307181f71043df4 Reviewed-by: J-P Nurmi --- src/quick/items/context2d/qquickcontext2d.cpp | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index d9ac3abdc3..b1af6f10dd 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -2801,28 +2801,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::CallContex } /*! - \qmltype TextMetrics - \inqmlmodule QtQuick - \since 5.0 - \ingroup qtquick-canvas - \brief Provides a Context2D TextMetrics interface - - The TextMetrics object can be created by QtQuick::Context2D::measureText method. - See \l{http://www.w3.org/TR/2dcontext/#textmetrics}{W3C 2d context TextMetrics} for more details. - - \sa Context2D::measureText - \sa width - */ + \qmlmethod object QtQuick::Context2D::measureText(text) -/*! - \qmlproperty int QtQuick::TextMetrics::width - Holds the advance width of the text that was passed to the QtQuick::Context2D::measureText() method. - This property is read only. - */ - -/*! - \qmlmethod variant QtQuick::Context2D::measureText(text) - Returns a TextMetrics object with the metrics of the given text in the current font. + Returns an object with a \c width property, whose value is equivalent to + calling \l {QFontMetrics::width()} with the given \a text in the current font. */ QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::CallContext *ctx) { -- cgit v1.2.3 From 94297b4ca50439d27dd5c3de6ff225185647cc46 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Tue, 28 Oct 2014 09:59:23 +0100 Subject: Do not crash QML apps on startup This started crashing because of 8f6436f125faae91eb472ddddbbae06dba5da671 Task-number: QTBUG-42227 Change-Id: I9e4862f6008c6ad6ec54469f2b39dd6be583e422 Reviewed-by: Friedemann Kleint Reviewed-by: Frederik Gladhorn --- src/quick/items/qquickaccessibleattached.cpp | 17 ++++++++++++----- src/quick/items/qquickaccessibleattached_p.h | 8 ++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp index 38b26a53d0..abb763c2eb 100644 --- a/src/quick/items/qquickaccessibleattached.cpp +++ b/src/quick/items/qquickaccessibleattached.cpp @@ -292,10 +292,10 @@ QT_BEGIN_NAMESPACE The corresponding handler is \c onDecreaseAction. */ -const QMetaMethod QQuickAccessibleAttached::sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction); -const QMetaMethod QQuickAccessibleAttached::sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction); -const QMetaMethod QQuickAccessibleAttached::sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction); -const QMetaMethod QQuickAccessibleAttached::sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction); +QMetaMethod QQuickAccessibleAttached::sigPress; +QMetaMethod QQuickAccessibleAttached::sigToggle; +QMetaMethod QQuickAccessibleAttached::sigIncrease; +QMetaMethod QQuickAccessibleAttached::sigDecrease; QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) : QObject(parent), m_role(QAccessible::NoRole) @@ -317,6 +317,13 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent) if (!parent->property("cursorPosition").isNull()) { connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged())); } + + if (!sigPress.isValid()) { + sigPress = QMetaMethod::fromSignal(&QQuickAccessibleAttached::pressAction); + sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction); + sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction); + sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction); + } } QQuickAccessibleAttached::~QQuickAccessibleAttached() @@ -343,7 +350,7 @@ void QQuickAccessibleAttached::setIgnored(bool ignored) bool QQuickAccessibleAttached::doAction(const QString &actionName) { - const QMetaMethod *sig = 0; + QMetaMethod *sig = 0; if (actionName == QAccessibleActionInterface::pressAction()) sig = &sigPress; else if (actionName == QAccessibleActionInterface::toggleAction()) diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h index 53b1d2954d..ad6165f936 100644 --- a/src/quick/items/qquickaccessibleattached_p.h +++ b/src/quick/items/qquickaccessibleattached_p.h @@ -221,10 +221,10 @@ private: QString m_name; QString m_description; - static const QMetaMethod sigPress; - static const QMetaMethod sigToggle; - static const QMetaMethod sigIncrease; - static const QMetaMethod sigDecrease; + static QMetaMethod sigPress; + static QMetaMethod sigToggle; + static QMetaMethod sigIncrease; + static QMetaMethod sigDecrease; public: using QObject::property; -- cgit v1.2.3 From 05d8ffb4dff5e693967c8ee7cee6d6158eadccbd Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 16 Oct 2014 10:10:04 +0200 Subject: Revert: use the new form of QTranslator::load() for more flexibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 427646b8d7c52e5b84240e07ffd391217ce3bfa8. It seems that it should have been more correct, but we are still not shipping English translations, and static QString find_translation() in qtranslator.cpp will return any language which is in QLocale::uiLanguages() for which the translation file is found. That is a long list on OSX. Reverting the patch means find_translation() is not called in such cases. This change can be re-done whenever we are more sure that the attempt to find a translation will succeed in finding a sensible one, or fall back to not translating, rather than choosing a language that the user didn't intend. Task-number: QTBUG-41977 Change-Id: I425946cc71cec96b4f38629eb2b7e80220c5236d Reviewed-by: Jan Arve Sæther --- examples/quick/demos/photoviewer/main.cpp | 3 +-- src/qml/qml/qqmlapplicationengine.cpp | 6 ++---- tools/qml/main.cpp | 6 ++++-- tools/qmlscene/main.cpp | 14 ++++++-------- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/examples/quick/demos/photoviewer/main.cpp b/examples/quick/demos/photoviewer/main.cpp index 1351f043f3..ca495242a4 100644 --- a/examples/quick/demos/photoviewer/main.cpp +++ b/examples/quick/demos/photoviewer/main.cpp @@ -40,9 +40,8 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - QLocale locale; QTranslator qtTranslator; - qtTranslator.load(locale, QLatin1String("qml"), QLatin1String("_"), QLatin1String(":/i18n")); + qtTranslator.load("qml_" + QLocale::system().name(), ":/i18n/"); app.installTranslator(&qtTranslator); QQmlApplicationEngine engine; diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 9ccaee7cd7..240c01233b 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -65,8 +65,7 @@ void QQmlApplicationEnginePrivate::init() q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit())); #ifndef QT_NO_TRANSLATION QTranslator* qtTranslator = new QTranslator; - QLocale locale; - if (qtTranslator->load(locale, QLatin1String("qt"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if (qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) QCoreApplication::installTranslator(qtTranslator); translators << qtTranslator; #endif @@ -83,8 +82,7 @@ void QQmlApplicationEnginePrivate::loadTranslations(const QUrl &rootFile) QFileInfo fi(rootFile.toLocalFile()); QTranslator *translator = new QTranslator; - QLocale locale; - if (translator->load(locale, QLatin1String("qml"), QLatin1String("_"), fi.path() + QLatin1String("/i18n"))) { + if (translator->load(QLatin1String("qml_") + QLocale::system().name(), fi.path() + QLatin1String("/i18n"))) { QCoreApplication::installTranslator(translator); translators << translator; } else { diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 7a08562a13..69ccd7a316 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -450,8 +450,10 @@ int main(int argc, char *argv[]) verboseMode = false; #ifndef QT_NO_TRANSLATION - // qt_ translations are loaded by QQmlApplicationEngine - if (!translationFile.isEmpty()) { // Note: installed before QQmlApplicationEngine's automatic translation loading + //qt_ translations loaded by QQmlApplicationEngine + QString sysLocale = QLocale::system().name(); + + if (!translationFile.isEmpty()) { //Note: installed before QQmlApplicationEngine's automatic translation loading QTranslator translator; if (translator.load(translationFile)) { diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp index 7c2fd9fc32..208226c8aa 100644 --- a/tools/qmlscene/main.cpp +++ b/tools/qmlscene/main.cpp @@ -307,8 +307,7 @@ static void displayFileDialog(Options *options) #ifndef QT_NO_TRANSLATION static void loadTranslationFile(QTranslator &translator, const QString& directory) { - QLocale locale; - translator.load(locale, QLatin1String("qml"), QLatin1String("_"), directory + QLatin1String("/i18n")); + translator.load(QLatin1String("qml_" )+QLocale::system().name(), directory + QLatin1String("/i18n")); QCoreApplication::installTranslator(&translator); } #endif @@ -416,18 +415,17 @@ int main(int argc, char ** argv) app.setOrganizationDomain("qt-project.org"); #ifndef QT_NO_TRANSLATION - QLocale locale; + QTranslator translator; QTranslator qtTranslator; - if (qtTranslator.load(locale, QLatin1String("qt"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + QString sysLocale = QLocale::system().name(); + if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) app.installTranslator(&qtTranslator); - - QTranslator translator; - if (translator.load(locale, QLatin1String("qmlscene"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if (translator.load(QLatin1String("qmlscene_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) app.installTranslator(&translator); QTranslator qmlTranslator; if (!options.translationFile.isEmpty()) { - if (qmlTranslator.load(locale, options.translationFile)) { + if (qmlTranslator.load(options.translationFile)) { app.installTranslator(&qmlTranslator); } else { qWarning() << "Could not load the translation file" << options.translationFile; -- cgit v1.2.3